Пример #1
0
bool Vectorize::vconncet()
{
     connect(m_gui.fileButton, SIGNAL(clicked()), this, SLOT(open()));
     connect(m_gui.runButton, SIGNAL(clicked()), this, SLOT(run()));
     connect(m_gui.meshButton, SIGNAL(clicked()), this, SLOT(delaunay()));
     connect(m_gui.testButton, SIGNAL(clicked()), this, SLOT(test()));
     connect(m_gui.saveButton, SIGNAL(clicked()), this, SLOT(save()));
     
     return true;
}
void ClusterHierarchyBuilder::CreateInitialEdges(const Vec2 *pts,int numPts)
{
	FortunesAlgorithm delaunay(pts,numPts);
	
	mEdges = new Edge[delaunay.mTriangles.size() * 3];
	Edge *freeEdge = mEdges;
	for(const FortunesAlgorithm::Triangle &tri : delaunay.mTriangles)
	{
		int prev = tri.mIndices[2];
		for(int j = 0;j < 3;j++)
		{
			int cur = tri.mIndices[j];
			
			int from = prev;
			int to = cur;
			if(from > to)
				std::swap(to,from);
			
			Edge *edge = freeEdge++;
			
			edge->mFrom = mNodes[from];
			edge->mFromLLNext = mNodes[from]->mEdgeLLHead;
			mNodes[from]->mEdgeLLHead = edge;
			
			edge->mTo = mNodes[to];
			edge->mToLLNext = mNodes[to]->mEdgeLLHead;
			mNodes[to]->mEdgeLLHead = edge;
			
			edge->mSqrLen = (mNodes[from]->mCentroid - mNodes[to]->mCentroid).GetSqrLen();
			edge->mInHeap = false;
			
			prev = cur;
		}
	}
	
	for(Node *node : mNodes)
	{
		node->mEdgeLLHead = SortSinglyLinkedList(node->mEdgeLLHead,SortEdgesTraits(node));
		node->mEdgeLLHead = RemoveDupsSinglyLinkedList(node->mEdgeLLHead, RemoveDupEdgesTraits(node));
		
		for(Edge *edge = node->mEdgeLLHead;edge;edge = edge->LLGetNext(node))
		{
			if(!edge->mInHeap)
			{
				edge->mInHeap = true;
				mEdgesHeap.Push(edge);
			}
		}
	}
}
Пример #3
0
//-----------------------------------------------------------------------
void Triangulator::triangulate(const Shape& shape, std::vector<int>& output)
{
	// Do the Delaunay triangulation
	PointList pl = shape.getPoints();
	DelaunayTriangleBuffer dtb;
	delaunay(pl, dtb);
	
	addConstraints(shape, dtb);
	
	//Outputs index buffer	
	for (DelaunayTriangleBuffer::iterator it = dtb.begin(); it!=dtb.end();it++)
	{
		output.push_back(it->i[0]);
		output.push_back(it->i[1]);
		output.push_back(it->i[2]);
	}
}
Пример #4
0
void EditorScene::addPoint(const cocos2d::Vec2 &rawpos)
{
    clearSelection();

    auto pos = help_touchPoint2editPosition(rawpos);
    auto point = std::make_shared<EEPoint>();
    point->position = help_editPosition2relativePosition(pos);
    point->height = findNearestHeight(point->position);
    point->sprite = Sprite::create("images/point_normal.png");
    point->sprite->setPosition(help_relativePosition2editPosition(point->position));
    point->sprite->setZOrder(Z_POINTS);
    point->sprite->setScale(DOT_SCALE);
    _pointLayer->addChild(point->sprite);
    point->pid = nextPid();
    _points[_frameIndex][point->pid] = point;
    delaunay();
    refreshLines();
    refreshTriangles();
}
Пример #5
0
void EditorScene::deletePoint(const cocos2d::Vec2 &rawpos)
{
    clearSelection();

    auto pos = help_touchPoint2editPosition(rawpos);

    for (auto & pair : _points[_frameIndex]) {
        auto distance = pair.second->sprite->getPosition().distance(pos);
        if (distance < pair.second->sprite->getContentSize().width * pair.second->sprite->getScale() /2){
            CCLOG("delete point");
            _pointLayer->removeChild(pair.second->sprite);
            _points[_frameIndex].erase(pair.first);
            _selectedPoints.remove(pair.second);

            delaunay();
            refreshLines();
            refreshTriangles();

            return;
        }
    }
}
Пример #6
0
void Tetgen::delaunay(Crowd* crowd)
{
	setCurrentCrowd(crowd);
	delaunay();
}
Пример #7
0
    // Customized triangulation call.
    void custom_triangulate(char *triswitches, struct triangulateio *in, struct triangulateio *out, struct triangulateio *vorout, const int *outside, const int *inside)
    {
        struct mesh m;
        struct behavior b;
        //REAL *holearray;
        //REAL *regionarray;
        triangleinit(& m);
        parsecommandline(1, & triswitches, & b);
        //b.verbose=2;
        m.steinerleft = b.steiner;
        transfernodes(& m, & b, in->pointlist, in->pointattributelist,
                      in->pointmarkerlist, in->numberofpoints,
                      in->numberofpointattributes);
        if ( b.refine ) {
            m.hullsize = reconstruct(& m, & b, in->trianglelist,
                                     in->triangleattributelist, in->trianglearealist,
                                     in->numberoftriangles, in->numberofcorners,
                                     in->numberoftriangleattributes,
                                     in->segmentlist, in->segmentmarkerlist,
                                     in->numberofsegments);
        } else {
            m.hullsize = delaunay(& m, & b);
        }
        m.infvertex1 = ( vertex ) NULL;
        m.infvertex2 = ( vertex ) NULL;
        m.infvertex3 = ( vertex ) NULL;
        if ( b.usesegments ) {
            m.checksegments = 1;
            if ( !b.refine ) {
                formskeleton(& m, & b, in->segmentlist,
                             in->segmentmarkerlist, in->numberofsegments);
            }
        }
 #if 0
        struct osub subsegloop;
        traversalinit(& m.subsegs);
        subsegloop.ss = subsegtraverse(& m);
        subsegloop.ssorient = 0;
        while ( subsegloop.ss != ( subseg * ) NULL ) {
            if ( subsegloop.ss != m.dummysub ) {
                REAL *p1, *p2;
                sorg(subsegloop, p1);
                sdest(subsegloop, p2);
                printf("  Connected (%f,%f) to (%f,%f)\n", p1 [ 0 ], p1 [ 1 ], p2 [ 0 ], p2 [ 1 ]);
                subsegloop.ss = subsegtraverse(& m);
            }
        }
 #endif
        if ( b.poly && ( m.triangles.items > 0 ) ) {
            //holearray = in->holelist;
            m.holes = in->numberofholes;
            //regionarray = in->regionlist;
            m.regions = in->numberofregions;
            if ( !b.refine ) {
                /* Only increase quality if the regions are properly defined. */
                int sane = custom_carveholes(& m, & b, outside, inside);
                b.quality *= sane;
                if ( sane == 0 ) {
                    printf("Probably bad PSLG\n");
                    exit(-1);
                }
            }
        } else {
            m.holes = 0;
            m.regions = 0;
        }
        if ( b.quality && ( m.triangles.items > 0 ) ) {
            enforcequality(& m, & b);
        }
        m.edges = ( 3l * m.triangles.items + m.hullsize ) / 2l;
        if ( b.order > 1 ) {
            highorder(& m, & b);
        }
        if ( !b.quiet ) {
            printf("\n");
        }
        if ( b.jettison ) {
            out->numberofpoints = m.vertices.items - m.undeads;
        } else {
            out->numberofpoints = m.vertices.items;
        }
        out->numberofpointattributes = m.nextras;
        out->numberoftriangles = m.triangles.items;
        out->numberofcorners = ( b.order + 1 ) * ( b.order + 2 ) / 2;
        out->numberoftriangleattributes = m.eextras;
        out->numberofedges = m.edges;
        if ( b.usesegments ) {
            out->numberofsegments = m.subsegs.items;
        } else {
            out->numberofsegments = m.hullsize;
        }
        if ( vorout != ( struct triangulateio * ) NULL ) {
            vorout->numberofpoints = m.triangles.items;
            vorout->numberofpointattributes = m.nextras;
            vorout->numberofedges = m.edges;
        }
        if ( b.nonodewritten || ( b.noiterationnum && m.readnodefile ) ) {
            if ( !b.quiet ) {
                printf("NOT writing vertices.\n");
            }
            numbernodes(& m, & b);
        } else {
            writenodes(& m, & b, & out->pointlist, & out->pointattributelist,
                       & out->pointmarkerlist);
        }

        // Simp. always write the triangles.
        writeelements(& m, & b, & out->trianglelist, & out->triangleattributelist);

        if ( b.poly || b.convex ) {
            writepoly(& m, & b, & out->segmentlist, & out->segmentmarkerlist);
            out->numberofholes = m.holes;
            out->numberofregions = m.regions;
            if ( b.poly ) {
                out->holelist = in->holelist;
                out->regionlist = in->regionlist;
            } else {
                out->holelist = ( REAL * ) NULL;
                out->regionlist = ( REAL * ) NULL;
            }
        }
        if ( b.edgesout ) {
            writeedges(& m, & b, & out->edgelist, & out->edgemarkerlist);
        }
        // Simp. no voronoi
        if ( b.neighbors ) {
            writeneighbors(& m, & b, & out->neighborlist);
        }
        // Simp. No statistics.
        if ( b.docheck ) {
            checkmesh(& m, & b);
            checkdelaunay(& m, & b);
        }
        triangledeinit(& m, & b);
    }
Пример #8
0
static int DelaunayClustering(int MaxClusterSize)
{
    int Count = 0, Count1, Count2 = 0, i, j = 0;
    Edge *EdgeSet, Key;
    Node *From, *To, *N, *F, *T;
    point *u, *v;
    edge *e_start, *e;

    delaunay(Dimension);
    for (i = 0; i < Dimension; i++) {
        u = &p_array[i];
        e_start = e = u->entry_pt;
        do {
            v = Other_point(e, u);
            if (u->id < v->id)
                Count++;
        } while ((e = Next(e, u)) != e_start);
    }
    assert(EdgeSet = (Edge *) malloc(Count * sizeof(Edge)));
    for (i = 0; i < Dimension; i++) {
        u = &p_array[i];
        e_start = e = u->entry_pt;
        do {
            v = Other_point(e, u);
            if (u->id < v->id) {
                EdgeSet[j].From = From = &NodeSet[u->id];
                EdgeSet[j].To = To = &NodeSet[v->id];
                EdgeSet[j++].Cost = FixedOrCommon(From, To) ? INT_MIN :
                    Distance(From, To) * Precision + From->Pi + To->Pi;
            }
        } while ((e = Next(e, u)) != e_start);
    }
    free_memory();
    if (WeightType == GEO || WeightType == GEOM ||
        WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS) {
        N = FirstNode;
        while ((N = N->Suc) != FirstNode)
            if ((N->Y > 0) != (FirstNode->Y > 0))
                break;
        if (N != FirstNode) {
            N = FirstNode;
            do
                N->Zc = N->Y;
            while ((N = N->Suc) != FirstNode);
            /* Transform longitude (180 and -180 map to 0) */
            From = FirstNode;
            do {
                From->Zc = From->Y;
                if (WeightType == GEO || WeightType == GEO_MEEUS)
                    From->Y =
                        (int) From->Y + 5.0 * (From->Y -
                                               (int) From->Y) / 3.0;
                From->Y += From->Y > 0 ? -180 : 180;
                if (WeightType == GEO || WeightType == GEO_MEEUS)
                    From->Y =
                        (int) From->Y + 3.0 * (From->Y -
                                               (int) From->Y) / 5.0;
            } while ((From = From->Suc) != FirstNode);
            delaunay(Dimension);
            do
                From->Y = From->Zc;
            while ((From = From->Suc) != FirstNode);

            qsort(EdgeSet, Count, sizeof(Edge), compareFromTo);
            for (i = 0; i < Dimension; i++) {
                u = &p_array[i];
                e_start = e = u->entry_pt;
                do {
                    v = Other_point(e, u);
                    if (u->id < v->id)
                        Count2++;
                } while ((e = Next(e, u)) != e_start);
            }
            Count1 = Count;
            assert(EdgeSet =
                   (Edge *) realloc(EdgeSet,
                                    (Count1 + Count2) * sizeof(Edge)));
            for (i = 0; i < Dimension; i++) {
                u = &p_array[i];
                e_start = e = u->entry_pt;
                do {
                    v = Other_point(e, u);
                    if (u->id > v->id)
                        continue;
                    Key.From = From = &NodeSet[u->id];
                    Key.To = To = &NodeSet[v->id];
                    if (!bsearch
                        (&Key, EdgeSet, Count1, sizeof(Edge),
                         compareFromTo)) {
                        EdgeSet[Count].From = From;
                        EdgeSet[Count].To = To;
                        EdgeSet[Count].Cost =
                            FixedOrCommon(From, To) ? INT_MIN :
                            Distance(From,
                                     To) * Precision + From->Pi + To->Pi;
                        Count++;
                    }
                } while ((e = Next(e, u)) != e_start);
            }
            free_memory();
        }
    }
    qsort(EdgeSet, Count, sizeof(Edge), compareCost);

    /* Union-Find with path compression */
    N = FirstNode;
    do {
        N->Next = N;
        N->Size = 1;
    } while ((N = N->Suc) != FirstNode);
    for (i = 0; i < Count; i++) {
        for (F = EdgeSet[i].From; F != F->Next;)
            F = F->Next = F->Next->Next;
        for (T = EdgeSet[i].To; T != T->Next;)
            T = T->Next = T->Next->Next;
        if (F != T && F->Size + T->Size <= MaxClusterSize) {
            if (F->Size < T->Size) {
                F->Next = T;
                T->Size += F->Size;
            } else {
                T->Next = F;
                F->Size += T->Size;
            }
        }
    }
    free(EdgeSet);

    Count = 0;
    N = FirstNode;
    do {
        if (N->Next == N && N->Size > 3)
            N->Subproblem = ++Count;
    } while ((N = N->Suc) != FirstNode);
    do {
        for (T = N; T != T->Next;)
            T = T->Next = T->Next->Next;
        N->Subproblem = T->Subproblem;
    } while ((N = N->Suc) != FirstNode);
    return Count;
}
void CreateDelaunayCandidateSet()
{
    Node *From, *To;
    point *u, *v;
    edge *e_start, *e;
    int d, i, Count;

    if (TraceLevel >= 2)
        printff("Creating Delaunay candidate set ... ");
    if (Level == 0 && MaxCandidates == 0) {
        AddTourCandidates();
        From = FirstNode;
        do {
            if (!From->CandidateSet)
                eprintf("MAX_CANDIDATES = 0: No candidates");
        } while ((From = From->Suc) != FirstNode);
        if (TraceLevel >= 2)
            printff("done\n");
        return;
    }

    /* Find the Delaunay edges */
    delaunay(Dimension);

    /* Add the Delaunay edges to the candidate set */
    for (i = 0; i < Dimension; i++) {
        u = &p_array[i];
        From = &NodeSet[u->id];
        e_start = e = u->entry_pt;
        Count = 0;
        do {
            v = Other_point(e, u);
            if (u < v) {
                To = &NodeSet[v->id];
                d = D(From, To);
                AddCandidate(From, To, d, 1);
                AddCandidate(To, From, d, 1);
            }
        } while ((e = Next(e, u)) != e_start && ++Count < Dimension);
    }
    free_memory();
    if (Level == 0 &&
        (WeightType == GEO || WeightType == GEOM ||
         WeightType == GEO_MEEUS || WeightType == GEOM_MEEUS)) {
        if (TraceLevel >= 2)
            printff("done\n");
        From = FirstNode;
        while ((From = From->Suc) != FirstNode)
            if ((From->Y > 0) != (FirstNode->Y > 0))
                break;
        if (From != FirstNode) {
            /* Transform longitude (180 and -180 map to 0) */
            From = FirstNode;
            do {
                From->Zc = From->Y;
                if (WeightType == GEO || WeightType == GEO_MEEUS)
                    From->Y =
                        (int) From->Y + 5.0 * (From->Y -
                                               (int) From->Y) / 3.0;
                From->Y += From->Y > 0 ? -180 : 180;
                if (WeightType == GEO || WeightType == GEO_MEEUS)
                    From->Y =
                        (int) From->Y + 3.0 * (From->Y -
                                               (int) From->Y) / 5.0;
            } while ((From = From->Suc) != FirstNode);
            Level++;
            CreateDelaunayCandidateSet();
            Level--;
            From = FirstNode;
            do
                From->Y = From->Zc;
            while ((From = From->Suc) != FirstNode);
        }
    }
    if (Level == 0) {
        AddTourCandidates();
        /* Add quadrant neighbors if any node has less than two candidates. 
           That is, if it should happen that delaunay_edges fails. */
        From = FirstNode;
        do {
            if (From->CandidateSet == 0 ||
                From->CandidateSet[0].To == 0 ||
                From->CandidateSet[1].To == 0) {
                if (TraceLevel >= 2)
                    printff("*** Not complete ***\n");
                AddExtraCandidates(CoordType == THREED_COORDS ? 8 : 4,
                                   QUADRANT, 1);
                break;
            }
        } while ((From = From->Suc) != FirstNode);
        if (TraceLevel >= 2)
            printff("done\n");
    }
}
Пример #10
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;
}
static bool buildPolyDetail(const float* in, const int nin, unsigned short reg,
							const float sampleDist, const float sampleMaxError,
							const rcCompactHeightfield& chf, const rcHeightPatch& hp,
							float* verts, int& nverts, rcIntArray& tris,
							rcIntArray& edges, rcIntArray& idx, rcIntArray& samples)
{
	static const int MAX_VERTS = 256;
	static const int MAX_EDGE = 64;
	float edge[(MAX_EDGE+1)*3];

	nverts = 0;

	for (int i = 0; i < nin; ++i)
		vcopy(&verts[i*3], &in[i*3]);
	nverts = nin;
	
	const float ics = 1.0f/chf.cs;
	
	// Tesselate outlines.
	// This is done in separate pass in order to ensure
	// seamless height values across the ply boundaries.
	if (sampleDist > 0)
	{
		for (int i = 0, j = nin-1; i < nin; j=i++)
		{
			const float* vj = &in[j*3];
			const float* vi = &in[i*3];
			// Make sure the segments are always handled in same order
			// using lexological sort or else there will be seams.
			if (fabsf(vj[0]-vi[0]) < 1e-6f)
			{
				if (vj[2] > vi[2])
					rcSwap(vj,vi);
			}
			else
			{
				if (vj[0] > vi[0])
					rcSwap(vj,vi);
			}
			// Create samples along the edge.
			float dx = vi[0] - vj[0];
			float dy = vi[1] - vj[1];
			float dz = vi[2] - vj[2];
			float d = sqrtf(dx*dx + dz*dz);
			int nn = 1 + (int)floorf(d/sampleDist);
			if (nn > MAX_EDGE) nn = MAX_EDGE;
			if (nverts+nn >= MAX_VERTS)
				nn = MAX_VERTS-1-nverts;
			for (int k = 0; k <= nn; ++k)
			{
				float u = (float)k/(float)nn;
				float* pos = &edge[k*3];
				pos[0] = vj[0] + dx*u;
				pos[1] = vj[1] + dy*u;
				pos[2] = vj[2] + dz*u;
				pos[1] = chf.bmin[1] + getHeight(pos, chf.bmin, ics, hp)*chf.ch;
			}
			// Simplify samples.
			int idx[MAX_EDGE] = {0,nn};
			int nidx = 2;
			for (int k = 0; k < nidx-1; )
			{
				const int a = idx[k];
				const int b = idx[k+1];
				const float* va = &edge[a*3];
				const float* vb = &edge[b*3];
				// Find maximum deviation along the segment.
				float maxd = 0;
				int maxi = -1;
				for (int m = a+1; m < b; ++m)
				{
					float d = distancePtSeg(&edge[m*3],va,vb);
					if (d > maxd)
					{
						maxd = d;
						maxi = m;
					}
				}
				// If the max deviation is larger than accepted error,
				// add new point, else continue to next segment.
				if (maxi != -1 && maxd > rcSqr(sampleMaxError))
				{
					for (int m = nidx; m > k; --m)
						idx[m] = idx[m-1];
					idx[k+1] = maxi;
					nidx++;
				}
				else
				{
					++k;
				}
			}
			// Add new vertices.
			for (int k = 1; k < nidx-1; ++k)
			{
				vcopy(&verts[nverts*3], &edge[idx[k]*3]);
				nverts++;
			}
		}
	}
	
	// Tesselate the base mesh.
	edges.resize(0);
	tris.resize(0);
	idx.resize(0);
	delaunay(nverts, verts, idx, tris, edges);

	if (sampleDist > 0)
	{
		// Create sample locations in a grid.
		float bmin[3], bmax[3];
		vcopy(bmin, in);
		vcopy(bmax, in);
		for (int i = 1; i < nin; ++i)
		{
			vmin(bmin, &in[i*3]);
			vmax(bmax, &in[i*3]);
		}
		int x0 = (int)floorf(bmin[0]/sampleDist);
		int x1 = (int)ceilf(bmax[0]/sampleDist);
		int z0 = (int)floorf(bmin[2]/sampleDist);
		int z1 = (int)ceilf(bmax[2]/sampleDist);
		samples.resize(0);
		for (int z = z0; z < z1; ++z)
		{
			for (int x = x0; x < x1; ++x)
			{
				float pt[3];
				pt[0] = x*sampleDist;
				pt[2] = z*sampleDist;
				// Make sure the samples are not too close to the edges.
				if (distToPoly(nin,in,pt) > -sampleDist/2) continue;
				samples.push(x);
				samples.push(getHeight(pt, chf.bmin, ics, hp));
				samples.push(z);
			}
		}
				
		// Add the samples starting from the one that has the most
		// error. The procedure stops when all samples are added
		// or when the max error is within treshold.
		const int nsamples = samples.size()/3;
		for (int iter = 0; iter < nsamples; ++iter)
		{
			// Find sample with most error.
			float bestpt[3];
			float bestd = 0;
			for (int i = 0; i < nsamples; ++i)
			{
				float pt[3];
				pt[0] = samples[i*3+0]*sampleDist;
				pt[1] = chf.bmin[1] + samples[i*3+1]*chf.ch;
				pt[2] = samples[i*3+2]*sampleDist;
				float d = distToTriMesh(pt, verts, nverts, &tris[0], tris.size()/4);
				if (d < 0) continue; // did not hit the mesh.
				if (d > bestd)
				{
					bestd = d;
					vcopy(bestpt,pt);
				}
			}
			// If the max error is within accepted threshold, stop tesselating.
			if (bestd <= sampleMaxError)
				break;

			// Add the new sample point.
			vcopy(&verts[nverts*3],bestpt);
			nverts++;
			
			// Create new triangulation.
			// TODO: Incremental add instead of full rebuild.
			edges.resize(0);
			tris.resize(0);
			idx.resize(0);
			delaunay(nverts, verts, idx, tris, edges);

			if (nverts >= MAX_VERTS)
				break;
		}
	}

	return true;
}
Пример #12
0
	std::vector<Triangle> Triangle::triangulate( const std::vector<ci::Vec2f> & points, const std::vector<ci::Vec2f> & contour)
	{
		// Initialize output list
		vector<Triangle> triangles;

		// Convert Cinder points to Delaunay points
		int size = points.size();
		Delaunay::Point position;
		vector<Delaunay::Point> positions;
		for ( float i = 0.0f; i < size; i++ ) {
			Vec2f point = points[i];
			position[ 0 ] = point.x;
			position[ 1 ] = point.y;
			positions.push_back( position );
		}

		// Triangulate points
		Delaunay delaunay( positions );
		delaunay.Triangulate();

		// Triangle IDs
		int32_t id = 0;
		int N = contour.size();

		// Iterate through triangles
		for ( Delaunay::fIterator triIt = delaunay.fbegin(); triIt != delaunay.fend(); ++triIt ) {

			// Get point indexes
			int a = delaunay.Org( triIt );
			int b = delaunay.Dest( triIt );
			int c = delaunay.Apex( triIt );

			// Set positions in triangles
			Vec2f triangle[ 3 ];
			triangle[ 0 ] = points[ a ];
			triangle[ 1 ] = points[ b ];
			triangle[ 2 ] = points[ c ];

			// Find center of triangle
			Vec2f p = Vec2f(
				( triangle[ 0 ].x + triangle[ 1 ].x + triangle[ 2 ].x ) / 3.0f, 
				( triangle[ 0 ].y + triangle[ 1 ].y + triangle[ 2 ].y ) / 3.0f
				);

			// Initialize properties to test triangle position
			Vec2f p1 = contour[ 0 ];

			// Iterate through points
			int32_t counter = 0;
			for (int i=1;i<=N;i++){
				const Vec2f& p2 = contour[i % N];

				// Compare centroid of this triangle to the previous one
				if ( p.y >  math<float>::min( p1.y, p2.y ) && 
					p.y <= math<float>::max( p1.y, p2.y ) && 
					p.x <= math<float>::max( p1.x, p2.x ) && 
					p1.y != p2.y && 
					( p1.x == p2.x || p.x <= ( p.y - p1.y ) * ( p2.x - p1.x ) / ( p2.y - p1.y ) + p1.x ) ) 
				{
					counter++;
				}

				// Assign this point to last
				p1 = p2;
			}

			// Only include triangles which are inside shape
			if ( counter % 2 != 0 ) {

				// Add triangle to list
				Triangle triData( triangle[ 0 ], triangle[ 1 ], triangle[ 2 ], id, (float)delaunay.area( triIt ), p );
				triData.mIndex[0] = a;
				triData.mIndex[1] = b;
				triData.mIndex[2] = c;
				triangles.push_back( triData );

				// Increase default ID
				id++;
			}
		}

		// Return triangles
		return triangles;

	}
Пример #13
0
/* Based on Lloyds Algorithm (Lloyd, S. IEEE, 1982) */	
void
smooth(configInfo *par, struct grid *gp){
  double mindist;	/* Distance to closest neighbor				*/
  int k=0,j,i;		/* counters									*/
  int sg;		/* counter for smoothing the grid			*/
  int cn;
  double move[3];	/* Auxillary array for smoothing the grid	*/
  double dist;		/* Distance to a neighbor					*/
  struct cell *dc=NULL; /* Not used at present. */
  unsigned long numCells;

  for(sg=0;sg<N_SMOOTH_ITERS;sg++){
    delaunay(DIM, gp, (unsigned long)par->ncell, 0, 0, &dc, &numCells);
    distCalc(par, gp);

    for(i=0;i<par->pIntensity;i++){
      mindist=1e30;
      cn=-1;
      for(k=0;k<gp[i].numNeigh;k++){
        if(gp[i].neigh[k]->sink==0){
          if(gp[i].ds[k]<mindist){
            mindist=gp[i].ds[k];
            cn=k;
          }
        }
      }

      if(par->radius-sqrt(gp[i].x[0]*gp[i].x[0] + gp[i].x[1]*gp[i].x[1] + gp[i].x[2]*gp[i].x[2])<mindist) cn=-1;

      if(cn>-1) {
        for(k=0;k<DIM;k++){
          move[k] = gp[i].x[k] - gp[i].dir[cn].x[k]*0.20;
        }			  
        if((move[0]*move[0]+move[1]*move[1]+move[2]*move[2])<par->radiusSqu &&
           (move[0]*move[0]+move[1]*move[1]+move[2]*move[2])>par->minScaleSqu){
          for(k=0;k<DIM;k++) gp[i].x[k]=move[k];
        }
      }
    }
		
    for(i=par->pIntensity;i<par->ncell;i++){
      mindist=1e30;
      cn=-1;
      for(k=0;k<gp[i].numNeigh;k++){
        if(gp[i].neigh[k]->sink==1){
          if(gp[i].ds[k]<mindist){
            mindist=gp[i].ds[k];
            cn=k;
          }
        }
      }
      j=gp[i].neigh[cn]->id;
      for(k=0;k<DIM;k++){
        gp[i].x[k] = gp[i].x[k] - (gp[j].x[k]-gp[i].x[k]) * 0.15;
      }			
      dist=par->radius/sqrt(gp[i].x[0]*gp[i].x[0] + gp[i].x[1]*gp[i].x[1] + gp[i].x[2]*gp[i].x[2]);	
      for(k=0;k<DIM;k++){
        gp[i].x[k] *= dist;
      }	
    }
		
    if(!silent) progressbar((double)(sg+1)/(double)N_SMOOTH_ITERS, 5);	
    free(dc);
  }	
}
Пример #14
0
void TIN::create(const mydefs::Points3d& thePoints3d)
{
	// Set input values for triangulation
	TTriangulationIO in;
	// Number of points
	in.numberofpoints = thePoints3d.size(); 
	// One attribute for Z coordinate
	in.numberofpointattributes = 1; 
	// Allocate memory for array of X and Y coordinates
	in.pointlist = (double *) malloc(in.numberofpoints * 2 * sizeof(double));
	// Allocate memory for array of Z coordinates
	in.pointattributelist = (double *) malloc(in.numberofpoints *
                                          in.numberofpointattributes *
                                          sizeof(double));
	in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
	// Zero segments, holes and regions
	in.numberofsegments = 0;
	in.numberofholes = 0;
	in.numberofregions = 0;

	// Populate arrays of coordinates
	int i = 0;
	for(mydefs::Points3d::const_iterator iter = thePoints3d.begin(); 
		iter != thePoints3d.end(); 
		++iter)
	{
		in.pointlist[2*i] = (*iter)[0];
		in.pointlist[2*i+1] = (*iter)[1];
		in.pointattributelist[i] = (*iter)[2];
		
		if(mMinZ > (*iter)[2])
		{
			mMinZ = (*iter)[2];
		}
		if(mMaxZ < (*iter)[2])
		{
			mMaxZ = (*iter)[2];
		}

		++i;
	}
	
	// Prepare for triangulation
	transfernodes(mMesh, mBehavior, in.pointlist, in.pointattributelist,
			in.pointmarkerlist, in.numberofpoints,
			in.numberofpointattributes);

	// Triangulate points
	mMesh->hullsize = delaunay(mMesh, mBehavior);

	// Necessary maintenance 
	mMesh->infvertex1 = (TVertex) NULL;
	mMesh->infvertex2 = (TVertex) NULL;
	mMesh->infvertex3 = (TVertex) NULL;
	mMesh->edges = (3l * mMesh->triangles.items + mMesh->hullsize) / 2l;

	// Set most recent triangle
	traversalinit(&mMesh->triangles);
	mRecentTri->tri = triangletraverse(mMesh);
	mRecentTri->orient = 0;

	// Free memory
	free(in.pointmarkerlist);
	free(in.pointattributelist);
	free(in.pointlist);
}
Пример #15
0
int main(int argc, char **argv) {

    /*
        We choose to handle simple command line input
    */

    int num_threads(0), box_length(0);

    try {

        if (argc == 5) {

            if (strcmp(argv[1], "-np") == 0 && 
                strcmp(argv[3], "-bl") == 0) {

                sscanf(argv[2], "%d", &num_threads);
                sscanf(argv[4], "%d", &box_length);
            } else
                throw std::runtime_error("Incorrect arugments");
        } else
            throw std::runtime_error("Incorrect number of arguments");

    } catch(std::runtime_error &error) {

        std::cout << error.what() << std::endl;
          std::cout << "Use the form :: ./regulus -np X -bl Y \n";
        return -1;
    }

    /*
        ... And we then build a point set to triangulate...
    */

    unsigned long int num_points = std::pow(box_length, 3);
    std::vector<mesh> meshes;

    {

        std::vector<point> tmp_point_buff;
        tmp_point_buff.reserve(num_points);

        write_sorted_set(tmp_point_buff, num_points, box_length);

        auto m = num_points % num_threads;
        auto ppp = (num_points - m) / num_threads; 

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

            unsigned long int num_per_tetra = 0;

            if (i != num_threads - 1)
                num_per_tetra = ppp;
            else
                num_per_tetra = ppp + m;

            meshes.emplace_back(num_per_tetra);

            /*
                Allocate root points
            */

            auto tl = 3 * (box_length - 1);

            meshes[i].p_buffer.emplace_back(0, 0, 0);
            meshes[i].p_buffer.emplace_back(tl, 0, 0);
            meshes[i].p_buffer.emplace_back(0, tl, 0);
            meshes[i].p_buffer.emplace_back(0, 0, tl);

            meshes[i].p_position += 4;

            /*
                Allocate root tetrahedron
            */

            new(meshes[i].t_position) tetra(&meshes[i].p_buffer[0],
                                            &meshes[i].p_buffer[1],
                                            &meshes[i].p_buffer[2],
                                            &meshes[i].p_buffer[3]);

            meshes[i].m_position = meshes[i].t_position;
            ++meshes[i].t_position;

            /*
                Copy partitioned points
            */

            for (unsigned long int j = 0; j < num_per_tetra; ++j) {

                auto &cpy = tmp_point_buff[i*ppp + j];
                meshes[i].p_buffer.emplace_back(cpy.x, cpy.y, cpy.z);
            }

            if (verbose >= 3) {

                std::cout << "\nthread : " << i << std::endl;

                for (auto it = meshes[i].p_buffer.begin(); it < meshes[i].p_buffer.end(); ++it)
                    std::cout << *it << std::endl;
            }

            std::cout << std::endl;
        }
    }    

    /*
        This is the crux of regulus
        
        We begin the triangulation
    */

    double start_time = get_wall_time();

    std::vector<std::thread> threads;

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

        threads.emplace_back([&meshes, i](void)->void {

            std::vector<std::pair<tetra*, unsigned int>> leaves;
            leaves.reserve(512);

            std::vector<tetra*> pile;
            pile.reserve(2048);

            point *p = meshes[i].p_buffer.data();

            for (unsigned long int j = 5; j < meshes[i].p_buffer.size(); ++j) {

                if (verbose >= 1)
                    std::cout << "\niterative index : " << j - 4 << std::endl;

                walk(leaves, p + j, meshes[i].m_position, &*(meshes[i].t_buffer.begin()));
                fracture(meshes[i], leaves, pile, p + j);
                delaunay(meshes[i], pile);

                leaves.clear();
                pile.clear();
            }
        });
    }

    for (auto &t : threads)
        t.join();

    unsigned long int tot_num_tetra = 0;

    for (auto &m : meshes)
        tot_num_tetra += m.num_tetra;

    double end_time = get_wall_time();

    std::cout << "\nTotal number of tetrahedra triangulated : " << tot_num_tetra << std::endl;
    std::cout<< "\nTriangulated " << num_points << " points in " << end_time - start_time << " seconds" << std::endl;
    std::cout << num_points / ((end_time - start_time) * num_threads) << " points per second per thread" << std::endl;

    return 0;
}