1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "surfaceSets.H"
30 #include "triSurface.H"
31 #include "triSurfaceSearch.H"
34 #include "surfaceToCell.H"
35 #include "cellToPoint.H"
36 #include "cellToCell.H"
37 #include "pointToCell.H"
38 #include "meshSearch.H"
39 #include "cellClassification.H"
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 //Foam::scalar Foam::surfaceSets::minEdgeLen
49 // const primitiveMesh& mesh,
53 // const edgeList& edges = mesh.edges();
55 // const pointField& points = mesh.points();
57 // const labelList& pEdges = mesh.pointEdges()[pointI];
59 // scalar minLen = GREAT;
63 // minLen = min(minLen, edges[pEdges[i]].mag(points));
69 //// Returns true if cell uses at least one selected point
70 //bool Foam::surfaceSets::usesPoint
72 // const primitiveMesh& mesh,
73 // const boolList& selectedPoint,
77 // const labelList& cFaces = mesh.cells()[cellI];
79 // forAll(cFaces, cFaceI)
81 // label faceI = cFaces[cFaceI];
83 // const face& f = mesh.faces()[faceI];
87 // if (selectedPoint[f[fp]])
98 //// Remove cells in allCells which are connected to other cells in allCells
99 //// by outside vertices only. Since these outside vertices will be moved onto
100 //// a surface they might result in flat cells.
101 //Foam::label Foam::surfaceSets::removeHangingCells
103 // const primitiveMesh& mesh,
104 // const triSurfaceSearch& querySurf,
105 // labelHashSet& internalCells
108 // const pointField& points = mesh.points();
109 // const cellList& cells = mesh.cells();
110 // const faceList& faces = mesh.faces();
112 // // Determine cells that have all points on the boundary.
113 // labelHashSet flatCandidates(getHangingCells(mesh, internalCells));
115 // // All boundary points will become visible after subsetting and will be
117 // // to surface. Calculate new volume for cells using only these points and
118 // // check if it does not become too small.
120 // // Get points used by flatCandidates.
121 // labelHashSet outsidePoints(flatCandidates.size());
123 // // Snap outside points to surface
124 // pointField newPoints(points);
128 // labelHashSet::const_iterator iter = flatCandidates.begin();
129 // iter != flatCandidates.end();
133 // const cell& cFaces = cells[iter.key()];
135 // forAll(cFaces, cFaceI)
137 // const face& f = faces[cFaces[cFaceI]];
141 // label pointI = f[fp];
143 // if (outsidePoints.insert(pointI))
145 // // Calculate new position for this outside point
146 // tmp<pointField> tnearest =
147 // querySurf.calcNearest(pointField(1, points[pointI]));
148 // newPoints[pointI] = tnearest()[0];
155 // // Calculate new volume for mixed cells
156 // label nRemoved = 0;
159 // labelHashSet::const_iterator iter = flatCandidates.begin();
160 // iter != flatCandidates.end();
164 // label cellI = iter.key();
166 // const cell& cll = cells[cellI];
168 // scalar newVol = cll.mag(newPoints, faces);
169 // scalar oldVol = mesh.cellVolumes()[cellI];
171 // if (newVol < 0.1 * oldVol)
173 // internalCells.erase(cellI);
182 //// Select all points out of pointSet where the distance to the surface is less
183 //// than a factor times a local length scale (minimum length of connected edges)
184 //void Foam::surfaceSets::getNearPoints
186 // const primitiveMesh& mesh,
187 // const triSurface&,
188 // const triSurfaceSearch& querySurf,
189 // const scalar edgeFactor,
190 // const pointSet& candidateSet,
191 // pointSet& nearPointSet
194 // if (edgeFactor <= 0)
199 // labelList candidates(candidateSet.toc());
201 // pointField candidatePoints(candidates.size());
202 // forAll(candidates, i)
204 // candidatePoints[i] = mesh.points()[candidates[i]];
207 // tmp<pointField> tnearest = querySurf.calcNearest(candidatePoints);
208 // const pointField& nearest = tnearest();
210 // const pointField& points = mesh.points();
212 // forAll(candidates, i)
214 // label pointI = candidates[i];
216 // scalar minLen = minEdgeLen(mesh, pointI);
218 // scalar dist = mag(nearest[i] - points[pointI]);
220 // if (dist < edgeFactor * minLen)
222 // nearPointSet.insert(pointI);
228 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
231 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
233 void Foam::surfaceSets::getSurfaceSets
235 const polyMesh& mesh,
238 const triSurfaceSearch& querySurf,
239 const pointField& outsidePts,
241 const label nCutLayers,
243 labelHashSet& inside,
244 labelHashSet& outside,
248 // Construct search engine on mesh
249 meshSearch queryMesh(mesh, true);
252 // Check all 'outside' points
253 forAll(outsidePts, outsideI)
255 const point& outsidePoint = outsidePts[outsideI];
257 // Find cell point is in. Linear search.
258 if (queryMesh.findCell(outsidePoint, -1, false) == -1)
262 "surfaceSets::getSurfaceSets"
263 "(const polyMesh&, const fileName&, const triSurface&"
264 ", const triSurfaceSearch&, const pointField&"
265 ", labelHashSet&, labelHashSet&, labelHashSet&)"
266 ) << "outsidePoint " << outsidePoint
267 << " is not inside any cell"
272 // Cut faces with surface and classify cells
273 cellClassification cellType
283 // Trim cutCells so they are max nCutLayers away (as seen in point-cell
284 // walk) from outside cells.
285 cellType.trimCutCells
288 cellClassification::OUTSIDE,
289 cellClassification::INSIDE
293 forAll(cellType, cellI)
295 label cType = cellType[cellI];
297 if (cType == cellClassification::CUT)
301 else if (cType == cellClassification::INSIDE)
303 inside.insert(cellI);
305 else if (cType == cellClassification::OUTSIDE)
307 outside.insert(cellI);
313 Foam::labelHashSet Foam::surfaceSets::getHangingCells
315 const primitiveMesh& mesh,
316 const labelHashSet& internalCells
319 const cellList& cells = mesh.cells();
320 const faceList& faces = mesh.faces();
323 // Divide points into
324 // -referenced by internal only
325 // -referenced by outside only
328 List<pointStatus> pointSide(mesh.nPoints(), NOTSET);
330 for (label cellI = 0; cellI < mesh.nCells(); cellI++)
332 if (internalCells.found(cellI))
334 // Inside cell. Mark all vertices seen from this cell.
335 const labelList& cFaces = cells[cellI];
337 forAll(cFaces, cFaceI)
339 const face& f = faces[cFaces[cFaceI]];
343 label pointI = f[fp];
345 if (pointSide[pointI] == NOTSET)
347 pointSide[pointI] = INSIDE;
349 else if (pointSide[pointI] == OUTSIDE)
351 pointSide[pointI] = MIXED;
355 // mixed or inside stay same
363 const labelList& cFaces = cells[cellI];
365 forAll(cFaces, cFaceI)
367 const face& f = faces[cFaces[cFaceI]];
371 label pointI = f[fp];
373 if (pointSide[pointI] == NOTSET)
375 pointSide[pointI] = OUTSIDE;
377 else if (pointSide[pointI] == INSIDE)
379 pointSide[pointI] = MIXED;
383 // mixed or outside stay same
391 //OFstream mixedStr("mixed.obj");
393 //forAll(pointSide, pointI)
395 // if (pointSide[pointI] == MIXED)
397 // const point& pt = points[pointI];
399 // mixedStr << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
405 // Determine cells using mixed points only
407 labelHashSet mixedOnlyCells(internalCells.size());
411 labelHashSet::const_iterator iter = internalCells.begin();
412 iter != internalCells.end();
416 label cellI = iter.key();
418 const cell& cFaces = cells[cellI];
420 label usesMixedOnly = true;
424 const face& f = faces[cFaces[i]];
428 if (pointSide[f[fp]] != MIXED)
430 usesMixedOnly = false;
442 mixedOnlyCells.insert(cellI);
446 return mixedOnlyCells;
450 //void Foam::surfaceSets::writeSurfaceSets
452 // const polyMesh& mesh,
453 // const fileName& surfName,
454 // const triSurface& surf,
455 // const triSurfaceSearch& querySurf,
456 // const pointField& outsidePts,
457 // const scalar edgeFactor
460 // // Cellsets for inside/outside determination
461 // cellSet rawInside(mesh, "rawInside", mesh.nCells()/10);
462 // cellSet rawOutside(mesh, "rawOutside", mesh.nCells()/10);
463 // cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
465 // // Get inside/outside/cut cells
480 // Pout<< "rawInside:" << rawInside.size() << endl;
485 // nRemoved = removeHangingCells(mesh, querySurf, rawInside);
488 // << "Removed " << nRemoved
489 // << " rawInside cells that have all their points on the outside"
492 // while (nRemoved != 0);
494 // Pout<< "Writing inside cells (" << rawInside.size() << ") to cellSet "
495 // << rawInside.instance()/rawInside.local()/rawInside.name()
497 // rawInside.write();
501 // // Select outside cells
502 // surfaceToCell outsideSource
509 // false, // includeCut
510 // false, // includeInside
511 // true, // includeOutside
512 // -GREAT, // nearDist
513 // -GREAT // curvature
516 // outsideSource.applyToSet(topoSetSource::NEW, rawOutside);
518 // Pout<< "rawOutside:" << rawOutside.size() << endl;
522 // nRemoved = removeHangingCells(mesh, querySurf, rawOutside);
525 // << "Removed " << nRemoved
526 // << " rawOutside cells that have all their points on the outside"
529 // while (nRemoved != 0);
531 // Pout<< "Writing outside cells (" << rawOutside.size() << ") to cellSet "
532 // << rawOutside.instance()/rawOutside.local()/rawOutside.name()
534 // rawOutside.write();
537 // // Select cut cells by negating inside and outside set.
538 // cutCells.invert(mesh.nCells());
540 // cellToCell deleteInsideSource(mesh, rawInside.name());
542 // deleteInsideSource.applyToSet(topoSetSource::DELETE, cutCells);
543 // Pout<< "Writing cut cells (" << cutCells.size() << ") to cellSet "
544 // << cutCells.instance()/cutCells.local()/cutCells.name()
550 // // Remove cells with points too close to surface.
554 // // Get all points in cutCells.
555 // pointSet cutPoints(mesh, "cutPoints", 4*cutCells.size());
556 // cellToPoint cutSource(mesh, "cutCells", cellToPoint::ALL);
557 // cutSource.applyToSet(topoSetSource::NEW, cutPoints);
559 // // Get all points that are too close to surface.
560 // pointSet nearPoints(mesh, "nearPoints", cutPoints.size());
573 // << "Selected " << nearPoints.size()
574 // << " points that are closer than " << edgeFactor
575 // << " times the local minimum lengthscale to the surface"
579 // // Remove cells that use any of the points in nearPoints
580 // // from the inside and outsideCells.
581 // nearPoints.write();
582 // pointToCell pToCell(mesh, nearPoints.name(), pointToCell::ANY);
586 // // Start off from copy of rawInside, rawOutside
587 // cellSet inside(mesh, "inside", rawInside);
588 // cellSet outside(mesh, "outside", rawOutside);
590 // pToCell.applyToSet(topoSetSource::DELETE, inside);
591 // pToCell.applyToSet(topoSetSource::DELETE, outside);
594 // << "Removed " << rawInside.size() - inside.size()
595 // << " inside cells that are too close to the surface" << endl;
598 // << "Removed " << rawOutside.size() - outside.size()
599 // << " inside cells that are too close to the surface" << nl << endl;
604 // // Remove cells with one or no faces on rest of cellSet. Note: Problem is
605 // // not these cells an sich but rather that all of their vertices will be
606 // // outside vertices and thus projected onto surface. Which might (if they
607 // // project onto same surface) result in flattened cells.
612 // nRemoved = removeHangingCells(mesh, querySurf, inside);
615 // << "Removed " << nRemoved
616 // << " inside cells that have all their points on the outside"
619 // while (nRemoved != 0);
622 // nRemoved = removeHangingCells(mesh, querySurf, outside);
625 // << "Removed " << nRemoved
626 // << " outside cells that have all their points on the inside"
629 // while (nRemoved != 0);
637 // Pout<< "Writing inside cells (" << inside.size() << ") to cellSet "
638 // << inside.instance()/inside.local()/inside.name()
643 // Pout<< "Writing outside cells (" << outside.size() << ") to cellSet "
644 // << outside.instance()/outside.local()/outside.name()
651 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
654 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
657 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
660 // ************************************************************************* //