00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "orientedSurface.H"
00029 #include <meshTools/triSurfaceTools.H>
00030 #include <meshTools/treeBoundBox.H>
00031
00032
00033
00034 defineTypeNameAndDebug(Foam::orientedSurface, 0);
00035
00036
00037
00038
00039
00040 bool Foam::orientedSurface::edgeOrder
00041 (
00042 const labelledTri& f,
00043 const edge& e
00044 )
00045 {
00046 if
00047 (
00048 (f[0] == e[0] && f[1] == e[1])
00049 || (f[1] == e[0] && f[2] == e[1])
00050 || (f[2] == e[0] && f[0] == e[1])
00051 )
00052 {
00053 return true;
00054 }
00055 else
00056 {
00057 return false;
00058 }
00059 }
00060
00061
00062
00063 bool Foam::orientedSurface::consistentEdge
00064 (
00065 const edge& e,
00066 const labelledTri& f0,
00067 const labelledTri& f1
00068 )
00069 {
00070 return edgeOrder(f0, e) ^ edgeOrder(f1, e);
00071 }
00072
00073
00074 Foam::labelList Foam::orientedSurface::faceToEdge
00075 (
00076 const triSurface& s,
00077 const labelList& changedFaces
00078 )
00079 {
00080 labelList changedEdges(3*changedFaces.size());
00081 label changedI = 0;
00082
00083 forAll(changedFaces, i)
00084 {
00085 const labelList& fEdges = s.faceEdges()[changedFaces[i]];
00086
00087 forAll(fEdges, j)
00088 {
00089 changedEdges[changedI++] = fEdges[j];
00090 }
00091 }
00092 changedEdges.setSize(changedI);
00093
00094 return changedEdges;
00095 }
00096
00097
00098 Foam::labelList Foam::orientedSurface::edgeToFace
00099 (
00100 const triSurface& s,
00101 const labelList& changedEdges,
00102 labelList& flip
00103 )
00104 {
00105 labelList changedFaces(2*changedEdges.size());
00106 label changedI = 0;
00107
00108 forAll(changedEdges, i)
00109 {
00110 label edgeI = changedEdges[i];
00111
00112 const labelList& eFaces = s.edgeFaces()[edgeI];
00113
00114 if (eFaces.size() < 2)
00115 {
00116
00117 }
00118 else if (eFaces.size() == 2)
00119 {
00120 label face0 = eFaces[0];
00121 label face1 = eFaces[1];
00122
00123 const labelledTri& f0 = s.localFaces()[face0];
00124 const labelledTri& f1 = s.localFaces()[face1];
00125
00126 if (flip[face0] == UNVISITED)
00127 {
00128 if (flip[face1] == UNVISITED)
00129 {
00130 FatalErrorIn("orientedSurface::edgeToFace") << "Problem"
00131 << abort(FatalError);
00132 }
00133 else
00134 {
00135
00136 if (consistentEdge(s.edges()[edgeI], f0, f1))
00137 {
00138
00139 flip[face0] = (flip[face1] == FLIP ? FLIP : NOFLIP);
00140 }
00141 else
00142 {
00143
00144 flip[face0] = (flip[face1] == FLIP ? NOFLIP : FLIP);
00145 }
00146 changedFaces[changedI++] = face0;
00147 }
00148 }
00149 else
00150 {
00151 if (flip[face1] == UNVISITED)
00152 {
00153
00154 if (consistentEdge(s.edges()[edgeI], f0, f1))
00155 {
00156 flip[face1] = (flip[face0] == FLIP ? FLIP : NOFLIP);
00157 }
00158 else
00159 {
00160 flip[face1] = (flip[face0] == FLIP ? NOFLIP : FLIP);
00161 }
00162 changedFaces[changedI++] = face1;
00163 }
00164 }
00165 }
00166 else
00167 {
00168
00169 }
00170 }
00171 changedFaces.setSize(changedI);
00172
00173 return changedFaces;
00174 }
00175
00176
00177 void Foam::orientedSurface::walkSurface
00178 (
00179 const triSurface& s,
00180 const label startFaceI,
00181 labelList& flipState
00182 )
00183 {
00184
00185 labelList changedFaces(1, startFaceI);
00186
00187 labelList changedEdges;
00188
00189 while(true)
00190 {
00191 changedEdges = faceToEdge(s, changedFaces);
00192
00193 if (debug)
00194 {
00195 Pout<< "From changedFaces:" << changedFaces.size()
00196 << " to changedEdges:" << changedEdges.size()
00197 << endl;
00198 }
00199
00200 if (changedEdges.empty())
00201 {
00202 break;
00203 }
00204
00205 changedFaces = edgeToFace(s, changedEdges, flipState);
00206
00207 if (debug)
00208 {
00209 Pout<< "From changedEdges:" << changedEdges.size()
00210 << " to changedFaces:" << changedFaces.size()
00211 << endl;
00212 }
00213
00214 if (changedFaces.empty())
00215 {
00216 break;
00217 }
00218 }
00219 }
00220
00221
00222 void Foam::orientedSurface::propagateOrientation
00223 (
00224 const triSurface& s,
00225 const point& samplePoint,
00226 const bool orientOutside,
00227 const label nearestFaceI,
00228 const point& nearestPt,
00229 labelList& flipState
00230 )
00231 {
00232
00233
00234
00235 triSurfaceTools::sideType side = triSurfaceTools::surfaceSide
00236 (
00237 s,
00238 samplePoint,
00239 nearestFaceI,
00240 nearestPt,
00241 10*SMALL
00242 );
00243
00244 if (side == triSurfaceTools::UNKNOWN)
00245 {
00246
00247
00248 flipState[nearestFaceI] = NOFLIP;
00249 }
00250 else if ((side == triSurfaceTools::OUTSIDE) == orientOutside)
00251 {
00252
00253
00254 flipState[nearestFaceI] = NOFLIP;
00255 }
00256 else
00257 {
00258
00259 flipState[nearestFaceI] = FLIP;
00260 }
00261
00262 if (debug)
00263 {
00264 vector n = triSurfaceTools::surfaceNormal(s, nearestFaceI, nearestPt);
00265
00266 Pout<< "orientedSurface::propagateOrientation : starting face"
00267 << " orientation:" << nl
00268 << " for samplePoint:" << samplePoint << nl
00269 << " starting from point:" << nearestPt << nl
00270 << " on face:" << nearestFaceI << nl
00271 << " with normal:" << n << nl
00272 << " decided side:" << label(side)
00273 << endl;
00274 }
00275
00276
00277 walkSurface(s, nearestFaceI, flipState);
00278 }
00279
00280
00281 bool Foam::orientedSurface::flipSurface
00282 (
00283 triSurface& s,
00284 const labelList& flipState
00285 )
00286 {
00287 bool hasFlipped = false;
00288
00289
00290 forAll(flipState, faceI)
00291 {
00292 if (flipState[faceI] == UNVISITED)
00293 {
00294 FatalErrorIn
00295 (
00296 "orientSurface(const point&, const label, const point&)"
00297 ) << "unvisited face " << faceI
00298 << abort(FatalError);
00299 }
00300 else if (flipState[faceI] == FLIP)
00301 {
00302 labelledTri& tri = s[faceI];
00303
00304 label tmp = tri[0];
00305
00306 tri[0] = tri[1];
00307 tri[1] = tmp;
00308
00309 hasFlipped = true;
00310 }
00311 }
00312
00313 s.clearOut();
00314
00315 return hasFlipped;
00316 }
00317
00318
00319
00320
00321
00322 Foam::orientedSurface::orientedSurface()
00323 :
00324 triSurface()
00325 {}
00326
00327
00328
00329 Foam::orientedSurface::orientedSurface
00330 (
00331 const triSurface& surf,
00332 const point& samplePoint,
00333 const bool orientOutside
00334 )
00335 :
00336 triSurface(surf)
00337 {
00338 orient(*this, samplePoint, orientOutside);
00339 }
00340
00341
00342
00343 Foam::orientedSurface::orientedSurface
00344 (
00345 const triSurface& surf,
00346 const bool orientOutside
00347 )
00348 :
00349 triSurface(surf)
00350 {
00351
00352 treeBoundBox bb(surf.points(), surf.meshPoints());
00353
00354 point outsidePoint = bb.max() + bb.span();
00355
00356 orient(*this, outsidePoint, orientOutside);
00357 }
00358
00359
00360
00361
00362 bool Foam::orientedSurface::orient
00363 (
00364 triSurface& s,
00365 const point& samplePoint,
00366 const bool orientOutside
00367 )
00368 {
00369 bool anyFlipped = false;
00370
00371
00372
00373
00374 if (s.size() > 0)
00375 {
00376
00377
00378
00379
00380 labelList flipState(s.size(), UNVISITED);
00381
00382 flipState[0] = NOFLIP;
00383 walkSurface(s, 0, flipState);
00384
00385 anyFlipped = flipSurface(s, flipState);
00386 }
00387
00388
00389
00390
00391
00392
00393 labelList flipState(s.size(), UNVISITED);
00394
00395
00396 while (true)
00397 {
00398
00399
00400 scalar minDist = GREAT;
00401 point minPoint;
00402 label minFaceI = -1;
00403
00404 forAll(s, faceI)
00405 {
00406 if (flipState[faceI] == UNVISITED)
00407 {
00408 const labelledTri& f = s[faceI];
00409
00410 pointHit curHit =
00411 triPointRef
00412 (
00413 s.points()[f[0]],
00414 s.points()[f[1]],
00415 s.points()[f[2]]
00416 ).nearestPoint(samplePoint);
00417
00418 if (curHit.distance() < minDist)
00419 {
00420 minDist = curHit.distance();
00421 minPoint = curHit.rawPoint();
00422 minFaceI = faceI;
00423 }
00424 }
00425 }
00426
00427
00428 if (minFaceI == -1)
00429 {
00430 break;
00431 }
00432
00433
00434
00435 propagateOrientation
00436 (
00437 s,
00438 samplePoint,
00439 orientOutside,
00440 minFaceI,
00441 minPoint,
00442 flipState
00443 );
00444 }
00445
00446
00447 bool geomFlipped = flipSurface(s, flipState);
00448
00449 return anyFlipped || geomFlipped;
00450 }
00451
00452
00453