00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "face.H"
00027 #include <OpenFOAM/triFace.H>
00028 #include <OpenFOAM/triPointRef.H>
00029 #include <OpenFOAM/mathematicalConstants.H>
00030
00031
00032
00033 const char* const Foam::face::typeName = "face";
00034
00035
00036
00037 Foam::tmp<Foam::vectorField>
00038 Foam::face::calcEdges(const pointField& points) const
00039 {
00040 tmp<vectorField> tedges(new vectorField(size()));
00041 vectorField& edges = tedges();
00042
00043 forAll(*this, i)
00044 {
00045 label ni = fcIndex(i);
00046
00047 point thisPt = points[operator[](i)];
00048 point nextPt = points[operator[](ni)];
00049
00050 vector vec(nextPt - thisPt);
00051 vec /= Foam::mag(vec) + VSMALL;
00052
00053 edges[i] = vec;
00054 }
00055
00056 return tedges;
00057 }
00058
00059
00060 Foam::scalar Foam::face::edgeCos
00061 (
00062 const vectorField& edges,
00063 const label index
00064 ) const
00065 {
00066 label leftEdgeI = left(index);
00067 label rightEdgeI = right(index);
00068
00069
00070 return -(edges[leftEdgeI] & edges[rightEdgeI]);
00071 }
00072
00073
00074 Foam::label Foam::face::mostConcaveAngle
00075 (
00076 const pointField& points,
00077 const vectorField& edges,
00078 scalar& maxAngle
00079 ) const
00080 {
00081 vector n(normal(points));
00082
00083 label index = 0;
00084 maxAngle = -GREAT;
00085
00086 forAll(edges, i)
00087 {
00088 label leftEdgeI = left(i);
00089 label rightEdgeI = right(i);
00090
00091 vector edgeNormal = edges[rightEdgeI] ^ edges[leftEdgeI];
00092
00093 scalar edgeCos = edges[leftEdgeI] & edges[rightEdgeI];
00094 scalar edgeAngle = acos(max(-1.0, min(1.0, edgeCos)));
00095
00096 scalar angle;
00097
00098 if ((edgeNormal & n) > 0)
00099 {
00100
00101 angle = mathematicalConstant::pi + edgeAngle;
00102 }
00103 else
00104 {
00105
00106
00107 angle = mathematicalConstant::pi - edgeAngle;
00108 }
00109
00110 if (angle > maxAngle)
00111 {
00112 maxAngle = angle;
00113 index = i;
00114 }
00115 }
00116
00117 return index;
00118 }
00119
00120
00121 Foam::label Foam::face::split
00122 (
00123 const face::splitMode mode,
00124 const pointField& points,
00125 label& triI,
00126 label& quadI,
00127 faceList& triFaces,
00128 faceList& quadFaces
00129 ) const
00130 {
00131 label oldIndices = (triI + quadI);
00132
00133 if (size() <= 2)
00134 {
00135 FatalErrorIn
00136 (
00137 "face::split"
00138 "(const face::splitMode, const pointField&, label&, label&"
00139 ", faceList&, faceList&)"
00140 )
00141 << "Serious problem: asked to split a face with < 3 vertices"
00142 << abort(FatalError);
00143 }
00144 if (size() == 3)
00145 {
00146
00147 if (mode == COUNTTRIANGLE || mode == COUNTQUAD)
00148 {
00149 triI++;
00150 }
00151 else
00152 {
00153 triFaces[triI++] = *this;
00154 }
00155 }
00156 else if (size() == 4)
00157 {
00158 if (mode == COUNTTRIANGLE)
00159 {
00160 triI += 2;
00161 }
00162 if (mode == COUNTQUAD)
00163 {
00164 quadI++;
00165 }
00166 else if (mode == SPLITTRIANGLE)
00167 {
00168
00169 const vectorField edges(calcEdges(points));
00170
00171 scalar minAngle;
00172 label startIndex = mostConcaveAngle(points, edges, minAngle);
00173
00174 label nextIndex = fcIndex(startIndex);
00175 label splitIndex = fcIndex(nextIndex);
00176
00177
00178 face triFace(3);
00179 triFace[0] = operator[](startIndex);
00180 triFace[1] = operator[](nextIndex);
00181 triFace[2] = operator[](splitIndex);
00182
00183 triFaces[triI++] = triFace;
00184
00185 triFace[0] = operator[](splitIndex);
00186 triFace[1] = operator[](fcIndex(splitIndex));
00187 triFace[2] = operator[](startIndex);
00188
00189 triFaces[triI++] = triFace;
00190 }
00191 else
00192 {
00193 quadFaces[quadI++] = *this;
00194 }
00195 }
00196 else
00197 {
00198
00199
00200 const vectorField edges(calcEdges(points));
00201
00202 scalar minAngle = 1;
00203 label startIndex = mostConcaveAngle(points, edges, minAngle);
00204
00205 scalar bisectAngle = minAngle/2;
00206 vector rightEdge = edges[right(startIndex)];
00207
00208
00209
00210
00211
00212
00213 label index = fcIndex(fcIndex(startIndex));
00214
00215 label minIndex = index;
00216 scalar minDiff = Foam::mathematicalConstant::pi;
00217
00218 for(label i = 0; i < size() - 3; i++)
00219 {
00220 vector splitEdge
00221 (
00222 points[operator[](index)]
00223 - points[operator[](startIndex)]
00224 );
00225 splitEdge /= Foam::mag(splitEdge) + VSMALL;
00226
00227 const scalar splitCos = splitEdge & rightEdge;
00228 const scalar splitAngle = acos(max(-1.0, min(1.0, splitCos)));
00229 const scalar angleDiff = fabs(splitAngle - bisectAngle);
00230
00231 if (angleDiff < minDiff)
00232 {
00233 minDiff = angleDiff;
00234 minIndex = index;
00235 }
00236
00237
00238 index = fcIndex(index);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 label diff = 0;
00248 if (minIndex > startIndex)
00249 {
00250 diff = minIndex - startIndex;
00251 }
00252 else
00253 {
00254
00255 diff = minIndex + size() - startIndex;
00256 }
00257
00258 label nPoints1 = diff + 1;
00259 label nPoints2 = size() - diff + 1;
00260
00261
00262 face face1(nPoints1);
00263
00264 index = startIndex;
00265 for (label i = 0; i < nPoints1; i++)
00266 {
00267 face1[i] = operator[](index);
00268 index = fcIndex(index);
00269 }
00270
00271
00272 face face2(nPoints2);
00273
00274 index = minIndex;
00275 for (label i = 0; i < nPoints2; i++)
00276 {
00277 face2[i] = operator[](index);
00278 index = fcIndex(index);
00279 }
00280
00281
00282 face1.split(mode, points, triI, quadI, triFaces, quadFaces);
00283 face2.split(mode, points, triI, quadI, triFaces, quadFaces);
00284 }
00285
00286 return (triI + quadI - oldIndices);
00287 }
00288
00289
00290
00291
00292 Foam::face::face(const triFace& f)
00293 :
00294 labelList(f)
00295 {}
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 int Foam::face::compare(const face& a, const face& b)
00306 {
00307
00308
00309
00310
00311
00312 label sizeA = a.size();
00313 label sizeB = b.size();
00314
00315 if (sizeA != sizeB)
00316 {
00317 return 0;
00318 }
00319
00320
00321
00322 const label firstA = a[0];
00323 label Bptr = -1;
00324
00325 forAll (b, i)
00326 {
00327 if (b[i] == firstA)
00328 {
00329 Bptr = i;
00330 break;
00331 }
00332 }
00333
00334
00335 if (Bptr < 0)
00336 {
00337 return 0;
00338 }
00339
00340
00341 label secondA = a[1];
00342
00343 if (sizeA > 1 && (secondA == firstA || firstA == a[sizeA - 1]))
00344 {
00345 face ca = a;
00346 ca.collapse();
00347
00348 face cb = b;
00349 cb.collapse();
00350
00351 return face::compare(ca, cb);
00352 }
00353
00354 int dir = 0;
00355
00356
00357 Bptr++;
00358 if (Bptr == b.size())
00359 {
00360 Bptr = 0;
00361 }
00362
00363
00364 if (b[Bptr] == secondA)
00365 {
00366
00367 dir = 1;
00368 }
00369 else
00370 {
00371
00372 Bptr -= 2;
00373
00374 if (Bptr < 0)
00375 {
00376
00377 Bptr += b.size();
00378 }
00379
00380
00381 if (b[Bptr] == secondA)
00382 {
00383
00384 dir = -1;
00385 }
00386 }
00387
00388
00389 if (dir == 0)
00390 {
00391 return 0;
00392 }
00393
00394
00395 sizeA -= 2;
00396
00397
00398
00399 label Aptr = 1;
00400 if (dir > 0)
00401 {
00402 while (sizeA--)
00403 {
00404 Aptr++;
00405 if (Aptr >= a.size())
00406 {
00407 Aptr = 0;
00408 }
00409
00410 Bptr++;
00411 if (Bptr >= b.size())
00412 {
00413 Bptr = 0;
00414 }
00415
00416 if (a[Aptr] != b[Bptr])
00417 {
00418 return 0;
00419 }
00420 }
00421 }
00422 else
00423 {
00424 while (sizeA--)
00425 {
00426 Aptr++;
00427 if (Aptr >= a.size())
00428 {
00429 Aptr = 0;
00430 }
00431
00432 Bptr--;
00433 if (Bptr < 0)
00434 {
00435 Bptr = b.size() - 1;
00436 }
00437
00438 if (a[Aptr] != b[Bptr])
00439 {
00440 return 0;
00441 }
00442 }
00443 }
00444
00445
00446 return dir;
00447 }
00448
00449
00450
00451
00452
00453 Foam::label Foam::face::collapse()
00454 {
00455 if (size() > 1)
00456 {
00457 label ci = 0;
00458 for (label i=1; i<size(); i++)
00459 {
00460 if (operator[](i) != operator[](ci))
00461 {
00462 operator[](++ci) = operator[](i);
00463 }
00464 }
00465
00466 if (operator[](ci) != operator[](0))
00467 {
00468 ci++;
00469 }
00470
00471 setSize(ci);
00472 }
00473
00474 return size();
00475 }
00476
00477
00478 Foam::point Foam::face::centre(const pointField& meshPoints) const
00479 {
00480
00481
00482
00483
00484 if (size() == 3)
00485 {
00486 return
00487 (1.0/3.0)
00488 *(
00489 meshPoints[operator[](0)]
00490 + meshPoints[operator[](1)]
00491 + meshPoints[operator[](2)]
00492 );
00493 }
00494
00495 label nPoints = size();
00496
00497 point centrePoint = point::zero;
00498 for (register label pI=0; pI<nPoints; pI++)
00499 {
00500 centrePoint += meshPoints[operator[](pI)];
00501 }
00502 centrePoint /= nPoints;
00503
00504 scalar sumA = 0;
00505 vector sumAc = vector::zero;
00506
00507 for (register label pI=0; pI<nPoints; pI++)
00508 {
00509 const point& nextPoint = meshPoints[operator[]((pI + 1) % nPoints)];
00510
00511
00512 vector ttc
00513 (
00514 meshPoints[operator[](pI)]
00515 + nextPoint
00516 + centrePoint
00517 );
00518
00519
00520 scalar ta = Foam::mag
00521 (
00522 (meshPoints[operator[](pI)] - centrePoint)
00523 ^ (nextPoint - centrePoint)
00524 );
00525
00526 sumA += ta;
00527 sumAc += ta*ttc;
00528 }
00529
00530 if (sumA > VSMALL)
00531 {
00532 return sumAc/(3*sumA);
00533 }
00534 else
00535 {
00536 return centrePoint;
00537 }
00538 }
00539
00540
00541 Foam::vector Foam::face::normal(const pointField& p) const
00542 {
00543
00544
00545
00546
00547
00548
00549
00550 if (size() == 3)
00551 {
00552 return triPointRef
00553 (
00554 p[operator[](0)],
00555 p[operator[](1)],
00556 p[operator[](2)]
00557 ).normal();
00558 }
00559
00560 label nPoints = size();
00561
00562 register label pI;
00563
00564 point centrePoint = vector::zero;
00565 for (pI = 0; pI < nPoints; pI++)
00566 {
00567 centrePoint += p[operator[](pI)];
00568 }
00569 centrePoint /= nPoints;
00570
00571 vector n = vector::zero;
00572
00573 point nextPoint = centrePoint;
00574
00575 for (pI = 0; pI < nPoints; pI++)
00576 {
00577 if (pI < nPoints - 1)
00578 {
00579 nextPoint = p[operator[](pI + 1)];
00580 }
00581 else
00582 {
00583 nextPoint = p[operator[](0)];
00584 }
00585
00586
00587
00588 n += triPointRef
00589 (
00590 p[operator[](pI)],
00591 nextPoint,
00592 centrePoint
00593 ).normal();
00594 }
00595
00596 return n;
00597 }
00598
00599
00600 Foam::face Foam::face::reverseFace() const
00601 {
00602
00603
00604
00605 const labelList& f = *this;
00606 labelList newList(size());
00607
00608 newList[0] = f[0];
00609
00610 for (label pointI = 1; pointI < newList.size(); pointI++)
00611 {
00612 newList[pointI] = f[size() - pointI];
00613 }
00614
00615 return face(xferMove(newList));
00616 }
00617
00618
00619 Foam::label Foam::face::which(const label globalIndex) const
00620 {
00621 label pointInFace = -1;
00622 const labelList& f = *this;
00623
00624 forAll (f, i)
00625 {
00626 if (f[i] == globalIndex)
00627 {
00628 pointInFace = i;
00629 break;
00630 }
00631 }
00632
00633 return pointInFace;
00634 }
00635
00636
00637 Foam::scalar Foam::face::sweptVol
00638 (
00639 const pointField& oldPoints,
00640 const pointField& newPoints
00641 ) const
00642 {
00643 scalar sv = 0;
00644
00645
00646
00647
00648
00649 point centreOldPoint = centre(oldPoints);
00650 point centreNewPoint = centre(newPoints);
00651
00652 label nPoints = size();
00653
00654 point nextOldPoint = centreOldPoint;
00655 point nextNewPoint = centreNewPoint;
00656
00657 register label pI;
00658
00659 for (pI = 0; pI < nPoints; pI++)
00660 {
00661 if (pI < nPoints - 1)
00662 {
00663 nextOldPoint = oldPoints[operator[](pI + 1)];
00664 nextNewPoint = newPoints[operator[](pI + 1)];
00665 }
00666 else
00667 {
00668 nextOldPoint = oldPoints[operator[](0)];
00669 nextNewPoint = newPoints[operator[](0)];
00670 }
00671
00672
00673 sv += triPointRef
00674 (
00675 centreOldPoint,
00676 oldPoints[operator[](pI)],
00677 nextOldPoint
00678 ).sweptVol
00679 (
00680 triPointRef
00681 (
00682 centreNewPoint,
00683 newPoints[operator[](pI)],
00684 nextNewPoint
00685 )
00686 );
00687 }
00688
00689 return sv;
00690 }
00691
00692
00693 Foam::edgeList Foam::face::edges() const
00694 {
00695 const labelList& points = *this;
00696
00697 edgeList e(points.size());
00698
00699 label pointI;
00700
00701 for (pointI = 0; pointI < points.size() - 1; pointI++)
00702 {
00703 e[pointI] = edge(points[pointI], points[pointI + 1]);
00704 }
00705
00706
00707 e[points.size() - 1] = edge(points[points.size() - 1], points[0]);
00708
00709 return e;
00710 }
00711
00712
00713 int Foam::face::edgeDirection(const edge& e) const
00714 {
00715 forAll (*this, i)
00716 {
00717 if (operator[](i) == e.start())
00718 {
00719 if (operator[](rcIndex(i)) == e.end())
00720 {
00721
00722 return -1;
00723 }
00724 else if (operator[](fcIndex(i)) == e.end())
00725 {
00726
00727 return 1;
00728 }
00729
00730
00731 return 0;
00732 }
00733 else if (operator[](i) == e.end())
00734 {
00735 if (operator[](rcIndex(i)) == e.start())
00736 {
00737
00738 return 1;
00739 }
00740 else if (operator[](fcIndex(i)) == e.start())
00741 {
00742
00743 return -1;
00744 }
00745
00746
00747 return 0;
00748 }
00749 }
00750
00751
00752 return 0;
00753 }
00754
00755
00756
00757 Foam::label Foam::face::nTriangles(const pointField&) const
00758 {
00759 return nTriangles();
00760 }
00761
00762
00763 Foam::label Foam::face::triangles
00764 (
00765 const pointField& points,
00766 label& triI,
00767 faceList& triFaces
00768 ) const
00769 {
00770 label quadI = 0;
00771 faceList quadFaces;
00772
00773 return split(SPLITTRIANGLE, points, triI, quadI, triFaces, quadFaces);
00774 }
00775
00776
00777 Foam::label Foam::face::nTrianglesQuads
00778 (
00779 const pointField& points,
00780 label& triI,
00781 label& quadI
00782 ) const
00783 {
00784 faceList triFaces;
00785 faceList quadFaces;
00786
00787 return split(COUNTQUAD, points, triI, quadI, triFaces, quadFaces);
00788 }
00789
00790
00791 Foam::label Foam::face::trianglesQuads
00792 (
00793 const pointField& points,
00794 label& triI,
00795 label& quadI,
00796 faceList& triFaces,
00797 faceList& quadFaces
00798 ) const
00799 {
00800 return split(SPLITQUAD, points, triI, quadI, triFaces, quadFaces);
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810