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,
86 const point centreA = (pointA0 + pointA1)/2;
87 const point centreB = (pointB0 + pointB1)/2;
88 const scalar radiusSqrA =
magSqr((pointA0 - pointA1)/2);
89 const scalar radiusSqrB =
magSqr((pointB0 - pointB1)/2);
91 if (
magSqr(centreA - centreB) > radiusSqrA + radiusSqrB)
return false;
96 const vector tau1 = normal ^ tau0;
98 const point2D point2DA0(tau0 & pointA0, tau1 & pointA0);
99 const point2D point2DA1(tau0 & pointA1, tau1 & pointA1);
100 const point2D point2DB0(tau0 & pointB0, tau1 & pointB0);
101 const point2D point2DB1(tau0 & pointB1, tau1 & pointB1);
104 tensor2D(point2DA0 - point2DA1, point2DB1 - point2DB0).T();
106 const scalar detM =
det(
M);
109 const vector2D magDetMTu =
sign(detM)*detMInvM & (point2DA0 - point2DB0);
115 template<
class Po
intField>
118 const edge& edgePoints,
139 template<
class Po
intField>
140 Foam::scalar Foam::polygonTriangulate::angle
151 const vector oaNegNNOa = oa - normal*(normal & oa);
152 const vector obNegNNOb = ob - normal*(normal & ob);
155 atan2(normal & (oaNegNNOa ^ obNegNNOb), - oaNegNNOa & obNegNNOb)
160 template<
class Po
intField>
161 bool Foam::polygonTriangulate::ear
174 const scalar detA =
det(
A);
185 if (detAY.
x() > 0 && detAY.
y() > 0 && detAY.
x() + detAY.
y() < detA)
218 bool incomplete =
true;
223 for (
label piA0 = 0; piA0 <
n; ++ piA0)
227 for (
label piB0 = piA0 + 2; piB0 < (piA0 == 0 ?
n - 1 :
n); ++ piB0)
235 edge(pointis[piA0], pointis[piA1]),
236 edge(pointis[piB0], pointis[piB1]),
247 if (incomplete)
break;
250 if (incomplete)
break;
272 template<
class Po
intField>
273 void Foam::polygonTriangulate::optimiseTriangulation
283 const triFace& t = triPoints[trii];
284 const scalar q = quality(t,
points, normal);
286 forAll(triEdges[trii], triEdgei)
288 const label edgei = triEdges[trii][triEdgei];
290 const label otherTrii = edgeTris[edgei][edgeTris[edgei][0] == trii];
292 if (otherTrii == -1)
continue;
294 const label otherTriEdgei =
findIndex(triEdges[otherTrii], edgei);
296 const triFace& otherT = triPoints[otherTrii];
297 const scalar otherQ = quality(otherT,
points, normal);
299 const label piA = triPoints[trii][(triEdgei + 1) % 3];
300 const label piB = triPoints[trii][(triEdgei + 2) % 3];
301 const label piC = triPoints[otherTrii][(otherTriEdgei + 1) % 3];
302 const label piD = triPoints[otherTrii][(otherTriEdgei + 2) % 3];
304 const triFace flipT0(piA, piB, piD);
305 const triFace flipT1(piC, piD, piB);
309 triPointsSet_.found(flipT0)
310 || triPointsSet_.found(flipT1)
313 const scalar flipQ0 = quality(flipT0,
points, normal);
314 const scalar flipQ1 = quality(flipT1,
points, normal);
316 if (
min(q, otherQ) <
min(flipQ0, flipQ1))
318 triPointsSet_.set(t);
319 triPointsSet_.set(otherT);
321 const label eiA = triEdges[trii][(triEdgei + 1) % 3];
322 const label eiB = triEdges[trii][(triEdgei + 2) % 3];
323 const label eiC = triEdges[otherTrii][(otherTriEdgei + 1) % 3];
324 const label eiD = triEdges[otherTrii][(otherTriEdgei + 2) % 3];
326 triPoints[trii] = {piA, piB, piD};
327 triEdges[trii] = {eiA, edgei, eiD};
328 edgeTris[eiD][edgeTris[eiD][0] != otherTrii] = trii;
330 triPoints[otherTrii] = {piC, piD, piB};
331 triEdges[otherTrii] = {eiC, edgei, eiB};
332 edgeTris[eiB][edgeTris[eiB][0] != trii] = otherTrii;
334 optimiseTriangulation
343 optimiseTriangulation
359 void Foam::polygonTriangulate::simpleTriangulate
361 const UList<point>& allPoints,
363 UList<triFace>& triPoints,
364 UList<FixedList<label, 3>>& triEdges,
365 UList<labelPair>& edgeTris,
370 const label n = allPoints.size();
373 triPoints =
triFace(-1, -1, -1);
374 triEdges = FixedList<label, 3>({-1, -1, -1});
386 angle_[i] = angle(i, allPoints, normal);
387 ear_[i] = ear(i, allPoints, normal);
391 UIndirectList<point>
points(allPoints, pointis_);
397 scalar minEarAngle = vGreat;
398 label minEarAnglei = -1;
399 for (
label i = 0; i < pointis_.size(); ++ i)
401 if (ear_[i] && minEarAngle > angle_[i])
403 minEarAngle = angle_[i];
410 if (minEarAnglei == -1)
412 minEarAnglei =
findMin(angle_);
416 label minEarAnglei0 = pointis_.rcIndex(minEarAnglei);
417 label minEarAnglei1 = pointis_.fcIndex(minEarAnglei);
422 pointis_[minEarAnglei0],
423 pointis_[minEarAnglei],
424 pointis_[minEarAnglei1]
426 triEdges[trii] = FixedList<label, 3>
428 edges_[minEarAnglei0],
429 edges_[minEarAnglei],
430 trii == triPoints.size() - 1 ? edges_[minEarAnglei1] :
n + trii
432 forAll(triEdges[trii], triEdgei)
434 const label edgei = triEdges[trii][triEdgei];
435 edgeTris[edgei][edgeTris[edgei][0] != -1] = trii;
439 edges_[minEarAnglei0] = triEdges[trii][2];
440 for (
label i = minEarAnglei; i < pointis_.size() - 1; ++ i)
442 pointis_[i] = pointis_[i + 1];
443 edges_[i] = edges_[i + 1];
444 angle_[i] = angle_[i + 1];
445 ear_[i] = ear_[i + 1];
447 pointis_.resize(pointis_.size() - 1);
448 edges_.resize(edges_.size() - 1);
449 angle_.resize(angle_.size() - 1);
450 ear_.resize(ear_.size() - 1);
453 if (minEarAnglei0 > minEarAnglei) -- minEarAnglei0;
454 angle_[minEarAnglei0] = angle(minEarAnglei0,
points, normal);
455 ear_[minEarAnglei0] = ear(minEarAnglei0,
points, normal);
456 if (minEarAnglei1 > minEarAnglei) -- minEarAnglei1;
457 angle_[minEarAnglei1] = angle(minEarAnglei1,
points, normal);
458 ear_[minEarAnglei1] = ear(minEarAnglei1,
points, normal);
463 triPointsSet_.clear();
464 optimiseTriangulation
478 void Foam::polygonTriangulate::partitionTriangulate
480 const UList<point>&
points,
482 const label spanPointi,
483 const label spanEdgei,
484 UList<triFace>& triPoints,
485 UList<FixedList<label, 3>>& triEdges,
486 UList<labelPair>& edgeTris,
495 const label piA = (spanEdgei + 1) %
n;
496 const label piP = spanPointi;
497 const label piB = spanEdgei;
501 const label nA = (piP - piA +
n) %
n + 1;
502 const label nB = (piB - piP +
n) %
n + 1;
505 const label eiA = nA >= 3 ?
n : piA;
506 const label eiB = nB >= 3 ?
n + (nA >= 3) : piP;
507 const label eiE = piB;
510 triPoints[0] =
triFace(piA, piP, piB);
511 triEdges[0] = FixedList<label, 3>({eiA, eiB, eiE});
521 SubList<triFace> triPointsA(triPoints, nA - 2, 1);
522 SubList<FixedList<label, 3>> triEdgesA(triEdges, nA - 2, 1);
523 SubList<labelPair> edgeTrisA(edgeTris, 2*nA - 3);
526 SubList<point>(
points, nA),
538 forAll(triPointsA[triAi], triPointAi)
540 label& pointi = triPointsA[triAi][triPointAi];
541 pointi = (pointi + piA) %
n;
548 forAll(triEdgesA[triAi], triEdgeAi)
550 label& edgei = triEdgesA[triAi][triEdgeAi];
552 edgei >= nA ?
max(eiA, eiB) + edgei - nA + 1
553 : edgei == nA - 1 ? eiA
561 forAll(edgeTrisA[edgeAi], edgeTriAi)
563 label& trii = edgeTrisA[edgeAi][edgeTriAi];
564 trii = trii == -1 ? -1 : trii + 1;
573 SubList<triFace> triPointsB(triPoints, nB - 2, nA - 1);
574 SubList<FixedList<label, 3>> triEdgesB(triEdges, nB - 2, nA - 1);
575 SubList<labelPair> edgeTrisB(edgeTris, 2*nB - 3, 2*nA - 3);
578 SubList<point>(
points, nB, nA - 1),
590 forAll(triPointsB[triBi], triPointBi)
592 label& pointi = triPointsB[triBi][triPointBi];
593 pointi = (pointi + piA + nA - 1) %
n;
600 forAll(triEdgesB[triBi], triEdgeBi)
602 label& edgei = triEdgesB[triBi][triEdgeBi];
604 edgei >= nB ?
max(eiA, eiB) + nA - 3 + edgei - nB + 1
605 : edgei == nB - 1 ? eiB
606 : (piA + nA - 1 + edgei) %
n;
613 forAll(edgeTrisB[edgeBi], edgeTriBi)
615 label& trii = edgeTrisB[edgeBi][edgeTriBi];
616 trii = trii == -1 ? -1 : trii + nA - 1;
628 SubList<labelPair> l(edgeTris, nA + nB - 3, nA - 1);
634 SubList<labelPair> l(edgeTris, nA + nB - 3, nA + nB - 2);
640 SubList<labelPair> l(edgeTris,
n);
643 if (nA >= 3 && nB >= 3)
647 const label fromi =
n + nA - 2, toi =
n + 1;
649 for (
label i = fromi; i > toi; -- i)
651 edgeTris[i] = edgeTris[i-1];
653 edgeTris[toi] = temp;
657 edgeTris[eiA][edgeTris[eiA][0] != -1] = 0;
658 edgeTris[eiB][edgeTris[eiB][0] != -1] = 0;
663 void Foam::polygonTriangulate::complexTriangulate
665 const UList<point>&
points,
667 UList<triFace>& triPoints,
668 UList<FixedList<label, 3>>& triEdges,
669 UList<labelPair>& edgeTris,
679 for (
label piA0 = 0; piA0 <
n; ++ piA0)
683 for (
label piB0 = piA0 + 2; piB0 < (piA0 == 0 ?
n - 1 :
n); ++ piB0)
700 FixedList<labelPair, 8> spanPointAndEdgeis
711 forAll(spanPointAndEdgeis, spani)
713 for (
label spanj = spani + 1; spanj < 8; ++ spanj)
717 spanPointAndEdgeis[spani]
718 == spanPointAndEdgeis[spanj]
721 spanPointAndEdgeis[spanj] =
labelPair(-1, -1);
728 scalar spanSumNegA = - vGreat;
729 label spanPointi = -1, spanEdgei = -1;
730 forAll(spanPointAndEdgeis, spani)
732 if (spanPointAndEdgeis[spani] ==
labelPair(-1, -1))
735 const label piP = spanPointAndEdgeis[spani].first();
736 const label ei = spanPointAndEdgeis[spani].second();
738 const label piA = ei;
744 const label netNIntersections =
745 - nIntersections(edge(piA, piB),
points, normal)
746 + (piP == piA0 ? -1 : +1)
747 *nIntersections(edge(piP, piA),
points, normal)
748 + (piP == piB1 ? -1 : +1)
749 *nIntersections(edge(piP, piB),
points, normal);
750 if (netNIntersections >= 0)
continue;
772 const scalar a = area(triPoints[trii],
points, normal);
775 if (sumNegA > spanSumNegA)
777 spanSumNegA = sumNegA;
781 if (spanSumNegA == 0)
789 if (spanPointi != -1)
811 simpleTriangulate(
points, normal, triPoints, triEdges, edgeTris, optimal);
815 void Foam::polygonTriangulate::triangulate
817 const UList<point>&
points,
819 UList<triFace>& triPoints,
820 UList<FixedList<label, 3>>& triEdges,
821 UList<labelPair>& edgeTris,
891 triPoints_.resize(
n - 2);
892 triEdges_.resize(
n - 2);
893 edgeTris_.resize(2*
n - 3);
#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)
static const coefficient A("A", dimPressure, 611.21)
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 T(LagrangianPatchField< Type > &f, const LagrangianPatchField< Type > &f1)
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.
void det(LagrangianPatchField< scalar > &f, const LagrangianPatchField< tensor > &f1)
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
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)
dimensionSet normalised(const dimensionSet &)
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,.
void magSqr(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
dimensionSet perpendicular(const dimensionSet &)
void sqrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
dimensionedScalar cos(const dimensionedScalar &ds)
randomGenerator rndGen(653213)