// 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); }
TriangleIterator::TriangleIterator(const TIN * theTIN) : mTIN( const_cast<TIN *>(theTIN) ) { traversalinit( &(theTIN->mMesh->triangles) ); mCurrentTriangle.tri = triangletraverse( theTIN->mMesh ); mCurrentTriangle.orient = 0; }
// This customized version carves holes defined by the regions. // It'll remove any element which doesn't receive any region. int custom_carveholes(struct mesh *m, struct behavior *b, const int *outside, const int *inside) { struct otri neighbortri; struct otri triangleloop; struct osub subsegloop; triangle **temptri; triangle ptr; /* Temporary variable used by sym(). */ double area; double attribute; double triangle_attribute; int sane_mesh; poolinit(& m->viri, sizeof( triangle * ), VIRUSPERBLOCK, VIRUSPERBLOCK, 0); /* Assigns every triangle a regional attribute of -1 */ traversalinit(& m->triangles); triangleloop.orient = 0; triangleloop.tri = triangletraverse(m); while ( triangleloop.tri != ( triangle * ) NULL ) { setelemattribute(triangleloop, m->eextras, -1.0); triangleloop.tri = triangletraverse(m); } sane_mesh = 1; /* Loop over all segments */ traversalinit(& m->subsegs); subsegloop.ss = subsegtraverse(m); subsegloop.ssorient = 0; while ( subsegloop.ss != ( subseg * ) NULL ) { if ( subsegloop.ss != m->dummysub ) { /* First neighbor. */ ssymself(subsegloop); stpivot(subsegloop, neighbortri); if ( neighbortri.tri != m->dummytri ) { area = 0.0; /// @todo Possible set this as the minimum as well. attribute = outside [ mark(subsegloop) - 1 ]; triangle_attribute = elemattribute(neighbortri, m->eextras); /* The region no number yet. */ if ( triangle_attribute < 0 && attribute >= 0 ) { infect(neighbortri); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = neighbortri.tri; /* Apply one region's attribute and/or area constraint. */ regionplague(m, b, attribute, area); /* The virus pool should be empty now. */ } else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) { /* Check for problems. */ vertex v1, v2, v3; org(neighbortri, v1); dest(neighbortri, v2); apex(neighbortri, v3); fprintf(stdout, "Error: inconsistent region information (new %d, old %d from %d) (outside) at (%e, %e)\n", ( int ) attribute, ( int ) triangle_attribute, ( int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3); sane_mesh = 0; } } /* Second neighbor (same procedure). */ ssymself(subsegloop); stpivot(subsegloop, neighbortri); if ( neighbortri.tri != m->dummytri ) { area = 0.0; attribute = inside [ mark(subsegloop) - 1 ]; triangle_attribute = elemattribute(neighbortri, m->eextras); if ( triangle_attribute < 0 && attribute >= 0 ) { infect(neighbortri); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = neighbortri.tri; regionplague(m, b, attribute, area); } else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) { vertex v1, v2, v3; org(neighbortri, v1); dest(neighbortri, v2); apex(neighbortri, v3); fprintf(stdout, "Error: inconsistent region information (new %d, old %d from %d) (inside) at (%e, %e)\n", ( int ) attribute, ( int ) triangle_attribute, ( int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3); sane_mesh = 0; } } subsegloop.ss = subsegtraverse(m); } } /* Remove all triangles with marker 0.0 */ traversalinit(& m->triangles); triangleloop.tri = triangletraverse(m); int triangle_number = 0; while ( triangleloop.tri != ( triangle * ) NULL ) { if ( triangleloop.tri != m->dummytri ) { triangle_number++; attribute = elemattribute(triangleloop, m->eextras); if ( attribute == -1.0 ) { fprintf(stderr, "Broken mesh at triangle %d\n", triangle_number); sane_mesh = 0; } else if ( attribute == 0.0 ) { infect(triangleloop); temptri = ( triangle ** ) poolalloc(& m->viri); * temptri = triangleloop.tri; } } triangleloop.tri = triangletraverse(m); } /* Remove the marked elements */ plague(m, b); if ( b->regionattrib && !b->refine ) { /* Note the fact that each triangle has an additional attribute. */ m->eextras++; } /* Free up memory. */ pooldeinit(& m->viri); return sane_mesh; }
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); }