1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 \*---------------------------------------------------------------------------*/
29 #include "triSurfaceTools.H"
31 #include "triSurface.H"
33 #include "mergePoints.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 const Foam::label Foam::triSurfaceTools::ANYEDGE = -1;
42 const Foam::label Foam::triSurfaceTools::NOEDGE = -2;
43 const Foam::label Foam::triSurfaceTools::COLLAPSED = -3;
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 Refine by splitting all three edges of triangle ('red' refinement).
49 Neighbouring triangles (which are not marked for refinement get split
50 in half ('green') refinement. (R. Verfuerth, "A review of a posteriori
51 error estimation and adaptive mesh refinement techniques",
55 // FaceI gets refined ('red'). Propagate edge refinement.
56 void Foam::triSurfaceTools::calcRefineStatus
58 const triSurface& surf,
60 List<refineType>& refine
63 if (refine[faceI] == RED)
65 // Already marked for refinement. Do nothing.
69 // Not marked or marked for 'green' refinement. Refine.
72 const labelList& myNeighbours = surf.faceFaces()[faceI];
74 forAll(myNeighbours, myNeighbourI)
76 label neighbourFaceI = myNeighbours[myNeighbourI];
78 if (refine[neighbourFaceI] == GREEN)
80 // Change to red refinement and propagate
81 calcRefineStatus(surf, neighbourFaceI, refine);
83 else if (refine[neighbourFaceI] == NONE)
85 refine[neighbourFaceI] = GREEN;
92 // Split faceI along edgeI at position newPointI
93 void Foam::triSurfaceTools::greenRefine
95 const triSurface& surf,
98 const label newPointI,
99 DynamicList<labelledTri>& newFaces
102 const labelledTri& f = surf.localFaces()[faceI];
103 const edge& e = surf.edges()[edgeI];
105 // Find index of edge in face.
107 label fp0 = findIndex(f, e[0]);
108 label fp1 = f.fcIndex(fp0);
109 label fp2 = f.fcIndex(fp1);
113 // Edge oriented like face
161 // Refine all triangles marked for refinement.
162 Foam::triSurface Foam::triSurfaceTools::doRefine
164 const triSurface& surf,
165 const List<refineType>& refineStatus
168 // Storage for new points. (start after old points)
169 DynamicList<point> newPoints(surf.nPoints());
170 forAll(surf.localPoints(), pointI)
172 newPoints.append(surf.localPoints()[pointI]);
174 label newVertI = surf.nPoints();
176 // Storage for new faces
177 DynamicList<labelledTri> newFaces(surf.size());
180 // Point index for midpoint on edge
181 labelList edgeMid(surf.nEdges(), -1);
183 forAll(refineStatus, faceI)
185 if (refineStatus[faceI] == RED)
187 // Create new vertices on all edges to be refined.
188 const labelList& fEdges = surf.faceEdges()[faceI];
192 label edgeI = fEdges[i];
194 if (edgeMid[edgeI] == -1)
196 const edge& e = surf.edges()[edgeI];
198 // Create new point on mid of edge
203 surf.localPoints()[e.start()]
204 + surf.localPoints()[e.end()]
207 edgeMid[edgeI] = newVertI++;
211 // Now we have new mid edge vertices for all edges on face
212 // so create triangles for RED rerfinement.
214 const edgeList& edges = surf.edges();
222 edges[fEdges[0]].commonVertex(edges[fEdges[1]]),
233 edges[fEdges[1]].commonVertex(edges[fEdges[2]]),
244 edges[fEdges[2]].commonVertex(edges[fEdges[0]]),
263 // Create triangles for GREEN refinement.
266 const label edgeI = fEdges[i];
268 label otherFaceI = otherFace(surf, faceI, edgeI);
270 if ((otherFaceI != -1) && (refineStatus[otherFaceI] == GREEN))
285 // Copy unmarked triangles since keep original vertex numbering.
286 forAll(refineStatus, faceI)
288 if (refineStatus[faceI] == NONE)
290 newFaces.append(surf.localFaces()[faceI]);
298 // Transfer DynamicLists to straight ones.
299 pointField allPoints;
300 allPoints.transfer(newPoints);
303 List<labelledTri> allFaces;
304 allFaces.transfer(newFaces);
307 return triSurface(allFaces, surf.patches(), allPoints);
311 // Angle between two neighbouring triangles,
312 // angle between shared-edge end points and left and right face end points
313 Foam::scalar Foam::triSurfaceTools::faceCosAngle
321 const vector common(pEnd - pStart);
322 const vector base0(pLeft - pStart);
323 const vector base1(pRight - pStart);
325 vector n0(common ^ base0);
328 vector n1(base1 ^ common);
335 // Protect edges around vertex from collapsing.
336 // Moving vertI to a different position
337 // - affects obviously the cost of the faces using it
338 // - but also their neighbours since the edge between the faces changes
339 void Foam::triSurfaceTools::protectNeighbours
341 const triSurface& surf,
343 labelList& faceStatus
346 // const labelList& myFaces = surf.pointFaces()[vertI];
347 // forAll(myFaces, i)
349 // label faceI = myFaces[i];
351 // if ((faceStatus[faceI] == ANYEDGE) || (faceStatus[faceI] >= 0))
353 // faceStatus[faceI] = NOEDGE;
357 const labelList& myEdges = surf.pointEdges()[vertI];
360 const labelList& myFaces = surf.edgeFaces()[myEdges[i]];
362 forAll(myFaces, myFaceI)
364 label faceI = myFaces[myFaceI];
366 if ((faceStatus[faceI] == ANYEDGE) || (faceStatus[faceI] >= 0))
368 faceStatus[faceI] = NOEDGE;
376 // Edge collapse helper functions
379 // Get all faces that will get collapsed if edgeI collapses.
380 Foam::labelHashSet Foam::triSurfaceTools::getCollapsedFaces
382 const triSurface& surf,
386 const edge& e = surf.edges()[edgeI];
387 label v1 = e.start();
390 // Faces using edge will certainly get collapsed.
391 const labelList& myFaces = surf.edgeFaces()[edgeI];
393 labelHashSet facesToBeCollapsed(2*myFaces.size());
395 forAll(myFaces, myFaceI)
397 facesToBeCollapsed.insert(myFaces[myFaceI]);
400 // From faces using v1 check if they share an edge with faces
402 // - share edge: are part of 'splay' tree and will collapse if edge
404 const labelList& v1Faces = surf.pointFaces()[v1];
406 forAll(v1Faces, v1FaceI)
408 label face1I = v1Faces[v1FaceI];
410 label otherEdgeI = oppositeEdge(surf, face1I, v1);
412 // Step across edge to other face
413 label face2I = otherFace(surf, face1I, otherEdgeI);
417 // found face on other side of edge. Now check if uses v2.
418 if (oppositeVertex(surf, face2I, otherEdgeI) == v2)
420 // triangles face1I and face2I form splay tree and will
422 facesToBeCollapsed.insert(face1I);
423 facesToBeCollapsed.insert(face2I);
428 return facesToBeCollapsed;
432 // Return value of faceUsed for faces using vertI
433 Foam::label Foam::triSurfaceTools::vertexUsesFace
435 const triSurface& surf,
436 const labelHashSet& faceUsed,
440 const labelList& myFaces = surf.pointFaces()[vertI];
442 forAll(myFaces, myFaceI)
444 label face1I = myFaces[myFaceI];
446 if (faceUsed.found(face1I))
455 // Calculate new edge-face addressing resulting from edge collapse
456 void Foam::triSurfaceTools::getMergedEdges
458 const triSurface& surf,
460 const labelHashSet& collapsedFaces,
461 HashTable<label, label, Hash<label> >& edgeToEdge,
462 HashTable<label, label, Hash<label> >& edgeToFace
465 const edge& e = surf.edges()[edgeI];
466 label v1 = e.start();
469 const labelList& v1Faces = surf.pointFaces()[v1];
470 const labelList& v2Faces = surf.pointFaces()[v2];
472 // Mark all (non collapsed) faces using v2
473 labelHashSet v2FacesHash(v2Faces.size());
475 forAll(v2Faces, v2FaceI)
477 if (!collapsedFaces.found(v2Faces[v2FaceI]))
479 v2FacesHash.insert(v2Faces[v2FaceI]);
484 forAll(v1Faces, v1FaceI)
486 label face1I = v1Faces[v1FaceI];
488 if (collapsedFaces.found(face1I))
494 // Check if face1I uses a vertex connected to a face using v2
507 //Pout<< "Face:" << surf.localFaces()[face1I] << " other vertices:"
508 // << vert1I << ' ' << vert2I << endl;
510 // Check vert1, vert2 for usage by v2Face.
512 label commonVert = vert1I;
513 label face2I = vertexUsesFace(surf, v2FacesHash, commonVert);
517 face2I = vertexUsesFace(surf, v2FacesHash, commonVert);
522 // Found one: commonVert is used by both face1I and face2I
523 label edge1I = getEdge(surf, v1, commonVert);
524 label edge2I = getEdge(surf, v2, commonVert);
526 edgeToEdge.insert(edge1I, edge2I);
527 edgeToEdge.insert(edge2I, edge1I);
529 edgeToFace.insert(edge1I, face2I);
530 edgeToFace.insert(edge2I, face1I);
536 // Calculates (cos of) angle across edgeI of faceI,
537 // taking into account updated addressing (resulting from edge collapse)
538 Foam::scalar Foam::triSurfaceTools::edgeCosAngle
540 const triSurface& surf,
543 const labelHashSet& collapsedFaces,
544 const HashTable<label, label, Hash<label> >& edgeToEdge,
545 const HashTable<label, label, Hash<label> >& edgeToFace,
550 const pointField& localPoints = surf.localPoints();
552 label A = surf.edges()[edgeI].start();
553 label B = surf.edges()[edgeI].end();
554 label C = oppositeVertex(surf, faceI, edgeI);
560 if (edgeToEdge.found(edgeI))
562 // Use merged addressing
563 label edge2I = edgeToEdge[edgeI];
564 face2I = edgeToFace[edgeI];
566 D = oppositeVertex(surf, face2I, edge2I);
570 // Use normal edge-face addressing
571 face2I = otherFace(surf, faceI, edgeI);
573 if ((face2I != -1) && !collapsedFaces.found(face2I))
575 D = oppositeVertex(surf, face2I, edgeI);
585 cosAngle = faceCosAngle
595 cosAngle = faceCosAngle
605 cosAngle = faceCosAngle
615 cosAngle = faceCosAngle
625 FatalErrorIn("edgeCosAngle")
626 << "face " << faceI << " does not use vertex "
627 << v1 << " of collapsed edge" << abort(FatalError);
634 //- Calculate minimum (cos of) edge angle using addressing from collapsing
636 Foam::scalar Foam::triSurfaceTools::collapseMinCosAngle
638 const triSurface& surf,
641 const labelHashSet& collapsedFaces,
642 const HashTable<label, label, Hash<label> >& edgeToEdge,
643 const HashTable<label, label, Hash<label> >& edgeToFace
646 const labelList& v1Faces = surf.pointFaces()[v1];
650 forAll(v1Faces, v1FaceI)
652 label faceI = v1Faces[v1FaceI];
654 if (collapsedFaces.found(faceI))
659 const labelList& myEdges = surf.faceEdges()[faceI];
661 forAll(myEdges, myEdgeI)
663 label edgeI = myEdges[myEdgeI];
688 // Calculate max dihedral angle after collapsing edge to v1 (at pt).
689 // Note that all edges of all faces using v1 are affected.
690 bool Foam::triSurfaceTools::collapseCreatesFold
692 const triSurface& surf,
695 const labelHashSet& collapsedFaces,
696 const HashTable<label, label, Hash<label> >& edgeToEdge,
697 const HashTable<label, label, Hash<label> >& edgeToFace,
701 const labelList& v1Faces = surf.pointFaces()[v1];
703 forAll(v1Faces, v1FaceI)
705 label faceI = v1Faces[v1FaceI];
707 if (collapsedFaces.found(faceI))
712 const labelList& myEdges = surf.faceEdges()[faceI];
714 forAll(myEdges, myEdgeI)
716 label edgeI = myEdges[myEdgeI];
743 //// Return true if collapsing edgeI creates triangles on top of each other.
744 //// Is when the triangles neighbouring the collapsed one already share
746 //bool Foam::triSurfaceTools::collapseCreatesDuplicates
748 // const triSurface& surf,
749 // const label edgeI,
750 // const labelHashSet& collapsedFaces
753 //Pout<< "duplicate : edgeI:" << edgeI << surf.edges()[edgeI]
754 // << " collapsedFaces:" << collapsedFaces.toc() << endl;
756 // // Mark neighbours of faces to be collapsed, i.e. get the first layer
757 // // of triangles outside collapsedFaces.
758 // // neighbours actually contains the
759 // // edge with which triangle connects to collapsedFaces.
761 // HashTable<label, label, Hash<label> > neighbours;
763 // labelList collapsed = collapsedFaces.toc();
765 // forAll(collapsed, collapseI)
767 // const label faceI = collapsed[collapseI];
769 // const labelList& myEdges = surf.faceEdges()[faceI];
771 // Pout<< "collapsing faceI:" << faceI << " uses edges:" << myEdges
774 // forAll(myEdges, myEdgeI)
776 // const labelList& myFaces = surf.edgeFaces()[myEdges[myEdgeI]];
778 // Pout<< "Edge " << myEdges[myEdgeI] << " is used by faces "
779 // << myFaces << endl;
781 // if ((myEdges[myEdgeI] != edgeI) && (myFaces.size() == 2))
783 // // Get the other face
784 // label neighbourFaceI = myFaces[0];
786 // if (neighbourFaceI == faceI)
788 // neighbourFaceI = myFaces[1];
791 // // Is 'outside' face if not in collapsedFaces itself
792 // if (!collapsedFaces.found(neighbourFaceI))
794 // neighbours.insert(neighbourFaceI, myEdges[myEdgeI]);
800 // // Now neighbours contains first layer of triangles outside of
802 // // There should be
803 // // -two if edgeI is a boundary edge
804 // // since the outside 'edge' of collapseFaces should
805 // // form a triangle and the face connected to edgeI is not inserted.
806 // // -four if edgeI is not a boundary edge since then the outside edge forms
809 // // Check if any of the faces in neighbours share an edge. (n^2)
811 // labelList neighbourList = neighbours.toc();
813 //Pout<< "edgeI:" << edgeI << " neighbourList:" << neighbourList << endl;
816 // forAll(neighbourList, i)
818 // const labelList& faceIEdges = surf.faceEdges()[neighbourList[i]];
820 // for (label j = i+1; j < neighbourList.size(); i++)
822 // const labelList& faceJEdges = surf.faceEdges()[neighbourList[j]];
824 // // Check if faceI and faceJ share an edge
825 // forAll(faceIEdges, fI)
827 // forAll(faceJEdges, fJ)
829 // Pout<< " comparing " << faceIEdges[fI] << " to "
830 // << faceJEdges[fJ] << endl;
832 // if (faceIEdges[fI] == faceJEdges[fJ])
840 // Pout<< "Found no match. Returning false" << endl;
845 // Finds the triangle edge cut by the plane between a point inside / on edge
846 // of a triangle and a point outside. Returns:
847 // - cut through edge/point
849 Foam::surfaceLocation Foam::triSurfaceTools::cutEdge
853 const label excludeEdgeI,
854 const label excludePointI,
856 const point& triPoint,
857 const plane& cutPlane,
861 const pointField& points = s.points();
862 const labelledTri& f = s[triI];
863 const labelList& fEdges = s.faceEdges()[triI];
865 // Get normal distance to planeN
866 FixedList<scalar, 3> d;
871 d[fp] = (points[f[fp]]-cutPlane.refPoint()) & cutPlane.normal();
875 // Normalise and truncate
880 if (mag(d[i]) < 1E-6)
886 // Return information
889 if (excludePointI != -1)
891 // Excluded point. Test only opposite edge.
893 label fp0 = findIndex(s.localFaces()[triI], excludePointI);
897 FatalErrorIn("cutEdge(..)") << "excludePointI:" << excludePointI
898 << " localF:" << s.localFaces()[triI] << abort(FatalError);
901 label fp1 = f.fcIndex(fp0);
902 label fp2 = f.fcIndex(fp1);
908 cut.setPoint(points[f[fp1]]);
909 cut.elementType() = triPointRef::POINT;
910 cut.setIndex(s.localFaces()[triI][fp1]);
912 else if (d[fp2] == 0.0)
915 cut.setPoint(points[f[fp2]]);
916 cut.elementType() = triPointRef::POINT;
917 cut.setIndex(s.localFaces()[triI][fp2]);
921 (d[fp1] < 0 && d[fp2] < 0)
922 || (d[fp1] > 0 && d[fp2] > 0)
925 // Both same sign. Not crossing edge at all.
926 // cut already set to miss().
933 (d[fp2]*points[f[fp1]] - d[fp1]*points[f[fp2]])
936 cut.elementType() = triPointRef::EDGE;
937 cut.setIndex(fEdges[fp1]);
942 // Find the two intersections
943 FixedList<surfaceLocation, 2> inters;
948 label fp1 = f.fcIndex(fp0);
954 FatalErrorIn("cutEdge(..)")
955 << "problem : triangle has three intersections." << nl
956 << "triangle:" << f.tri(points)
957 << " d:" << d << abort(FatalError);
959 inters[interI].setHit();
960 inters[interI].setPoint(points[f[fp0]]);
961 inters[interI].elementType() = triPointRef::POINT;
962 inters[interI].setIndex(s.localFaces()[triI][fp0]);
967 (d[fp0] < 0 && d[fp1] > 0)
968 || (d[fp0] > 0 && d[fp1] < 0)
973 FatalErrorIn("cutEdge(..)")
974 << "problem : triangle has three intersections." << nl
975 << "triangle:" << f.tri(points)
976 << " d:" << d << abort(FatalError);
978 inters[interI].setHit();
979 inters[interI].setPoint
981 (d[fp0]*points[f[fp1]] - d[fp1]*points[f[fp0]])
984 inters[interI].elementType() = triPointRef::EDGE;
985 inters[interI].setIndex(fEdges[fp0]);
995 else if (interI == 1)
997 // Only one intersection. Should not happen!
1000 else if (interI == 2)
1002 // Handle excludeEdgeI
1005 inters[0].elementType() == triPointRef::EDGE
1006 && inters[0].index() == excludeEdgeI
1013 inters[1].elementType() == triPointRef::EDGE
1014 && inters[1].index() == excludeEdgeI
1021 // Two cuts. Find nearest.
1024 magSqr(inters[0].rawPoint() - toPoint)
1025 < magSqr(inters[1].rawPoint() - toPoint)
1041 // 'Snap' point on to endPoint.
1042 void Foam::triSurfaceTools::snapToEnd
1044 const triSurface& s,
1045 const surfaceLocation& end,
1046 surfaceLocation& current
1049 if (end.elementType() == triPointRef::NONE)
1051 if (current.elementType() == triPointRef::NONE)
1053 // endpoint on triangle; current on triangle
1054 if (current.index() == end.index())
1058 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1065 // No need to handle current on edge/point since tracking handles this.
1067 else if (end.elementType() == triPointRef::EDGE)
1069 if (current.elementType() == triPointRef::NONE)
1071 // endpoint on edge; current on triangle
1072 const labelList& fEdges = s.faceEdges()[current.index()];
1074 if (findIndex(fEdges, end.index()) != -1)
1078 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1085 else if (current.elementType() == triPointRef::EDGE)
1087 // endpoint on edge; current on edge
1088 if (current.index() == end.index())
1092 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1101 // endpoint on edge; current on point
1102 const edge& e = s.edges()[end.index()];
1104 if (current.index() == e[0] || current.index() == e[1])
1108 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1116 else // end.elementType() == POINT
1118 if (current.elementType() == triPointRef::NONE)
1120 // endpoint on point; current on triangle
1121 const labelledTri& f = s.localFaces()[current.index()];
1123 if (findIndex(f, end.index()) != -1)
1127 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1134 else if (current.elementType() == triPointRef::EDGE)
1136 // endpoint on point; current on edge
1137 const edge& e = s.edges()[current.index()];
1139 if (end.index() == e[0] || end.index() == e[1])
1143 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1152 // endpoint on point; current on point
1153 if (current.index() == end.index())
1157 // Pout<< "snapToEnd : snapping:" << current << " onto:"
1170 // - element type (triangle/edge/point) and index
1171 // - triangle to exclude
1172 Foam::surfaceLocation Foam::triSurfaceTools::visitFaces
1174 const triSurface& s,
1175 const labelList& eFaces,
1176 const surfaceLocation& start,
1177 const label excludeEdgeI,
1178 const label excludePointI,
1179 const surfaceLocation& end,
1180 const plane& cutPlane
1183 surfaceLocation nearest;
1185 scalar minDistSqr = Foam::sqr(GREAT);
1189 label triI = eFaces[i];
1191 // Make sure we don't revisit previous face
1192 if (triI != start.triangle())
1194 if (end.elementType() == triPointRef::NONE && end.index() == triI)
1196 // Endpoint is in this triangle. Jump there.
1199 nearest.triangle() = triI;
1204 // Which edge is cut.
1206 surfaceLocation cutInfo = cutEdge
1210 excludeEdgeI, // excludeEdgeI
1211 excludePointI, // excludePointI
1217 // If crossing an edge we expect next edge to be cut.
1218 if (excludeEdgeI != -1 && !cutInfo.hit())
1220 FatalErrorIn("triSurfaceTools::visitFaces(..)")
1221 << "Triangle:" << triI
1222 << " excludeEdge:" << excludeEdgeI
1223 << " point:" << start.rawPoint()
1224 << " plane:" << cutPlane
1225 << " . No intersection!" << abort(FatalError);
1230 scalar distSqr = magSqr(cutInfo.rawPoint()-end.rawPoint());
1232 if (distSqr < minDistSqr)
1234 minDistSqr = distSqr;
1236 nearest.triangle() = triI;
1244 if (nearest.triangle() == -1)
1246 // Did not move from edge. Give warning? Return something special?
1247 // For now responsability of caller to make sure that nothing has
1255 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1258 // Write pointField to file
1259 void Foam::triSurfaceTools::writeOBJ
1261 const fileName& fName,
1262 const pointField& pts
1265 OFstream outFile(fName);
1269 const point& pt = pts[pointI];
1271 outFile<< "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
1273 Pout<< "Written " << pts.size() << " vertices to file " << fName << endl;
1277 // Write vertex subset to OBJ format file
1278 void Foam::triSurfaceTools::writeOBJ
1280 const triSurface& surf,
1281 const fileName& fName,
1282 const boolList& markedVerts
1285 OFstream outFile(fName);
1288 forAll(markedVerts, vertI)
1290 if (markedVerts[vertI])
1292 const point& pt = surf.localPoints()[vertI];
1294 outFile<< "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
1299 Pout<< "Written " << nVerts << " vertices to file " << fName << endl;
1303 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1304 // Addressing helper functions:
1307 // Get all triangles using vertices of edge
1308 void Foam::triSurfaceTools::getVertexTriangles
1310 const triSurface& surf,
1315 const edge& e = surf.edges()[edgeI];
1316 const labelList& myFaces = surf.edgeFaces()[edgeI];
1318 label face1I = myFaces[0];
1320 if (myFaces.size() == 2)
1322 face2I = myFaces[1];
1325 const labelList& startFaces = surf.pointFaces()[e.start()];
1326 const labelList& endFaces = surf.pointFaces()[e.end()];
1328 // Number of triangles is sum of pointfaces - common faces
1329 // (= faces using edge)
1330 edgeTris.setSize(startFaces.size() + endFaces.size() - myFaces.size());
1333 forAll(startFaces, startFaceI)
1335 edgeTris[nTris++] = startFaces[startFaceI];
1338 forAll(endFaces, endFaceI)
1340 label faceI = endFaces[endFaceI];
1342 if ((faceI != face1I) && (faceI != face2I))
1344 edgeTris[nTris++] = faceI;
1350 // Get all vertices connected to vertices of edge
1351 Foam::labelList Foam::triSurfaceTools::getVertexVertices
1353 const triSurface& surf,
1357 const edgeList& edges = surf.edges();
1359 label v1 = e.start();
1362 // Get all vertices connected to v1 or v2 through an edge
1363 labelHashSet vertexNeighbours;
1365 const labelList& v1Edges = surf.pointEdges()[v1];
1367 forAll(v1Edges, v1EdgeI)
1369 const edge& e = edges[v1Edges[v1EdgeI]];
1370 vertexNeighbours.insert(e.otherVertex(v1));
1373 const labelList& v2Edges = surf.pointEdges()[v2];
1375 forAll(v2Edges, v2EdgeI)
1377 const edge& e = edges[v2Edges[v2EdgeI]];
1379 label vertI = e.otherVertex(v2);
1381 vertexNeighbours.insert(vertI);
1383 return vertexNeighbours.toc();
1387 //// Order vertices consistent with face
1388 //void Foam::triSurfaceTools::orderVertices
1390 // const labelledTri& f,
1397 // // Order v1, v2 in anticlockwise order.
1398 // bool reverse = false;
1407 // else if (f[1] == v1)
1435 // Get the other face using edgeI
1436 Foam::label Foam::triSurfaceTools::otherFace
1438 const triSurface& surf,
1443 const labelList& myFaces = surf.edgeFaces()[edgeI];
1445 if (myFaces.size() != 2)
1451 if (faceI == myFaces[0])
1463 // Get the two edges on faceI counterclockwise after edgeI
1464 void Foam::triSurfaceTools::otherEdges
1466 const triSurface& surf,
1473 const labelList& eFaces = surf.faceEdges()[faceI];
1475 label i0 = findIndex(eFaces, edgeI);
1482 "(const triSurface&, const label, const label,"
1484 ) << "Edge " << surf.edges()[edgeI] << " not in face "
1485 << surf.localFaces()[faceI] << abort(FatalError);
1488 label i1 = eFaces.fcIndex(i0);
1489 label i2 = eFaces.fcIndex(i1);
1496 // Get the two vertices on faceI counterclockwise vertI
1497 void Foam::triSurfaceTools::otherVertices
1499 const triSurface& surf,
1506 const labelledTri& f = surf.localFaces()[faceI];
1513 else if (vertI == f[1])
1518 else if (vertI == f[2])
1528 "(const triSurface&, const label, const label,"
1530 ) << "Vertex " << vertI << " not in face " << f << abort(FatalError);
1535 // Get edge opposite vertex
1536 Foam::label Foam::triSurfaceTools::oppositeEdge
1538 const triSurface& surf,
1543 const labelList& myEdges = surf.faceEdges()[faceI];
1545 forAll(myEdges, myEdgeI)
1547 label edgeI = myEdges[myEdgeI];
1549 const edge& e = surf.edges()[edgeI];
1551 if ((e.start() != vertI) && (e.end() != vertI))
1560 "(const triSurface&, const label, const label)"
1561 ) << "Cannot find vertex " << vertI << " in edges of face " << faceI
1562 << abort(FatalError);
1568 // Get vertex opposite edge
1569 Foam::label Foam::triSurfaceTools::oppositeVertex
1571 const triSurface& surf,
1576 const labelledTri& f = surf.localFaces()[faceI];
1578 const edge& e = surf.edges()[edgeI];
1582 label vertI = f[fp];
1584 if (vertI != e.start() && vertI != e.end())
1590 FatalErrorIn("triSurfaceTools::oppositeVertex")
1591 << "Cannot find vertex opposite edge " << edgeI << " vertices " << e
1592 << " in face " << faceI << " vertices " << f << abort(FatalError);
1598 // Returns edge label connecting v1, v2
1599 Foam::label Foam::triSurfaceTools::getEdge
1601 const triSurface& surf,
1606 const labelList& v1Edges = surf.pointEdges()[v1];
1608 forAll(v1Edges, v1EdgeI)
1610 label edgeI = v1Edges[v1EdgeI];
1612 const edge& e = surf.edges()[edgeI];
1614 if ((e.start() == v2) || (e.end() == v2))
1623 // Return index of triangle (or -1) using all three edges
1624 Foam::label Foam::triSurfaceTools::getTriangle
1626 const triSurface& surf,
1632 if ((e0I == e1I) || (e0I == e2I) || (e1I == e2I))
1637 "(const triSurface&, const label, const label,"
1639 ) << "Duplicate edge labels : e0:" << e0I << " e1:" << e1I
1641 << abort(FatalError);
1644 const labelList& eFaces = surf.edgeFaces()[e0I];
1646 forAll(eFaces, eFaceI)
1648 label faceI = eFaces[eFaceI];
1650 const labelList& myEdges = surf.faceEdges()[faceI];
1655 || (myEdges[1] == e1I)
1656 || (myEdges[2] == e1I)
1662 || (myEdges[1] == e2I)
1663 || (myEdges[2] == e2I)
1674 // Collapse indicated edges. Return new tri surface.
1675 Foam::triSurface Foam::triSurfaceTools::collapseEdges
1677 const triSurface& surf,
1678 const labelList& collapsableEdges
1681 pointField edgeMids(surf.nEdges());
1683 forAll(edgeMids, edgeI)
1685 const edge& e = surf.edges()[edgeI];
1690 surf.localPoints()[e.start()]
1691 + surf.localPoints()[e.end()]
1696 labelList faceStatus(surf.size(), ANYEDGE);
1698 //// Protect triangles which are on the border of different regions
1699 //forAll(edges, edgeI)
1701 // const labelList& neighbours = edgeFaces[edgeI];
1703 // if ((neighbours.size() != 2) && (neighbours.size() != 1))
1705 // FatalErrorIn("collapseEdges")
1706 // << abort(FatalError);
1709 // if (neighbours.size() == 2)
1711 // if (surf[neighbours[0]].region() != surf[neighbours[1]].region())
1713 // // Neighbours on different regions. For now dont allow
1715 // //Pout<< "protecting face " << neighbours[0]
1716 // // << ' ' << neighbours[1] << endl;
1717 // faceStatus[neighbours[0]] = NOEDGE;
1718 // faceStatus[neighbours[1]] = NOEDGE;
1723 return collapseEdges(surf, collapsableEdges, edgeMids, faceStatus);
1727 // Collapse indicated edges. Return new tri surface.
1728 Foam::triSurface Foam::triSurfaceTools::collapseEdges
1730 const triSurface& surf,
1731 const labelList& collapseEdgeLabels,
1732 const pointField& edgeMids,
1733 labelList& faceStatus
1736 const labelListList& edgeFaces = surf.edgeFaces();
1737 const pointField& localPoints = surf.localPoints();
1738 const edgeList& edges = surf.edges();
1740 // Storage for new points
1741 pointField newPoints(localPoints);
1743 // Map for old to new points
1744 labelList pointMap(localPoints.size());
1745 forAll(localPoints, pointI)
1747 pointMap[pointI] = pointI;
1751 // Do actual 'collapsing' of edges
1753 forAll(collapseEdgeLabels, collapseEdgeI)
1755 const label edgeI = collapseEdgeLabels[collapseEdgeI];
1757 if ((edgeI < 0) || (edgeI >= surf.nEdges()))
1759 FatalErrorIn("collapseEdges")
1760 << "Edge label outside valid range." << endl
1761 << "edge label:" << edgeI << endl
1762 << "total number of edges:" << surf.nEdges() << endl
1763 << abort(FatalError);
1766 const labelList& neighbours = edgeFaces[edgeI];
1768 if (neighbours.size() == 2)
1770 const label stat0 = faceStatus[neighbours[0]];
1771 const label stat1 = faceStatus[neighbours[1]];
1773 // Check faceStatus to make sure this one can be collapsed
1776 ((stat0 == ANYEDGE) || (stat0 == edgeI))
1777 && ((stat1 == ANYEDGE) || (stat1 == edgeI))
1780 const edge& e = edges[edgeI];
1782 // Set up mapping to 'collapse' points of edge
1785 (pointMap[e.start()] != e.start())
1786 || (pointMap[e.end()] != e.end())
1789 FatalErrorIn("collapseEdges")
1790 << "points already mapped. Double collapse." << endl
1791 << "edgeI:" << edgeI
1792 << " start:" << e.start()
1793 << " end:" << e.end()
1794 << " pointMap[start]:" << pointMap[e.start()]
1795 << " pointMap[end]:" << pointMap[e.end()]
1796 << abort(FatalError);
1799 const label minVert = min(e.start(), e.end());
1800 pointMap[e.start()] = minVert;
1801 pointMap[e.end()] = minVert;
1803 // Move shared vertex to mid of edge
1804 newPoints[minVert] = edgeMids[edgeI];
1806 // Protect neighbouring faces
1807 protectNeighbours(surf, e.start(), faceStatus);
1808 protectNeighbours(surf, e.end(), faceStatus);
1812 oppositeVertex(surf, neighbours[0], edgeI),
1818 oppositeVertex(surf, neighbours[1], edgeI),
1822 // Mark all collapsing faces
1823 labelList collapseFaces =
1830 forAll(collapseFaces, collapseI)
1832 faceStatus[collapseFaces[collapseI]] = COLLAPSED;
1839 // Storage for new triangles
1840 List<labelledTri> newTris(surf.size());
1843 const List<labelledTri>& localFaces = surf.localFaces();
1846 // Get only non-collapsed triangles and renumber vertex labels.
1847 forAll(localFaces, faceI)
1849 const labelledTri& f = localFaces[faceI];
1851 const label a = pointMap[f[0]];
1852 const label b = pointMap[f[1]];
1853 const label c = pointMap[f[2]];
1857 (a != b) && (a != c) && (b != c)
1858 && (faceStatus[faceI] != COLLAPSED)
1861 // uncollapsed triangle
1862 newTris[newTriI++] = labelledTri(a, b, c, f.region());
1866 //Pout<< "Collapsed triangle " << faceI
1867 // << " vertices:" << f << endl;
1870 newTris.setSize(newTriI);
1876 triSurface tempSurf(newTris, surf.patches(), newPoints);
1881 tempSurf.localFaces(),
1883 tempSurf.localPoints()
1888 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1890 Foam::triSurface Foam::triSurfaceTools::redGreenRefine
1892 const triSurface& surf,
1893 const labelList& refineFaces
1896 List<refineType> refineStatus(surf.size(), NONE);
1898 // Mark & propagate refinement
1899 forAll(refineFaces, refineFaceI)
1901 calcRefineStatus(surf, refineFaces[refineFaceI], refineStatus);
1904 // Do actual refinement
1905 return doRefine(surf, refineStatus);
1909 Foam::triSurface Foam::triSurfaceTools::greenRefine
1911 const triSurface& surf,
1912 const labelList& refineEdges
1915 // Storage for marking faces
1916 List<refineType> refineStatus(surf.size(), NONE);
1918 // Storage for new faces
1919 DynamicList<labelledTri> newFaces(0);
1921 pointField newPoints(surf.localPoints());
1922 newPoints.setSize(surf.nPoints() + surf.nEdges());
1923 label newPointI = surf.nPoints();
1927 forAll(refineEdges, refineEdgeI)
1929 label edgeI = refineEdges[refineEdgeI];
1931 const labelList& myFaces = surf.edgeFaces()[edgeI];
1933 bool neighbourIsRefined= false;
1935 forAll(myFaces, myFaceI)
1937 if (refineStatus[myFaces[myFaceI]] != NONE)
1939 neighbourIsRefined = true;
1943 // Only refine if none of the faces is refined
1944 if (!neighbourIsRefined)
1947 const edge& e = surf.edges()[edgeI];
1952 surf.localPoints()[e.start()]
1953 + surf.localPoints()[e.end()]
1956 newPoints[newPointI] = mid;
1958 // Refine faces using edge
1959 forAll(myFaces, myFaceI)
1961 // Add faces to newFaces
1972 refineStatus[myFaces[myFaceI]] = GREEN;
1979 // Add unrefined faces
1980 forAll(surf.localFaces(), faceI)
1982 if (refineStatus[faceI] == NONE)
1984 newFaces.append(surf.localFaces()[faceI]);
1989 newPoints.setSize(newPointI);
1991 return triSurface(newFaces, surf.patches(), newPoints);
1996 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1997 // Geometric helper functions:
2000 // Returns element in edgeIndices with minimum length
2001 Foam::label Foam::triSurfaceTools::minEdge
2003 const triSurface& surf,
2004 const labelList& edgeIndices
2007 scalar minLength = GREAT;
2008 label minIndex = -1;
2009 forAll(edgeIndices, i)
2011 const edge& e = surf.edges()[edgeIndices[i]];
2016 surf.localPoints()[e.end()]
2017 - surf.localPoints()[e.start()]
2020 if (length < minLength)
2026 return edgeIndices[minIndex];
2030 // Returns element in edgeIndices with maximum length
2031 Foam::label Foam::triSurfaceTools::maxEdge
2033 const triSurface& surf,
2034 const labelList& edgeIndices
2037 scalar maxLength = -GREAT;
2038 label maxIndex = -1;
2039 forAll(edgeIndices, i)
2041 const edge& e = surf.edges()[edgeIndices[i]];
2046 surf.localPoints()[e.end()]
2047 - surf.localPoints()[e.start()]
2050 if (length > maxLength)
2056 return edgeIndices[maxIndex];
2060 // Merge points and reconstruct surface
2061 Foam::triSurface Foam::triSurfaceTools::mergePoints
2063 const triSurface& surf,
2064 const scalar mergeTol
2067 pointField newPoints(surf.nPoints());
2069 labelList pointMap(surf.nPoints());
2071 bool hasMerged = Foam::mergePoints
2082 // Pack the triangles
2084 // Storage for new triangles
2085 List<labelledTri> newTriangles(surf.size());
2086 label newTriangleI = 0;
2090 const labelledTri& f = surf.localFaces()[faceI];
2092 label newA = pointMap[f[0]];
2093 label newB = pointMap[f[1]];
2094 label newC = pointMap[f[2]];
2096 if ((newA != newB) && (newA != newC) && (newB != newC))
2098 newTriangles[newTriangleI++] =
2099 labelledTri(newA, newB, newC, f.region());
2102 newTriangles.setSize(newTriangleI);
2118 // Calculate normal on triangle
2119 Foam::vector Foam::triSurfaceTools::surfaceNormal
2121 const triSurface& surf,
2122 const label nearestFaceI,
2123 const point& nearestPt
2126 const labelledTri& f = surf[nearestFaceI];
2127 const pointField& points = surf.points();
2136 ).classify(nearestPt, 1E-6, nearType, nearLabel);
2138 if (nearType == triPointRef::NONE)
2141 return surf.faceNormals()[nearestFaceI];
2143 else if (nearType == triPointRef::EDGE)
2145 // Nearest to edge. Assume order of faceEdges same as face vertices.
2146 label edgeI = surf.faceEdges()[nearestFaceI][nearLabel];
2148 // Calculate edge normal by averaging face normals
2149 const labelList& eFaces = surf.edgeFaces()[edgeI];
2151 vector edgeNormal(vector::zero);
2155 edgeNormal += surf.faceNormals()[eFaces[i]];
2157 return edgeNormal/(mag(edgeNormal) + VSMALL);
2162 const labelledTri& localF = surf.localFaces()[nearestFaceI];
2163 return surf.pointNormals()[localF[nearLabel]];
2168 Foam::triSurfaceTools::sideType Foam::triSurfaceTools::edgeSide
2170 const triSurface& surf,
2171 const point& sample,
2172 const point& nearestPoint,
2176 const labelList& eFaces = surf.edgeFaces()[edgeI];
2178 if (eFaces.size() != 2)
2180 // Surface not closed.
2185 const vectorField& faceNormals = surf.faceNormals();
2187 // Compare to bisector. This is actually correct since edge is
2188 // nearest so there is a knife-edge.
2190 vector n = 0.5*(faceNormals[eFaces[0]] + faceNormals[eFaces[1]]);
2192 if (((sample - nearestPoint) & n) > 0)
2204 // Calculate normal on triangle
2205 Foam::triSurfaceTools::sideType Foam::triSurfaceTools::surfaceSide
2207 const triSurface& surf,
2208 const point& sample,
2209 const label nearestFaceI, // nearest face
2210 const point& nearestPoint // nearest point on nearest face
2213 const labelledTri& f = surf[nearestFaceI];
2214 const pointField& points = surf.points();
2216 // Find where point is on triangle. Note tolerance needed. Is relative
2217 // one (used in comparing normalized [0..1] triangle coordinates).
2218 label nearType, nearLabel;
2224 ).classify(nearestPoint, 1E-6, nearType, nearLabel);
2226 if (nearType == triPointRef::NONE)
2228 // Nearest to face interior. Use faceNormal to determine side
2229 scalar c = (sample - nearestPoint) & surf.faceNormals()[nearestFaceI];
2240 else if (nearType == triPointRef::EDGE)
2242 // Nearest to edge nearLabel. Note that this can only be a knife-edge
2243 // situation since otherwise the nearest point could never be the edge.
2245 // Get the edge. Assume order of faceEdges same as face vertices.
2246 label edgeI = surf.faceEdges()[nearestFaceI][nearLabel];
2250 // // Check order of faceEdges same as face vertices.
2251 // const edge& e = surf.edges()[edgeI];
2252 // const labelList& meshPoints = surf.meshPoints();
2253 // const edge meshEdge(meshPoints[e[0]], meshPoints[e[1]]);
2258 // != edge(f[nearLabel], f[f.fcIndex(nearLabel)])
2261 // FatalErrorIn("triSurfaceTools::surfaceSide")
2262 // << "Edge:" << edgeI << " local vertices:" << e
2263 // << " mesh vertices:" << meshEdge
2264 // << " not at position " << nearLabel
2265 // << " in face " << f
2266 // << abort(FatalError);
2270 return edgeSide(surf, sample, nearestPoint, edgeI);
2274 // Nearest to point. Could use pointNormal here but is not correct.
2275 // Instead determine which edge using point is nearest and use test
2276 // above (nearType == triPointRef::EDGE).
2279 const labelledTri& localF = surf.localFaces()[nearestFaceI];
2280 label nearPointI = localF[nearLabel];
2282 const edgeList& edges = surf.edges();
2283 const pointField& localPoints = surf.localPoints();
2284 const point& base = localPoints[nearPointI];
2286 const labelList& pEdges = surf.pointEdges()[nearPointI];
2288 scalar minDistSqr = Foam::sqr(GREAT);
2289 label minEdgeI = -1;
2293 label edgeI = pEdges[i];
2295 const edge& e = edges[edgeI];
2297 label otherPointI = e.otherVertex(nearPointI);
2300 vector eVec(localPoints[otherPointI] - base);
2301 scalar magEVec = mag(eVec);
2303 if (magEVec > VSMALL)
2307 // Get point along vector and determine closest.
2308 const point perturbPoint = base + eVec;
2310 scalar distSqr = Foam::magSqr(sample - perturbPoint);
2312 if (distSqr < minDistSqr)
2314 minDistSqr = distSqr;
2322 FatalErrorIn("treeDataTriSurface::getSide")
2323 << "Problem: did not find edge closer than " << minDistSqr
2324 << abort(FatalError);
2327 return edgeSide(surf, sample, nearestPoint, minEdgeI);
2332 // triangulation of boundaryMesh
2333 Foam::triSurface Foam::triSurfaceTools::triangulate
2335 const polyBoundaryMesh& bMesh,
2336 const labelHashSet& includePatches,
2340 const polyMesh& mesh = bMesh.mesh();
2342 // Storage for surfaceMesh. Size estimate.
2343 DynamicList<labelledTri> triangles
2345 mesh.nFaces() - mesh.nInternalFaces()
2348 label newPatchI = 0;
2352 labelHashSet::const_iterator iter = includePatches.begin();
2353 iter != includePatches.end();
2357 label patchI = iter.key();
2359 const polyPatch& patch = bMesh[patchI];
2361 const pointField& points = patch.points();
2363 label nTriTotal = 0;
2365 forAll(patch, patchFaceI)
2367 const face& f = patch[patchFaceI];
2369 faceList triFaces(f.nTriangles(points));
2373 f.triangles(points, nTri, triFaces);
2375 forAll(triFaces, triFaceI)
2377 const face& f = triFaces[triFaceI];
2379 triangles.append(labelledTri(f[0], f[1], f[2], newPatchI));
2387 Pout<< patch.name() << " : generated " << nTriTotal
2388 << " triangles from " << patch.size() << " faces with"
2389 << " new patchid " << newPatchI << endl;
2396 // Create globally numbered tri surface
2397 triSurface rawSurface(triangles, mesh.points());
2399 // Create locally numbered tri surface
2402 rawSurface.localFaces(),
2403 rawSurface.localPoints()
2406 // Add patch names to surface
2407 surface.patches().setSize(newPatchI);
2413 labelHashSet::const_iterator iter = includePatches.begin();
2414 iter != includePatches.end();
2418 label patchI = iter.key();
2420 const polyPatch& patch = bMesh[patchI];
2422 surface.patches()[newPatchI].name() = patch.name();
2424 surface.patches()[newPatchI].geometricType() = patch.type();
2433 // triangulation of boundaryMesh
2434 Foam::triSurface Foam::triSurfaceTools::triangulateFaceCentre
2436 const polyBoundaryMesh& bMesh,
2437 const labelHashSet& includePatches,
2441 const polyMesh& mesh = bMesh.mesh();
2443 // Storage for new points = meshpoints + face centres.
2444 const pointField& points = mesh.points();
2445 const pointField& faceCentres = mesh.faceCentres();
2447 pointField newPoints(points.size() + faceCentres.size());
2449 label newPointI = 0;
2451 forAll(points, pointI)
2453 newPoints[newPointI++] = points[pointI];
2455 forAll(faceCentres, faceI)
2457 newPoints[newPointI++] = faceCentres[faceI];
2461 // Count number of faces.
2462 DynamicList<labelledTri> triangles
2464 mesh.nFaces() - mesh.nInternalFaces()
2467 label newPatchI = 0;
2471 labelHashSet::const_iterator iter = includePatches.begin();
2472 iter != includePatches.end();
2476 label patchI = iter.key();
2478 const polyPatch& patch = bMesh[patchI];
2480 label nTriTotal = 0;
2482 forAll(patch, patchFaceI)
2484 // Face in global coords.
2485 const face& f = patch[patchFaceI];
2487 // Index in newPointI of face centre.
2488 label fc = points.size() + patchFaceI + patch.start();
2492 label fp1 = (fp + 1) % f.size();
2494 triangles.append(labelledTri(f[fp], f[fp1], fc, newPatchI));
2502 Pout<< patch.name() << " : generated " << nTriTotal
2503 << " triangles from " << patch.size() << " faces with"
2504 << " new patchid " << newPatchI << endl;
2512 // Create globally numbered tri surface
2513 triSurface rawSurface(triangles, newPoints);
2515 // Create locally numbered tri surface
2518 rawSurface.localFaces(),
2519 rawSurface.localPoints()
2522 // Add patch names to surface
2523 surface.patches().setSize(newPatchI);
2529 labelHashSet::const_iterator iter = includePatches.begin();
2530 iter != includePatches.end();
2534 label patchI = iter.key();
2536 const polyPatch& patch = bMesh[patchI];
2538 surface.patches()[newPatchI].name() = patch.name();
2540 surface.patches()[newPatchI].geometricType() = patch.type();
2549 Foam::triSurface Foam::triSurfaceTools::delaunay2D(const List<vector2D>& pts)
2551 // Vertices in geompack notation. Note that could probably just use
2552 // pts.begin() if double precision.
2553 List<doubleScalar> geompackVertices(2*pts.size());
2557 geompackVertices[doubleI++] = pts[i][0];
2558 geompackVertices[doubleI++] = pts[i][1];
2561 // Storage for triangles
2563 List<int> triangle_node(m2*3*pts.size());
2564 List<int> triangle_neighbor(m2*3*pts.size());
2571 geompackVertices.begin(),
2573 triangle_node.begin(),
2574 triangle_neighbor.begin()
2578 triangle_node.setSize(3*nTris);
2579 triangle_neighbor.setSize(3*nTris);
2581 // Convert to triSurface.
2582 List<labelledTri> faces(nTris);
2586 faces[i] = labelledTri
2588 triangle_node[3*i]-1,
2589 triangle_node[3*i+1]-1,
2590 triangle_node[3*i+2]-1,
2595 pointField points(pts.size());
2598 points[i][0] = pts[i][0];
2599 points[i][1] = pts[i][1];
2603 return triSurface(faces, points);
2607 //// Use CGAL to do Delaunay
2608 //#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
2609 //#include <CGAL/Delaunay_triangulation_2.h>
2610 //#include <CGAL/Triangulation_vertex_base_with_info_2.h>
2611 //#include <cassert>
2613 //struct K : CGAL::Exact_predicates_inexact_constructions_kernel {};
2615 //typedef CGAL::Triangulation_vertex_base_with_info_2<Foam::label, K> Vb;
2616 //typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
2617 //typedef CGAL::Delaunay_triangulation_2<K,Tds> Triangulation;
2619 //typedef Triangulation::Vertex_handle Vertex_handle;
2620 //typedef Triangulation::Vertex_iterator Vertex_iterator;
2621 //typedef Triangulation::Face_handle Face_handle;
2622 //typedef Triangulation::Finite_faces_iterator Finite_faces_iterator;
2623 //typedef Triangulation::Point Point;
2624 //Foam::triSurface Foam::triSurfaceTools::delaunay2D(const List<vector2D>& pts)
2628 // // Insert 2D vertices; building triangulation
2631 // const point& pt = pts[i];
2633 // T.insert(Point(pt[0], pt[1]));
2637 // // Number vertices
2638 // // ~~~~~~~~~~~~~~~
2643 // Vertex_iterator it = T.vertices_begin();
2644 // it != T.vertices_end();
2648 // it->info() = vertI++;
2654 // List<labelledTri> faces(T.number_of_faces());
2660 // Finite_faces_iterator fc = T.finite_faces_begin();
2661 // fc != T.finite_faces_end();
2665 // faces[faceI++] = labelledTri
2667 // fc->vertex(0)->info(),
2668 // f[1] = fc->vertex(1)->info(),
2669 // f[2] = fc->vertex(2)->info()
2673 // pointField points(pts.size());
2676 // points[i][0] = pts[i][0];
2677 // points[i][1] = pts[i][1];
2678 // points[i][2] = 0.0;
2681 // return triSurface(faces, points);
2685 void Foam::triSurfaceTools::calcInterpolationWeights
2687 const triPointRef& tri,
2689 FixedList<scalar, 3>& weights
2692 // calculate triangle edge vectors and triangle face normal
2693 // the 'i':th edge is opposite node i
2694 FixedList<vector, 3> edge;
2695 edge[0] = tri.c()-tri.b();
2696 edge[1] = tri.a()-tri.c();
2697 edge[2] = tri.b()-tri.a();
2699 vector triangleFaceNormal = edge[1] ^ edge[2];
2701 // calculate edge normal (pointing inwards)
2702 FixedList<vector, 3> normal;
2703 for(label i=0; i<3; i++)
2705 normal[i] = triangleFaceNormal ^ edge[i];
2706 normal[i] /= mag(normal[i]) + VSMALL;
2709 weights[0] = ((p-tri.b()) & normal[0]) / max(VSMALL, normal[0] & edge[1]);
2710 weights[1] = ((p-tri.c()) & normal[1]) / max(VSMALL, normal[1] & edge[2]);
2711 weights[2] = ((p-tri.a()) & normal[2]) / max(VSMALL, normal[2] & edge[0]);
2715 // Calculate weighting factors from samplePts to triangle it is in.
2716 // Uses linear search.
2717 void Foam::triSurfaceTools::calcInterpolationWeights
2719 const triSurface& s,
2720 const pointField& samplePts,
2721 List<FixedList<label, 3> >& allVerts,
2722 List<FixedList<scalar, 3> >& allWeights
2725 allVerts.setSize(samplePts.size());
2726 allWeights.setSize(samplePts.size());
2728 const pointField& points = s.points();
2730 forAll(samplePts, i)
2732 const point& samplePt = samplePts[i];
2735 FixedList<label, 3>& verts = allVerts[i];
2736 FixedList<scalar, 3>& weights = allWeights[i];
2738 scalar minDistance = GREAT;
2742 const labelledTri& f = s[faceI];
2744 triPointRef tri(f.tri(points));
2746 pointHit nearest = tri.nearestPoint(samplePt);
2750 // samplePt inside triangle
2755 calcInterpolationWeights(tri, nearest.rawPoint(), weights);
2757 //Pout<< "calcScalingFactors : samplePt:" << samplePt
2758 // << " inside triangle:" << faceI
2759 // << " verts:" << verts
2760 // << " weights:" << weights
2765 else if (nearest.distance() < minDistance)
2767 minDistance = nearest.distance();
2769 // Outside triangle. Store nearest.
2770 label nearType, nearLabel;
2774 1E-6, // relative tolerance
2779 if (nearType == triPointRef::POINT)
2781 verts[0] = f[nearLabel];
2784 weights[1] = -GREAT;
2786 weights[2] = -GREAT;
2788 //Pout<< "calcScalingFactors : samplePt:" << samplePt
2789 // << " distance:" << nearest.distance()
2790 // << " from point:" << points[f[nearLabel]]
2793 else if (nearType == triPointRef::EDGE)
2795 verts[0] = f[nearLabel];
2796 verts[1] = f[f.fcIndex(nearLabel)];
2799 const point& p0 = points[verts[0]];
2800 const point& p1 = points[verts[1]];
2808 mag(nearest.rawPoint()-p0)/mag(p1-p0)
2815 weights[2] = -GREAT;
2817 //Pout<< "calcScalingFactors : samplePt:" << samplePt
2818 // << " distance:" << nearest.distance()
2819 // << " from edge:" << p0 << p1 << " s:" << s
2824 // triangle. Can only happen because of truncation errors.
2829 calcInterpolationWeights(tri, nearest.rawPoint(), weights);
2839 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2843 // Test point on surface to see if is on face,edge or point.
2844 Foam::surfaceLocation Foam::triSurfaceTools::classify
2846 const triSurface& s,
2848 const point& trianglePoint
2851 surfaceLocation nearest;
2853 // Nearest point could be on point or edge. Retest.
2854 label index, elemType;
2856 triPointRef(s[triI].tri(s.points())).classify
2864 nearest.setPoint(trianglePoint);
2866 if (elemType == triPointRef::NONE)
2869 nearest.setIndex(triI);
2870 nearest.elementType() = triPointRef::NONE;
2872 else if (elemType == triPointRef::EDGE)
2875 nearest.setIndex(s.faceEdges()[triI][index]);
2876 nearest.elementType() = triPointRef::EDGE;
2878 else //if (elemType == triPointRef::POINT)
2881 nearest.setIndex(s.localFaces()[triI][index]);
2882 nearest.elementType() = triPointRef::POINT;
2889 Foam::surfaceLocation Foam::triSurfaceTools::trackToEdge
2891 const triSurface& s,
2892 const surfaceLocation& start,
2893 const surfaceLocation& end,
2894 const plane& cutPlane
2897 // Start off from starting point
2898 surfaceLocation nearest = start;
2901 // See if in same triangle as endpoint. If so snap.
2902 snapToEnd(s, end, nearest);
2906 // Not yet at end point
2908 if (start.elementType() == triPointRef::NONE)
2910 // Start point is inside triangle. Trivial cases already handled
2913 // end point is on edge or point so cross currrent triangle to
2914 // see which edge is cut.
2919 start.index(), // triangle
2926 nearest.elementType() = triPointRef::EDGE;
2927 nearest.triangle() = start.index();
2930 else if (start.elementType() == triPointRef::EDGE)
2932 // Pick connected triangle that is most in direction.
2933 const labelList& eFaces = s.edgeFaces()[start.index()];
2935 nearest = visitFaces
2940 start.index(), // excludeEdgeI
2941 -1, // excludePointI
2946 else // start.elementType() == triPointRef::POINT
2948 const labelList& pFaces = s.pointFaces()[start.index()];
2950 nearest = visitFaces
2956 start.index(), // excludePointI
2961 snapToEnd(s, end, nearest);
2967 void Foam::triSurfaceTools::track
2969 const triSurface& s,
2970 const surfaceLocation& endInfo,
2971 const plane& cutPlane,
2972 surfaceLocation& hitInfo
2975 //OFstream str("track.obj");
2977 //meshTools::writeOBJ(str, hitInfo.rawPoint());
2980 // Track across surface.
2983 //Pout<< "Tracking from:" << nl
2984 // << " " << hitInfo.info()
2987 hitInfo = trackToEdge
2995 //meshTools::writeOBJ(str, hitInfo.rawPoint());
2997 //str<< "l " << vertI-1 << ' ' << vertI << nl;
2999 //Pout<< "Tracked to:" << nl
3000 // << " " << hitInfo.info() << endl;
3002 if (hitInfo.hit() || hitInfo.triangle() == -1)
3010 // ************************************************************************* //