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
25 \*---------------------------------------------------------------------------*/
27 #include "cuttingPlane.H"
28 #include "primitiveMesh.H"
29 #include "linePointRef.H"
30 #include "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 labelList& 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 Foam::labelList Foam::cuttingPlane::intersectEdges
109 const primitiveMesh& mesh,
110 const scalarField& dotProducts
113 // Use the dotProducts to find out the cut edges.
114 const edgeList& edges = mesh.edges();
115 const pointField& points = mesh.points();
117 // Per edge -1 or the label of the intersection point
118 labelList edgePoint(edges.size(), -1);
120 DynamicList<point> dynCuttingPoints(4*cutCells_.size());
124 const edge& e = edges[edgeI];
128 (dotProducts[e[0]] < zeroish && dotProducts[e[1]] > positive)
129 || (dotProducts[e[1]] < zeroish && dotProducts[e[0]] > positive)
133 const point& p0 = points[e[0]];
134 const point& p1 = points[e[1]];
136 scalar alpha = lineIntersect(linePointRef(p0, p1));
140 dynCuttingPoints.append(p0);
142 else if (alpha > 1.0)
144 dynCuttingPoints.append(p1);
148 dynCuttingPoints.append((1-alpha)*p0 + alpha*p1);
151 edgePoint[edgeI] = dynCuttingPoints.size() - 1;
155 dynCuttingPoints.shrink();
156 cutPoints_.transfer(dynCuttingPoints);
157 dynCuttingPoints.clear();
163 // Coming from startEdgeI cross the edge to the other face
164 // across to the next cut edge.
165 bool Foam::cuttingPlane::walkCell
167 const primitiveMesh& mesh,
168 const labelList& edgePoint,
170 const label startEdgeI,
171 DynamicList<label>& faceVerts
175 label edgeI = startEdgeI;
181 faceVerts.append(edgePoint[edgeI]);
183 // Cross edge to other face
184 faceI = meshTools::otherFace(mesh, cellI, faceI, edgeI);
186 // Find next cut edge on face.
187 const labelList& fEdges = mesh.faceEdges()[faceI];
189 label nextEdgeI = -1;
191 //Note: here is where we should check for whether there are more
192 // than 2 intersections with the face (warped/non-convex face).
193 // If so should e.g. decompose the cells on both faces and redo
198 label edge2I = fEdges[i];
200 if (edge2I != edgeI && edgePoint[edge2I] != -1)
209 // Did not find another cut edge on faceI. Do what?
210 WarningIn("Foam::cuttingPlane::walkCell")
211 << "Did not find closed walk along surface of cell " << cellI
212 << " starting from edge " << startEdgeI
213 << " in " << nIter << " iterations." << nl
214 << "Collected cutPoints so far:" << faceVerts
226 WarningIn("Foam::cuttingPlane::walkCell")
227 << "Did not find closed walk along surface of cell " << cellI
228 << " starting from edge " << startEdgeI
229 << " in " << nIter << " iterations." << nl
230 << "Collected cutPoints so far:" << faceVerts
235 } while (edgeI != startEdgeI);
238 if (faceVerts.size() >= 3)
244 WarningIn("Foam::cuttingPlane::walkCell")
245 << "Did not find closed walk along surface of cell " << cellI
246 << " starting from edge " << startEdgeI << nl
247 << "Collected cutPoints so far:" << faceVerts
255 // For every cut cell determine a walk through all? its cuts.
256 void Foam::cuttingPlane::walkCellCuts
258 const primitiveMesh& mesh,
259 const labelList& edgePoint
262 cutFaces_.setSize(cutCells_.size());
267 label cellI = cutCells_[i];
269 // Find the starting edge to walk from.
270 const labelList& cEdges = mesh.cellEdges()[cellI];
272 label startEdgeI = -1;
274 forAll(cEdges, cEdgeI)
276 label edgeI = cEdges[cEdgeI];
278 if (edgePoint[edgeI] != -1)
285 // Check for the unexpected ...
286 if (startEdgeI == -1)
288 FatalErrorIn("Foam::cuttingPlane::walkCellCuts")
289 << "Cannot find cut edge for cut cell " << cellI
290 << abort(FatalError);
293 // Walk from starting edge around the circumference of the cell.
294 DynamicList<label> faceVerts(2*mesh.faces()[cellI].size());
295 bool okCut = walkCell
308 face cutFace(faceVerts);
311 if ((cutFace.normal(cutPoints_) && normal()) < 0)
313 cutFace = cutFace.reverseFace();
316 cutFaces_[cutFaceI++] = cutFace;
320 cutFaces_.setSize(cutFaceI);
324 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
326 // Construct without cutting
327 Foam::cuttingPlane::cuttingPlane(const plane& newPlane)
333 // Construct from components
334 Foam::cuttingPlane::cuttingPlane
336 const primitiveMesh& mesh,
337 const plane& newPlane
345 // Construct from mesh reference and plane, restricted to a list of cells
346 Foam::cuttingPlane::cuttingPlane
348 const primitiveMesh& mesh,
349 const plane& newPlane,
350 const labelList& cellIdLabels
355 reCut(mesh, cellIdLabels);
360 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
362 // reCut mesh with existing planeDesc
363 void Foam::cuttingPlane::reCut
365 const primitiveMesh& mesh
372 scalarField dotProducts = (mesh.points() - refPoint()) & normal();
374 //// Perturb points cuts so edges are cut properly.
375 //const tmp<scalarField> tdotProducts = stabilise(rawDotProducts, SMALL);
376 //const scalarField& dotProducts = tdotProducts();
378 // Determine cells that are (probably) cut.
379 calcCutCells(mesh, dotProducts);
381 // Determine cutPoints and return list of edge cuts. (per edge -1 or
382 // the label of the intersection point (in cutPoints_)
383 labelList edgePoint(intersectEdges(mesh, dotProducts));
385 // Do topological walk around cell to find closed loop.
386 walkCellCuts(mesh, edgePoint);
390 // recut mesh with existing planeDesc
391 void Foam::cuttingPlane::reCut
393 const primitiveMesh& mesh,
394 const labelList& cellIdLabels
401 scalarField dotProducts = (mesh.points() - refPoint()) & normal();
403 // Determine cells that are (probably) cut.
404 calcCutCells(mesh, dotProducts, cellIdLabels);
406 // Determine cutPoints and return list of edge cuts. (per edge -1 or
407 // the label of the intersection point (in cutPoints_)
408 labelList edgePoint(intersectEdges(mesh, dotProducts));
410 // Do topological walk around cell to find closed loop.
411 walkCellCuts(mesh, edgePoint);
417 const Foam::plane& Foam::cuttingPlane::planeDesc() const
419 return static_cast<const plane&>(*this);
423 // Return vectorField of cutting points
424 const Foam::pointField& Foam::cuttingPlane::points() const
430 // Return unallocFaceList of points in cells
431 const Foam::faceList& Foam::cuttingPlane::faces() const
437 // Return labelList of cut cells
438 const Foam::labelList& Foam::cuttingPlane::cells() const
444 bool Foam::cuttingPlane::cut()
446 if (cutCells_.size() > 0)
457 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
459 void Foam::cuttingPlane::operator=(const cuttingPlane& rhs)
461 // Check for assignment to self
464 FatalErrorIn ("Foam::cuttingPlane::operator=(const cuttingPlane&)")
465 << "Attempted assignment to self"
466 << abort(FatalError);
469 static_cast<plane&>(*this) = rhs;
471 cutCells_ = rhs.cells();
472 cutPoints_ = rhs.points();
473 cutFaces_ = rhs.faces();
477 // ************************************************************************* //