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 "cuttingPlane.H"
28 #include <OpenFOAM/primitiveMesh.H>
29 #include <OpenFOAM/linePointRef.H>
30 #include <meshTools/meshTools.H>
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 // set values for what is close to zero and what is considered to
35 // be positive (and not just rounding noise)
37 const Foam::scalar zeroish = Foam::SMALL;
38 const Foam::scalar positive = Foam::SMALL * 1E3;
39 //! @endcond localScope
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 void Foam::cuttingPlane::calcCutCells
46 const primitiveMesh& mesh,
47 const scalarField& dotProducts,
48 const UList<label>& cellIdLabels
51 const labelListList& cellEdges = mesh.cellEdges();
52 const edgeList& edges = mesh.edges();
54 label listSize = cellEdges.size();
57 listSize = cellIdLabels.size();
60 cutCells_.setSize(listSize);
63 // Find the cut cells by detecting any cell that uses points with
64 // opposing dotProducts.
65 for (label listI = 0; listI < listSize; ++listI)
70 cellI = cellIdLabels[listI];
73 const labelList& cEdges = cellEdges[cellI];
79 const edge& e = edges[cEdges[i]];
83 (dotProducts[e[0]] < zeroish && dotProducts[e[1]] > positive)
84 || (dotProducts[e[1]] < zeroish && dotProducts[e[0]] > positive)
91 cutCells_[cutcellI++] = cellI;
99 // Set correct list size
100 cutCells_.setSize(cutcellI);
104 // Determine for each edge the intersection point. Calculates
105 // - cutPoints_ : coordinates of all intersection points
106 // - edgePoint : per edge -1 or the index into cutPoints
107 void Foam::cuttingPlane::intersectEdges
109 const primitiveMesh& mesh,
110 const scalarField& dotProducts,
111 List<label>& edgePoint
114 // Use the dotProducts to find out the cut edges.
115 const edgeList& edges = mesh.edges();
116 const pointField& points = mesh.points();
118 // Per edge -1 or the label of the intersection point
119 edgePoint.setSize(edges.size());
121 DynamicList<point> dynCuttingPoints(4*cutCells_.size());
125 const edge& e = edges[edgeI];
129 (dotProducts[e[0]] < zeroish && dotProducts[e[1]] > positive)
130 || (dotProducts[e[1]] < zeroish && dotProducts[e[0]] > positive)
134 edgePoint[edgeI] = dynCuttingPoints.size();
136 const point& p0 = points[e[0]];
137 const point& p1 = points[e[1]];
139 scalar alpha = lineIntersect(linePointRef(p0, p1));
143 dynCuttingPoints.append(p0);
145 else if (alpha >= 1.0)
147 dynCuttingPoints.append(p1);
151 dynCuttingPoints.append((1-alpha)*p0 + alpha*p1);
156 edgePoint[edgeI] = -1;
160 this->storedPoints().transfer(dynCuttingPoints);
164 // Coming from startEdgeI cross the edge to the other face
165 // across to the next cut edge.
166 bool Foam::cuttingPlane::walkCell
168 const primitiveMesh& mesh,
169 const UList<label>& edgePoint,
171 const label startEdgeI,
172 DynamicList<label>& faceVerts
176 label edgeI = startEdgeI;
183 faceVerts.append(edgePoint[edgeI]);
185 // Cross edge to other face
186 faceI = meshTools::otherFace(mesh, cellI, faceI, edgeI);
188 // Find next cut edge on face.
189 const labelList& fEdges = mesh.faceEdges()[faceI];
191 label nextEdgeI = -1;
193 //Note: here is where we should check for whether there are more
194 // than 2 intersections with the face (warped/non-convex face).
195 // If so should e.g. decompose the cells on both faces and redo
200 label edge2I = fEdges[i];
202 if (edge2I != edgeI && edgePoint[edge2I] != -1)
211 // Did not find another cut edge on faceI. Do what?
212 WarningIn("Foam::cuttingPlane::walkCell")
213 << "Did not find closed walk along surface of cell " << cellI
214 << " starting from edge " << startEdgeI
215 << " in " << nIter << " iterations." << nl
216 << "Collected cutPoints so far:" << faceVerts
228 WarningIn("Foam::cuttingPlane::walkCell")
229 << "Did not find closed walk along surface of cell " << cellI
230 << " starting from edge " << startEdgeI
231 << " in " << nIter << " iterations." << nl
232 << "Collected cutPoints so far:" << faceVerts
237 } while (edgeI != startEdgeI);
240 if (faceVerts.size() >= 3)
246 WarningIn("Foam::cuttingPlane::walkCell")
247 << "Did not find closed walk along surface of cell " << cellI
248 << " starting from edge " << startEdgeI << nl
249 << "Collected cutPoints so far:" << faceVerts
257 // For every cut cell determine a walk through all? its cuts.
258 void Foam::cuttingPlane::walkCellCuts
260 const primitiveMesh& mesh,
261 const UList<label>& edgePoint
264 const pointField& cutPoints = this->points();
266 // use dynamic lists to handle triangulation and/or missed cuts
267 DynamicList<face> dynCutFaces(cutCells_.size());
268 DynamicList<label> dynCutCells(cutCells_.size());
270 // scratch space for calculating the face vertices
271 DynamicList<label> faceVerts(10);
275 label cellI = cutCells_[i];
277 // Find the starting edge to walk from.
278 const labelList& cEdges = mesh.cellEdges()[cellI];
280 label startEdgeI = -1;
282 forAll(cEdges, cEdgeI)
284 label edgeI = cEdges[cEdgeI];
286 if (edgePoint[edgeI] != -1)
293 // Check for the unexpected ...
294 if (startEdgeI == -1)
296 FatalErrorIn("Foam::cuttingPlane::walkCellCuts")
297 << "Cannot find cut edge for cut cell " << cellI
298 << abort(FatalError);
301 // Walk from starting edge around the circumference of the cell.
302 bool okCut = walkCell
315 // Orient face to point in the same direction as the plane normal
316 if ((f.normal(cutPoints) && normal()) < 0)
321 // the cut faces are usually quite ugly, so always triangulate
322 label nTri = f.triangles(cutPoints, dynCutFaces);
325 dynCutCells.append(cellI);
330 this->storedFaces().transfer(dynCutFaces);
331 cutCells_.transfer(dynCutCells);
335 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
337 // Construct without cutting
338 Foam::cuttingPlane::cuttingPlane(const plane& pln)
344 // Construct from plane and mesh reference, restricted to a list of cells
345 Foam::cuttingPlane::cuttingPlane
348 const primitiveMesh& mesh,
349 const UList<label>& cellIdLabels
354 reCut(mesh, cellIdLabels);
359 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
361 // recut mesh with existing planeDesc
362 void Foam::cuttingPlane::reCut
364 const primitiveMesh& mesh,
365 const UList<label>& cellIdLabels
368 MeshStorage::clear();
371 scalarField dotProducts = (mesh.points() - refPoint()) & normal();
373 // Determine cells that are (probably) cut.
374 calcCutCells(mesh, dotProducts, cellIdLabels);
376 // Determine cutPoints and return list of edge cuts.
377 // per edge -1 or the label of the intersection point
379 intersectEdges(mesh, dotProducts, edgePoint);
381 // Do topological walk around cell to find closed loop.
382 walkCellCuts(mesh, edgePoint);
386 // remap action on triangulation
387 void Foam::cuttingPlane::remapFaces
389 const UList<label>& faceMap
392 // recalculate the cells cut
393 if (&faceMap && faceMap.size())
395 MeshStorage::remapFaces(faceMap);
397 List<label> newCutCells(faceMap.size());
398 forAll(faceMap, faceI)
400 newCutCells[faceI] = cutCells_[faceMap[faceI]];
402 cutCells_.transfer(newCutCells);
406 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
408 void Foam::cuttingPlane::operator=(const cuttingPlane& rhs)
410 // Check for assignment to self
413 FatalErrorIn ("Foam::cuttingPlane::operator=(const cuttingPlane&)")
414 << "Attempted assignment to self"
415 << abort(FatalError);
418 static_cast<MeshStorage&>(*this) = rhs;
419 static_cast<plane&>(*this) = rhs;
420 cutCells_ = rhs.cutCells();
424 // ************************ vim: set sw=4 sts=4 et: ************************ //