1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "intersectedSurface.H"
27 #include "surfaceIntersection.H"
29 #include "faceTriangulation.H"
30 #include "treeBoundBox.H"
33 #include "meshTools.H"
34 #include "edgeSurface.H"
35 #include "DynamicList.H"
36 #include "transform.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 defineTypeNameAndDebug(Foam::intersectedSurface, 0);
42 const Foam::label Foam::intersectedSurface::UNVISITED = 0;
43 const Foam::label Foam::intersectedSurface::STARTTOEND = 1;
44 const Foam::label Foam::intersectedSurface::ENDTOSTART = 2;
45 const Foam::label Foam::intersectedSurface::BOTH = STARTTOEND | ENDTOSTART;
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 // Write whole pointField and edges to stream
50 void Foam::intersectedSurface::writeOBJ
52 const pointField& points,
53 const edgeList& edges,
57 forAll(points, pointI)
59 const point& pt = points[pointI];
61 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
65 const edge& e = edges[edgeI];
67 os << "l " << e.start()+1 << ' ' << e.end()+1 << nl;
72 // Write whole pointField and selected edges to stream
73 void Foam::intersectedSurface::writeOBJ
75 const pointField& points,
76 const edgeList& edges,
77 const labelList& faceEdges,
81 forAll(points, pointI)
83 const point& pt = points[pointI];
85 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
89 const edge& e = edges[faceEdges[i]];
91 os << "l " << e.start()+1 << ' ' << e.end()+1 << nl;
96 // write local points and edges to stream
97 void Foam::intersectedSurface::writeLocalOBJ
99 const pointField& points,
100 const edgeList& edges,
101 const labelList& faceEdges,
102 const fileName& fName
107 labelList pointMap(points.size(), -1);
113 const edge& e = edges[faceEdges[i]];
119 if (pointMap[pointI] == -1)
121 const point& pt = points[pointI];
123 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
125 pointMap[pointI] = maxVertI++;
132 const edge& e = edges[faceEdges[i]];
134 os << "l " << pointMap[e.start()]+1 << ' ' << pointMap[e.end()]+1
140 // Write whole pointField and face to stream
141 void Foam::intersectedSurface::writeOBJ
143 const pointField& points,
148 forAll(points, pointI)
150 const point& pt = points[pointI];
152 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
159 os << ' ' << f[fp]+1;
165 // Print current visited state.
166 void Foam::intersectedSurface::printVisit
168 const edgeList& edges,
169 const labelList& edgeLabels,
170 const Map<label>& visited
173 Pout<< "Visited:" << nl;
174 forAll(edgeLabels, i)
176 label edgeI = edgeLabels[i];
178 const edge& e = edges[edgeI];
180 label stat = visited[edgeI];
182 if (stat == UNVISITED)
184 Pout<< " edge:" << edgeI << " verts:" << e
185 << " unvisited" << nl;
187 else if (stat == STARTTOEND)
189 Pout<< " edge:" << edgeI << " from " << e[0]
190 << " to " << e[1] << nl;
192 else if (stat == ENDTOSTART)
194 Pout<< " edge:" << edgeI << " from " << e[1]
195 << " to " << e[0] << nl;
199 Pout<< " edge:" << edgeI << " both " << e
207 // Check if the two vertices that f0 and f1 share are in the same order on
209 bool Foam::intersectedSurface::sameEdgeOrder
211 const labelledTri& fA,
212 const labelledTri& fB
217 label fpB = findIndex(fB, fA[fpA]);
221 // Get prev/next vertex on fA
222 label vA1 = fA[fA.fcIndex(fpA)];
223 label vAMin1 = fA[fA.rcIndex(fpA)];
225 // Get prev/next vertex on fB
226 label vB1 = fB[fB.fcIndex(fpB)];
227 label vBMin1 = fB[fB.rcIndex(fpB)];
229 if (vA1 == vB1 || vAMin1 == vBMin1)
233 else if (vA1 == vBMin1 || vAMin1 == vB1)
235 // shared vertices in opposite order.
240 FatalErrorIn("intersectedSurface::sameEdgeOrder")
241 << "Triangle:" << fA << " and triangle:" << fB
242 << " share a point but not an edge"
243 << abort(FatalError);
248 FatalErrorIn("intersectedSurface::sameEdgeOrder")
249 << "Triangle:" << fA << " and triangle:" << fB
250 << " do not share an edge"
251 << abort(FatalError);
257 void Foam::intersectedSurface::incCount
264 Map<label>::iterator iter = visited.find(key);
266 if (iter == visited.end())
268 visited.insert(key, offset);
277 // Calculate point to edge addressing for the face given by the edge
278 // subset faceEdges. Constructs facePointEdges which for every point
279 // gives a list of edge labels connected to it.
280 Foam::Map<Foam::DynamicList<Foam::label> >
281 Foam::intersectedSurface::calcPointEdgeAddressing
283 const edgeSurface& eSurf,
287 const pointField& points = eSurf.points();
288 const edgeList& edges = eSurf.edges();
290 const labelList& fEdges = eSurf.faceEdges()[faceI];
292 Map<DynamicList<label> > facePointEdges(4*fEdges.size());
296 label edgeI = fEdges[i];
298 const edge& e = edges[edgeI];
300 // Add e.start to point-edges
301 Map<DynamicList<label> >::iterator iter =
302 facePointEdges.find(e.start());
304 if (iter == facePointEdges.end())
306 DynamicList<label> oneEdge;
307 oneEdge.append(edgeI);
308 facePointEdges.insert(e.start(), oneEdge);
312 iter().append(edgeI);
315 // Add e.end to point-edges
316 Map<DynamicList<label> >::iterator iter2 =
317 facePointEdges.find(e.end());
319 if (iter2 == facePointEdges.end())
321 DynamicList<label> oneEdge;
322 oneEdge.append(edgeI);
323 facePointEdges.insert(e.end(), oneEdge);
327 iter2().append(edgeI);
332 forAllIter(Map< DynamicList<label> >, facePointEdges, iter)
336 // Check on dangling points.
341 "intersectedSurface::calcPointEdgeAddressing"
342 "(const edgeSurface&, const label)"
343 ) << "Point:" << iter.key() << " used by too few edges:"
344 << iter() << abort(FatalError);
350 // Print facePointEdges
351 Pout<< "calcPointEdgeAddressing: face consisting of edges:" << endl;
354 label edgeI = fEdges[i];
355 const edge& e = edges[edgeI];
356 Pout<< " " << edgeI << ' ' << e
358 << points[e.end()] << endl;
361 Pout<< " Constructed point-edge adressing:" << endl;
362 forAllConstIter(Map< DynamicList<label> >, facePointEdges, iter)
364 Pout<< " vertex " << iter.key() << " is connected to edges "
370 return facePointEdges;
374 // Find next (triangle or cut) edge label coming from point prevVertI on
375 // prevEdgeI doing a right handed walk (i.e. following right wall).
376 // Note: normal is provided externally. Could be deducted from angle between
377 // two triangle edges but these could be in line.
378 Foam::label Foam::intersectedSurface::nextEdge
380 const edgeSurface& eSurf,
381 const Map<label>& visited,
384 const Map<DynamicList<label> >& facePointEdges,
385 const label prevEdgeI,
386 const label prevVertI
389 const pointField& points = eSurf.points();
390 const edgeList& edges = eSurf.edges();
391 const labelList& fEdges = eSurf.faceEdges()[faceI];
394 // Edges connected to prevVertI
395 const DynamicList<label>& connectedEdges = facePointEdges[prevVertI];
397 if (connectedEdges.size() <= 1)
399 // Problem. Point not connected.
401 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
402 OFstream str("face.obj");
403 writeOBJ(points, edges, fEdges, str);
405 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
406 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
411 "intersectedSurface::nextEdge(const pointField&, const edgeList&"
412 ", const vector&, Map<DynamicList<label> >, const label"
414 ) << "Problem: prevVertI:" << prevVertI << " on edge " << prevEdgeI
415 << " has less than 2 connected edges."
416 << " connectedEdges:" << connectedEdges << abort(FatalError);
421 if (connectedEdges.size() == 2)
423 // Simple case. Take other edge
424 if (connectedEdges[0] == prevEdgeI)
428 Pout<< "Stepped from edge:" << edges[prevEdgeI]
429 << " to edge:" << edges[connectedEdges[1]]
430 << " chosen from candidates:" << connectedEdges << endl;
432 return connectedEdges[1];
438 Pout<< "Stepped from edge:" << edges[prevEdgeI]
439 << " to edge:" << edges[connectedEdges[0]]
440 << " chosen from candidates:" << connectedEdges << endl;
442 return connectedEdges[0];
447 // Multiple choices. Look at angle between edges.
449 const edge& prevE = edges[prevEdgeI];
451 // x-axis of coordinate system
452 vector e0 = n ^ (points[prevE.otherVertex(prevVertI)] - points[prevVertI]);
453 e0 /= mag(e0) + VSMALL;
455 // Get y-axis of coordinate system
458 if (mag(mag(e1) - 1) > SMALL)
461 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
462 OFstream str("face.obj");
463 writeOBJ(points, edges, fEdges, str);
465 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
466 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
469 FatalErrorIn("intersectedSurface::nextEdge")
470 << "Unnormalized normal e1:" << e1
471 << " formed from cross product of e0:" << e0 << " n:" << n
472 << abort(FatalError);
477 // Determine maximum angle over all connected (unvisited) edges.
480 scalar maxAngle = -GREAT;
483 forAll(connectedEdges, connI)
485 label edgeI = connectedEdges[connI];
487 if (edgeI != prevEdgeI)
489 label stat = visited[edgeI];
491 const edge& e = edges[edgeI];
493 // Find out whether walk of edge from prevVert would be acceptible.
507 // Calculate angle of edge with respect to base e0, e1
509 n ^ (points[e.otherVertex(prevVertI)] - points[prevVertI]);
511 vec /= mag(vec) + VSMALL;
513 scalar angle = pseudoAngle(e0, e1, vec);
515 if (angle > maxAngle)
527 // No unvisited edge found
529 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
530 OFstream str("face.obj");
531 writeOBJ(points, edges, fEdges, str);
533 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
534 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
539 "intersectedSurface::nextEdge(const pointField&, const edgeList&"
540 ", const Map<label>&, const vector&"
541 ", const Map<DynamicList<label> >&"
542 ", const label, const label"
543 ) << "Trying to step from edge " << edges[prevEdgeI]
544 << ", vertex " << prevVertI
545 << " but cannot find 'unvisited' edges among candidates:"
547 << abort(FatalError);
552 Pout<< "Stepped from edge:" << edges[prevEdgeI]
553 << " to edge:" << maxEdgeI << " angle:" << edges[maxEdgeI]
554 << " with angle:" << maxAngle
562 // Create (polygonal) face by walking full circle starting from startVertI on
564 // Uses nextEdge(..) to do the walking. Returns face. Updates visited with
565 // the labels of visited edges.
566 Foam::face Foam::intersectedSurface::walkFace
568 const edgeSurface& eSurf,
571 const Map<DynamicList<label> >& facePointEdges,
573 const label startEdgeI,
574 const label startVertI,
579 const pointField& points = eSurf.points();
580 const edgeList& edges = eSurf.edges();
582 // Overestimate size of face
583 face f(eSurf.faceEdges()[faceI].size());
587 label vertI = startVertI;
588 label edgeI = startEdgeI;
592 const edge& e = edges[edgeI];
596 Pout<< "Now at:" << endl
597 << " edge:" << edgeI << " vertices:" << e
598 << " positions:" << points[e.start()] << ' ' << points[e.end()]
599 << " vertex:" << vertI << endl;
602 // Mark edge as visited
605 visited[edgeI] |= STARTTOEND;
609 visited[edgeI] |= ENDTOSTART;
616 // step to other vertex
617 vertI = e.otherVertex(vertI);
619 if (vertI == startVertI)
624 // step from vertex to next edge
643 void Foam::intersectedSurface::findNearestVisited
645 const edgeSurface& eSurf,
647 const Map<DynamicList<label> >& facePointEdges,
648 const Map<label>& pointVisited,
650 const label excludePointI,
659 forAllConstIter(Map<label>, pointVisited, iter)
661 label pointI = iter.key();
663 if (pointI != excludePointI)
665 label nVisits = iter();
667 if (nVisits == 2*facePointEdges[pointI].size())
669 // Fully visited (i.e. both sides of all edges)
670 scalar dist = mag(eSurf.points()[pointI] - pt);
683 const labelList& fEdges = eSurf.faceEdges()[faceI];
685 SeriousErrorIn("intersectedSurface::findNearestVisited")
686 << "Dumping face edges to faceEdges.obj" << endl;
688 writeLocalOBJ(eSurf.points(), eSurf.edges(), fEdges, "faceEdges.obj");
690 FatalErrorIn("intersectedSurface::findNearestVisited")
691 << "No fully visited edge found for pt " << pt
692 << abort(FatalError);
697 // Sometimes there are bunches of edges that are not connected to the
698 // other edges in the face. This routine tries to connect the loose
699 // edges up to the 'proper' edges by adding two extra edges between a
700 // properly connected edge and an unconnected one. Since at this level the
701 // adressing is purely in form of points and a cloud of edges this can
703 // (edges are to existing points. Don't want to introduce new vertices here
704 // since then also neighbouring face would have to be split)
705 Foam::faceList Foam::intersectedSurface::resplitFace
707 const triSurface& surf,
709 const Map<DynamicList<label> >& facePointEdges,
710 const Map<label>& visited,
715 // Dump face for debugging.
716 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
717 OFstream str("face.obj");
718 writeOBJ(eSurf.points(), eSurf.edges(), eSurf.faceEdges()[faceI], str);
722 // Count the number of times point has been visited so we
723 // can compare number to facePointEdges.
724 Map<label> pointVisited(2*facePointEdges.size());
728 OFstream str0("visitedNone.obj");
729 OFstream str1("visitedOnce.obj");
730 OFstream str2("visitedTwice.obj");
731 forAll(eSurf.points(), pointI)
733 const point& pt = eSurf.points()[pointI];
735 str0 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
736 str1 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
737 str2 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
741 forAllConstIter(Map<label>, visited, iter)
743 label edgeI = iter.key();
745 const edge& e = eSurf.edges()[edgeI];
749 if (stat == STARTTOEND || stat == ENDTOSTART)
751 incCount(pointVisited, e[0], 1);
752 incCount(pointVisited, e[1], 1);
754 str1 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
756 else if (stat == BOTH)
758 incCount(pointVisited, e[0], 2);
759 incCount(pointVisited, e[1], 2);
761 str2 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
763 else if (stat == UNVISITED)
765 incCount(pointVisited, e[0], 0);
766 incCount(pointVisited, e[1], 0);
768 str0 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
775 forAllConstIter(Map<label>, pointVisited, iter)
777 label pointI = iter.key();
779 label nVisits = iter();
781 Pout<< "point:" << pointI << " nVisited:" << nVisits
782 << " pointEdges:" << facePointEdges[pointI].size() << endl;
787 // Find nearest point pair where one is not fully visited and
790 label visitedVert0 = -1;
791 label unvisitedVert0 = -1;
794 scalar minDist = GREAT;
796 forAllConstIter(Map<DynamicList<label> >, facePointEdges, iter)
798 label pointI = iter.key();
800 label nVisits = pointVisited[pointI];
802 const DynamicList<label>& pEdges = iter();
804 if (nVisits < 2*pEdges.size())
806 // Not fully visited. Find nearest fully visited.
817 eSurf.points()[pointI],
818 -1, // Do not exclude vertex
824 if (nearDist < minDist)
827 visitedVert0 = nearVertI;
828 unvisitedVert0 = pointI;
835 // Find second intersection.
836 label visitedVert1 = -1;
837 label unvisitedVert1 = -1;
839 scalar minDist = GREAT;
841 forAllConstIter(Map<DynamicList<label> >, facePointEdges, iter)
843 label pointI = iter.key();
845 if (pointI != unvisitedVert0)
847 label nVisits = pointVisited[pointI];
849 const DynamicList<label>& pEdges = iter();
851 if (nVisits < 2*pEdges.size())
853 // Not fully visited. Find nearest fully visited.
864 eSurf.points()[pointI],
865 visitedVert0, // vertex to exclude
871 if (nearDist < minDist)
874 visitedVert1 = nearVertI;
875 unvisitedVert1 = pointI;
883 Pout<< "resplitFace : adding intersection from " << visitedVert0
884 << " to " << unvisitedVert0 << endl
885 << " and from " << visitedVert1
886 << " to " << unvisitedVert1 << endl;
889 // // Add the new intersection edges to the edgeSurface
890 // edgeList additionalEdges(2);
891 // additionalEdges[0] = edge(visitedVert0, unvisitedVert0);
892 // additionalEdges[1] = edge(visitedVert1, unvisitedVert1);
894 // Add the new intersection edges to the edgeSurface
895 edgeList additionalEdges(1);
896 additionalEdges[0] = edge(visitedVert0, unvisitedVert0);
898 eSurf.addIntersectionEdges(faceI, additionalEdges);
900 fileName newFName("face_" + Foam::name(faceI) + "_newEdges.obj");
901 Pout<< "Dumping face:" << faceI << " to " << newFName << endl;
906 eSurf.faceEdges()[faceI],
910 // Retry splitFace. Use recursion since is rare situation.
911 return splitFace(surf, faceI, eSurf);
915 Foam::faceList Foam::intersectedSurface::splitFace
917 const triSurface& surf,
923 const pointField& points = eSurf.points();
924 const edgeList& edges = eSurf.edges();
925 const labelList& fEdges = eSurf.faceEdges()[faceI];
927 // Create local (for the face only) point-edge connectivity.
928 Map<DynamicList<label> > facePointEdges
930 calcPointEdgeAddressing
937 // Order in which edges have been walked. Initialize outside edges.
938 Map<label> visited(fEdges.size()*2);
942 label edgeI = fEdges[i];
944 if (eSurf.isSurfaceEdge(edgeI))
946 // Edge is edge from original surface so an outside edge for
948 label surfEdgeI = eSurf.parentEdge(edgeI);
950 label owner = surf.edgeOwner()[surfEdgeI];
957 surf.localFaces()[owner],
958 surf.localFaces()[faceI]
962 // Edge is in same order as current face.
963 // Mark off the opposite order.
964 visited.insert(edgeI, ENDTOSTART);
968 // Edge is in same order as current face.
969 // Mark off the opposite order.
970 visited.insert(edgeI, STARTTOEND);
975 visited.insert(edgeI, UNVISITED);
982 DynamicList<face> faces(fEdges.size());
986 // Find starting edge:
987 // - unvisted triangle edge
988 // - once visited intersection edge
989 // Give priority to triangle edges.
990 label startEdgeI = -1;
991 label startVertI = -1;
995 label edgeI = fEdges[i];
997 const edge& e = edges[edgeI];
999 label stat = visited[edgeI];
1001 if (stat == STARTTOEND)
1006 if (eSurf.isSurfaceEdge(edgeI))
1011 else if (stat == ENDTOSTART)
1016 if (eSurf.isSurfaceEdge(edgeI))
1023 if (startEdgeI == -1)
1028 //Pout<< "splitFace: starting walk from edge:" << startEdgeI
1029 // << ' ' << edges[startEdgeI] << " vertex:" << startVertI << endl;
1031 //// Print current visited state.
1032 //printVisit(eSurf.edges(), fEdges, visited);
1035 // Pout<< "Writing face:" << faceI << " to face.obj" << endl;
1036 // OFstream str("face.obj");
1037 // writeOBJ(eSurf.points(), eSurf.edges(), fEdges, str);
1046 surf.faceNormals()[faceI],
1058 // Check if any unvisited edges left.
1061 label edgeI = fEdges[i];
1063 label stat = visited[edgeI];
1065 if (eSurf.isSurfaceEdge(edgeI) && stat != BOTH)
1067 SeriousErrorIn("Foam::intersectedSurface::splitFace")
1068 << "Dumping face edges to faceEdges.obj" << endl;
1070 writeLocalOBJ(points, edges, fEdges, "faceEdges.obj");
1072 FatalErrorIn("intersectedSurface::splitFace")
1073 << "Problem: edge " << edgeI << " vertices "
1074 << edges[edgeI] << " on face " << faceI
1075 << " has visited status " << stat << " from a "
1076 << "righthanded walk along all"
1077 << " of the triangle edges. Are the original surfaces"
1078 << " closed and non-intersecting?"
1079 << abort(FatalError);
1081 else if (stat != BOTH)
1084 // Pout<< "Dumping faces so far to faces.obj" << nl
1085 // << faces << endl;
1087 // OFstream str("faces.obj");
1091 // writeOBJ(points, faces[i], str);
1095 Pout<< "** Resplitting **" << endl;
1097 // Redo face after introducing extra edge. Edge introduced
1098 // should be one nearest to any fully visited edge.
1111 // See if normal needs flipping.
1114 vector n = faces[0].normal(eSurf.points());
1116 if ((n & surf.faceNormals()[faceI]) < 0)
1128 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1131 Foam::intersectedSurface::intersectedSurface()
1134 intersectionEdges_(0),
1140 // Construct from components
1141 Foam::intersectedSurface::intersectedSurface(const triSurface& surf)
1144 intersectionEdges_(0),
1150 // Construct from surface and intersection
1151 Foam::intersectedSurface::intersectedSurface
1153 const triSurface& surf,
1154 const bool isFirstSurface,
1155 const surfaceIntersection& inter
1159 intersectionEdges_(0),
1161 nSurfacePoints_(surf.nPoints())
1163 if (inter.cutPoints().empty() && inter.cutEdges().empty())
1165 // No intersection. Make straight copy.
1166 triSurface::operator=(surf);
1168 // Identity for face map
1169 faceMap_.setSize(size());
1171 forAll(faceMap_, faceI)
1173 faceMap_[faceI] = faceI;
1179 // Calculate face-edge addressing for surface + intersection.
1180 edgeSurface eSurf(surf, isFirstSurface, inter);
1182 // Update point information for any removed points. (when are they removed?
1183 // - but better make sure)
1184 nSurfacePoints_ = eSurf.nSurfacePoints();
1186 // Now we have full points, edges and edge addressing for surf. Start
1187 // extracting faces and triangulate them.
1189 // Storage for new triangles of surface.
1190 DynamicList<labelledTri> newTris(eSurf.edges().size()/2);
1192 // Start in newTris for decomposed face.
1193 labelList startTriI(surf.size(), 0);
1197 startTriI[faceI] = newTris.size();
1199 if (eSurf.faceEdges()[faceI].size() != surf.faceEdges()[faceI].size())
1201 // Face has been cut by intersection.
1202 // Cut face into multiple subfaces. Use faceEdge information
1203 // from edgeSurface only. (original triSurface 'surf' is used for
1204 // faceNormals and regionnumber only)
1210 faceI, // current triangle
1211 eSurf // face-edge description of surface
1215 forAll(newFaces, newFaceI)
1217 const face& newF = newFaces[newFaceI];
1223 // + Foam::name(faceI)
1225 // + Foam::name(newFaceI)
1228 // Pout<< "Writing original face:" << faceI << " subFace:"
1229 // << newFaceI << " to " << fName << endl;
1231 // OFstream str(fName);
1235 // meshTools::writeOBJ(str, eSurf.points()[newF[fp]]);
1240 // str << ' ' << fp+1;
1242 // str<< " 1" << nl;
1246 const vector& n = surf.faceNormals()[faceI];
1247 const label region = surf[faceI].region();
1249 faceTriangulation tris(eSurf.points(), newF, n);
1253 const triFace& t = tris[triI];
1257 if (t[i] < 0 || t[i] >= eSurf.points().size())
1261 "intersectedSurface::intersectedSurface"
1262 ) << "Face triangulation of face " << faceI
1263 << " uses points outside range 0.."
1264 << eSurf.points().size()-1 << endl
1266 << tris << abort(FatalError);
1270 newTris.append(labelledTri(t[0], t[1], t[2], region));
1276 // Face has not been cut at all. No need to renumber vertices since
1277 // eSurf keeps surface vertices first.
1278 newTris.append(surf.localFaces()[faceI]);
1285 // Construct triSurface. Note that addressing will be compact since
1286 // edgeSurface is compact.
1287 triSurface::operator=
1297 // Construct mapping back into original surface
1298 faceMap_.setSize(size());
1300 for (label faceI = 0; faceI < surf.size()-1; faceI++)
1302 for (label triI = startTriI[faceI]; triI < startTriI[faceI+1]; triI++)
1304 faceMap_[triI] = faceI;
1307 for (label triI = startTriI[surf.size()-1]; triI < size(); triI++)
1309 faceMap_[triI] = surf.size()-1;
1313 // Find edges on *this which originate from 'cuts'. (i.e. newEdgeI >=
1314 // nSurfaceEdges) Renumber edges into local triSurface numbering.
1316 intersectionEdges_.setSize(eSurf.edges().size() - eSurf.nSurfaceEdges());
1318 label intersectionEdgeI = 0;
1322 label edgeI = eSurf.nSurfaceEdges();
1323 edgeI < eSurf.edges().size();
1327 // Get edge vertices in triSurface local numbering
1328 const edge& e = eSurf.edges()[edgeI];
1329 label surfStartI = meshPointMap()[e.start()];
1330 label surfEndI = meshPointMap()[e.end()];
1332 // Find edge connected to surfStartI which also uses surfEndI.
1333 label surfEdgeI = -1;
1335 const labelList& pEdges = pointEdges()[surfStartI];
1339 const edge& surfE = edges()[pEdges[i]];
1341 // Edge already connected to surfStart for sure. See if also
1342 // connects to surfEnd
1343 if (surfE.start() == surfEndI || surfE.end() == surfEndI)
1345 surfEdgeI = pEdges[i];
1351 if (surfEdgeI != -1)
1353 intersectionEdges_[intersectionEdgeI++] = surfEdgeI;
1357 FatalErrorIn("intersectedSurface::intersectedSurface")
1358 << "Cannot find edge among candidates " << pEdges
1359 << " which uses points " << surfStartI
1360 << " and " << surfEndI
1361 << abort(FatalError);
1367 // ************************************************************************* //