Пример #1
0
         Edge(1, 5), Edge(5, 5), Edge(1, 7), Edge(7, 1)});
    this->checkAddEdge(6, Edge(1, 7), {Edge(0, 5), Edge(5, 0), Edge(1, 7)},
        {Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6),
         Edge(1, 5), Edge(5, 5), Edge(7, 1)});
    this->checkAddEdge(6, Edge(5, 5),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5)},
        {Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6), Edge(1, 5), Edge(7, 1)});
    this->checkAddEdge(7, Edge(5, 6),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5), Edge(5, 6)}, {});
    this->checkAddEdge(8, Edge(6, 5),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5), Edge(5, 6), Edge(6, 5)}, {});
}

TYPED_TEST_P(BipartiteGraphTest, addEdge_tooBigIndex)
{
    ASSERT_THROW(this->g.addEdge(Edge(TypeParam::INDEX_LIMIT, 0)), typename TypeParam::exception_t);
    ASSERT_THROW(this->g.addEdge(Edge(TypeParam::INDEX_LIMIT + 1, 0)), typename TypeParam::exception_t);
    ASSERT_THROW(this->g.addEdge(Edge(0, TypeParam::INDEX_LIMIT)), typename TypeParam::exception_t);
    ASSERT_THROW(this->g.addEdge(Edge(0, TypeParam::INDEX_LIMIT + 1)), typename TypeParam::exception_t);
    ASSERT_THROW(
        this->g.addEdge(Edge(TypeParam::INDEX_LIMIT, TypeParam::INDEX_LIMIT)),
        typename TypeParam::exception_t);
    ASSERT_THROW(
        this->g.addEdge(Edge(TypeParam::INDEX_LIMIT + 1, TypeParam::INDEX_LIMIT + 1)),
        typename TypeParam::exception_t);
}

TYPED_TEST_P(BipartiteGraphTest, simpleMaximumMatching)
{
    this->checkMatching(3, {Edge(0, 0), Edge(1, 1), Edge(2, 2)});
}
Пример #2
0
	inline void addEdge(int u,int v,Type cost){
		e[cnt] = Edge(v,cost);
		int tmp = head[u];
		head[u] = cnt;
		nxt[cnt++] = tmp;	
	}
Пример #3
0
// edges are given as (edges[i], edges[i+1])
void find_non_manifold_verts(const cvcraw_geometry::cvcgeom_t& geom,
                             std::vector<int>& non_manifold_vertices) {
  static log4cplus::Logger logger =
      log4cplus::Logger::getInstance("find_non_manifold_verts");

  const vector<Point_3> vertices = sm_vertices(geom);
  const vector<Triangle> triangles = sm_triangles(geom);

  const vector<vector<Triangle> > v2t = build_v2t(triangles.begin(), triangles.end());

  // set<Edge> non_manifold_edges;
  // vector<int> non_manifold_vertices;
  for (int vi = 0; vi < v2t.size(); ++vi) {
    set<Edge> edges;
    bool manifold = true;
    const vector<Triangle>& tris = v2t[vi];
    if (!tris.empty()){
      set<Triangle> tri_set(tris.begin(), tris.end());

      Triangle start_t = *tri_set.begin();
      Triangle t = *tri_set.begin();

      bool done = false;

      const int li = t.g2l(vi);
      const Edge er(t[(li+1)%3], vi);
      const Edge el(t[(li+2)%3], vi);
      Edge e = er;


      //walk right when count = 0 and left when count =1
      int count = 0;
      while (count < 2){
        while (!done && manifold && !tri_set.empty() && tri_set.find(t) != tri_set.end()) {
          tri_set.erase(t);
          // Local triangle index [012] of vi in triangle t
          const vector<Triangle> adjs = adj_triangles(e, v2t);
          if (adjs.size() < 2) {
            // boundary
            done = true;
          } else if (adjs.size() > 2) {
            // non_manifold edge
            done = true;
            manifold = false;
          } else {
            Triangle adj = adjs[0];
            if (adj == t) {
              adj = adjs[1];
            }
            t = adj;
            e = Edge(adj.opposite(e), vi);
          }
        }
        t = start_t;
        if (count == 0 && !tri_set.empty()){
          tri_set.insert(t); //just so it can be removed again
        }
        done = false;
        e = el;
        count++;
      }

      if (!tri_set.empty() || !manifold) {
        LOG4CPLUS_TRACE(logger, "Non Manifold vert is: " << vi);
        non_manifold_vertices.push_back(vi);
      }
    }
  }
}
Пример #4
0
    TriMesh<FloatType> TriMesh<FloatType>::flatLoopSubdivision(float minEdgeLength) const
    {
        struct Edge
        {
            Edge(UINT32 _v0, UINT32 _v1)
            {
                v0 = std::min(_v0, _v1);
                v1 = std::max(_v0, _v1);
            }

            union
            {
                struct {
                    UINT32 v0, v1;
                };
                UINT64 val;
            };
        };

        struct edgeCompare
        {
            bool operator() (const Edge &a, const Edge &b)
            {
                return a.val < b.val;
            }
        };
        
        map<Edge, UINT, edgeCompare> edgeToNewVertexMap;

        TriMesh<FloatType> result;
        
        result.m_Vertices = m_Vertices;
        result.m_Indices.reserve(m_Indices.size() * 4);

        for (const vec3ui &tri : m_Indices)
        {
            /*bool subdivide = true;
            for (UINT eIndex = 0; eIndex < 3; eIndex++)
            {
                const vec3f &v0 = m_Vertices[tri[eIndex]].position;
                const vec3f &v1 = m_Vertices[tri[(eIndex + 1) % 3]].position;
                float edgeLength = vec3f::dist(v0, v1);
                if (edgeLength < minEdgeLength)
                    subdivide = false;
            }*/
            bool subdivide = math::triangleArea(m_Vertices[tri[0]].position, m_Vertices[tri[1]].position, m_Vertices[tri[2]].position) >= (minEdgeLength * minEdgeLength);

            if (subdivide)
            {
                UINT edgeMidpoints[3];

                for (UINT eIndex = 0; eIndex < 3; eIndex++)
                {
                    const UINT v0 = tri[eIndex];
                    const UINT v1 = tri[(eIndex + 1) % 3];
                    Edge e = Edge(v0, v1);
                    if (edgeToNewVertexMap.count(e) == 0)
                    {
                        edgeToNewVertexMap[e] = (UINT)result.m_Vertices.size();
                        result.m_Vertices.push_back((m_Vertices[v0] + m_Vertices[v1]) * (FloatType)0.5);
                    }

                    edgeMidpoints[eIndex] = edgeToNewVertexMap[e];
                }

                result.m_Indices.push_back(vec3ui(tri[0], edgeMidpoints[0], edgeMidpoints[2]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[0], tri[1], edgeMidpoints[1]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[2], edgeMidpoints[1], tri[2]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[2], edgeMidpoints[0], edgeMidpoints[1]));
            }
            else
            {
                result.m_Indices.push_back(tri);
            }
        }

        return result;
    }
Пример #5
0
bool ConvexHull2<Real>::Update (Edge*& rpkHull, int i)
{
    // Locate an edge visible to the input point (if possible).
    Edge* pkVisible = 0;
    Edge* pkCurrent = rpkHull;
    do
    {
        if (pkCurrent->GetSign(i,m_pkQuery) > 0)
        {
            pkVisible = pkCurrent;
            break;
        }

        pkCurrent = pkCurrent->A[1];
    }
    while (pkCurrent != rpkHull);

    if (!pkVisible)
    {
        // The point is inside the current hull; nothing to do.
        return true;
    }

    // Remove the visible edges.
    Edge* pkAdj0 = pkVisible->A[0];
    assert(pkAdj0);
    if (!pkAdj0)
    {
        return false;
    }

    Edge* pkAdj1 = pkVisible->A[1];
    assert(pkAdj1);
    if (!pkAdj1)
    {
        return false;
    }

    pkVisible->DeleteSelf();

    while (pkAdj0->GetSign(i,m_pkQuery) > 0)
    {
        rpkHull = pkAdj0;
        pkAdj0 = pkAdj0->A[0];
        assert(pkAdj0);
        if (!pkAdj0)
        {
            return false;
        }

        pkAdj0->A[1]->DeleteSelf();
    }

    while (pkAdj1->GetSign(i,m_pkQuery) > 0)
    {
        rpkHull = pkAdj1;
        pkAdj1 = pkAdj1->A[1];
        assert(pkAdj1);
        if (!pkAdj1)
        {
            return false;
        }

        pkAdj1->A[0]->DeleteSelf();
    }

    // Insert the new edges formed by the input point and the end points of
    // the polyline of invisible edges.
    Edge* pkEdge0 = WM4_NEW Edge(pkAdj0->V[1],i);
    Edge* pkEdge1 = WM4_NEW Edge(i,pkAdj1->V[0]);
    pkEdge0->Insert(pkAdj0,pkEdge1);
    pkEdge1->Insert(pkEdge0,pkAdj1);
    rpkHull = pkEdge0;

    return true;
}
	void addEdge(int from, int to, FLOW cost) {
		edges[from].push_back(Edge(to, cost, size_of(edges[to])));
		edges[to].push_back(Edge(from, FLOW(), size_of(edges[from]) - 1));
	}
Пример #7
0
 int add_edge(int from, int to, T cost) {
   adj_[from].push_back(Edge(edgeIndex_++, from, to, cost));
   return edgeIndex_;
 }
Пример #8
0
	Tree::Node* Tree::contructTree_R( IndexVec& idxEdges )
	{
		if ( idxEdges.empty() )
			return nullptr;

		int idx = choiceBestSplitEdge( idxEdges );

		Node* node = new Node;

		node->idxEdge   = idx;

		if ( idx < 0 ) // leaf
		{
			node->tag   = ~uint32( mLeaves.size() );
			node->front = nullptr;
			node->back  = nullptr;

			mLeaves.push_back( Leaf() );
			Leaf& data = mLeaves.back();
			data.node = node;
			data.edges.swap( idxEdges );
			return node;
		}
		else
		{
			node->tag = uint32( mNodes.size() );
			mNodes.push_back( node );
		}

		//triList.erase( cIter );

		IndexVec idxFronts;
		IndexVec idxBacks;

		Plane& plane = mEdges[ idx ].plane;

		for( IndexVec::iterator iter( idxEdges.begin() ) , itEnd( idxEdges.end() ) ; 
			iter != itEnd ; ++iter  )
		{
			int idxTest = *iter;
			Edge& edgeTest = mEdges[ idxTest ];

			Vec2f vSplit[2];
			switch ( plane.splice( edgeTest.v , vSplit ) )
			{
			case SIDE_FRONT:
			case SIDE_IN:
				idxFronts.push_back( idxTest );
				break;
			case SIDE_BACK:
				idxBacks.push_back( idxTest );
				break;
			case SIDE_SPLIT:
				{
					idxFronts.push_back( idxTest );
					idxBacks.push_back( (int)mEdges.size() );
					mEdges.push_back( Edge() );
					Edge& edge = mEdges.back();
					edge.v[0] = vSplit[0];
					edge.v[1] = vSplit[1];
					edge.plane = edgeTest.plane;
					edge.idx   = edgeTest.idx;
				}
				break;
			}				
		}

		node->front = contructTree_R( idxFronts );
		if ( node->front )
			node->front->parent = node;

		node->back  = contructTree_R( idxBacks );
		if ( node->back )
			node->back->parent = node;

		node->tag   = 0;

		return node;
	}
void PolygonPathFinder::setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections) {


	ERR_FAIL_COND(p_connections.size()&1);

	points.clear();
	edges.clear();

	//insert points

	int point_count=p_points.size();
	points.resize(point_count+2);
	bounds=Rect2();

	for(int i=0;i<p_points.size();i++) {

		points[i].pos=p_points[i];
		points[i].penalty=0;

		outside_point.x = i==0?p_points[0].x:(MAX( p_points[i].x, outside_point.x ));
		outside_point.y = i==0?p_points[0].y:(MAX( p_points[i].y, outside_point.y ));

		if (i==0) {
			bounds.pos=points[i].pos;
		} else {
			bounds.expand_to(points[i].pos);
		}
	}

	outside_point.x+=20.451+Math::randf()*10.2039;
	outside_point.y+=21.193+Math::randf()*12.5412;

	//insert edges (which are also connetions)

	for(int i=0;i<p_connections.size();i+=2) {

		Edge e(p_connections[i],p_connections[i+1]);
		ERR_FAIL_INDEX(e.points[0],point_count);
		ERR_FAIL_INDEX(e.points[1],point_count);
		points[p_connections[i]].connections.insert(p_connections[i+1]);
		points[p_connections[i+1]].connections.insert(p_connections[i]);
		edges.insert(e);
	}


	//fill the remaining connections based on visibility

	for(int i=0;i<point_count;i++) {

		for(int j=i+1;j<point_count;j++) {

			if (edges.has(Edge(i,j)))
				continue; //if in edge ignore

			Vector2 from=points[i].pos;
			Vector2 to=points[j].pos;

			if (!_is_point_inside(from*0.5+to*0.5)) //connection between points in inside space
				continue;

			bool valid=true;

			for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {

				const Edge& e=E->get();
				if (e.points[0]==i || e.points[1]==i || e.points[0]==j || e.points[1]==j )
					continue;


				Vector2 a = points[e.points[0]].pos;
				Vector2 b = points[e.points[1]].pos;


				if (Geometry::segment_intersects_segment_2d(a,b,from,to,NULL)) {
					valid=false;
					break;
				}

			}

			if (valid) {
				points[i].connections.insert(j);
				points[j].connections.insert(i);
			}
		}
	}
}
Пример #10
0
void Link(int x, int y, int z){
	E[++ tot] = Edge(y, Last[x], z), Last[x] = tot;
}
Пример #11
0
int main() {
    Vertex v1, v2, v3;
    std::vector<Edge> v {Edge(v1, v2, 1.0), Edge(v2, v3, 2.0), Edge(v3, v1, 5.0)};
    return 0;
}
Пример #12
0
Edge Edge::reversed() const {
    return Edge(toVertex, fromVertex);
}
Пример #13
0
 R2 H(int i) const { ASSERTION(i>=0 && i <3);
 R2 E=Edge(i);return E.perp()/(2.*this->mesure());} // heigth 
Пример #14
0
TYPED_TEST_P(BipartiteGraphTest, addEdge)
{
    this->checkAddEdge(2, Edge(0, 5), {Edge(0, 5)},
        {Edge(5, 0), Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6),
         Edge(1, 5), Edge(5, 5), Edge(1, 7), Edge(7, 1)});
    this->checkAddEdge(4, Edge(5, 0), {Edge(0, 5), Edge(5, 0)},
        {Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6),
         Edge(1, 5), Edge(5, 5), Edge(1, 7), Edge(7, 1)});
    this->checkAddEdge(6, Edge(1, 7), {Edge(0, 5), Edge(5, 0), Edge(1, 7)},
        {Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6),
         Edge(1, 5), Edge(5, 5), Edge(7, 1)});
    this->checkAddEdge(6, Edge(5, 5),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5)},
        {Edge(0, 1), Edge(0, 0), Edge(0, 4), Edge(0, 6), Edge(1, 5), Edge(7, 1)});
    this->checkAddEdge(7, Edge(5, 6),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5), Edge(5, 6)}, {});
    this->checkAddEdge(8, Edge(6, 5),
        {Edge(0, 5), Edge(5, 0), Edge(1, 7), Edge(5, 5), Edge(5, 6), Edge(6, 5)}, {});
}
Пример #15
0
//simplified version of divideEdges that accepts only one index => one edge
//it is a common case that one edge still goes deeper e.g. an edge between a high leaf in the tree
//and a node that goes deeper and deepper. Therefore a  lot of effort can be saved by providing
//a method that works with just one edge
void EdgeHierarchy::divideEdges(TravelIndex t1, TravelIndex t2, int index) {

	QuadTreeMetaNode* m1 = _quadTree->getMeta(t1.level, t1.index);
	QuadTreeMetaNode* m2 = _quadTree->getMeta(t2.level, t2.index);

	if (_quadTree->isLeaf(m1) && _quadTree->isLeaf(m2)) {
		//both nodes are leafs add the edge as leaf edge and return
		int depth = t2.level; 
		if (t1.level > t2.level) {
			depth = t1.level;
		} 

		Edge tmp(_edges->at(index));
		tmp.depth = depth; //leaf edge positive depth
		addEdge(tmp, depth);
	} else {

		int nodeIndexI;
		int nodeIndexJ;

		if (t1.level == t2.level && t1.index == t2.index) {
			//edge start and end point to the same meta node
			//can't be a leaf (-> if above)

			Edge e = _edges->at(index);

			//test where the edge belongs to
			nodeIndexI = _quadTree->travelSelect(e.x1, e.y1, &t1) - 1;
			nodeIndexJ = _quadTree->travelSelect(e.x2, e.y2, &t2) - 1; //t1=t2

		} else {
			//different nodes => insert edges
			Node* n1 = _quadTree->getNode(t1.level, t1.index);
			Node* n2 = _quadTree->getNode(t2.level, t2.index);
			int depth = t2.level; 
			if (t1.level > t2.level) {
				depth = t1.level;
			} 
			depth = 0 - depth; //inner edge indicated by negative depth
			float weight = _edges->at(index).weight;
			addEdge(Edge(n1, n2, depth, weight), abs(depth));

			Edge e = _edges->at(index);

			if (!_quadTree->isLeaf(m1)) {
				nodeIndexI = _quadTree->travelSelect(e.x1, e.y1, &t1) - 1;
			}
			if (!_quadTree->isLeaf(m2)) {
				nodeIndexJ = _quadTree->travelSelect(e.x2, e.y2, &t2) - 1;
			}
		}


		//recursive calls

		TravelIndex newT1(t1);
		TravelIndex newT2(t2);

		//go on with t1
		if (!_quadTree->isLeaf(m1)) {
			_quadTree->travelDown((nodeIndexI+1), &newT1);
		}
		//and with t2
		if (!_quadTree->isLeaf(m2)) {
			_quadTree->travelDown((nodeIndexJ+1), &newT2);
		}										

		divideEdges(newT1, newT2, index);
	}
}
Пример #16
0
Edge Traversor2VE<MAP>::end()
{
	return Edge(NIL) ;
}
Пример #17
0
void EdgeHierarchy::divideEdges(TravelIndex t1, TravelIndex t2, vector<int>* indices, float weightSum) {

	QuadTreeMetaNode* m1 = _quadTree->getMeta(t1.level, t1.index);
	QuadTreeMetaNode* m2 = _quadTree->getMeta(t2.level, t2.index);

	if (_quadTree->isLeaf(m1) && _quadTree->isLeaf(m2)) {
		//both nodes are leafs add the edge as leaf edge and return
		short depth = t2.level; 
		if (t1.level > t2.level) {
			depth = t1.level;
		} 

		Edge tmp(_edges->at(indices->at(0)));
		tmp.depth = depth; //leaf edge positive depth
		addEdge(tmp, depth);
	} else {

		vector<int>* splitArray[4][4];
		float weightArray[4][4];
		for (int i = 0; i < 4; i++) {
			for (int j  = 0; j < 4; j++) {
				splitArray[i][j] = NULL;
				weightArray[i][j] = 0.0f;
			}
		}

		if (t1.level == t2.level && t1.index == t2.index) {
			//edge start and end point to the same meta node
			//can't be a leaf (-> if above)

			for (int index = 0; index < indices->size(); index++) {
				Edge e = _edges->at(indices->at(index));

				//test where the edge belongs to
				int i = _quadTree->travelSelect(e.x1, e.y1, &t1) - 1;
				int j = _quadTree->travelSelect(e.x2, e.y2, &t2) - 1; //t1=t2
				//insert it into the correct place
				if (splitArray[i][j] == NULL) {
					splitArray[i][j] = new vector<int>();
				}
				splitArray[i][j]->push_back(indices->at(index));
				weightArray[i][j] += _edges->at(indices->at(index)).weight;
			}			
		} else {
			//different nodes => insert edges
			Node* n1 = _quadTree->getNode(t1.level, t1.index);
			Node* n2 = _quadTree->getNode(t2.level, t2.index);
			int depth = t2.level; 
			if (t1.level > t2.level) {
				depth = t1.level;
			} 
			depth = 0 - depth; //inner edge indicated by negative depth

			addEdge(Edge(n1, n2, depth, weightSum), abs(depth));


			for (int index = 0; index < indices->size(); index++) {
				Edge e = _edges->at(indices->at(index));

				int i = 0;
				int j = 0;
				if (!_quadTree->isLeaf(m1)) {
					i = _quadTree->travelSelect(e.x1, e.y1, &t1) - 1;
				}
				if (!_quadTree->isLeaf(m2)) {
					j = _quadTree->travelSelect(e.x2, e.y2, &t2) - 1;
				}
				//insert it into the correct place
				if (splitArray[i][j] == NULL) {
					splitArray[i][j] = new vector<int>();
				}
				splitArray[i][j]->push_back(indices->at(index));
				weightArray[i][j] += _edges->at(indices->at(index)).weight;
			}			
		}


		//recursive calls

		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (splitArray[i][j] != NULL) {
					TravelIndex newT1(t1);
					TravelIndex newT2(t2);

					//go on with t1
					if (!_quadTree->isLeaf(m1)) {
						_quadTree->travelDown((i+1), &newT1);
					}
					//and with t2
					if (!_quadTree->isLeaf(m2)) {
						_quadTree->travelDown((j+1), &newT2);
					}										

					if (splitArray[i][j]->size() > 1) {
						divideEdges(newT1, newT2, splitArray[i][j], weightArray[i][j]);
					} else {
						//speed up for single edges
						divideEdges(newT1, newT2, splitArray[i][j]->at(0));
					}
					delete splitArray[i][j];
				}
			}
		}
	}
}
    void handleNode()
    {
        switch (m_node->op()) {
        case BitOr:
            handleCommutativity();

            if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
                convertToIdentityOverChild1();
                break;
            }
            break;

        case BitXor:
        case BitAnd:
            handleCommutativity();
            break;

        case BitLShift:
        case BitRShift:
        case BitURShift:
            if (m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
                convertToIdentityOverChild1();
                break;
            }
            break;

        case UInt32ToNumber:
            if (m_node->child1()->op() == BitURShift
                    && m_node->child1()->child2()->isInt32Constant()
                    && (m_node->child1()->child2()->asInt32() & 0x1f)
                    && m_node->arithMode() != Arith::DoOverflow) {
                m_node->convertToIdentity();
                m_changed = true;
                break;
            }
            break;

        case ArithAdd:
            handleCommutativity();

            if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
                convertToIdentityOverChild1();
                break;
            }
            break;

        case ArithMul:
            handleCommutativity();
            break;

        case ArithSub:
            if (m_node->child2()->isInt32Constant()
                    && m_node->isBinaryUseKind(Int32Use)) {
                int32_t value = m_node->child2()->asInt32();
                if (-value != value) {
                    m_node->setOp(ArithAdd);
                    m_node->child2().setNode(
                        m_insertionSet.insertConstant(
                            m_nodeIndex, m_node->origin, jsNumber(-value)));
                    m_changed = true;
                    break;
                }
            }
            break;

        case GetArrayLength:
            if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node))
                foldTypedArrayPropertyToConstant(view, jsNumber(view->length()));
            break;

        case GetTypedArrayByteOffset:
            if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node()))
                foldTypedArrayPropertyToConstant(view, jsNumber(view->byteOffset()));
            break;

        case GetIndexedPropertyStorage:
            if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) {
                if (view->mode() != FastTypedArray) {
                    prepareToFoldTypedArray(view);
                    m_node->convertToConstantStoragePointer(view->vector());
                    m_changed = true;
                    break;
                } else {
                    // FIXME: It would be awesome to be able to fold the property storage for
                    // these GC-allocated typed arrays. For now it doesn't matter because the
                    // most common use-cases for constant typed arrays involve large arrays with
                    // aliased buffer views.
                    // https://bugs.webkit.org/show_bug.cgi?id=125425
                }
            }
            break;

        case ValueRep:
        case Int52Rep:
        case DoubleRep: {
            // This short-circuits circuitous conversions, like ValueRep(DoubleRep(value)) or
            // even more complicated things. Like, it can handle a beast like
            // ValueRep(DoubleRep(Int52Rep(value))).

            // The only speculation that we would do beyond validating that we have a type that
            // can be represented a certain way is an Int32 check that would appear on Int52Rep
            // nodes. For now, if we see this and the final type we want is an Int52, we use it
            // as an excuse not to fold. The only thing we would need is a Int52RepInt32Use kind.
            bool hadInt32Check = false;
            if (m_node->op() == Int52Rep) {
                if (m_node->child1().useKind() != Int32Use)
                    break;
                hadInt32Check = true;
            }
            for (Node* node = m_node->child1().node(); ; node = node->child1().node()) {
                if (canonicalResultRepresentation(node->result()) ==
                        canonicalResultRepresentation(m_node->result())) {
                    m_insertionSet.insertNode(
                        m_nodeIndex, SpecNone, Phantom, m_node->origin, m_node->child1());
                    if (hadInt32Check) {
                        // FIXME: Consider adding Int52RepInt32Use or even DoubleRepInt32Use,
                        // which would be super weird. The latter would only arise in some
                        // seriously circuitous conversions.
                        if (canonicalResultRepresentation(node->result()) != NodeResultJS)
                            break;

                        m_insertionSet.insertNode(
                            m_nodeIndex, SpecNone, Phantom, m_node->origin,
                            Edge(node, Int32Use));
                    }
                    m_node->child1() = node->defaultEdge();
                    m_node->convertToIdentity();
                    m_changed = true;
                    break;
                }

                switch (node->op()) {
                case Int52Rep:
                    if (node->child1().useKind() != Int32Use)
                        break;
                    hadInt32Check = true;
                    continue;

                case DoubleRep:
                case ValueRep:
                    continue;

                default:
                    break;
                }
                break;
            }
            break;
        }

        case Flush: {
            ASSERT(m_graph.m_form != SSA);

            Node* setLocal = nullptr;
            VirtualRegister local = m_node->local();

            if (m_node->variableAccessData()->isCaptured()) {
                for (unsigned i = m_nodeIndex; i--;) {
                    Node* node = m_block->at(i);
                    bool done = false;
                    switch (node->op()) {
                    case GetLocal:
                    case Flush:
                        if (node->local() == local)
                            done = true;
                        break;

                    case GetLocalUnlinked:
                        if (node->unlinkedLocal() == local)
                            done = true;
                        break;

                    case SetLocal: {
                        if (node->local() != local)
                            break;
                        setLocal = node;
                        done = true;
                        break;
                    }

                    case Phantom:
                    case Check:
                    case HardPhantom:
                    case MovHint:
                    case JSConstant:
                    case DoubleConstant:
                    case Int52Constant:
                        break;

                    default:
                        done = true;
                        break;
                    }
                    if (done)
                        break;
                }
            } else {
                for (unsigned i = m_nodeIndex; i--;) {
                    Node* node = m_block->at(i);
                    if (node->op() == SetLocal && node->local() == local) {
                        setLocal = node;
                        break;
                    }
                    if (accessesOverlap(m_graph, node, AbstractHeap(Variables, local)))
                        break;
                }
            }

            if (!setLocal)
                break;

            m_node->convertToPhantom();
            Node* dataNode = setLocal->child1().node();
            DFG_ASSERT(m_graph, m_node, dataNode->hasResult());
            m_node->child1() = dataNode->defaultEdge();
            m_graph.dethread();
            m_changed = true;
            break;
        }

        default:
            break;
        }
    }
Пример #19
0
 static Edge DISCONNECTED()
 {
     return Edge(MAXFLOAT);
 }
static bool ResolveNormalsWithMST(ccPointCloud* cloud, const Graph& graph, CCLib::GenericProgressCallback* progressCb = 0)
{
	assert(cloud && cloud->hasNormals());

//#define COLOR_PATCHES
#ifdef COLOR_PATCHES
	//Test: color patches
	cloud->setRGBColor(ccColor::white);
	cloud->showColors(true);

	//Test: arrival time
	int sfIdx = cloud->getScalarFieldIndexByName("MST arrival time");
	if (sfIdx < 0)
		sfIdx = cloud->addScalarField("MST arrival time");
	ccScalarField* sf = static_cast<ccScalarField*>(cloud->getScalarField(sfIdx));
	sf->fill(NAN_VALUE);
	cloud->setCurrentDisplayedScalarField(sfIdx);
#endif

	//reset
	std::priority_queue<Edge> priorityQueue;
	std::vector<bool> visited;
	unsigned visitedCount = 0;

	size_t vertexCount = graph.vertexCount();

	//instantiate the 'visited' table
	try
	{
		visited.resize(vertexCount,false);
	}
	catch(std::bad_alloc)
	{
		//not enough memory
		return false;
	}

	//progress notification
	CCLib::NormalizedProgress* nProgress(0);
	if (progressCb)
	{
		progressCb->reset();
		progressCb->setMethodTitle("Orient normals (MST)");
		progressCb->setInfo(qPrintable(QString("Compute Minimum spanning tree\nPoints: %1\nEdges: %2").arg(vertexCount).arg(graph.edgeCount())));
		nProgress = new CCLib::NormalizedProgress(progressCb,static_cast<unsigned>(vertexCount));
		progressCb->start();
	}

	//while unvisited vertices remain...
	size_t firstUnvisitedIndex = 0;
	size_t patchCount = 0;
	size_t inversionCount = 0;
	while (visitedCount < vertexCount)
	{
		//find the first not-yet-visited vertex
		while (visited[firstUnvisitedIndex])
			++firstUnvisitedIndex;

		//set it as "visited"
		{
			visited[firstUnvisitedIndex] = true;
			++visitedCount;
			//add its neighbors to the priority queue
			const std::set<size_t>& neighbors = graph.getVertexNeighbors(firstUnvisitedIndex);
			for (std::set<size_t>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it)
				priorityQueue.push(Edge(firstUnvisitedIndex, *it, graph.weight(firstUnvisitedIndex, *it)));

			if (nProgress && !nProgress->oneStep())
				break;
		}

#ifdef COLOR_PATCHES
		colorType patchCol[3];
		ccColor::Generator::Random(patchCol);
		cloud->setPointColor(static_cast<unsigned>(firstUnvisitedIndex), patchCol);
		sf->setValue(static_cast<unsigned>(firstUnvisitedIndex),static_cast<ScalarType>(visitedCount));
#endif

		while(!priorityQueue.empty() && visitedCount < vertexCount)
		{
			//process next edge (with the lowest 'weight')
			Edge element = priorityQueue.top();
			priorityQueue.pop();

			//there should only be (at most) one unvisited vertex in the edge
			size_t v = 0;
			if (!visited[element.v1()])
				v = element.v1();
			else if (!visited[element.v2()])
				v = element.v2();
			else
				continue;

			//invert normal if necessary (DO THIS BEFORE SETTING THE VERTEX AS 'VISITED'!)
			const CCVector3& N1 = cloud->getPointNormal(static_cast<unsigned>(element.v1()));
			const CCVector3& N2 = cloud->getPointNormal(static_cast<unsigned>(element.v2()));
			if (N1.dot(N2) < 0)
			{
				if (!visited[element.v1()])
				{
					cloud->setPointNormal(static_cast<unsigned>(v), -N1);
				}
				else
				{
					cloud->setPointNormal(static_cast<unsigned>(v), -N2);
				}
				++inversionCount;
			}

			//set it as "visited"
			{
				visited[v] = true;
				++visitedCount;
				//add its neighbors to the priority queue
				const std::set<size_t>& neighbors = graph.getVertexNeighbors(v);
				for (std::set<size_t>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it)
					priorityQueue.push(Edge(v, *it, graph.weight(v,*it)));
			}

#ifdef COLOR_PATCHES
			cloud->setPointColor(static_cast<unsigned>(v), patchCol);
			sf->setValue(static_cast<unsigned>(v),static_cast<ScalarType>(visitedCount));
#endif
			if (nProgress && !nProgress->oneStep())
			{
				visitedCount = static_cast<unsigned>(vertexCount); //early stop
				break;
			}
		}

		//new patch
		++patchCount;
	}

#ifdef COLOR_PATCHES
	sf->computeMinAndMax();
	cloud->showSF(true);
#endif

	if (nProgress)
	{
		delete nProgress;
		nProgress = 0;
		progressCb->stop();
	}

	ccLog::Print(QString("[ResolveNormalsWithMST] Patches = %1 / Inversions: %2").arg(patchCount).arg(inversionCount));

	return true;
}
Пример #21
0
	void add_Edge(int u, int v, Type dist) {
		edges[m++] = Edge(u, v, dist);
	}
Пример #22
0
/*
 * Gets an edge from the graph
 */
EdgeData *Graph::get_edge(Index a, Index b)
{
    return this->get_edge(Edge(a, b));
}
Пример #23
0
//------------------------Delaunay triangulation----------------------------
void triangulate(const std::vector<Vector2>& vertices, std::vector<Triangle>& retTriangles, Graph& neighborhoodGraph)
{
	//Possible check for less than 3 points, not required now

	std::vector<Triangle> triangles;

	Triangle superTriangle = createSuperTriangle(vertices);
	triangles.push_back(superTriangle);

	// Include each point one at a time into the existing triangulation
	for (std::vector<Vector2>::const_iterator vertIt = vertices.begin(); vertIt != vertices.end(); ++vertIt)
	{
		std::vector<Edge> edgeBuffer;

		// If the actual vertex lies inside the circumcircle, then the three edges of the 
		// triangle are added to the edge buffer and the triangle is removed from list.
		std::vector<Triangle>::reverse_iterator rit = triangles.rbegin();
		while (rit != triangles.rend())
		{
			if (rit->isPointInCircumCircle(*vertIt))
			{
				insertWithDuplicateCheck(edgeBuffer, Edge(rit->mP1, rit->mP2));
				insertWithDuplicateCheck(edgeBuffer, Edge(rit->mP2, rit->mP3));
				insertWithDuplicateCheck(edgeBuffer, Edge(rit->mP3, rit->mP1));
				++rit;
				rit = std::vector<Triangle>::reverse_iterator(triangles.erase(rit.base()));
			}
			else
			{
				++rit;
			}
		}

		//Create triangles from the Edges
		for (std::vector<Edge>::iterator it = edgeBuffer.begin(); it != edgeBuffer.end(); ++it)
		{
			triangles.push_back(Triangle(it->mP1, it->mP2, *vertIt));
		}
	}

	//Remove all triangles sharing a vertex with the supertriangle
	std::vector<Triangle>::reverse_iterator rit = triangles.rbegin();
	while (rit != triangles.rend())
	{
		Triangle t = *rit;
		if (t.hasCommonVertexWith(superTriangle))
		{
			++rit;
			rit = std::vector<Triangle>::reverse_iterator(triangles.erase(rit.base()));
		}
		else
		{
			++rit;
		}
	}

	retTriangles = triangles;

	//Add neighborhood data to graph
	for (std::vector<Triangle>::const_iterator it = triangles.begin(); it != triangles.end(); ++it)
	{
		neighborhoodGraph.addNeighbor(it->mMidP1, it->mMidP2);
		neighborhoodGraph.addNeighbor(it->mMidP1, it->mMidP3);

		neighborhoodGraph.addNeighbor(it->mMidP2, it->mMidP1);
		neighborhoodGraph.addNeighbor(it->mMidP2, it->mMidP3);

		neighborhoodGraph.addNeighbor(it->mMidP3, it->mMidP1);
		neighborhoodGraph.addNeighbor(it->mMidP3, it->mMidP2);
	}
}
// отрисовка из прошлой лабы, только берём цвета из текстуры
void Triangle::draw(Canvas& canvas, Texture* texture = 0) {
    std::vector<TexturedPoint> points;

    // преобразование и упорядочивание по x
    transform(points);
    std::sort(points.begin(), points.end());

    std::vector<Edge> edges;

    // установка границ
    int minY = (points.front().y() < 0) ? 0: points.front().y();
    int maxY = (points.back().y() < this->maxY) ? points.back().y() : this->maxY - 1;

    int curY = minY;
    int i = 0;

    while (curY < maxY) {
        int nextY = maxY;

        while ( i != (int)points.size() && trunc( points[i].y()) <= curY ){
            TexturedPoint a = points[i];
            TexturedPoint b = points[(points.size() - i - 1 ) % points.size()];
            TexturedPoint c = points[(i + 1) % points.size()];

            if (b.y() > curY ) {
                edges.push_back(Edge(a,b));
                if ( b.y() < nextY ) {
                    nextY = b.y() ;
                }
            }
            if (c.y() > curY) {
                edges.push_back(Edge(a,c));
                if ( c.y() < nextY) {
                    nextY = c.y();
                }
            }
            ++i;
        }

        while(curY <= nextY && curY <= maxY) {

            std::vector<TexturedPoint> borderX;
            for (int i = 0; i < (int)edges.size(); ++i) {
                int n = curY - edges[i].getA().y();
                double curX = (edges[i].getA().x()) + n * edges[i].getK();
                TexturedPoint texCoord(curX, curY);
                texCoord.calcTextureCoordinates(edges[i].getA(), edges[i].getB());
                borderX.push_back(texCoord);
            }

            std::sort(borderX.begin(), borderX.end(), TexturedPoint::compX);
            int begin = borderX.front().x() > 0 ? borderX.front().x() : 0;

            for (int x = begin; x < borderX.back().x() && x < maxX; ++x) {
                TexturedPoint curPoint(x, curY);

                curPoint.calcTextureCoordinates(borderX.front(),borderX.back());

                if (0 == texture) {
                    // если текстуры нет( то как градиент )
                    canvas.drawPixel(x, curY, TexturedPoint::transformToColor(curPoint.getTexX(), curPoint.getTexY()));
                } else {
                    canvas.drawPixel(x, curY, texture->get_color(curPoint));
                }
            }

            ++curY;
        }

        std::vector<Edge>::iterator iter = edges.begin();
        while (iter != edges.end()) {
           if ( (*iter).getB().y() < curY) {
               edges.erase(iter);
           }
           else {
               ++iter;
           }
        }

   }
}
Пример #25
0
ConvexHull2<Real>::ConvexHull2 (int iVertexQuantity, Vector2<Real>* akVertex,
    Real fEpsilon, bool bOwner, Query::Type eQueryType)
    :
    ConvexHull<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType),
    m_kLineOrigin(Vector2<Real>::ZERO),
    m_kLineDirection(Vector2<Real>::ZERO)
{
    assert(akVertex);
    m_akVertex = akVertex;
    m_akSVertex = 0;
    m_pkQuery = 0;

    Mapper2<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon);
    if (kMapper.GetDimension() == 0)
    {
        // The values of m_iDimension, m_aiIndex, and m_aiAdjacent were
        // already initialized by the ConvexHull base class.
        return;
    }

    if (kMapper.GetDimension() == 1)
    {
        // The set is (nearly) collinear.  The caller is responsible for
        // creating a ConvexHull1 object.
        m_iDimension = 1;
        m_kLineOrigin = kMapper.GetOrigin();
        m_kLineDirection = kMapper.GetDirection(0);
        return;
    }

    m_iDimension = 2;

    int i0 = kMapper.GetExtremeIndex(0);
    int i1 = kMapper.GetExtremeIndex(1);
    int i2 = kMapper.GetExtremeIndex(2);

    m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity];
    int i;

    if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED)
    {
        // Transform the vertices to the square [0,1]^2.
        Vector2<Real> kMin = kMapper.GetMin();
        Real fScale = ((Real)1.0)/kMapper.GetMaxRange();
        for (i = 0; i < m_iVertexQuantity; i++)
        {
            m_akSVertex[i] = (m_akVertex[i] - kMin)*fScale;
        }

        Real fExpand;
        if (eQueryType == Query::QT_INT64)
        {
            // Scale the vertices to the square [0,2^{20}]^2 to allow use of
            // 64-bit integers.
            fExpand = (Real)(1 << 20);
            m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity,
                m_akSVertex);
        }
        else if (eQueryType == Query::QT_INTEGER)
        {
            // Scale the vertices to the square [0,2^{24}]^2 to allow use of
            // TInteger.
            fExpand = (Real)(1 << 24);
            m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity,
                m_akSVertex);
        }
        else  // eQueryType == Query::QT_REAL
        {
            // No scaling for floating point.
            fExpand = (Real)1.0;
            m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex);
        }

        for (i = 0; i < m_iVertexQuantity; i++)
        {
            m_akSVertex[i] *= fExpand;
        }
    }
    else
    {
        // No transformation needed for exact rational arithmetic or filtered
        // predicates.
        size_t uiSize = m_iVertexQuantity*sizeof(Vector2<Real>);
        System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize);

        if (eQueryType == Query::QT_RATIONAL)
        {
            m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity,
                m_akSVertex);
        }
        else // eQueryType == Query::QT_FILTERED
        {
            m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity,
                m_akSVertex,m_fEpsilon);
        }
    }

    Edge* pkE0;
    Edge* pkE1;
    Edge* pkE2;

    if (kMapper.GetExtremeCCW())
    {
        pkE0 = WM4_NEW Edge(i0,i1);
        pkE1 = WM4_NEW Edge(i1,i2);
        pkE2 = WM4_NEW Edge(i2,i0);
    }
    else
    {
        pkE0 = WM4_NEW Edge(i0,i2);
        pkE1 = WM4_NEW Edge(i2,i1);
        pkE2 = WM4_NEW Edge(i1,i0);
    }

    pkE0->Insert(pkE2,pkE1);
    pkE1->Insert(pkE0,pkE2);
    pkE2->Insert(pkE1,pkE0);

    Edge* pkHull = pkE0;
    for (i = 0; i < m_iVertexQuantity; i++)
    {
        if (!Update(pkHull,i))
        {
            pkHull->DeleteAll();
            return;
        }
    }

    pkHull->GetIndices(m_iSimplexQuantity,m_aiIndex);
    pkHull->DeleteAll();
}
Пример #26
0
///\todo Enable this codepath. This if rom Geometric Tools for Computer Graphics,
/// but the algorithm in the book is broken and does not take into account the
/// direction of the gradient to determine the proper region of intersection.
/// Instead using a slower code path above.
float3 Triangle::ClosestPoint(const Line &line, float3 *otherPt) const
{
	float3 e0 = b - a;
	float3 e1 = c - a;
	float3 v_p = a - line.pos;
	float3 d = line.dir;

	float v_p_dot_e0 = Dot(v_p, e0);
	float v_p_dot_e1 = Dot(v_p, e1);
	float v_p_dot_d = Dot(v_p, d);

	float3x3 m;
	m[0][0] = Dot(e0, e0); m[0][1] = Dot(e0, e1); m[0][2] = -Dot(e0, d);
	m[1][0] =     m[0][1]; m[1][1] = Dot(e1, e1); m[1][2] = -Dot(e1, d);
	m[2][0] =     m[0][2]; m[2][1] =     m[1][2]; m[2][2] =  Dot(d, d);

	float3 B(-v_p_dot_e0, -v_p_dot_e1, v_p_dot_d);

	float3 uvt;
	bool success = m.SolveAxb(B, uvt);
	if (!success)
	{
		float t1, t2, t3;
		float s1, s2, s3;
		LineSegment e1 = Edge(0);
		LineSegment e2 = Edge(1);
		LineSegment e3 = Edge(2);
		float d1 = e1.Distance(line, &t1, &s1);
		float d2 = e2.Distance(line, &t2, &s2);
		float d3 = e3.Distance(line, &t3, &s3);
		if (d1 < d2 && d1 < d3)
		{
			if (otherPt)
				*otherPt = line.GetPoint(s1);
			return e1.GetPoint(t1);
		}
		else if (d2 < d3)
		{
			if (otherPt)
				*otherPt = line.GetPoint(s2);
			return e2.GetPoint(t2);
		}
		else
		{
			if (otherPt)
				*otherPt = line.GetPoint(s3);
			return e3.GetPoint(t3);
		}
	}

	if (uvt.x < 0.f)
	{
		// Clamp to u == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[1][2];
		float m_10 = -m[2][1];
		float m_11 = m[1][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float v = m_00 * B[1] + m_01 * B[2];
		float t = m_10 * B[1] + m_11 * B[2];
		v /= det;
		t /= det;
		if (v < 0.f)
		{
			// Clamp to v == 0 and solve for t.
			t = B[2] / m[2][2];
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return a;
		}
		else if (v > 1.f)
		{
			// Clamp to v == 1 and solve for t.
			t = (B[2] - m[2][1]) / m[2][2];
			// The solution is (u,v,t)=(0,1,t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return c; // == a + v*e1
		}
		else
		{
			// The solution is (u,v,t)=(0,v,t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return a + v * e1;
		}
	}
	else if (uvt.y < 0.f)
	{
		// Clamp to v == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[0][2];
		float m_10 = -m[2][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * B[0] + m_01 * B[2];
		float t = m_10 * B[0] + m_11 * B[2];
		u /= det;
		t /= det;

		if (u < 0.f)
		{
			// Clamp to u == 0 and solve for t.
			t = B[2] / m[2][2];
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return a;
		}
		else if (u > 1.f)
		{
			// Clamp to u == 1 and solve for t.
			t = (B[2] - m[2][0]) / m[2][2];
			// The solution is (u,v,t)=(1,0,t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return b;
		}
		else
		{
			// The solution is (u, 0, t).
			if (otherPt)
				*otherPt = line.GetPoint(t);
			return a + u * e0;
		}
	}
	else if (uvt.x + uvt.y > 1.f)
	{
		// Clamp to v = 1-u and solve again.
		float m_00 = m[2][2];
		float m_01 = m[1][2] - m[0][2];
		float m_10 = m_01;
		float m_11 = m[0][0] + m[1][1] - 2.f * m[0][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float b0 = m[1][1] - m[0][1] + v_p_dot_e1 - v_p_dot_e0;
		float b1 = -m[1][2] + v_p_dot_d;
		float u = m_00 * b0 + m_01 * b1;
		float t = m_10 * b0 + m_11 * b1;
		u /= det;
		t /= det;

		if (otherPt)
			*otherPt = line.GetPoint(t);

		if (u < 0.f)
		{
			// The solution is (u,v,t)=(0,1,t)
			return c;
		}
		if (u > 1.f)
		{
			// The solution is (u,v,t)=(1,0,t)
			return b;
		}
		return a + u*e0 + (1.f-u)*e1;
	}
	else // All parameters are within range, so the triangle and the line segment intersect, and the intersection point is the closest point.
	{
		if (otherPt)
			*otherPt = line.GetPoint(uvt.z);
		return a + uvt.x * e0 + uvt.y * e1;
	}
}
Пример #27
0
 void Graph :: addEdge(const Edge&edge)
 {
     edges.push_back(edge);
     matrix[edge.start].push_back(edge);
     matrix[edge.finish].push_back(Edge(edge.finish, edge.start, edge.weight));
 }
Пример #28
0
///\todo Enable this codepath. This if rom Geometric Tools for Computer Graphics,
/// but the algorithm in the book is broken and does not take into account the
/// direction of the gradient to determine the proper region of intersection.
/// Instead using a slower code path above.
/// [groupSyntax]
float3 Triangle::ClosestPoint(const LineSegment &lineSegment, float3 *otherPt) const
{
	float3 e0 = b - a;
	float3 e1 = c - a;
	float3 v_p = a - lineSegment.a;
	float3 d = lineSegment.b - lineSegment.a;

	// Q(u,v) = a + u*e0 + v*e1
	// L(t)   = ls.a + t*d
	// Minimize the distance |Q(u,v) - L(t)|^2 under u >= 0, v >= 0, u+v <= 1, t >= 0, t <= 1.

	float v_p_dot_e0 = Dot(v_p, e0);
	float v_p_dot_e1 = Dot(v_p, e1);
	float v_p_dot_d = Dot(v_p, d);

	float3x3 m;
	m[0][0] = Dot(e0, e0); m[0][1] = Dot(e0, e1); m[0][2] = -Dot(e0, d);
	m[1][0] =     m[0][1]; m[1][1] = Dot(e1, e1); m[1][2] = -Dot(e1, d);
	m[2][0] =     m[0][2]; m[2][1] =     m[1][2]; m[2][2] =  Dot(d, d);

	float3 B(-v_p_dot_e0, -v_p_dot_e1, v_p_dot_d);

	float3 uvt;
	bool success = m.SolveAxb(B, uvt);
	if (!success)
	{
		float t1, t2, t3;
		float s1, s2, s3;
		LineSegment e1 = Edge(0);
		LineSegment e2 = Edge(1);
		LineSegment e3 = Edge(2);
		float d1 = e1.Distance(lineSegment, &t1, &s1);
		float d2 = e2.Distance(lineSegment, &t2, &s2);
		float d3 = e3.Distance(lineSegment, &t3, &s3);
		if (d1 < d2 && d1 < d3)
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s1);
			return e1.GetPoint(t1);
		}
		else if (d2 < d3)
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s2);
			return e2.GetPoint(t2);
		}
		else
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s3);
			return e3.GetPoint(t3);
		}
	}

	if (uvt.x < 0.f)
	{
		// Clamp to u == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[1][2];
		float m_10 = -m[2][1];
		float m_11 = m[1][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float v = m_00 * B[1] + m_01 * B[2];
		float t = m_10 * B[1] + m_11 * B[2];
		v /= det;
		t /= det;
		if (v < 0.f)
		{
			// Clamp to v == 0 and solve for t.
			t = B[2] / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a;
		}
		else if (v > 1.f)
		{
			// Clamp to v == 1 and solve for t.
			t = (B[2] - m[2][1]) / m[2][2];
			t = Clamp01(t);
			// The solution is (u,v,t)=(0,1,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return c; // == a + v*e1
		}
		else if (t < 0.f)
		{
			// Clamp to t == 0 and solve for v.
			v = B[1] / m[1][1];
//			mathassert(EqualAbs(v, Clamp01(v)));
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(0,v,0).
			if (otherPt)
				*otherPt = lineSegment.a;
			return a + v * e1;
		}
		else if (t > 1.f)
		{
			// Clamp to t == 1 and solve for v.
			v = (B[1] - m[1][2]) / m[1][1];
//			mathassert(EqualAbs(v, Clamp01(v)));
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(0,v,1).
			if (otherPt)
				*otherPt = lineSegment.b;
			return a + v * e1;
		}
		else
		{
			// The solution is (u,v,t)=(0,v,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + v * e1;
		}
	}
	else if (uvt.y < 0.f)
	{
		// Clamp to v == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[0][2];
		float m_10 = -m[2][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * B[0] + m_01 * B[2];
		float t = m_10 * B[0] + m_11 * B[2];
		u /= det;
		t /= det;

		if (u < 0.f)
		{
			// Clamp to u == 0 and solve for t.
			t = B[2] / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a;
		}
		else if (u > 1.f)
		{
			// Clamp to u == 1 and solve for t.
			t = (B[2] - m[2][0]) / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(1,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return b;
		}
		else if (t < 0.f)
		{
			// Clamp to t == 0 and solve for u.
			u = B[0] / m[0][0];
//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u); // The solution for u must also be in the range [0,1].
			if (otherPt)
				*otherPt = lineSegment.a;
			return a + u * e0;
		}
		else if (t > 1.f)
		{
			// Clamp to t == 1 and solve for u.
			u = (B[0] - m[0][2]) / m[0][0];
//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u); // The solution for u must also be in the range [0,1].
			if (otherPt)
				*otherPt = lineSegment.b;
			return a + u * e0;
		}
		else
		{
			// The solution is (u, 0, t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + u * e0;
		}
	}
	else if (uvt.z < 0.f)
	{
		if (otherPt)
			*otherPt = lineSegment.a;
		// Clamp to t == 0 and solve again.
		float m_00 = m[1][1];
		float m_01 = -m[0][1];
		float m_10 = -m[1][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * B[0] + m_01 * B[1];
		float v = m_10 * B[0] + m_11 * B[1];
		u /= det;
		v /= det;
		if (u < 0.f)
		{
			// Clamp to u == 0 and solve for v.
			v = B[1] / m[1][1];
			v = Clamp01(v);
			return a + v*e1;
		}
		else if (v < 0.f)
		{
			// Clamp to v == 0 and solve for u.
			u = B[0] / m[0][0];
			u = Clamp01(u);
			return a + u*e0;
		}
		else if (u+v > 1.f)
		{
			// Set v = 1-u and solve again.
//			u = (B[0] - m[0][0]) / (m[0][0] - m[0][1]);
//			mathassert(EqualAbs(u, Clamp01(u)));
//			u = Clamp01(u); // The solution for u must also be in the range [0,1].
//			return a + u*e0;

			// Clamp to v = 1-u and solve again.
			float m_00 = m[2][2];
			float m_01 = m[1][2] - m[0][2];
			float m_10 = m_01;
			float m_11 = m[0][0] + m[1][1] - 2.f * m[0][1];
			float det = m_00 * m_11 - m_01 * m_10;
			float b0 = m[1][1] - m[0][1] + v_p_dot_e1 - v_p_dot_e0;
			float b1 = -m[1][2] + v_p_dot_d;
			float u = m_00 * b0 + m_01 * b1;
			u /= det;
			u = Clamp01(u);

			float t = m_10 * b0 + m_11 * b1;
			t /= det;
			t = Clamp01(t);
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + u*e0 + (1.f-u)*e1;
		}
		else
		{
			// The solution is (u, v, 0)
			return a + u * e0 + v * e1;
		}
	}
	else if (uvt.z > 1.f)
	{
		if (otherPt)
			*otherPt = lineSegment.b;
		// Clamp to t == 1 and solve again.
		float m_00 = m[1][1];
		float m_01 = -m[0][1];
		float m_10 = -m[1][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * (B[0]-m[0][2]) + m_01 * (B[1]-m[1][2]);
		float v = m_10 * (B[0]-m[0][2]) + m_11 * (B[1]-m[1][2]);
		u /= det;
		v /= det;
		if (u < 0.f)
		{
			// Clamp to u == 0 and solve again.
			v = (B[1] - m[1][2]) / m[1][1];
			v = Clamp01(v);
			return a + v*e1;
		}
		else if (u > 1.f)
		{
			// Clamp to u == 1 and solve again.
			v = (B[1] - m[1][0] - m[1][2]) / m[1][1];
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(1,v,1).
			return a + e0 + v*e1;
		}
		else if (u+v > 1.f)
		{
			// Set v = 1-u and solve again.

			// Q(u,1-u) = a + u*e0 + e1 - u*e1 = a+e1 + u*(e0-e1)
			// L(1)   = ls.a + t*d = ls.b
			// Minimize the distance |Q(u,1-u) - L(1)| = |a+e1+ls.b + u*(e0-e1)|

			// |K + u*(e0-e1)|^2 = (K,K) + 2*u(K,e0-e1) + u^2 * (e0-e1,e0-e1)

			// grad = 2*(K,e0-e1) + 2*u*(e0-e1,e0-e1) == 0
			//                                      u == (K,e1-e0) / (e0-e1,e0-e1)

			u = (B[0] - m[0][1] - m[0][2]) / (m[0][0] - m[0][1]);
//			u = Dot(a + e1 + lineSegment.b, e1 - e0) / Dot(e0-e1, e0-e1);

//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u);
			return a + u*e0 + (1-u)*e1;
		}
		else
		{
			// The solution is (u, v, 1)
			return a + u*e0 + v*e1;
		}
	}
	else if (uvt.x + uvt.y > 1.f)
	{
		// Clamp to v = 1-u and solve again.
		float m_00 = m[2][2];
		float m_01 = m[1][2] - m[0][2];
		float m_10 = m_01;
		float m_11 = m[0][0] + m[1][1] - 2.f * m[0][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float b0 = m[1][1] - m[0][1] + v_p_dot_e1 - v_p_dot_e0;
		float b1 = -m[1][2] + v_p_dot_d;
		float u = m_00 * b0 + m_01 * b1;
		float t = m_10 * b0 + m_11 * b1;
		u /= det;
		t /= det;

		t = Clamp01(t);
		if (otherPt)
			*otherPt = lineSegment.GetPoint(t);

		if (u < 0.f)
		{
			// The solution is (u,v,t)=(0,1,t)
			return c;
		}
		if (u > 1.f)
		{
			// The solution is (u,v,t)=(1,0,t)
			return b;
		}
		mathassert(t >= 0.f);
		mathassert(t <= 1.f);
		return a + u*e0 + (1.f-u)*e1;
	}
	else // All parameters are within range, so the triangle and the line segment intersect, and the intersection point is the closest point.
	{
		if (otherPt)
			*otherPt = lineSegment.GetPoint(uvt.z);
		return a + uvt.x * e0 + uvt.y * e1;
	}
}
Пример #29
0
 void add(ELV &g, int u, int v, int w) { g[u].push_back(Edge(v, w)); }
Пример #30
0
	Triangle::Triangle() 
	{
	    M_points[0] = M_points[1] = M_points[2] = Point(); 
	    M_edges[0] = M_edges[1] = M_edges[2] = Edge();
	}