1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh 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 cfMesh 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 cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "triSurfaceClassifyEdges.H"
29 #include "demandDrivenData.H"
30 #include "helperFunctions.H"
32 #include "meshOctree.H"
33 #include "labelPair.H"
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 void triSurfaceClassifyEdges::checkOrientation()
48 const triSurf& surf = octree_.surface();
49 const boundBox& rootBox = octree_.rootBox();
50 const pointField& points = surf.points();
51 const VRWGraph& facetEdges = surf.facetEdges();
52 const VRWGraph& edgeFacets = surf.edgeFacets();
54 facetOrientation_.setSize(surf.size());
56 //- sort all surface facets into groups consisting of facets with consistent
57 //- orientation. Do not cross non-manifold edges
58 labelLongList orientationGroup(surf.size(), -1);
63 if( orientationGroup[triI] != -1 )
66 orientationGroup[triI] = nGroups;
70 while( front.size() != 0 )
72 const label tLabel = front.removeLastElement();
74 const labelledTri& facet = surf[tLabel];
78 const label edgeI = facetEdges(tLabel, eI);
80 if( edgeFacets.sizeOfRow(edgeI) != 2 )
83 forAllRow(edgeFacets, edgeI, efI)
85 const label neiFacetI = edgeFacets(edgeI, efI);
87 if( orientationGroup[neiFacetI] != -1 )
89 if( neiFacetI == tLabel )
92 const labelledTri& neiFacet = surf[neiFacetI];
94 //- check the orientation of triangles at this edge
95 //- check the sign of the angle
96 //- if the orientation is not consistent
97 DynList<labelPair, 2> sharedIndices;
102 if( facet[i] == neiFacet[j] )
103 sharedIndices.append(labelPair(i, j));
107 if( sharedIndices.size() == 2 )
109 const labelPair& pair0 = sharedIndices[0];
110 const labelPair& pair1 = sharedIndices[1];
111 if( ((pair0.first() + 1) % 3) == pair1.first() )
113 if( (pair1.second() + 1) % 3 == pair0.second() )
115 orientationGroup[neiFacetI] = nGroups;
116 front.append(neiFacetI);
121 if( (pair0.second() + 1) % 3 == pair1.second() )
123 orientationGroup[neiFacetI] = nGroups;
124 front.append(neiFacetI);
135 Info << "Found " << nGroups
136 << " groups of triangles with consistent orientation" << endl;
138 //- find the octree leaves containing each triangle
139 VRWGraph triangleInLeaves(surf.size());
140 labelLongList ntl(surf.size(), 0);
142 DynList<label> helper;
143 for(label leafI=0;leafI<octree_.numberOfLeaves();++leafI)
146 octree_.containedTriangles(leafI, helper);
153 triangleInLeaves.setRowSize(triI, ntl[triI]);
156 for(label leafI=0;leafI<octree_.numberOfLeaves();++leafI)
159 octree_.containedTriangles(leafI, helper);
163 const label triI = helper[i];
165 triangleInLeaves(triI, ntl[triI]++) = leafI;
169 //- check the orientation of all facets in a group and collect their votes
170 DynList<labelPair> groupVotes;
171 groupVotes.setSize(nGroups);
172 groupVotes = labelPair(0, 0);
175 # pragma omp parallel if( surf.size() > 1000 ) private(helper)
178 DynList<labelPair> localVotes;
179 localVotes.setSize(nGroups);
180 localVotes = labelPair(0, 0);
183 # pragma omp for schedule(dynamic, 40)
185 forAll(orientationGroup, triI)
187 const labelledTri& tri = surf[triI];
188 const point c = tri.centre(points);
189 vector n = tri.normal(points);
190 const scalar magN = mag(n);
197 //- find the OUTSIDE octree cubes in the vicinity of the triangle
198 //- and check the orientation of the triangle
199 forAllRow(triangleInLeaves, triI, tlI)
201 const label leafI = triangleInLeaves(triI, tlI);
203 octree_.findAllLeafNeighbours(leafI, helper);
207 const label leafJ = helper[i];
209 const meshOctreeCubeBasic& oc = octree_.returnLeaf(leafJ);
211 if( oc.cubeType() & meshOctreeCubeBasic::OUTSIDE )
213 const scalar length = 3.0 * oc.size(rootBox);
216 oc.cubeBox(rootBox, pMin, pMax);
218 const boundBox bb(pMin, pMax);
220 //- check whether the ray casted from
221 //- the centre of the triangle intersects the cube
222 const point endPos = c + length * n;
223 const point endNeg = c - length * n;
225 if( help::boundBoxLineIntersection(c, endPos, bb) )
227 //- found an intersection in the positive direction
228 ++localVotes[orientationGroup[triI]].first();
230 else if( help::boundBoxLineIntersection(c, endNeg, bb) )
232 //- found an intersection in the negative direction
233 ++localVotes[orientationGroup[triI]].second();
241 # pragma omp critical(grouping)
244 forAll(localVotes, groupI)
246 groupVotes[groupI].first() += localVotes[groupI].first();
247 groupVotes[groupI].second() += localVotes[groupI].second();
252 Info << "Before determining of orientation" << endl;
254 //- determine whether a group is oriented outward or inward
255 List<direction> outwardGroup(nGroups, direction(0));
257 forAll(groupVotes, groupI)
259 if( groupVotes[groupI].first() > groupVotes[groupI].second() )
261 outwardGroup[groupI] = 1;
263 else if( groupVotes[groupI].first() < groupVotes[groupI].second() )
265 outwardGroup[groupI] = 2;
269 Info << "Here setting orientation" << endl;
270 //- Finally, set the orientation of the normal
271 facetOrientation_.setSize(surf.size());
272 forAll(facetOrientation_, triI)
273 facetOrientation_[triI] = outwardGroup[orientationGroup[triI]];
276 void triSurfaceClassifyEdges::classifyEdgesTypes()
278 const triSurf& surf = octree_.surface();
279 const pointField& points = surf.points();
280 const VRWGraph& edgeFacets = surf.edgeFacets();
281 const edgeLongList& edges = surf.edges();
282 const VRWGraph& pointEdges = surf.pointEdges();
283 const edgeLongList& featureEdges = surf.featureEdges();
285 edgeTypes_.setSize(edgeFacets.size());
288 //- set feature edge types
290 # pragma omp parallel for schedule(dynamic, 20)
292 forAll(featureEdges, feI)
294 const edge& e = featureEdges[feI];
296 forAllRow(pointEdges, e.start(), peI)
298 if( edges[pointEdges(e.start(), peI)] == e )
299 edgeTypes_[pointEdges(e.start(), peI)] |= FEATUREEDGE;
303 //- Finally, check the edges and assign flags
305 # pragma omp parallel for schedule(dynamic, 40)
307 forAll(edgeFacets, edgeI)
309 if( edgeFacets.sizeOfRow(edgeI) != 2 )
311 //- this is not a manifold edge
312 edgeTypes_[edgeI] = NONE;
316 //- surface is a manifold at this edge
317 const label f0 = edgeFacets(edgeI, 0);
318 const label f1 = edgeFacets(edgeI, 1);
320 const labelledTri& tri0 = surf[f0];
321 const labelledTri& tri1 = surf[f1];
323 if( tri0.region() != tri1.region() )
324 edgeTypes_[edgeI] |= FEATUREEDGE;
332 if( tri0[pJ] == tri1[pI] )
349 const tetrahedron<point, point> tet
357 const scalar vol = tet.mag();
359 if( facetOrientation_[f0] == 1 )
361 //- facet is outward oriented
364 //- this is a convex edge
365 edgeTypes_[edgeI] |= CONVEXEDGE;
367 else if( vol > VSMALL )
369 //- this is a concave edge
370 edgeTypes_[edgeI] |= CONCAVEEDGE;
374 edgeTypes_[edgeI] |= FLATSURFACEEDGE;
377 else if( facetOrientation_[f0] == 2 )
379 //- facet is inward oriented
382 //- this is a convex edge
383 edgeTypes_[edgeI] |= CONVEXEDGE;
385 else if( vol < -VSMALL )
387 //- this is a concave edge
388 edgeTypes_[edgeI] |= CONCAVEEDGE;
392 edgeTypes_[edgeI] |= FLATSURFACEEDGE;
398 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
400 } // End namespace Foam
402 // ************************************************************************* //