31 template<
class Po
intField>
32 Foam::scalar Foam::polygonTriangulate::area
43 return (ao ^ ab) & normal;
47 template<
class Po
intField>
48 Foam::scalar Foam::polygonTriangulate::quality
55 const scalar An = area(triPoints,
points, normal);
58 forAll(triPoints, triEdgei)
61 const point& p1 =
points[triPoints[(triEdgei + 1) % 3]];
65 static const scalar equilateralAnByPSqr =
sqrt(scalar(3))/12;
67 return PSqr != 0 ? An/PSqr/equilateralAnByPSqr : 0;
71 template<
class Po
intField>
72 bool Foam::polygonTriangulate::intersection
74 const edge& edgePointsA,
75 const edge& edgePointsB,
81 const vector tau1 = normal ^ tau0;
88 const point2D point2DA0(tau0 & pointA0, tau1 & pointA0);
89 const point2D point2DA1(tau0 & pointA1, tau1 & pointA1);
90 const point2D point2DB0(tau0 & pointB0, tau1 & pointB0);
91 const point2D point2DB1(tau0 & pointB1, tau1 & pointB1);
94 tensor2D(point2DA0 - point2DA1, point2DB1 - point2DB0).T();
96 const scalar detM =
det(
M);
99 const vector2D magDetMTu =
sign(detM)*detMInvM & (point2DA0 - point2DB0);
105 template<
class Po
intField>
108 const edge& edgePoints,
129 template<
class Po
intField>
130 Foam::scalar Foam::polygonTriangulate::angle
141 const vector oaNegNNOa = oa - normal*(normal & oa);
142 const vector obNegNNOb = ob - normal*(normal & ob);
145 atan2(normal & (oaNegNNOa ^ obNegNNOb), - oaNegNNOa & obNegNNOb)
150 template<
class Po
intField>
151 bool Foam::polygonTriangulate::ear
164 const scalar detA =
det(
A);
175 if (detAY.
x() > 0 && detAY.
y() > 0 && detAY.
x() + detAY.
y() < detA)
208 bool incomplete =
true;
213 for (
label piA0 = 0; piA0 <
n; ++ piA0)
217 for (
label piB0 = piA0 + 2; piB0 < (piA0 == 0 ?
n - 1 :
n); ++ piB0)
225 edge(pointis[piA0], pointis[piA1]),
226 edge(pointis[piB0], pointis[piB1]),
237 if (incomplete)
break;
240 if (incomplete)
break;
262 template<
class Po
intField>
263 void Foam::polygonTriangulate::optimiseTriangulation
273 const triFace& t = triPoints[trii];
274 const scalar q = quality(t,
points, normal);
276 forAll(triEdges[trii], triEdgei)
278 const label edgei = triEdges[trii][triEdgei];
280 const label otherTrii = edgeTris[edgei][edgeTris[edgei][0] == trii];
282 if (otherTrii == -1)
continue;
284 const label otherTriEdgei =
findIndex(triEdges[otherTrii], edgei);
286 const triFace& otherT = triPoints[otherTrii];
287 const scalar otherQ = quality(otherT,
points, normal);
289 const label piA = triPoints[trii][(triEdgei + 1) % 3];
290 const label piB = triPoints[trii][(triEdgei + 2) % 3];
291 const label piC = triPoints[otherTrii][(otherTriEdgei + 1) % 3];
292 const label piD = triPoints[otherTrii][(otherTriEdgei + 2) % 3];
294 const triFace flipT0(piA, piB, piD);
295 const triFace flipT1(piC, piD, piB);
299 triPointsSet_.found(flipT0)
300 || triPointsSet_.found(flipT1)
303 const scalar flipQ0 = quality(flipT0,
points, normal);
304 const scalar flipQ1 = quality(flipT1,
points, normal);
306 if (
min(q, otherQ) <
min(flipQ0, flipQ1))
308 triPointsSet_.set(t);
309 triPointsSet_.set(otherT);
311 const label eiA = triEdges[trii][(triEdgei + 1) % 3];
312 const label eiB = triEdges[trii][(triEdgei + 2) % 3];
313 const label eiC = triEdges[otherTrii][(otherTriEdgei + 1) % 3];
314 const label eiD = triEdges[otherTrii][(otherTriEdgei + 2) % 3];
316 triPoints[trii] = {piA, piB, piD};
317 triEdges[trii] = {eiA, edgei, eiD};
318 edgeTris[eiD][edgeTris[eiD][0] != otherTrii] = trii;
320 triPoints[otherTrii] = {piC, piD, piB};
321 triEdges[otherTrii] = {eiC, edgei, eiB};
322 edgeTris[eiB][edgeTris[eiB][0] != trii] = otherTrii;
324 optimiseTriangulation
333 optimiseTriangulation
349 void Foam::polygonTriangulate::simpleTriangulate
351 const UList<point>& allPoints,
353 UList<triFace>& triPoints,
354 UList<FixedList<label, 3>>& triEdges,
355 UList<labelPair>& edgeTris,
360 const label n = allPoints.size();
363 triPoints =
triFace(-1, -1, -1);
364 triEdges = FixedList<label, 3>({-1, -1, -1});
376 angle_[i] = angle(i, allPoints, normal);
377 ear_[i] = ear(i, allPoints, normal);
381 UIndirectList<point>
points(allPoints, pointis_);
387 scalar minEarAngle = vGreat;
388 label minEarAnglei = -1;
389 for (
label i = 0; i < pointis_.size(); ++ i)
391 if (ear_[i] && minEarAngle > angle_[i])
393 minEarAngle = angle_[i];
400 if (minEarAnglei == -1)
402 minEarAnglei =
findMin(angle_);
406 label minEarAnglei0 = pointis_.rcIndex(minEarAnglei);
407 label minEarAnglei1 = pointis_.fcIndex(minEarAnglei);
412 pointis_[minEarAnglei0],
413 pointis_[minEarAnglei],
414 pointis_[minEarAnglei1]
416 triEdges[trii] = FixedList<label, 3>
418 edges_[minEarAnglei0],
419 edges_[minEarAnglei],
420 trii == triPoints.size() - 1 ? edges_[minEarAnglei1] :
n + trii
422 forAll(triEdges[trii], triEdgei)
424 const label edgei = triEdges[trii][triEdgei];
425 edgeTris[edgei][edgeTris[edgei][0] != -1] = trii;
429 edges_[minEarAnglei0] = triEdges[trii][2];
430 for (
label i = minEarAnglei; i < pointis_.size() - 1; ++ i)
432 pointis_[i] = pointis_[i + 1];
433 edges_[i] = edges_[i + 1];
434 angle_[i] = angle_[i + 1];
435 ear_[i] = ear_[i + 1];
437 pointis_.resize(pointis_.size() - 1);
438 edges_.resize(edges_.size() - 1);
439 angle_.resize(angle_.size() - 1);
440 ear_.resize(ear_.size() - 1);
443 if (minEarAnglei0 > minEarAnglei) -- minEarAnglei0;
444 angle_[minEarAnglei0] = angle(minEarAnglei0,
points, normal);
445 ear_[minEarAnglei0] = ear(minEarAnglei0,
points, normal);
446 if (minEarAnglei1 > minEarAnglei) -- minEarAnglei1;
447 angle_[minEarAnglei1] = angle(minEarAnglei1,
points, normal);
448 ear_[minEarAnglei1] = ear(minEarAnglei1,
points, normal);
453 triPointsSet_.clear();
454 optimiseTriangulation
468 void Foam::polygonTriangulate::partitionTriangulate
470 const UList<point>&
points,
472 const label spanPointi,
473 const label spanEdgei,
474 UList<triFace>& triPoints,
475 UList<FixedList<label, 3>>& triEdges,
476 UList<labelPair>& edgeTris,
485 const label piA = (spanEdgei + 1) %
n;
486 const label piP = spanPointi;
487 const label piB = spanEdgei;
491 const label nA = (piP - piA +
n) %
n + 1;
492 const label nB = (piB - piP +
n) %
n + 1;
495 const label eiA = nA >= 3 ?
n : piA;
496 const label eiB = nB >= 3 ?
n + (nA >= 3) : piP;
497 const label eiE = piB;
500 triPoints[0] =
triFace(piA, piP, piB);
501 triEdges[0] = FixedList<label, 3>({eiA, eiB, eiE});
511 SubList<triFace> triPointsA(triPoints, nA - 2, 1);
512 SubList<FixedList<label, 3>> triEdgesA(triEdges, nA - 2, 1);
513 SubList<labelPair> edgeTrisA(edgeTris, 2*nA - 3);
516 SubList<point>(
points, nA),
528 forAll(triPointsA[triAi], triPointAi)
530 label& pointi = triPointsA[triAi][triPointAi];
531 pointi = (pointi + piA) %
n;
538 forAll(triEdgesA[triAi], triEdgeAi)
540 label& edgei = triEdgesA[triAi][triEdgeAi];
542 edgei >= nA ?
max(eiA, eiB) + edgei - nA + 1
543 : edgei == nA - 1 ? eiA
551 forAll(edgeTrisA[edgeAi], edgeTriAi)
553 label& trii = edgeTrisA[edgeAi][edgeTriAi];
554 trii = trii == -1 ? -1 : trii + 1;
563 SubList<triFace> triPointsB(triPoints, nB - 2, nA - 1);
564 SubList<FixedList<label, 3>> triEdgesB(triEdges, nB - 2, nA - 1);
565 SubList<labelPair> edgeTrisB(edgeTris, 2*nB - 3, 2*nA - 3);
568 SubList<point>(
points, nB, nA - 1),
580 forAll(triPointsB[triBi], triPointBi)
582 label& pointi = triPointsB[triBi][triPointBi];
583 pointi = (pointi + piA + nA - 1) %
n;
590 forAll(triEdgesB[triBi], triEdgeBi)
592 label& edgei = triEdgesB[triBi][triEdgeBi];
594 edgei >= nB ?
max(eiA, eiB) + nA - 3 + edgei - nB + 1
595 : edgei == nB - 1 ? eiB
596 : (piA + nA - 1 + edgei) %
n;
603 forAll(edgeTrisB[edgeBi], edgeTriBi)
605 label& trii = edgeTrisB[edgeBi][edgeTriBi];
606 trii = trii == -1 ? -1 : trii + nA - 1;
618 SubList<labelPair> l(edgeTris, nA + nB - 3, nA - 1);
624 SubList<labelPair> l(edgeTris, nA + nB - 3, nA + nB - 2);
630 SubList<labelPair> l(edgeTris,
n);
633 if (nA >= 3 && nB >= 3)
637 const label fromi =
n + nA - 2, toi =
n + 1;
639 for (
label i = fromi; i > toi; -- i)
641 edgeTris[i] = edgeTris[i-1];
643 edgeTris[toi] = temp;
647 edgeTris[eiA][edgeTris[eiA][0] != -1] = 0;
648 edgeTris[eiB][edgeTris[eiB][0] != -1] = 0;
653 void Foam::polygonTriangulate::complexTriangulate
655 const UList<point>&
points,
657 UList<triFace>& triPoints,
658 UList<FixedList<label, 3>>& triEdges,
659 UList<labelPair>& edgeTris,
669 for (
label piA0 = 0; piA0 <
n; ++ piA0)
673 for (
label piB0 = piA0 + 2; piB0 < (piA0 == 0 ?
n - 1 :
n); ++ piB0)
690 FixedList<labelPair, 8> spanPointAndEdgeis
701 forAll(spanPointAndEdgeis, spani)
703 for (
label spanj = spani + 1; spanj < 8; ++ spanj)
707 spanPointAndEdgeis[spani]
708 == spanPointAndEdgeis[spanj]
711 spanPointAndEdgeis[spanj] =
labelPair(-1, -1);
718 scalar spanSumNegA = - vGreat;
719 label spanPointi = -1, spanEdgei = -1;
720 forAll(spanPointAndEdgeis, spani)
722 if (spanPointAndEdgeis[spani] ==
labelPair(-1, -1))
725 const label piP = spanPointAndEdgeis[spani].first();
726 const label ei = spanPointAndEdgeis[spani].second();
728 const label piA = ei;
734 const label netNIntersections =
735 - nIntersections(edge(piA, piB),
points, normal)
736 + (piP == piA0 ? -1 : +1)
737 *nIntersections(edge(piP, piA),
points, normal)
738 + (piP == piB1 ? -1 : +1)
739 *nIntersections(edge(piP, piB),
points, normal);
740 if (netNIntersections >= 0)
continue;
762 const scalar a = area(triPoints[trii],
points, normal);
765 if (sumNegA > spanSumNegA)
767 spanSumNegA = sumNegA;
771 if (spanSumNegA == 0)
779 if (spanPointi != -1)
801 simpleTriangulate(
points, normal, triPoints, triEdges, edgeTris, optimal);
805 void Foam::polygonTriangulate::triangulate
807 const UList<point>&
points,
809 UList<triFace>& triPoints,
810 UList<FixedList<label, 3>>& triEdges,
811 UList<labelPair>& edgeTris,
881 triPoints_.resize(
n - 2);
882 triEdges_.resize(
n - 2);
883 edgeTris_.resize(2*
n - 3);
static const Foam::dimensionedScalar A("A", Foam::dimPressure, 611.21)
#define forAll(list, i)
Loop across all elements in list.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
void size(const label)
Override size to be inconsistent with allocated storage.
A List obtained as a section of another List.
Templated 2D tensor derived from VectorSpace adding construction from 4 components,...
Tensor< Cmpt > T() const
Return transpose.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
label commonVertex(const edge &a) const
Return common vertex.
Class to handle errors and exceptions in a simple, consistent stream-based manner.
static vector area(const PointField &ps)
Return vector area given face points.
static List< point > randomPolygon(randomGenerator &rndGen, const label n, const scalar error)
Generate a random polygon for testing purposes.
~polygonTriangulate()
Destructor.
polygonTriangulate()
Construct null.
const UList< triFace > & triPoints() const
Get the triangles' points.
Type sample01()
Return a type with components uniformly distributed between.
A triangular face using a FixedList of labels corresponding to mesh vertices.
simpleControl simple(mesh)
dimensionedScalar det(const dimensionedSphericalTensor &dt)
Pair< label > labelPair
Label pair.
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Tensor< scalar > tensor
Tensor of scalars.
void inplaceReverseList(ListType &list)
Inplace reversal of a list using Swap.
dimensionedScalar sin(const dimensionedScalar &ds)
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Tensor2D< scalar > tensor2D
Tensor2D or scalars.
void inplaceRotateList(ListType< DataType > &list, label n)
Inplace reversal of a list using the Reversal Block Swapping algorithm.
vector point
Point is a vector.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar atan2(const dimensionedScalar &x, const dimensionedScalar &y)
dimensionedSymmTensor cof(const dimensionedSymmTensor &dt)
Vector< scalar > vector
A scalar version of the templated Vector.
dimensionedScalar negPart(const dimensionedScalar &ds)
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensionSet normalised(const dimensionSet &)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
dimensionSet perpendicular(const dimensionSet &)
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
dimensionedScalar cos(const dimensionedScalar &ds)
randomGenerator rndGen(653213)