1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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
25 \*---------------------------------------------------------------------------*/
27 #include "intersectedSurface.H"
28 #include "surfaceIntersection.H"
30 #include "faceTriangulation.H"
31 #include "treeBoundBox.H"
34 #include "meshTools.H"
35 #include "edgeSurface.H"
36 #include "DynamicList.H"
37 #include "transform.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 defineTypeNameAndDebug(Foam::intersectedSurface, 0);
43 const Foam::label Foam::intersectedSurface::UNVISITED = 0;
44 const Foam::label Foam::intersectedSurface::STARTTOEND = 1;
45 const Foam::label Foam::intersectedSurface::ENDTOSTART = 2;
46 const Foam::label Foam::intersectedSurface::BOTH = STARTTOEND | ENDTOSTART;
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 // Write whole pointField and edges to stream
51 void Foam::intersectedSurface::writeOBJ
53 const pointField& points,
54 const edgeList& edges,
58 forAll(points, pointI)
60 const point& pt = points[pointI];
62 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
66 const edge& e = edges[edgeI];
68 os << "l " << e.start()+1 << ' ' << e.end()+1 << nl;
73 // Write whole pointField and selected edges to stream
74 void Foam::intersectedSurface::writeOBJ
76 const pointField& points,
77 const edgeList& edges,
78 const labelList& faceEdges,
82 forAll(points, pointI)
84 const point& pt = points[pointI];
86 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
90 const edge& e = edges[faceEdges[i]];
92 os << "l " << e.start()+1 << ' ' << e.end()+1 << nl;
97 // write local points and edges to stream
98 void Foam::intersectedSurface::writeLocalOBJ
100 const pointField& points,
101 const edgeList& edges,
102 const labelList& faceEdges,
103 const fileName& fName
108 labelList pointMap(points.size(), -1);
114 const edge& e = edges[faceEdges[i]];
120 if (pointMap[pointI] == -1)
122 const point& pt = points[pointI];
124 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
126 pointMap[pointI] = maxVertI++;
133 const edge& e = edges[faceEdges[i]];
135 os << "l " << pointMap[e.start()]+1 << ' ' << pointMap[e.end()]+1
141 // Write whole pointField and face to stream
142 void Foam::intersectedSurface::writeOBJ
144 const pointField& points,
149 forAll(points, pointI)
151 const point& pt = points[pointI];
153 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
160 os << ' ' << f[fp]+1;
166 // Print current visited state.
167 void Foam::intersectedSurface::printVisit
169 const edgeList& edges,
170 const labelList& edgeLabels,
171 const Map<label>& visited
174 Pout<< "Visited:" << nl;
175 forAll(edgeLabels, i)
177 label edgeI = edgeLabels[i];
179 const edge& e = edges[edgeI];
181 label stat = visited[edgeI];
183 if (stat == UNVISITED)
185 Pout<< " edge:" << edgeI << " verts:" << e
186 << " unvisited" << nl;
188 else if (stat == STARTTOEND)
190 Pout<< " edge:" << edgeI << " from " << e[0]
191 << " to " << e[1] << nl;
193 else if (stat == ENDTOSTART)
195 Pout<< " edge:" << edgeI << " from " << e[1]
196 << " to " << e[0] << nl;
200 Pout<< " edge:" << edgeI << " both " << e
209 // Check if the two vertices that f0 and f1 share are in the same order on
211 bool Foam::intersectedSurface::sameEdgeOrder
213 const labelledTri& fA,
214 const labelledTri& fB
219 label fpB = findIndex(fB, fA[fpA]);
223 // Get prev/next vertex on fA
224 label vA1 = fA[(fpA + 1) % 3];
225 label vAMin1 = fA[fpA ? fpA-1 : 2];
227 // Get prev/next vertex on fB
228 label vB1 = fB[(fpB + 1) % 3];
229 label vBMin1 = fB[fpB ? fpB-1 : 2];
231 if (vA1 == vB1 || vAMin1 == vBMin1)
235 else if (vA1 == vBMin1 || vAMin1 == vB1)
237 // shared vertices in opposite order.
242 FatalErrorIn("intersectedSurface::sameEdgeOrder")
243 << "Triangle:" << fA << " and triangle:" << fB
244 << " share a point but not an edge"
245 << abort(FatalError);
250 FatalErrorIn("intersectedSurface::sameEdgeOrder")
251 << "Triangle:" << fA << " and triangle:" << fB
252 << " do not share an edge"
253 << abort(FatalError);
259 void Foam::intersectedSurface::incCount
266 Map<label>::iterator iter = visited.find(key);
268 if (iter == visited.end())
270 visited.insert(key, offset);
279 // Calculate point to edge addressing for the face given by the edge
280 // subset faceEdges. Constructs facePointEdges which for every point
281 // gives a list of edge labels connected to it.
282 Foam::Map<Foam::DynamicList<Foam::label> >
283 Foam::intersectedSurface::calcPointEdgeAddressing
285 const edgeSurface& eSurf,
289 const pointField& points = eSurf.points();
290 const edgeList& edges = eSurf.edges();
292 const labelList& fEdges = eSurf.faceEdges()[faceI];
294 Map<DynamicList<label> > facePointEdges(4*fEdges.size());
298 label edgeI = fEdges[i];
300 const edge& e = edges[edgeI];
302 // Add e.start to point-edges
303 Map<DynamicList<label> >::iterator iter =
304 facePointEdges.find(e.start());
306 if (iter == facePointEdges.end())
308 DynamicList<label> oneEdge;
309 oneEdge.append(edgeI);
310 facePointEdges.insert(e.start(), oneEdge);
314 iter().append(edgeI);
317 // Add e.end to point-edges
318 Map<DynamicList<label> >::iterator iter2 =
319 facePointEdges.find(e.end());
321 if (iter2 == facePointEdges.end())
323 DynamicList<label> oneEdge;
324 oneEdge.append(edgeI);
325 facePointEdges.insert(e.end(), oneEdge);
329 iter2().append(edgeI);
336 Map<DynamicList<label> >::iterator iter = facePointEdges.begin();
337 iter != facePointEdges.end();
343 // Check on dangling points.
348 "intersectedSurface::calcPointEdgeAddressing"
349 "(const edgeSurface&, const label)"
350 ) << "Point:" << iter.key() << " used by too few edges:"
351 << iter() << abort(FatalError);
357 // Print facePointEdges
358 Pout<< "calcPointEdgeAddressing: face consisting of edges:" << endl;
361 label edgeI = fEdges[i];
362 const edge& e = edges[edgeI];
363 Pout<< " " << edgeI << ' ' << e << points[e.start()]
364 << points[e.end()] << endl;
367 Pout<< " Constructed point-edge adressing:" << endl;
370 Map<DynamicList<label> >::iterator iter = facePointEdges.begin();
371 iter != facePointEdges.end();
375 Pout<< " vertex " << iter.key() << " is connected to edges "
381 return facePointEdges;
385 // Find next (triangle or cut) edge label coming from point prevVertI on
386 // prevEdgeI doing a right handed walk (i.e. following right wall).
387 // Note: normal is provided externally. Could be deducted from angle between
388 // two triangle edges but these could be in line.
389 Foam::label Foam::intersectedSurface::nextEdge
391 const edgeSurface& eSurf,
392 const Map<label>& visited,
395 const Map<DynamicList<label> >& facePointEdges,
396 const label prevEdgeI,
397 const label prevVertI
400 const pointField& points = eSurf.points();
401 const edgeList& edges = eSurf.edges();
402 const labelList& fEdges = eSurf.faceEdges()[faceI];
405 // Edges connected to prevVertI
406 const DynamicList<label>& connectedEdges = facePointEdges[prevVertI];
408 if (connectedEdges.size() <= 1)
410 // Problem. Point not connected.
412 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
413 OFstream str("face.obj");
414 writeOBJ(points, edges, fEdges, str);
416 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
417 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
422 "intersectedSurface::nextEdge(const pointField&, const edgeList&"
423 ", const vector&, Map<DynamicList<label> >, const label"
425 ) << "Problem: prevVertI:" << prevVertI << " on edge " << prevEdgeI
426 << " has less than 2 connected edges."
427 << " connectedEdges:" << connectedEdges << abort(FatalError);
432 if (connectedEdges.size() == 2)
434 // Simple case. Take other edge
435 if (connectedEdges[0] == prevEdgeI)
439 Pout<< "Stepped from edge:" << edges[prevEdgeI]
440 << " to edge:" << edges[connectedEdges[1]]
441 << " chosen from candidates:" << connectedEdges << endl;
443 return connectedEdges[1];
449 Pout<< "Stepped from edge:" << edges[prevEdgeI]
450 << " to edge:" << edges[connectedEdges[0]]
451 << " chosen from candidates:" << connectedEdges << endl;
453 return connectedEdges[0];
458 // Multiple choices. Look at angle between edges.
460 const edge& prevE = edges[prevEdgeI];
462 // x-axis of coordinate system
463 vector e0 = n ^ (points[prevE.otherVertex(prevVertI)] - points[prevVertI]);
464 e0 /= mag(e0) + VSMALL;
466 // Get y-axis of coordinate system
469 if (mag(mag(e1) - 1) > SMALL)
472 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
473 OFstream str("face.obj");
474 writeOBJ(points, edges, fEdges, str);
476 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
477 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
480 FatalErrorIn("intersectedSurface::nextEdge")
481 << "Unnormalized normal e1:" << e1
482 << " formed from cross product of e0:" << e0 << " n:" << n
483 << abort(FatalError);
488 // Determine maximum angle over all connected (unvisited) edges.
491 scalar maxAngle = -GREAT;
494 forAll(connectedEdges, connI)
496 label edgeI = connectedEdges[connI];
498 if (edgeI != prevEdgeI)
500 label stat = visited[edgeI];
502 const edge& e = edges[edgeI];
504 // Find out whether walk of edge from prevVert would be acceptible.
518 // Calculate angle of edge with respect to base e0, e1
520 n ^ (points[e.otherVertex(prevVertI)] - points[prevVertI]);
522 vec /= mag(vec) + VSMALL;
524 scalar angle = pseudoAngle(e0, e1, vec);
526 if (angle > maxAngle)
538 // No unvisited edge found
540 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
541 OFstream str("face.obj");
542 writeOBJ(points, edges, fEdges, str);
544 Pout<< "Writing connectedEdges edges to faceEdges.obj" << endl;
545 writeLocalOBJ(points, edges, connectedEdges, "faceEdges.obj");
550 "intersectedSurface::nextEdge(const pointField&, const edgeList&"
551 ", const Map<label>&, const vector&"
552 ", const Map<DynamicList<label> >&"
553 ", const label, const label"
554 ) << "Trying to step from edge " << edges[prevEdgeI]
555 << ", vertex " << prevVertI
556 << " but cannot find 'unvisited' edges among candidates:"
558 << abort(FatalError);
563 Pout<< "Stepped from edge:" << edges[prevEdgeI]
564 << " to edge:" << maxEdgeI << " angle:" << edges[maxEdgeI]
565 << " with angle:" << maxAngle
573 // Create (polygonal) face by walking full circle starting from startVertI on
575 // Uses nextEdge(..) to do the walking. Returns face. Updates visited with
576 // the labels of visited edges.
577 Foam::face Foam::intersectedSurface::walkFace
579 const edgeSurface& eSurf,
582 const Map<DynamicList<label> >& facePointEdges,
584 const label startEdgeI,
585 const label startVertI,
590 const pointField& points = eSurf.points();
591 const edgeList& edges = eSurf.edges();
593 // Overestimate size of face
594 face f(eSurf.faceEdges()[faceI].size());
598 label vertI = startVertI;
599 label edgeI = startEdgeI;
603 const edge& e = edges[edgeI];
607 Pout<< "Now at:" << endl
608 << " edge:" << edgeI << " vertices:" << e
609 << " positions:" << points[e.start()] << ' ' << points[e.end()]
610 << " vertex:" << vertI << endl;
613 // Mark edge as visited
616 visited[edgeI] |= STARTTOEND;
620 visited[edgeI] |= ENDTOSTART;
627 // step to other vertex
628 vertI = e.otherVertex(vertI);
630 if (vertI == startVertI)
635 // step from vertex to next edge
654 void Foam::intersectedSurface::findNearestVisited
656 const edgeSurface& eSurf,
658 const Map<DynamicList<label> >& facePointEdges,
659 const Map<label>& pointVisited,
661 const label excludePointI,
670 forAllConstIter(Map<label>, pointVisited, iter)
672 label pointI = iter.key();
674 if (pointI != excludePointI)
676 label nVisits = iter();
678 if (nVisits == 2*facePointEdges[pointI].size())
680 // Fully visited (i.e. both sides of all edges)
681 scalar dist = mag(eSurf.points()[pointI] - pt);
694 const labelList& fEdges = eSurf.faceEdges()[faceI];
696 SeriousErrorIn("intersectedSurface::findNearestVisited")
697 << "Dumping face edges to faceEdges.obj" << endl;
699 writeLocalOBJ(eSurf.points(), eSurf.edges(), fEdges, "faceEdges.obj");
701 FatalErrorIn("intersectedSurface::findNearestVisited")
702 << "No fully visited edge found for pt " << pt
703 << abort(FatalError);
708 // Sometimes there are bunches of edges that are not connected to the
709 // other edges in the face. This routine tries to connect the loose
710 // edges up to the 'proper' edges by adding two extra edges between a
711 // properly connected edge and an unconnected one. Since at this level the
712 // adressing is purely in form of points and a cloud of edges this can
714 // (edges are to existing points. Don't want to introduce new vertices here
715 // since then also neighbouring face would have to be split)
716 Foam::faceList Foam::intersectedSurface::resplitFace
718 const triSurface& surf,
720 const Map<DynamicList<label> >& facePointEdges,
721 const Map<label>& visited,
726 // Dump face for debugging.
727 Pout<< "Writing face:" << faceI << " to face.obj" << endl;
728 OFstream str("face.obj");
729 writeOBJ(eSurf.points(), eSurf.edges(), eSurf.faceEdges()[faceI], str);
733 // Count the number of times point has been visited so we
734 // can compare number to facePointEdges.
735 Map<label> pointVisited(2*facePointEdges.size());
739 OFstream str0("visitedNone.obj");
740 OFstream str1("visitedOnce.obj");
741 OFstream str2("visitedTwice.obj");
742 forAll(eSurf.points(), pointI)
744 const point& pt = eSurf.points()[pointI];
746 str0 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
747 str1 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
748 str2 << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
752 forAllConstIter(Map<label>, visited, iter)
754 label edgeI = iter.key();
756 const edge& e = eSurf.edges()[edgeI];
760 if (stat == STARTTOEND || stat == ENDTOSTART)
762 incCount(pointVisited, e[0], 1);
763 incCount(pointVisited, e[1], 1);
765 str1 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
767 else if (stat == BOTH)
769 incCount(pointVisited, e[0], 2);
770 incCount(pointVisited, e[1], 2);
772 str2 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
774 else if (stat == UNVISITED)
776 incCount(pointVisited, e[0], 0);
777 incCount(pointVisited, e[1], 0);
779 str0 << "l " << e[0]+1 << ' ' << e[1]+1 << nl;
786 forAllConstIter(Map<label>, pointVisited, iter)
788 label pointI = iter.key();
790 label nVisits = iter();
792 Pout<< "point:" << pointI << " nVisited:" << nVisits
793 << " pointEdges:" << facePointEdges[pointI].size() << endl;
798 // Find nearest point pair where one is not fully visited and
801 label visitedVert0 = -1;
802 label unvisitedVert0 = -1;
805 scalar minDist = GREAT;
807 forAllConstIter(Map<DynamicList<label> >, facePointEdges, iter)
809 label pointI = iter.key();
811 label nVisits = pointVisited[pointI];
813 const DynamicList<label>& pEdges = iter();
815 if (nVisits < 2*pEdges.size())
817 // Not fully visited. Find nearest fully visited.
828 eSurf.points()[pointI],
829 -1, // Do not exclude vertex
835 if (nearDist < minDist)
838 visitedVert0 = nearVertI;
839 unvisitedVert0 = pointI;
846 // Find second intersection.
847 label visitedVert1 = -1;
848 label unvisitedVert1 = -1;
850 scalar minDist = GREAT;
852 forAllConstIter(Map<DynamicList<label> >, facePointEdges, iter)
854 label pointI = iter.key();
856 if (pointI != unvisitedVert0)
858 label nVisits = pointVisited[pointI];
860 const DynamicList<label>& pEdges = iter();
862 if (nVisits < 2*pEdges.size())
864 // Not fully visited. Find nearest fully visited.
875 eSurf.points()[pointI],
876 visitedVert0, // vertex to exclude
882 if (nearDist < minDist)
885 visitedVert1 = nearVertI;
886 unvisitedVert1 = pointI;
894 Pout<< "resplitFace : adding intersection from " << visitedVert0
895 << " to " << unvisitedVert0 << endl
896 << " and from " << visitedVert1
897 << " to " << unvisitedVert1 << endl;
900 // // Add the new intersection edges to the edgeSurface
901 // edgeList additionalEdges(2);
902 // additionalEdges[0] = edge(visitedVert0, unvisitedVert0);
903 // additionalEdges[1] = edge(visitedVert1, unvisitedVert1);
905 // Add the new intersection edges to the edgeSurface
906 edgeList additionalEdges(1);
907 additionalEdges[0] = edge(visitedVert0, unvisitedVert0);
909 eSurf.addIntersectionEdges(faceI, additionalEdges);
911 fileName newFName("face_" + Foam::name(faceI) + "_newEdges.obj");
912 Pout<< "Dumping face:" << faceI << " to " << newFName << endl;
917 eSurf.faceEdges()[faceI],
921 // Retry splitFace. Use recursion since is rare situation.
922 return splitFace(surf, faceI, eSurf);
926 Foam::faceList Foam::intersectedSurface::splitFace
928 const triSurface& surf,
934 const pointField& points = eSurf.points();
935 const edgeList& edges = eSurf.edges();
936 const labelList& fEdges = eSurf.faceEdges()[faceI];
938 // Create local (for the face only) point-edge connectivity.
939 Map<DynamicList<label> > facePointEdges
941 calcPointEdgeAddressing
948 // Order in which edges have been walked. Initialize outside edges.
949 Map<label> visited(fEdges.size()*2);
953 label edgeI = fEdges[i];
955 if (eSurf.isSurfaceEdge(edgeI))
957 // Edge is edge from original surface so an outside edge for
959 label surfEdgeI = eSurf.parentEdge(edgeI);
961 label owner = surf.edgeOwner()[surfEdgeI];
968 surf.localFaces()[owner],
969 surf.localFaces()[faceI]
973 // Edge is in same order as current face.
974 // Mark off the opposite order.
975 visited.insert(edgeI, ENDTOSTART);
979 // Edge is in same order as current face.
980 // Mark off the opposite order.
981 visited.insert(edgeI, STARTTOEND);
986 visited.insert(edgeI, UNVISITED);
993 DynamicList<face> faces(fEdges.size());
997 // Find starting edge:
998 // - unvisted triangle edge
999 // - once visited intersection edge
1000 // Give priority to triangle edges.
1001 label startEdgeI = -1;
1002 label startVertI = -1;
1006 label edgeI = fEdges[i];
1008 const edge& e = edges[edgeI];
1010 label stat = visited[edgeI];
1012 if (stat == STARTTOEND)
1017 if (eSurf.isSurfaceEdge(edgeI))
1022 else if (stat == ENDTOSTART)
1027 if (eSurf.isSurfaceEdge(edgeI))
1034 if (startEdgeI == -1)
1039 //Pout<< "splitFace: starting walk from edge:" << startEdgeI
1040 // << ' ' << edges[startEdgeI] << " vertex:" << startVertI << endl;
1042 //// Print current visited state.
1043 //printVisit(eSurf.edges(), fEdges, visited);
1046 // Pout<< "Writing face:" << faceI << " to face.obj" << endl;
1047 // OFstream str("face.obj");
1048 // writeOBJ(eSurf.points(), eSurf.edges(), fEdges, str);
1057 surf.faceNormals()[faceI],
1069 // Check if any unvisited edges left.
1072 label edgeI = fEdges[i];
1074 label stat = visited[edgeI];
1076 if (eSurf.isSurfaceEdge(edgeI) && stat != BOTH)
1078 SeriousErrorIn("Foam::intersectedSurface::splitFace")
1079 << "Dumping face edges to faceEdges.obj" << endl;
1081 writeLocalOBJ(points, edges, fEdges, "faceEdges.obj");
1083 FatalErrorIn("intersectedSurface::splitFace")
1084 << "Problem: edge " << edgeI << " vertices "
1085 << edges[edgeI] << " on face " << faceI
1086 << " has visited status " << stat << " from a "
1087 << "righthanded walk along all"
1088 << " of the triangle edges. Are the original surfaces"
1089 << " closed and non-intersecting?"
1090 << abort(FatalError);
1092 else if (stat != BOTH)
1095 // Pout<< "Dumping faces so far to faces.obj" << nl
1096 // << faces << endl;
1098 // OFstream str("faces.obj");
1102 // writeOBJ(points, faces[i], str);
1106 Pout<< "** Resplitting **" << endl;
1108 // Redo face after introducing extra edge. Edge introduced
1109 // should be one nearest to any fully visited edge.
1122 // See if normal needs flipping.
1125 vector n = faces[0].normal(eSurf.points());
1127 if ((n & surf.faceNormals()[faceI]) < 0)
1139 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1142 Foam::intersectedSurface::intersectedSurface()
1145 intersectionEdges_(0),
1151 // Construct from components
1152 Foam::intersectedSurface::intersectedSurface(const triSurface& surf)
1155 intersectionEdges_(0),
1161 // Construct from surface and intersection
1162 Foam::intersectedSurface::intersectedSurface
1164 const triSurface& surf,
1165 const bool isFirstSurface,
1166 const surfaceIntersection& inter
1170 intersectionEdges_(0),
1172 nSurfacePoints_(surf.nPoints())
1174 if (inter.cutPoints().empty() && inter.cutEdges().empty())
1176 // No intersection. Make straight copy.
1177 triSurface::operator=(surf);
1179 // Identity for face map
1180 faceMap_.setSize(size());
1182 forAll(faceMap_, faceI)
1184 faceMap_[faceI] = faceI;
1190 // Calculate face-edge addressing for surface + intersection.
1191 edgeSurface eSurf(surf, isFirstSurface, inter);
1193 // Update point information for any removed points. (when are they removed?
1194 // - but better make sure)
1195 nSurfacePoints_ = eSurf.nSurfacePoints();
1197 // Now we have full points, edges and edge addressing for surf. Start
1198 // extracting faces and triangulate them.
1200 // Storage for new triangles of surface.
1201 DynamicList<labelledTri> newTris(eSurf.edges().size()/2);
1203 // Start in newTris for decomposed face.
1204 labelList startTriI(surf.size(), 0);
1208 startTriI[faceI] = newTris.size();
1210 if (eSurf.faceEdges()[faceI].size() != surf.faceEdges()[faceI].size())
1212 // Face has been cut by intersection.
1213 // Cut face into multiple subfaces. Use faceEdge information
1214 // from edgeSurface only. (original triSurface 'surf' is used for
1215 // faceNormals and regionnumber only)
1221 faceI, // current triangle
1222 eSurf // face-edge description of surface
1226 forAll(newFaces, newFaceI)
1228 const face& newF = newFaces[newFaceI];
1234 // + Foam::name(faceI)
1236 // + Foam::name(newFaceI)
1239 // Pout<< "Writing original face:" << faceI << " subFace:"
1240 // << newFaceI << " to " << fName << endl;
1242 // OFstream str(fName);
1246 // meshTools::writeOBJ(str, eSurf.points()[newF[fp]]);
1251 // str << ' ' << fp+1;
1253 // str<< " 1" << nl;
1257 const vector& n = surf.faceNormals()[faceI];
1258 const label region = surf[faceI].region();
1260 faceTriangulation tris(eSurf.points(), newF, n);
1264 const triFace& t = tris[triI];
1268 if (t[i] < 0 || t[i] >= eSurf.points().size())
1272 "intersectedSurface::intersectedSurface"
1273 ) << "Face triangulation of face " << faceI
1274 << " uses points outside range 0.."
1275 << eSurf.points().size()-1 << endl
1277 << tris << abort(FatalError);
1281 newTris.append(labelledTri(t[0], t[1], t[2], region));
1287 // Face has not been cut at all. No need to renumber vertices since
1288 // eSurf keeps surface vertices first.
1289 newTris.append(surf.localFaces()[faceI]);
1296 // Construct triSurface. Note that addressing will be compact since
1297 // edgeSurface is compact.
1298 triSurface::operator=
1308 // Construct mapping back into original surface
1309 faceMap_.setSize(size());
1311 for (label faceI = 0; faceI < surf.size()-1; faceI++)
1313 for (label triI = startTriI[faceI]; triI < startTriI[faceI+1]; triI++)
1315 faceMap_[triI] = faceI;
1318 for (label triI = startTriI[surf.size()-1]; triI < size(); triI++)
1320 faceMap_[triI] = surf.size()-1;
1324 // Find edges on *this which originate from 'cuts'. (i.e. newEdgeI >=
1325 // nSurfaceEdges) Renumber edges into local triSurface numbering.
1327 intersectionEdges_.setSize(eSurf.edges().size() - eSurf.nSurfaceEdges());
1329 label intersectionEdgeI = 0;
1333 label edgeI = eSurf.nSurfaceEdges();
1334 edgeI < eSurf.edges().size();
1338 // Get edge vertices in triSurface local numbering
1339 const edge& e = eSurf.edges()[edgeI];
1340 label surfStartI = meshPointMap()[e.start()];
1341 label surfEndI = meshPointMap()[e.end()];
1343 // Find edge connected to surfStartI which also uses surfEndI.
1344 label surfEdgeI = -1;
1346 const labelList& pEdges = pointEdges()[surfStartI];
1350 const edge& surfE = edges()[pEdges[i]];
1352 // Edge already connected to surfStart for sure. See if also
1353 // connects to surfEnd
1354 if (surfE.start() == surfEndI || surfE.end() == surfEndI)
1356 surfEdgeI = pEdges[i];
1362 if (surfEdgeI != -1)
1364 intersectionEdges_[intersectionEdgeI++] = surfEdgeI;
1368 FatalErrorIn("intersectedSurface::intersectedSurface")
1369 << "Cannot find edge among candidates " << pEdges
1370 << " which uses points " << surfStartI
1371 << " and " << surfEndI
1372 << abort(FatalError);
1378 // ************************************************************************* //