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/>.
28 Class for convexSetAlgorithms pertaining to faces
32 University of Massachusetts Amherst
35 \*---------------------------------------------------------------------------*/
37 #include "faceSetAlgorithm.H"
42 #include "triIntersection.H"
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
51 // Construct from components
52 faceSetAlgorithm::faceSetAlgorithm
55 const pointField& newPoints,
56 const UList<edge>& newEdges,
57 const UList<face>& newFaces,
58 const UList<cell>& newCells,
59 const UList<label>& newOwner,
60 const UList<label>& newNeighbour
76 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
78 void faceSetAlgorithm::computeNormFactor(const label index) const
80 // Clear existing fields
86 // Compute refNorm and normFactor
87 refNorm_ = newFaces_[index].normal(newPoints_);
88 normFactor_ = mag(refNorm_);
90 // Normalize for later use
91 refNorm_ /= normFactor_ + VSMALL;
93 // Compute a bounding box around the face
94 box_ = boundBox(newFaces_[index].points(newPoints_), false);
96 vector minToXb = (box_.min() - box_.midpoint());
97 vector maxToXb = (box_.max() - box_.midpoint());
100 box_.min() += (1.5 * minToXb);
101 box_.max() += (1.5 * maxToXb);
105 // Check whether the bounding box contains the entity
106 bool faceSetAlgorithm::contains(const label index) const
109 const face& checkFace = mesh_.faces()[index];
111 // Check if the bounding box contains any of the supplied points
112 forAll(checkFace, pointI)
114 if (box_.contains(mesh_.points()[checkFace[pointI]]))
124 // Compute intersection
125 bool faceSetAlgorithm::computeIntersection
127 const label newIndex,
128 const label oldIndex,
133 bool intersects = false;
135 const pointField& newPoints = newPoints_;
136 const pointField& oldPoints = mesh_.points();
138 const face& newFace = newFaces_[newIndex];
139 const face& oldFace = mesh_.faces()[oldIndex];
141 // Compute the normal for the old face
142 vector oldNorm = oldFace.normal(oldPoints);
145 oldNorm /= mag(oldNorm) + VSMALL;
147 if ((oldNorm & refNorm_) < 0.0)
149 // Opposite face orientation. Skip it.
153 // Check if decomposition is necessary
154 if (oldFace.size() > 3 || newFace.size() > 3)
156 // Decompose new / old faces
157 DynamicList<FixedList<point, 3> > clippingTris(15);
158 DynamicList<FixedList<point, 3> > subjectTris(15);
160 label ntOld = 0, ntNew = 0;
162 if (oldFace.size() == 3)
165 subjectTris.append(FixedList<point, 3>(vector::zero));
167 subjectTris[ntOld][0] = oldPoints[oldFace[0]];
168 subjectTris[ntOld][1] = oldPoints[oldFace[1]];
169 subjectTris[ntOld][2] = oldPoints[oldFace[2]];
175 // Configure tris from oldFace
176 vector ofCentre = oldFace.centre(oldPoints);
181 subjectTris.append(FixedList<point, 3>(vector::zero));
183 subjectTris[ntOld][0] = oldPoints[oldFace[pI]];
184 subjectTris[ntOld][1] = oldPoints[oldFace.nextLabel(pI)];
185 subjectTris[ntOld][2] = ofCentre;
191 if (newFace.size() == 3)
194 clippingTris.append(FixedList<point, 3>(vector::zero));
196 clippingTris[ntNew][0] = newPoints[newFace[0]];
197 clippingTris[ntNew][1] = newPoints[newFace[1]];
198 clippingTris[ntNew][2] = newPoints[newFace[2]];
204 // Configure tris from newFace
205 vector nfCentre = newFace.centre(newPoints);
210 clippingTris.append(FixedList<point, 3>(vector::zero));
212 clippingTris[ntNew][0] = newPoints[newFace[pI]];
213 clippingTris[ntNew][1] = newPoints[newFace.nextLabel(pI)];
214 clippingTris[ntNew][2] = nfCentre;
220 // Accumulate area / centroid over all intersections
221 bool foundIntersect = false;
223 scalar totalArea = 0.0;
224 vector totalCentre = vector::zero;
226 // Loop through all clipping tris
227 forAll(clippingTris, i)
229 // Initialize the intersector
230 triIntersection intersector(clippingTris[i]);
232 // Test for intersection and evaluate
233 // against all subject tris
234 forAll(subjectTris, j)
236 intersects = intersector.evaluate(subjectTris[j]);
241 vector centre = vector::zero;
243 // Fetch area and centre
244 intersector.getAreaAndCentre(area, centre);
246 // Accumulate area / centroid
248 totalCentre += (area * centre);
250 foundIntersect = true;
257 + Foam::name(newIndex)
259 + Foam::name(oldIndex)
260 + '_' + Foam::name(i)
261 + '_' + Foam::name(j),
262 intersector.getIntersection()
269 // Size-up the internal lists
270 if (foundIntersect && !output)
273 totalCentre /= totalArea + VSMALL;
275 // Normalize and check if this is worth it
276 if (mag(totalArea/normFactor_) > SMALL)
278 // Size-up the internal lists
279 meshOps::sizeUpList((oldIndex - offset), parents_);
280 meshOps::sizeUpList(totalArea, weights_);
281 meshOps::sizeUpList(totalCentre, centres_);
293 // Configure points for clipping triangle
294 FixedList<point, 3> clippingTri(vector::zero);
297 clippingTri[0] = newPoints[newFace[0]];
298 clippingTri[1] = newPoints[newFace[1]];
299 clippingTri[2] = newPoints[newFace[2]];
301 // Configure points for subject triangle
302 FixedList<point, 3> subjectTri(vector::zero);
305 subjectTri[0] = oldPoints[oldFace[0]];
306 subjectTri[1] = oldPoints[oldFace[1]];
307 subjectTri[2] = oldPoints[oldFace[2]];
309 // Initialize the intersector
310 triIntersection intersector(clippingTri);
312 // Test for intersection and evaluate
313 intersects = intersector.evaluate(subjectTri);
320 // Fetch area and centre
321 intersector.getAreaAndCentre(area, centre);
323 // Normalize and check if this is worth it
324 if (mag(area/normFactor_) > SMALL)
331 + Foam::name(newIndex),
332 List<FixedList<point, 3> >(1, clippingTri)
338 + Foam::name(newIndex)
340 + Foam::name(oldIndex),
341 List<FixedList<point, 3> >(1, subjectTri)
347 + Foam::name(newIndex)
349 + Foam::name(oldIndex),
350 intersector.getIntersection()
354 // Size-up the internal lists
355 meshOps::sizeUpList((oldIndex - offset), parents_);
356 meshOps::sizeUpList(area, weights_);
357 meshOps::sizeUpList(centre, centres_);
370 //- Write out tris as a VTK
371 void faceSetAlgorithm::writeVTK
374 const List<FixedList<point, 3> >& triList
377 // Fill up all points
380 List<face> allTris(triList.size(), face(3));
381 pointField allPoints(3 * triList.size());
383 forAll(triList, triI)
385 allTris[triI][0] = pI;
386 allPoints[pI++] = triList[triI][0];
388 allTris[triI][1] = pI;
389 allPoints[pI++] = triList[triI][1];
391 allTris[triI][2] = pI;
392 allPoints[pI++] = triList[triI][2];
395 // Write out in face-to-node addressing
400 identity(triList.size()),
411 } // End namespace Foam
413 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //