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
27 \*---------------------------------------------------------------------------*/
29 #include "faceCollapser.H"
31 #include "polyTopoChange.H"
32 #include "polyModifyPoint.H"
33 #include "polyModifyFace.H"
34 #include "polyRemoveFace.H"
35 #include "SortableList.H"
36 #include "meshTools.H"
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 // Insert labelList into labelHashSet. Optional excluded element.
43 void Foam::faceCollapser::insert
45 const labelList& elems,
46 const label excludeElem,
52 if (elems[i] != excludeElem)
60 // Find edge amongst candidate edges. FatalError if none.
61 Foam::label Foam::faceCollapser::findEdge
63 const edgeList& edges,
64 const labelList& edgeLabels,
71 label edgeI = edgeLabels[i];
73 const edge& e = edges[edgeI];
77 (e[0] == v0 && e[1] == v1)
78 || (e[0] == v1 && e[1] == v0)
85 FatalErrorIn("findEdge") << "Cannot find edge between vertices " << v0
86 << " and " << v1 << " in edge labels " << edgeLabels
93 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
95 // Replace vertices in face
96 void Foam::faceCollapser::filterFace
98 const Map<labelList>& splitEdges,
100 polyTopoChange& meshMod
103 const face& f = mesh_.faces()[faceI];
104 const labelList& fEdges = mesh_.faceEdges()[faceI];
106 // Space for replaced vertices and split edges.
107 DynamicList<label> newFace(10 * f.size());
115 // Look ahead one to get edge.
116 label fp1 = f.fcIndex(fp);
120 // Get split on edge if any.
121 label edgeI = findEdge(mesh_.edges(), fEdges, v0, v1);
123 Map<labelList>::const_iterator edgeFnd =
124 splitEdges.find(edgeI);
126 if (edgeFnd != splitEdges.end())
128 // edgeI has been split (by introducing new vertices).
129 // Insert new vertices in face in correct order
130 // (splitEdges was constructed to be from edge.start() to end())
132 const labelList& extraVerts = edgeFnd();
134 if (v0 == mesh_.edges()[edgeI].start())
136 forAll(extraVerts, i)
138 newFace.append(extraVerts[i]);
143 forAllReverse(extraVerts, i)
145 newFace.append(extraVerts[i]);
150 face newF(newFace.shrink());
152 //Pout<< "Modifying face:" << faceI << " from " << f << " to " << newFace
161 if (mesh_.isInternalFace(faceI))
163 nei = mesh_.faceNeighbour()[faceI];
167 patchI = mesh_.boundaryMesh().whichPatch(faceI);
170 // Get current zone info
171 label zoneID = mesh_.faceZones().whichZone(faceI);
173 bool zoneFlip = false;
177 const faceZone& fZone = mesh_.faceZones()[zoneID];
179 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
186 newF, // modified face
187 faceI, // label of face being modified
188 mesh_.faceOwner()[faceI], // owner
191 patchI, // patch for face
192 false, // remove from zone
193 zoneID, // zone for face
194 zoneFlip // face flip in zone
201 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
203 // Construct from mesh
204 Foam::faceCollapser::faceCollapser(const polyMesh& mesh)
210 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
212 void Foam::faceCollapser::setRefinement
214 const labelList& faceLabels,
215 const labelList& fpStart,
216 const labelList& fpEnd,
217 polyTopoChange& meshMod
220 const pointField& points = mesh_.points();
221 const edgeList& edges = mesh_.edges();
222 const faceList& faces = mesh_.faces();
223 const labelListList& edgeFaces = mesh_.edgeFaces();
226 // From split edge to newly introduced point(s). Can be more than one per
228 Map<labelList> splitEdges(faceLabels.size());
230 // Mark faces in any way affect by modifying points/edges. Used later on
231 // to prevent having to redo all faces.
232 labelHashSet affectedFaces(4*faceLabels.size());
236 // Add/remove vertices and construct mapping
239 forAll(faceLabels, i)
241 const label faceI = faceLabels[i];
243 const face& f = faces[faceI];
245 const label fpA = fpStart[i];
246 const label fpB = fpEnd[i];
248 const point& pA = points[f[fpA]];
249 const point& pB = points[f[fpB]];
251 Pout<< "Face:" << f << " collapsed to fp:" << fpA << ' ' << fpB
252 << " with points:" << pA << ' ' << pB
255 // Create line from fpA to fpB
256 linePointRef lineAB(pA, pB);
258 // Get projections of all vertices onto line.
260 // Distance(squared) to pA for every point on face.
261 SortableList<scalar> dist(f.size());
264 dist[fpB] = magSqr(pB - pA);
266 // Step from fpA to fpB
267 // ~~~~~~~~~~~~~~~~~~~~
271 label fp = f.fcIndex(fpMin1);
275 // See where fp sorts. Make sure it is above fpMin1!
276 pointHit near = lineAB.nearestDist(points[f[fp]]);
278 scalar w = magSqr(near.rawPoint() - pA);
280 if (w <= dist[fpMin1])
283 w = dist[fpMin1] + 1E-6*(dist[fpB] - dist[fpA]);
287 pA + Foam::sqrt(w / (dist[fpB] - dist[fpA]))*(pB - pA)
290 Pout<< "Adapting position of vertex " << f[fp] << " on face "
291 << f << " from " << near.rawPoint() << " to " << newPoint
294 near.setPoint(newPoint);
297 // Responsability of caller to make sure polyModifyPoint is only
298 // called once per point. (so max only one collapse face per
314 // Step to next vertex.
316 fp = f.fcIndex(fpMin1);
319 // Step from fpA to fpB
320 // ~~~~~~~~~~~~~~~~~~~~
324 fp = f.rcIndex(fpMin1);
328 // See where fp sorts. Make sure it is below fpMin1!
329 pointHit near = lineAB.nearestDist(points[f[fp]]);
331 scalar w = magSqr(near.rawPoint() - pA);
333 if (w <= dist[fpMin1])
336 w = dist[fpMin1] + 1E-6*(dist[fpB] - dist[fpA]);
340 pA + Foam::sqrt(w / (dist[fpB] - dist[fpA]))*(pB - pA)
343 Pout<< "Adapting position of vertex " << f[fp] << " on face "
344 << f << " from " << near.rawPoint() << " to " << newPoint
347 near.setPoint(newPoint);
350 // Responsability of caller to make sure polyModifyPoint is only
351 // called once per point. (so max only one collapse face per
367 // Step to previous vertex.
369 fp = f.rcIndex(fpMin1);
374 // Check that fpB sorts latest.
375 if (dist.indices()[dist.size()-1] != fpB)
377 OFstream str("conflictingFace.obj");
378 meshTools::writeOBJ(str, faceList(1, f), points);
380 FatalErrorIn("faceCollapser::setRefinement")
381 << "Trying to collapse face:" << faceI << " vertices:" << f
382 << " to edges between vertices " << f[fpA] << " and "
383 << f[fpB] << " but " << f[fpB] << " does not seem to be the"
384 << " vertex furthest away from " << f[fpA] << endl
385 << "Dumped conflicting face to obj file conflictingFace.obj"
386 << abort(FatalError);
390 // From fp to index in sort:
391 Pout<< "Face:" << f << " fpA:" << fpA << " fpB:" << fpB << nl;
393 labelList sortedFp(f.size());
394 forAll(dist.indices(), i)
396 label fp = dist.indices()[i];
398 Pout<< " fp:" << fp << " distance:" << dist[i] << nl;
403 const labelList& fEdges = mesh_.faceEdges()[faceI];
405 // Now look up all edges in the face and see if they get extra
406 // vertices inserted and build an edge-to-intersected-points table.
408 // Order of inserted points is in edge order (from e.start to
413 label fp1 = f.fcIndex(fp);
415 // Get index in sorted list
416 label sorted0 = sortedFp[fp];
417 label sorted1 = sortedFp[fp1];
419 // Get indices in increasing order
420 DynamicList<label> edgePoints(f.size());
422 // Whether edgePoints are from fp to fp1
425 if (sorted0 < sorted1)
429 for (label j = sorted0+1; j < sorted1; j++)
431 edgePoints.append(f[dist.indices()[j]]);
438 for (label j = sorted1+1; j < sorted0; j++)
440 edgePoints.append(f[dist.indices()[j]]);
444 if (edgePoints.size())
448 label edgeI = findEdge(edges, fEdges, f[fp], f[fp1]);
450 const edge& e = edges[edgeI];
452 if (fpToFp1 == (f[fp] == e.start()))
454 splitEdges.insert(edgeI, edgePoints);
459 splitEdges.insert(edgeI, edgePoints);
462 // Mark all faces affected
463 insert(edgeFaces[edgeI], faceI, affectedFaces);
470 Map<labelList>::const_iterator iter = splitEdges.begin();
471 iter != splitEdges.end();
475 Pout<< "Split edge:" << iter.key()
476 << " verts:" << mesh_.edges()[iter.key()]
478 const labelList& edgePoints = iter();
480 forAll(edgePoints, i)
482 Pout<< " " << edgePoints[i] << nl;
491 forAll(faceLabels, i)
493 const label faceI = faceLabels[i];
495 meshMod.setAction(polyRemoveFace(faceI));
497 // Update list of faces we still have to modify
498 affectedFaces.erase(faceI);
503 // Modify faces affected (but not removed)
508 labelHashSet::const_iterator iter = affectedFaces.begin();
509 iter != affectedFaces.end();
513 filterFace(splitEdges, iter.key(), meshMod);
518 // ************************************************************************* //