43#ifdef __TRIANGLE_MODULE
48 void parsecommandline(
int argc,
char **argv,
struct behavior *b);
49 void transfernodes(
struct mesh *m,
struct behavior *b, REAL *pointlist, REAL *pointattriblist,
int *pointmarkerlist,
int numberofpoints,
int numberofpointattribs);
50 void formskeleton(
struct mesh *m,
struct behavior *b,
int *segmentlist,
int *segmentmarkerlist,
int numberofsegments);
51 void highorder(
struct mesh *m,
struct behavior *b);
52 void numbernodes(
struct mesh *m,
struct behavior *b);
53 void writeelements(
struct mesh *m,
struct behavior *b,
int **trianglelist, REAL **triangleattriblist);
54 void writepoly(
struct mesh *m,
struct behavior *b,
int **segmentlist,
int **segmentmarkerlist);
55 void writeedges(
struct mesh *m,
struct behavior *b,
int **edgelist,
int **edgemarkerlist);
56 void statistics(
struct mesh *m,
struct behavior *b);
57 void writenodes(
struct mesh *m,
struct behavior *b, REAL **pointlist, REAL **pointattriblist,
int **pointmarkerlist);
58 void checkmesh(
struct mesh *m,
struct behavior *b);
59 void checkdelaunay(
struct mesh *m,
struct behavior *b);
60 void writeneighbors(
struct mesh *m,
struct behavior *b,
int **neighborlist);
61 void writevoronoi(
struct mesh *m,
struct behavior *b, REAL **vpointlist, REAL **vpointattriblist,
int **vpointmarkerlist,
int **vedgelist,
int **vedgemarkerlist, REAL **vnormlist);
62 int reconstruct(
struct mesh *m,
struct behavior *b,
int *trianglelist, REAL *triangleattriblist, REAL *trianglearealist,
int elements,
int corners,
int attribs,
int *segmentlist,
int *segmentmarkerlist,
int numberofsegments);
63 subseg *subsegtraverse(
struct mesh *m);
64 void regionplague(
struct mesh *m,
struct behavior *b, REAL attribute, REAL area);
65 void plague(
struct mesh *m,
struct behavior *b);
66 void poolinit(
struct memorypool *pool,
int bytecount,
int itemcount,
int firstitemcount,
int alignment);
67 void pooldeinit(
struct memorypool *pool);
70 #define setelemattribute(otri, attnum, value) \
71 ( ( REAL * ) ( otri ).tri ) [ m->elemattribindex + ( attnum ) ] = value
72 #define elemattribute(otri, attnum) \
73 ( ( REAL * ) ( otri ).tri ) [ m->elemattribindex + ( attnum ) ]
75 #define stpivot(osub, otri) \
76 ptr = ( triangle ) ( osub ).ss [ 6 + ( osub ).ssorient ]; \
78 #define ssymself(osub) \
79 ( osub ).ssorient = 1 - ( osub ).ssorient
80 #define mark(osub) ( * ( int * ) ( ( osub ).ss + 8 ) )
81 #define decode(ptr, otri) \
82 ( otri ).orient = ( int ) ( ( long ) ptr & ( long ) 3l ); \
83 ( otri ).tri = ( triangle * ) ( ( long ) ( ptr ) ^ ( long ) ( otri ).orient )
84 #define infect(otri) \
85 ( otri ).tri [ 6 ] = ( triangle ) ( ( long ) ( otri ).tri [ 6 ] | ( long ) 2l )
86 #define org(otri, vertexptr) \
87 vertexptr = ( vertex ) ( otri ).tri [ plus1mod3 [ ( otri ).orient ] + 3 ]
88 #define dest(otri, vertexptr) \
89 vertexptr = ( vertex ) ( otri ).tri [ minus1mod3 [ ( otri ).orient ] + 3 ]
90 #define apex(otri, vertexptr) \
91 vertexptr = ( vertex ) ( otri ).tri [ ( otri ).orient + 3 ]
92 #define sorg(osub, vertexptr) \
93 vertexptr = ( vertex ) ( osub ).ss [ 2 + ( osub ).ssorient ]
94 #define sdest(osub, vertexptr) \
95 vertexptr = ( vertex ) ( osub ).ss [ 3 - ( osub ).ssorient ]
98 #define VIRUSPERBLOCK 1020
102 int custom_carveholes(
struct mesh *m,
struct behavior *b,
const int *outside,
const int *inside)
104 struct otri neighbortri;
105 struct otri triangleloop;
106 struct osub subsegloop;
111 double triangle_attribute;
114 poolinit(& m->viri,
sizeof( triangle * ), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
117 traversalinit(& m->triangles);
118 triangleloop.orient = 0;
119 triangleloop.tri = triangletraverse(m);
120 while ( triangleloop.tri != ( triangle * ) NULL ) {
121 setelemattribute(triangleloop, m->eextras, -1.0);
122 triangleloop.tri = triangletraverse(m);
128 traversalinit(& m->subsegs);
129 subsegloop.ss = subsegtraverse(m);
130 subsegloop.ssorient = 0;
131 while ( subsegloop.ss != ( subseg * ) NULL ) {
132 if ( subsegloop.ss != m->dummysub ) {
134 ssymself(subsegloop);
135 stpivot(subsegloop, neighbortri);
136 if ( neighbortri.tri != m->dummytri ) {
138 attribute = outside [ mark(subsegloop) - 1 ];
139 triangle_attribute = elemattribute(neighbortri, m->eextras);
142 if ( triangle_attribute < 0 && attribute >= 0 ) {
144 temptri = ( triangle ** ) poolalloc(& m->viri);
145 * temptri = neighbortri.tri;
147 regionplague(m, b, attribute, area);
149 }
else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) {
152 org(neighbortri, v1);
153 dest(neighbortri, v2);
154 apex(neighbortri, v3);
155 fprintf(stdout,
"Error: inconsistent region information (new %d, old %d from %d) (outside) at (%e, %e)\n",
156 (
int ) attribute, (
int ) triangle_attribute, (
int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3);
162 ssymself(subsegloop);
163 stpivot(subsegloop, neighbortri);
164 if ( neighbortri.tri != m->dummytri ) {
166 attribute = inside [ mark(subsegloop) - 1 ];
167 triangle_attribute = elemattribute(neighbortri, m->eextras);
169 if ( triangle_attribute < 0 && attribute >= 0 ) {
171 temptri = ( triangle ** ) poolalloc(& m->viri);
172 * temptri = neighbortri.tri;
173 regionplague(m, b, attribute, area);
174 }
else if ( attribute >= 0 && triangle_attribute >= 0 && attribute != triangle_attribute ) {
176 org(neighbortri, v1);
177 dest(neighbortri, v2);
178 apex(neighbortri, v3);
179 fprintf(stdout,
"Error: inconsistent region information (new %d, old %d from %d) (inside) at (%e, %e)\n",
180 (
int ) attribute, (
int ) triangle_attribute, (
int ) mark(subsegloop), ( v1 [ 0 ] + v2 [ 0 ] + v3 [ 0 ] ) / 3, ( v1 [ 1 ] + v2 [ 1 ] + v3 [ 1 ] ) / 3);
185 subsegloop.ss = subsegtraverse(m);
190 traversalinit(& m->triangles);
191 triangleloop.tri = triangletraverse(m);
192 int triangle_number = 0;
193 while ( triangleloop.tri != ( triangle * ) NULL ) {
194 if ( triangleloop.tri != m->dummytri ) {
196 attribute = elemattribute(triangleloop, m->eextras);
197 if ( attribute == -1.0 ) {
198 fprintf(stderr,
"Broken mesh at triangle %d\n", triangle_number);
200 }
else if ( attribute == 0.0 ) {
201 infect(triangleloop);
202 temptri = ( triangle ** ) poolalloc(& m->viri);
203 * temptri = triangleloop.tri;
206 triangleloop.tri = triangletraverse(m);
211 if ( b->regionattrib && !b->refine ) {
217 pooldeinit(& m->viri);
223 void custom_triangulate(
char *triswitches,
struct triangulateio *in,
struct triangulateio *out,
struct triangulateio *vorout,
const int *outside,
const int *inside)
230 parsecommandline(1, & triswitches, & b);
232 m.steinerleft = b.steiner;
233 transfernodes(& m, & b, in->pointlist, in->pointattributelist,
234 in->pointmarkerlist, in->numberofpoints,
235 in->numberofpointattributes);
237 m.hullsize = reconstruct(& m, & b, in->trianglelist,
238 in->triangleattributelist, in->trianglearealist,
239 in->numberoftriangles, in->numberofcorners,
240 in->numberoftriangleattributes,
241 in->segmentlist, in->segmentmarkerlist,
242 in->numberofsegments);
244 m.hullsize = delaunay(& m, & b);
246 m.infvertex1 = ( vertex ) NULL;
247 m.infvertex2 = ( vertex ) NULL;
248 m.infvertex3 = ( vertex ) NULL;
249 if ( b.usesegments ) {
252 formskeleton(& m, & b, in->segmentlist,
253 in->segmentmarkerlist, in->numberofsegments);
257 struct osub subsegloop;
258 traversalinit(& m.subsegs);
259 subsegloop.ss = subsegtraverse(& m);
260 subsegloop.ssorient = 0;
261 while ( subsegloop.ss != ( subseg * ) NULL ) {
262 if ( subsegloop.ss != m.dummysub ) {
264 sorg(subsegloop, p1);
265 sdest(subsegloop, p2);
266 printf(
" Connected (%f,%f) to (%f,%f)\n", p1 [ 0 ], p1 [ 1 ], p2 [ 0 ], p2 [ 1 ]);
267 subsegloop.ss = subsegtraverse(& m);
271 if ( b.poly && ( m.triangles.items > 0 ) ) {
273 m.holes = in->numberofholes;
275 m.regions = in->numberofregions;
278 int sane = custom_carveholes(& m, & b, outside, inside);
281 printf(
"Probably bad PSLG\n");
289 if ( b.quality && ( m.triangles.items > 0 ) ) {
290 enforcequality(& m, & b);
292 m.edges = ( 3l * m.triangles.items + m.hullsize ) / 2l;
300 out->numberofpoints = m.vertices.items - m.undeads;
302 out->numberofpoints = m.vertices.items;
304 out->numberofpointattributes = m.nextras;
305 out->numberoftriangles = m.triangles.items;
306 out->numberofcorners = ( b.order + 1 ) * ( b.order + 2 ) / 2;
307 out->numberoftriangleattributes = m.eextras;
308 out->numberofedges = m.edges;
309 if ( b.usesegments ) {
310 out->numberofsegments = m.subsegs.items;
312 out->numberofsegments = m.hullsize;
314 if ( vorout != (
struct triangulateio * ) NULL ) {
315 vorout->numberofpoints = m.triangles.items;
316 vorout->numberofpointattributes = m.nextras;
317 vorout->numberofedges = m.edges;
319 if ( b.nonodewritten || ( b.noiterationnum && m.readnodefile ) ) {
321 printf(
"NOT writing vertices.\n");
323 numbernodes(& m, & b);
325 writenodes(& m, & b, & out->pointlist, & out->pointattributelist,
326 & out->pointmarkerlist);
330 writeelements(& m, & b, & out->trianglelist, & out->triangleattributelist);
332 if ( b.poly || b.convex ) {
333 writepoly(& m, & b, & out->segmentlist, & out->segmentmarkerlist);
334 out->numberofholes = m.holes;
335 out->numberofregions = m.regions;
337 out->holelist = in->holelist;
338 out->regionlist = in->regionlist;
340 out->holelist = ( REAL * ) NULL;
341 out->regionlist = ( REAL * ) NULL;
345 writeedges(& m, & b, & out->edgelist, & out->edgemarkerlist);
349 writeneighbors(& m, & b, & out->neighborlist);
354 checkdelaunay(& m, & b);
356 triangledeinit(& m, & b);
361void clearTriangulateIO(
struct triangulateio &t)
364 t.pointattributelist = NULL;
365 t.pointmarkerlist = NULL;
366 t.numberofpoints = 0;
367 t.numberofpointattributes = 0;
369 t.trianglelist = NULL;
370 t.triangleattributelist = NULL;
371 t.trianglearealist = NULL;
372 t.numberoftriangles = 0;
373 t.numberofcorners = 0;
374 t.numberoftriangleattributes = 0;
376 t.segmentlist = NULL;
377 t.segmentmarkerlist = NULL;
378 t.numberofsegments = 0;
384 t.numberofregions = 0;
391 std :: vector< FloatArray > &nodes, std :: vector< IntArray > &n_markers,
392 std :: vector< IntArray > &triangles,
IntArray &t_markers,
393 std :: vector< IntArray > &segments,
IntArray &s_markers)
const
395#ifdef __TRIANGLE_MODULE
397 struct triangulateio mesh;
398 clearTriangulateIO(mesh);
402 mesh.pointlist =
new REAL [ mesh.numberofpoints * 2 ];
404 for (
int i = 0; i < mesh.numberofpoints; ++i ) {
405 mesh.pointlist [ i * 2 ] = pslg.
nx(i);
406 mesh.pointlist [ i * 2 + 1 ] = pslg.
ny(i);
411 printf(
"Copying segment data\n");
413 mesh.segmentlist =
new int [ mesh.numberofsegments * 2 ];
414 for (
int i = 0; i < mesh.numberofsegments; ++i ) {
415 mesh.segmentlist [ i * 2 ] = pslg.
segment_a(i);
416 mesh.segmentlist [ i * 2 + 1 ] = pslg.
segment_b(i);
420 mesh.segmentmarkerlist =
new int [ mesh.numberofsegments ];
421 for (
int i = 0; i < mesh.numberofsegments; ++i ) {
427 char options [ 100 ];
430 struct triangulateio output;
431 clearTriangulateIO(output);
435 nodes.resize(output.numberofpoints);
437 for (
int i = 0; i < output.numberofpoints; ++i ) {
438 nodes [ i ].resize(2);
439 nodes [ i ].at(1) = output.pointlist [ i * 2 ];
440 nodes [ i ].at(2) = output.pointlist [ i * 2 + 1 ];
444 triangles.resize(output.numberoftriangles);
445 t_markers.
resize(output.numberoftriangles);
446 for (
int i = 0; i < output.numberoftriangles; ++i ) {
447 IntArray &triangle = triangles [ i ];
448 triangle.
resize(output.numberofcorners);
449 for (
int j = 0; j < 3; j++ ) {
450 triangle(j) = output.trianglelist [ i * output.numberofcorners + j ];
453 if ( output.numberofcorners == 6 ) {
454 triangle(3) = output.trianglelist [ i * output.numberofcorners + 5 ];
455 triangle(4) = output.trianglelist [ i * output.numberofcorners + 3 ];
456 triangle(5) = output.trianglelist [ i * output.numberofcorners + 4 ];
458 t_markers.
at(i + 1) = ( int ) round(output.triangleattributelist [ i ]);
462 std :: set< std :: size_t > *node_triangle = NULL;
464 node_triangle =
new std :: set< std :: size_t > [ output.numberofpoints ];
465 for ( std :: size_t i = 0; i < triangles.size(); ++i ) {
466 IntArray &triangle = triangles [ i ];
467 for (
int j = 1; j <= 3; ++j ) {
468 node_triangle [ triangle.
at(j) - 1 ].insert(i);
473 segments.resize(output.numberofsegments);
474 s_markers.
resize(output.numberofsegments);
475 for (
int i = 0; i < output.numberofsegments; ++i ) {
478 segment.
at(1) = output.segmentlist [ i * 2 + 0 ];
479 segment.
at(2) = output.segmentlist [ i * 2 + 1 ];
483 std :: set< std :: size_t >tris = node_triangle [ segment.
at(1) - 1 ];
485 for (
auto tri: tris ) {
486 IntArray &triangle = triangles [ tri ];
491 }
else if ( a + b == 5 ) {
496 segment.
at(3) = triangle.
at(c);
501 s_markers.
at(i + 1) = output.segmentmarkerlist [ i ];
504 delete[] node_triangle;
507 this->
fixNodeMarkers(nodes, n_markers, triangles, t_markers, segments, s_markers);
510 delete[] mesh.pointlist;
516 delete[] mesh.segmentlist;
517 delete[] mesh.segmentmarkerlist;
522 free(output.pointlist);
524 free(output.pointmarkerlist);
525 free(output.trianglelist);
526 free(output.triangleattributelist);
528 free(output.segmentlist);
529 free(output.segmentmarkerlist);
534 OOFEM_ERROR(
"OOFEM is not compiled with support for triangle.");
539void TriangleMesherInterface :: fixNodeMarkers(
const std :: vector< FloatArray > &nodes, std :: vector< IntArray > &n_markers,
540 const std :: vector< IntArray > &triangles,
const IntArray &t_markers,
541 const std :: vector< IntArray > &segments,
const IntArray &s_markers)
543 n_markers.resize( nodes.size() );
545 for ( std :: size_t i = 0; i < segments.size(); ++i ) {
546 for (
int segment : segments [ i ] ) {
547 n_markers [ segment - 1 ].insertSortedOnce( s_markers[i] );
550 for ( std :: size_t i = 0; i < triangles.size(); ++i ) {
551 for (
int triangle : triangles [ i ] ) {
552 n_markers [ triangle - 1 ].insertSortedOnce( t_markers[i] );
563 std :: set< int > *connectivity =
new std :: set< int > [ nodes ];
564 for (
int i = 0; i < segments; i++ ) {
565 connectivity [ pslg.
segment_a[i] - 1 ].insert(i + 1);
566 connectivity [ pslg.
segment_b[i] - 1 ].insert(i + 1);
577 FloatArray error_x(nodes), error_y(nodes), ab(2), ac(2), bc(2), err_vec(2);
581 for (
int j = 0; j < 2; ++j ) {
582 double allowed = j * limit / 2;
583 for (
int i = 1; i <= nodes; i++ ) {
584 std :: set< int > &elems = connectivity [ i - 1 ];
586 if ( elems.size() < 2 ) {
588 nodeRemoval.
at(i) =
true;
589 if ( elems.size() == 1 ) {
590 int e0 = * elems.begin();
591 edgeRemoval.
at(e0) =
true;
593 int n1 = seg_a.
at(e0) == i ? seg_b.
at(e0) : seg_a.
at(e0);
594 connectivity [ n1 - 1 ].erase(e0);
613 if ( elems.size() == 2 ) {
614 int e0 = * elems.begin();
615 int e1 = * ( ++elems.begin() );
620 n0 = seg_a.
at(e0) == i ? seg_b.
at(e0) : seg_a.
at(e0);
622 n2 = seg_a.
at(e1) == i ? seg_b.
at(e1) : seg_a.
at(e1);
624 ab[0] = pslg.
nx.
at(n1) - pslg.
nx.
at(n0);
625 ab[1] = pslg.
ny.
at(n1) - pslg.
ny.
at(n0);
626 ac[0] = pslg.
nx.
at(n2) - pslg.
nx.
at(n0);
627 ac[1] = pslg.
ny.
at(n2) - pslg.
ny.
at(n0);
629 abac = ab.dotProduct(ac);
630 acac = ac.computeSquaredNorm();
633 if ( abac <= 0 || acac == 0 ) {
636 }
else if ( abac >= acac ) {
637 err_vec[0] = pslg.
nx.
at(n2) - pslg.
nx.
at(n1);
638 err_vec[1] = pslg.
ny.
at(n2) - pslg.
ny.
at(n1);
641 err_vec.
times(abac / acac);
647 double real_error = 0.0;
648 if ( ev_norm == 0 ) {
651 error_x.at(n1) += err_vec[0];
652 error_y.
at(n1) += err_vec[1];
653 real_error = sqrt( error_x.at(n1) * error_x.at(n1) + error_y.at(n1) * error_y.at(n1) );
656 if ( real_error <= allowed ) {
658 nodeRemoval.
at(i) =
true;
659 edgeRemoval.
at(e1) =
true;
660 connectivity [ n2 - 1 ].erase(e1);
661 connectivity [ n2 - 1 ].insert(e0);
662 if ( seg_a.
at(e0) == n1 ) {
669 error_x.at(n0) += error_x.at(n1);
670 error_y.at(n0) += error_y.at(n1);
671 error_x.at(n2) += error_x.at(n1);
672 error_y.at(n2) += error_y.at(n1);
680 bool edgeRemoved =
true;
681 while ( edgeRemoved ) {
683 for (
int i = 1; i <= nodes; i++ ) {
684 std :: set< int > &elems = connectivity [ i - 1 ];
685 if ( elems.size() == 2 ) {
686 int e0 = * elems.begin();
687 int e1 = * ( ++elems.begin() );
691 n0 = seg_a.
at(e0) == i ? seg_b.
at(e0) : seg_a.
at(e0);
693 n2 = seg_a.
at(e1) == i ? seg_b.
at(e1) : seg_a.
at(e1);
695 ab[0] = pslg.
nx.
at(n1) - pslg.
nx.
at(n0);
696 ab[1] = pslg.
ny.
at(n1) - pslg.
ny.
at(n0);
697 bc[0] = pslg.
nx.
at(n2) - pslg.
nx.
at(n1);
698 bc[1] = pslg.
ny.
at(n2) - pslg.
ny.
at(n1);
700 if ( ab.computeSquaredNorm() < minlen * minlen || bc.computeSquaredNorm() < minlen * minlen ) {
702 nodeRemoval.
at(i) =
true;
703 edgeRemoval.
at(e1) =
true;
704 connectivity [ n2 - 1 ].erase(e1);
705 connectivity [ n2 - 1 ].insert(e0);
706 if ( seg_a.
at(e0) == n1 ) {
721 for (
int i = 1; i <= nodes; i++ ) {
722 std :: set< int > &elems = connectivity [ i - 1 ];
723 if ( elems.size() == 2 ) {
724 int e0 = * elems.begin();
725 int e1 = * ( ++elems.begin() );
726 int n0 = seg_a.
at(e0) == i ? seg_b.
at(e0) : seg_a.
at(e0);
728 int n2 = seg_a.
at(e1) == i ? seg_b.
at(e1) : seg_a.
at(e1);
732 nodeRemoval.
at(n1) =
true;
733 edgeRemoval.
at(e0) =
true;
734 edgeRemoval.
at(e1) =
true;
735 connectivity [ n1 - 1 ].erase(e0);
736 connectivity [ n1 - 1 ].erase(e1);
737 connectivity [ n2 - 1 ].erase(e0);
738 connectivity [ n2 - 1 ].erase(e1);
739 if ( connectivity [ n1 - 1 ].size() == 0 ) {
740 nodeRemoval.
at(n2) =
true;
746 delete[] connectivity;
754 for (
int i = 1; i <= nodes; i++ ) {
755 if ( !nodeRemoval.
at(i) ) {
757 coarse.
nx.
at(newNodes) = pslg.
nx.
at(i);
758 coarse.
ny.
at(newNodes) = pslg.
ny.
at(i);
759 newNumber.
at(i) = newNodes;
770 for (
int i = 1; i <= segments; i++ ) {
771 if ( !edgeRemoval.
at(i) ) {
double computeNorm() const
Index giveSize() const
Returns the size of receiver.
void subtract(const FloatArray &src)
const int * givePointer() const
void zero()
Sets all component to zero.
int findFirstIndexOf(int value) const
static void fixNodeMarkers(const std ::vector< FloatArray > &nodes, std ::vector< IntArray > &n_markers, const std ::vector< IntArray > &triangles, const IntArray &t_markers, const std ::vector< IntArray > &segments, const IntArray &s_markers)
IntArray segment_b
Second segment connection.
IntArray segment_marker
Segment markers.
IntArray segment_a
First segment connection.
FloatArray ny
Nodes y coordinates.
FloatArray nx
Nodes x coordinates.