31 template<
class Po
intField>
32 Foam::scalar Foam::polygonTriangulate::area
39 const point& o = points[triPoints[0]];
40 const vector ao = points[triPoints[1]] - o;
41 const vector ab = points[triPoints[2]] - o;
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)
60 const point& p0 = points[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;
83 const point& pointA0 = points[edgePointsA[0]];
84 const point& pointA1 = points[edgePointsA[1]];
85 const point& pointB0 = points[edgePointsB[0]];
86 const point& pointB1 = points[edgePointsB[1]];
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>
106 Foam::label Foam::polygonTriangulate::nIntersections
108 const edge& edgePoints,
121 n +=
intersection(edgePoints, otherEdgePoints, points, normal);
129 template<
class Po
intField>
130 Foam::scalar Foam::polygonTriangulate::angle
137 const point& o = points[pointi];
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
158 const point& o = points[pointi];
164 const scalar detA =
det(A);
169 pointj != points.
rcIndex(pointi);
170 pointj = points.
fcIndex(pointj)
173 const vector detAY = (points[pointj] - o) &
T;
175 if (detAY.
x() > 0 && detAY.
y() > 0 && detAY.
x() + detAY.
y() < detA)
201 points[pointi] =
point(r*
cos(theta), r*
sin(theta), 0);
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;
251 (1 - error)*points[pointi]
262 template<
class Po
intField>
263 void Foam::polygonTriangulate::optimiseTriangulation
273 const triFace& t = triPoints[trii];
274 const scalar q = quality(t, points, normal);
280 const label otherTrii = edgeTris[edgei][edgeTris[edgei][0] == trii];
282 if (otherTrii == -1)
continue;
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);
313 const label eiC =
triEdges[otherTrii][(otherTriEdgei + 1) % 3];
314 const label eiD =
triEdges[otherTrii][(otherTriEdgei + 2) % 3];
316 triPoints[trii] = {piA, piB, piD};
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
363 triPoints =
triFace(-1, -1, -1);
376 angle_[i] = angle(i, allPoints, normal);
377 ear_[i] = ear(i, allPoints, normal);
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]
418 edges_[minEarAnglei0],
419 edges_[minEarAnglei],
420 trii == triPoints.
size() - 1 ? edges_[minEarAnglei1] : n + trii
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);
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
472 const label spanPointi,
473 const label spanEdgei,
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);
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;
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;
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
669 for (
label piA0 = 0; piA0 <
n; ++ piA0)
673 for (
label piB0 = piA0 + 2; piB0 < (piA0 == 0 ? n - 1 :
n); ++ piB0)
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
881 triPoints_.resize(n - 2);
882 triEdges_.resize(n - 2);
883 edgeTris_.resize(2*n - 3);
dimensionedScalar sign(const dimensionedScalar &ds)
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
#define forAll(list, i)
Loop across all elements in list.
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
void resize(const label)
Alter the addressed list size.
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
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.
Tensor< Cmpt > T() const
Return transpose.
const UList< FixedList< label, 3 > > & triEdges() const
Get the triangles' edges.
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
dimensionedScalar sqrt(const dimensionedScalar &ds)
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
static vector area(const PointField &ps)
Return vector area given face points.
Vector< scalar > vector
A scalar version of the templated Vector.
dimensionedScalar det(const dimensionedSphericalTensor &dt)
label commonVertex(const edge &a) const
Return common vertex.
polygonTriangulate()
Construct null.
Templated 2D tensor derived from VectorSpace adding construction from 4 components, element access using xx(), xy(), yx() and yy() member functions and the iner-product (dot-product) and outer-product of two Vector2Ds (tensor-product) operators.
~polygonTriangulate()
Destructor.
void inplaceReverseList(ListType &list)
Inplace reversal of a list using Swap.
A List obtained as a section of another List.
Type sample01()
Advance the state and return a sample of a given type from a.
void setSize(const label)
Alter the addressed list size.
An ordered pair of two objects of type <T> with first() and second() elements.
Form normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
dimensionedScalar cos(const dimensionedScalar &ds)
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
A triangular face using a FixedList of labels corresponding to mesh vertices.
static List< point > randomPolygon(Random &rndGen, const label n, const scalar error)
Generate a random polygon for testing purposes.
T & first()
Return the first element of the list.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
Pair< label > labelPair
Label pair.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
dimensioned< scalar > magSqr(const dimensioned< Type > &)
dimensionedScalar sin(const dimensionedScalar &ds)
dimensionedScalar atan2(const dimensionedScalar &x, const dimensionedScalar &y)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Vector< Cmpt > perpendicular(const Vector< Cmpt > &v)
vector point
Point is a vector.
void inplaceRotateList(ListType< DataType > &list, label n)
Inplace reversal of a list using the Reversal Block Swapping algorithm.
A List with indirect addressing.
dimensioned< scalar > mag(const dimensioned< Type > &)
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
label size() const
Return the number of elements in the UList.
Tensor2D< scalar > tensor2D
Tensor2D or scalars.
dimensionedSymmTensor cof(const dimensionedSymmTensor &dt)
Tensor< scalar > tensor
Tensor of scalars.
dimensionedScalar negPart(const dimensionedScalar &ds)