Beispiel #1
0
//
// s is a spoke pointing OUT from x
//
void Subdivision::optimize(Vec2& x, Edge *s)
{
    Edge *start_spoke = s;
    Edge *spoke = s;

    do {

	Edge *e = spoke->Lnext();
	Edge *t = e->Oprev();

	if( isInterior(e) && shouldSwap(x, e) )
	    swap(e);
	else
	{
	    spoke = spoke->Onext();
	    if( spoke == start_spoke )
		break;
	}

    } while( true );

    //
    // Now, update all the triangles

    spoke = start_spoke;

    do {
	Edge *e = spoke->Lnext();
	Triangle *t = e->Lface();

	if( t ) t->update(*this);

	spoke = spoke->Onext();
    } while( spoke != start_spoke );
}
Edge * splitFace(Face *fl, Vertex *v1, Vertex *v2) {

	Face *fr = new Face();

	//cout << "  split vertices: " << v1->p << "-" << v2->p << endl;
	Edge *a = v1->getEdge();
	Edge *b = v2->getEdge();
	Edge *c = Edge::makeEdge(v1, v2, fl, fr);

	while (a->Left() != fl) { a = a->Onext(); }
	while (b->Left() != fl) { b = b->Onext(); }

	Edge::splice(a, c);
	Edge::splice(b, c->Sym());

	Edge *cIter = c->Lnext();
	while (cIter != c) {
		cIter->setLeft(fl);
		cIter = cIter->Lnext();
	}
	cIter = c->Rnext();
	while (cIter != c) {
		cIter->setRight(fr);
		cIter = cIter->Rnext();
	}

	return c;
}
void Edge::splice(Edge *a, Edge *b) {
	Edge *temp;
	Edge *alpha = a->Onext()->Rot();
	Edge *beta  = b->Onext()->Rot();

	temp = a->Onext();
	a->next = b->Onext();
	b->next = temp;
	temp = alpha->Onext();
	alpha->next = beta->Onext();
	beta->next = temp;
}
Beispiel #4
0
void splice(Edge *a, Edge *b)
{
    Edge *alpha = a->Onext()->Rot();
    Edge *beta  = b->Onext()->Rot();

    Edge *t1 = b->Onext();
    Edge *t2 = a->Onext();
    Edge *t3 = beta->Onext();
    Edge *t4 = alpha->Onext();

    a->next = t1;
    b->next = t2;
    alpha->next = t3;
    beta->next = t4;
}
int getVertexOrder(Edge *e, vector<Point>& pts) {
	int count = 1;
	Edge *iter = e->Onext();

	if (iter == NULL) {
		cout << "Erro: ponteiro next == NULL\n";
		return -1;
	}

	pts.clear();
	pts.push_back(e->Sym()->Orig()->p);

	while (iter != e && count < 100) {
		count++;
		iter = iter->Onext();
		pts.push_back(iter->Sym()->Orig()->p);
	}

	if (count == 100) {
		cout << "Erro: loop infinito\n";
		return -1;
	}

	return count;
}
Beispiel #6
0
void Edge::splice(Edge *a, Edge *b) {
    assert(a != 0);
    assert(b != 0);

    // see Guibas and Stolfi
    Edge* alpha = a->Onext()->Rot();
    Edge* beta  = b->Onext()->Rot();

    Edge* t1 = b->Onext();
    Edge* t2 = a->Onext();
    Edge* t3 = beta->Onext();
    Edge* t4 = alpha->Onext();

    a->next     = t1;
    b->next     = t2;
    alpha->next = t3;
    beta->next  = t4;
}
Beispiel #7
0
void Subdivision::InsertSite(const Point2d& x)
// Inserts a new point into a subdivision representing a Delaunay
// triangulation, and fixes the affected edges so that the result
// is still a Delaunay triangulation. This is based on the
// pseudocode from Guibas and Stolfi (1985) p.120, with slight
// modifications and a bug fix.
{
	Edge* e = Locate(x);
	if ((x == e->Org2d()) || (x == e->Dest2d()))  // point is already in
	    return;
	else if (OnEdge(x, e)) {
		e = e->Oprev();
		DeleteEdge(e->Onext());
	}

	// Connect the new point to the vertices of the containing
	// triangle (or quadrilateral, if the new point fell on an
	// existing edge.)
	Edge* base = MakeEdge();
	base->EndPoints(e->Org(), new Point2d(x));
	Splice(base, e);
	startingEdge = base;
	do {
		base = Connect(e, base->Sym());
		e = base->Oprev();
	} while (e->Lnext() != startingEdge);

	// Examine suspect edges to ensure that the Delaunay condition
	// is satisfied.
	do {
		Edge* t = e->Oprev();
		if (RightOf(t->Dest2d(), e) &&
			InCircle(e->Org2d(), t->Dest2d(), e->Dest2d(), x)) {
				Swap(e);
				e = e->Oprev();
		}
		else if (e->Onext() == startingEdge)  // no more suspect edges
			return;
		else  // pop a suspect edge
		    e = e->Onext()->Lprev();
	} while (TRUE);
}
Beispiel #8
0
Edge* Subdivision::Locate(const Point2d& x)
// Returns an edge e, s.t. either x is on e, or e is an edge of
// a triangle containing x. The search starts from startingEdge
// and proceeds in the general direction of x. Based on the
// pseudocode in Guibas and Stolfi (1985) p.121.
{
	Edge* e = startingEdge;

	while (TRUE) {
		if (x == e->Org2d() || x == e->Dest2d())
		    return e;
		else if (RightOf(x, e))
			 e = e->Sym();
		else if (!RightOf(x, e->Onext()))
			 e = e->Onext();
		else if (!RightOf(x, e->Dprev()))
			 e = e->Dprev();
		else
		    return e;
	}
}
Beispiel #9
0
Edge *Subdivision::locate(const Vec2& x, Edge *start)
{
    Edge *e = start;
    double t = triArea(x, e->Dest(), e->Org());

    if (t>0) {                  // x is to the right of edge e
        t = -t;
        e = e->Sym();
    }


    while (true)
    {
        Edge *eo = e->Onext();
        Edge *ed = e->Dprev();

        double to = triArea(x, eo->Dest(), eo->Org());
        double td = triArea(x, ed->Dest(), ed->Org());

        if (td>0)                       // x is below ed
            if (to>0 || to==0 && t==0) {// x is interior, or origin endpoint
                startingEdge = e;
                return e;
            }
            else {                      // x is below ed, below eo
                t = to;
                e = eo;
            }
        else                            // x is on or above ed
            if (to>0)                   // x is above eo
                if (td==0 && t==0) {    // x is destination endpoint
                    startingEdge = e;
                    return e;
                }
                else {                  // x is on or above ed and above eo
                    t = td;
                    e = ed;
                }
            else                        // x is on or below eo
                if (t==0 && !leftOf(eo->Dest(), e))
		    // x on e but subdiv. is to right
                    e = e->Sym();
                else if (rand()&1) {  // x is on or above ed and
                    t = to;             // on or below eo; step randomly
                    e = eo;
                }
                else {
                    t = td;
                    e = ed;
                }
    }
}
Beispiel #10
0
void Cell::setOrbitOrg(Edge *edge, Vertex *org) {
    assert(edge != 0);
    assert(org != 0);

    // traverse the Onext orbit of _edge_, setting the origin of each edge to
    // _org_
    Edge *scan = edge;

    do {
        scan->setOrg(org);
        scan = scan->Onext();
    } while (scan != edge);
}
Edge *getVerticesEdge(Vertex *v1, Vertex *v2) {
	if (v1 == NULL || v2 == NULL)
		return NULL;

	Edge *e = v1->getEdge();
	while (e->Dest() != v2) {
		e = e->Onext();
		if (e == v1->getEdge()) {
			e = NULL;
			break;
		}
	}
	return e;
}
Beispiel #12
0
void Splice(Edge* a, Edge* b)
// This operator affects the two edge rings around the origins of a and b,
// and, independently, the two edge rings around the left faces of a and b.
// In each case, (i) if the two rings are distinct, Splice will combine
// them into one; (ii) if the two are the same ring, Splice will break it
// into two separate pieces.
// Thus, Splice can be used both to attach the two edges together, and
// to break them apart. See Guibas and Stolfi (1985) p.96 for more details
// and illustrations.
{
	Edge* alpha = a->Onext()->Rot();
	Edge* beta  = b->Onext()->Rot();

	Edge* t1 = b->Onext();
	Edge* t2 = a->Onext();
	Edge* t3 = beta->Onext();
	Edge* t4 = alpha->Onext();

	a->next = t1;
	b->next = t2;
	alpha->next = t3;
	beta->next = t4;
}
Beispiel #13
0
Edge *Cell::getOrbitLeft(Edge *edge, Face *left) {
    assert(edge != 0);
    assert(left != 0);

    // traverse the Onext orbit of _edge_ looking for an edge whose left face is
    // _left
    Edge *scan = edge;

    do {
        if (scan->Left() == left) {
            return scan;
        }

        scan = scan->Onext();
    } while (scan != edge);

    return 0;
}
int getVertexOrder(Edge *e) {
	int count = 1;
	Edge *iter = e->Onext();

	if (iter == NULL) {
		cout << "Erro: ponteiro next == NULL\n";
		return -1;
	}

	while (iter != e && count < 100) {
		count++;
		iter = iter->Onext();
	}

	if (count == 100) {
		cout << "Erro: loop infinito\n";
		return -1;
	}

	return count;
}
Beispiel #15
0
int main() {
        using cgl::Point2d;
        using cgl::Edge;
        using cgl::make_edge;

        // Point2d *a = new Point2d(0.0, 0.0); // 0
        // Point2d *b = new Point2d(1.0, 0.0); // 1
        // Point2d *c = new Point2d(1.0, 1.0); // 2
        // Point2d *d = new Point2d(0.0, 1.0); // 3

        Edge *ea = make_edge(0, 1);
        Edge *eb = make_edge(ea->Dest(), 2);
        Edge *ec = make_edge(eb->Dest(), 3);
        Edge *ed = make_edge(ec->Dest(), 0);
        Edge *ee = make_edge(eb->Dest(), ea->Org());

        // Connect eb to ea->Dest()
        splice(ea->Sym(), eb);
        // Connect ec to eb->Dest()
        splice(eb->Sym(), ec);
        // Connect ed to ec->Sym() and ea
        splice(ec->Sym(), ed);
        splice(ed->Sym(), ea);
        // Connect ee to ec and ea -- this is equivalent to Delaunay::connect
        splice(ee, eb->Lnext());
        splice(ee->Sym(), ea);

        // Traverse the convex hull
        if (ea->Dnext() != eb->Sym()) {
                std::cerr << "Error: ea->Dnext() != eb->Sym()" << std::endl;
                return 1;
        }

        if (eb->Dnext() != ec->Sym()) {
                std::cerr << "Error: eb->Dnext() != ec->Sym()" << std::endl;
                return 1;
        }

        if (ec->Dnext() != ed->Sym()) {
                std::cerr << "Error: ec->Dnext() != ed->Sym()" << std::endl;
                return 1;
        }

        if (ed->Dprev() != ee) {
                std::cerr << "Error: ed->Dprev() != ee" << std::endl;
                return 1;
        }

        // Cross linkage -- test algebra
        // Rot / invRot
        if (ee->Rot()->Org() != ed->invRot()->Org()) {
                std::cerr << "Error: ee->Rot()->Org() != ed->invRot()->Org()" <<
                        std::endl;
                return 1;
        }

        // Sym
        if (ee->Sym()->Org() != 0) {
                std::cerr << "Error: ee->Sym()->Org() != a" << std::endl;
                return 1;
        }

        // Onext
        if (ee->Onext() != eb->Sym()) {
                std::cerr << "Error: ee->Onext() != eb->Sym()" << std::endl;
                return 1;
        }

        // Oprev
        if (ee->Oprev() != ec) {
                std::cerr << "Error: ee->Oprev() != ec" << std::endl;
                return 1;
        }

        // Dnext
        if (ee->Dnext() != ed) {
                std::cerr << "Error: ee->Dnext() != ed" << std::endl;
                return 1;
        }

        // Dprev
        if (ee->Dprev() != ea->Sym()) {
                std::cerr << "Error: ee->Dprev() != ea->Sym()" << std::endl;
                return 1;
        }

        // Lnext
        if (ee->Lnext() != ea) {
                std::cerr << "Error: ee->Lnext() != ea" << std::endl;
                return 1;
        }

        // Lprev
        if (ee->Lprev() != eb) {
                std::cerr << "Error: ee->Lprev() != eb" << std::endl;
                return 1;
        }

        // Rnext
        if (ee->Rnext() != ec->Sym()) {
                std::cerr << "Error: ee->Rnext() != ec->Sym()" << std::endl;
                return 1;
        }

        // Rprev
        if (ee->Rprev() != ed->Sym()) {
                std::cerr << "Error: ee->Rprev() != ed->Sym()" << std::endl;
                return 1;
        }

        // Org / Dest
        if (ed->Org() != 3) {
                std::cerr << "Error: ed->Org() != d" << std::endl;
                return 1;
        }

        if (ed->Dest() != 0) {
                std::cerr << "Error: ed->Dest() != a" << std::endl;
                return 1;
        }

        if (ee->Org()  != 2) {
                std::cerr << "Error: ee->Org() != c" << std::endl;
                return 1;
        }

        if (ee->Dest()  != 0) {
                std::cerr << "Error: ee->Dest() != a" << std::endl;
                return 1;
        }

        // Let the system clean up the memory

        return 0;
}
void Edge::killEdge(Edge *e) {
	Edge *f = e->Sym();
	if (e->Onext() != e) splice(e, e->Oprev());
	if (f->Onext() != f) splice(f, f->Oprev());
	delete (QuadEdge *)(e - e->r);
}
Beispiel #17
0
/*Type of Cut Strategy is defined as:
 * (useAltCut, useVertical) = (true, true)  => Alternating Cuts
 * (useAltCut, useVertical) = (true, false) => Horizontal Cuts*
 * (useAltCut, useVertical) = (false, true)  => Vertical Cuts
 * */
void delaunay(Vertex **ppVertices, long numVertices, Edge **ppLe, Edge **ppRe,
		bool useAltCuts, bool useVertical) {
    NOT_NULL(ppVertices);
    
    if(numVertices == 2) {
        Edge *pA = Edge::makeEdge();
        if(*ppVertices[0] > *ppVertices[1]) {
            ELEM_SWAP(ppVertices[0], ppVertices[1]);
        }
        pA->setOrg(ppVertices[0]);
        pA->setDest(ppVertices[1]);
        *ppLe = pA;
        *ppRe = pA->Sym();
    }
    else if(numVertices == 3) {
        Edge *pA = Edge::makeEdge(),
             *pB = Edge::makeEdge(),
             *pC = 0;

        if(*ppVertices[0] > *ppVertices[1]) {
            ELEM_SWAP(ppVertices[0], ppVertices[1]);
        }
        if(*ppVertices[1] > *ppVertices[2]) {
            ELEM_SWAP(ppVertices[1], ppVertices[2]);
        }

        Edge::splice(pA->Sym(), pB);
        pA->setOrg(ppVertices[0]);
        pA->setDest(ppVertices[1]);
        pB->setOrg(ppVertices[1]);
        pB->setDest(ppVertices[2]);
        
        REAL ccw = orient2d(ppVertices[0]->Pos(), ppVertices[1]->Pos(), ppVertices[2]->Pos());
        if(ccw > 0) {
            pC = Edge::connect(pB, pA);
            *ppLe = pA;
            *ppRe = pB->Sym();
        }
        else if(ccw < 0) {
            pC = Edge::connect(pB, pA);
            *ppLe = pC->Sym();
            *ppRe = pC;
        }
        else {
            *ppLe = pA;
            *ppRe = pB->Sym();
        }
    }
    else {
        long middle = std::floor(numVertices/2);
        Edge *pLdo = 0, 
             *pLdi = 0, 
             *pRdi = 0, 
             *pRdo = 0;

        //These vertices are used for merging a horizontal cut
        Vertex *pBotMax = 0, //highest vertex of bottom half
               *pTopMin = 0, //lowest vertex of top half
               *pMin    = 0, //Lexicographically max vertex
               *pMax    = 0; //Lexicographically min vertex
        
        //Find median partition by X or Y, depending on whether we're using a vertical cut
        std::nth_element(ppVertices, ppVertices+middle, ppVertices+numVertices, useVertical ? Vertex::lessX : Vertex::lessY);

        //Recursive calls
        delaunay(ppVertices, middle, &pLdo, &pLdi, useAltCuts, useAltCuts ? !useVertical : useVertical);
        delaunay(ppVertices+middle, numVertices - middle, &pRdi, &pRdo, useAltCuts, useAltCuts ? !useVertical : useVertical);
        
        //Modify ldi be highest in bottom half and rdi to be lowest in top half
        if(!useVertical) {
            pBotMax = ppVertices[0];
            pTopMin = ppVertices[middle];
            pMin    = (*ppVertices[0] < *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle];
            pMax    = (*ppVertices[0] > *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle];;
            for(long i=1; i < middle; i++) {
                if(*ppVertices[i] < *pMin) {
                    pMin = ppVertices[i];
                }
                else if(*ppVertices[i] > *pMax) {
                    pMax = ppVertices[i];
                }
                
                if(ppVertices[i]->gtY(*pBotMax)) {
                    pBotMax = ppVertices[i];
                }
            }
            for(long i=middle+1; i < numVertices; i++) {
                if(*ppVertices[i] < *pMin) {
                    pMin = ppVertices[i];
                }
                else if(*ppVertices[i] > *pMax) {
                    pMax = ppVertices[i];
                }
                
                if(ppVertices[i]->ltY(*pTopMin)) {
                    pTopMin = ppVertices[i];
                }
            }
            
            pLdi = pBotMax->getCWHullEdge();
            pRdi = pTopMin->getCCWHullEdge();
        }
        
        
        //Compute the lower common tangent of two sets of vertices
        while (1) {
            if(pLdi->leftOf(pRdi->Org())) {
                pLdi = pLdi->Lnext();
            }
            else if(pRdi->rightOf(pLdi->Org())) {
                pRdi = pRdi->Rprev();
            }
            else {
                break;
            }
        }

        // Create a first cross edge pBasel from pRdi.origin to pLdi.origin
        Edge *pBasel = Edge::connect(pRdi->Sym(), pLdi);

        if(pLdi->Org() == pLdo->Org()) {
            pLdo = pBasel->Sym();
        }
        if(pRdi->Org() == pRdo->Org()) {
            pRdo = pBasel;
        }

        //Merging two halves
        while(1) {
            //Locate the first Left point pLcand to be encou
        	Edge *pLcand = pBasel->Sym()->Onext();
            bool leftFinished  = !pLcand->valid(pBasel);
            if(!leftFinished) {
                while(incircle(pBasel->Dest()->Pos(), 
                               pBasel->Org()->Pos(), 
                               pLcand->Dest()->Pos(),  
                               pLcand->Onext()->Dest()->Pos()) > 0) {
                
                    Edge *pT = pLcand->Onext();
                    Edge::deleteEdge(pLcand);
                    pLcand = pT;
                }
            }
            
            //Symmetrically locate the first R point to be hit
            Edge *pRcand = pBasel->Oprev();
            bool rightFinished = !pRcand->valid(pBasel);
            if(!rightFinished) {
                while(incircle(pBasel->Dest()->Pos(), 
                               pBasel->Org()->Pos(), 
                               pRcand->Dest()->Pos(),  
                               pRcand->Oprev()->Dest()->Pos()) > 0) {
                
                    Edge *pT = pRcand->Oprev();
                    Edge::deleteEdge(pRcand);
                    pRcand = pT;
                }
            }

            //both are invalid, pBasel is upper common tangent
            if(leftFinished && rightFinished) {
                break;
            }
            //the next cross edge is to be connected to either pLcand.dest or pRcand.dest
            if(leftFinished || 
               (!rightFinished && incircle(pLcand->Dest()->Pos(), 
                                                  pLcand->Org()->Pos(), 
                                                  pRcand->Org()->Pos(), 
                                                  pRcand->Dest()->Pos()) > 0)) {
                pBasel = Edge::connect(pRcand, pBasel->Sym());
            }
            else {
                pBasel = Edge::connect(pBasel->Sym(), pLcand->Sym());
            }
        }

        //Modify pLdo and pRdo if we merging a horizontal cut
        if(!useVertical) {
            pLdo = pMin->getCCWHullEdge();
            pRdo = pMax->getCWHullEdge();
        }

        *ppLe = pLdo;
        *ppRe = pRdo;
    }
    return;
}
Beispiel #18
0
Edge *Subdivision::spoke(Vec2& x, Edge *e)
{
    Triangle *new_faces[4];
    int facedex = 0;

    //
    // NOTE: e is the edge returned by locate(x)
    //

    if ( (x == e->Org()) || (x == e->Dest()) ) {
        // point is already in the mesh
	//
#ifdef _INC_IOSTREAM
        std::cerr << "WARNING: Tried to reinsert point: " << x << std::endl;
	std::cerr << "         org: " << e->Org() << std::endl;
	std::cerr << "        dest: " << e->Dest() << std::endl;
#endif
        return NULL;
    }

    Edge *boundary_edge = NULL;

    Triangle *lface = e->Lface();
    lface->dontAnchor(e);
    new_faces[facedex++] = lface;

    if( onEdge(x,e) )
    {
	if( ccwBoundary(e) ) {
	    //
	    // e lies on the boundary
	    // Defer deletion until after new edges are added.
	    boundary_edge = e;
	}
	else {
	    Triangle *sym_lface = e->Sym()->Lface();
	    new_faces[facedex++] = sym_lface;
	    sym_lface->dontAnchor(e->Sym());


	    e = e->Oprev();
	    deleteEdge(e->Onext());
	}
    }
    else
    {
	// x lies within the Lface of e
    }

    Edge *base = makeEdge(e->Org(), x.clone());

    splice(base, e);

    startingEdge = base;
    do {
	base = connect(e, base->Sym());
	e = base->Oprev();
    } while( e->Lnext() != startingEdge );

    if( boundary_edge )
	deleteEdge(boundary_edge);

    // Update all the faces in our new spoked polygon.
    // If point x on perimeter, then don't add an exterior face


    base = boundary_edge ? startingEdge->Rprev() : startingEdge->Sym();
    do {
	if( facedex )
	    new_faces[--facedex]->reshape(base);
	else
	    makeFace(base);

	base = base->Onext();

    } while( base != startingEdge->Sym() );

    return startingEdge;
}