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);
361 void 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);
533 OOFEM_ERROR(
"OOFEM is not compiled with support for triangle.");
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 j = 1; j <= segments [ i ].giveSize(); ++j ) {
547 n_markers [ segments [ i ].at(j) - 1 ].insertSortedOnce( s_markers(i) );
550 for ( std :: size_t i = 0; i < triangles.size(); ++i ) {
551 for (
int j = 1; j <= triangles [ i ].giveSize(); ++j ) {
552 n_markers [ triangles [ i ].at(j) - 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) ) {
void subtract(const FloatArray &src)
Subtracts array src to receiver.
IntArray segment_b
Second segment connection.
void zero()
Sets all component to zero.
double & at(int i)
Coefficient access function.
static void simplifyPSLG(Triangle_PSLG &coarse, const Triangle_PSLG &pslg, double limit, double minlen=0.0)
Simplifies a PSLG while respecting topology, running in linear time.
bool meshPSLG(const Triangle_PSLG &pslg, const IntArray &outside, const IntArray &inside, std::vector< FloatArray > &nodes, std::vector< IntArray > &n_markers, std::vector< IntArray > &triangles, IntArray &t_markers, std::vector< IntArray > &segments, IntArray &s_markers) const
Constructs a mesh from a PSLG.
const int * givePointer() const
Breaks encapsulation.
Class implementing an array of integers.
int & at(int i)
Coefficient access function.
FloatArray ny
Nodes y coordinates.
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)
Adds all neighboring regions to every node region.
Plane straight line graph used as input for meshing with triangle.
void resize(int n)
Checks size of receiver towards requested bounds.
Class representing vector of real numbers.
double computeNorm() const
Computes the norm (or length) of the vector.
void times(double s)
Multiplies receiver with scalar.
int giveSize() const
Returns the size of receiver.
FloatArray nx
Nodes x coordinates.
the oofem namespace is to define a context or scope in which all oofem names are defined.
IntArray segment_a
First segment connection.
int findFirstIndexOf(int value) const
Finds index of first occurrence of given value in array.
IntArray segment_marker
Segment markers.
void resize(int s)
Resizes receiver towards requested size.