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 #include "treeDataTriSurface.H"
00027 #include <meshTools/triSurfaceTools.H>
00028 #include <meshTools/triangleFuncs.H>
00029 #include "indexedOctree.H"
00030
00031
00032
00033 defineTypeNameAndDebug(Foam::treeDataTriSurface, 0);
00034
00035
00036
00037
00038
00039
00040
00041
00042 Foam::scalar Foam::treeDataTriSurface::nearestCoords
00043 (
00044 const point& base,
00045 const point& E0,
00046 const point& E1,
00047 const scalar a,
00048 const scalar b,
00049 const scalar c,
00050 const point& P,
00051 scalar& s,
00052 scalar& t
00053 )
00054 {
00055
00056 const vector D(base - P);
00057
00058
00059 const scalar d = E0 & D;
00060 const scalar e = E1 & D;
00061
00062
00063 const scalar det = a*c - b*b;
00064
00065 s = b*e - c*d;
00066 t = b*d - a*e;
00067
00068 if (s+t < det)
00069 {
00070 if (s < 0)
00071 {
00072 if (t < 0)
00073 {
00074
00075 if (e > 0)
00076 {
00077
00078 t = 0;
00079 s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
00080 }
00081 else
00082 {
00083
00084 s = 0;
00085 t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
00086 }
00087 }
00088 else
00089 {
00090
00091 s = 0;
00092 t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
00093 }
00094 }
00095 else if (t < 0)
00096 {
00097
00098 t = 0;
00099 s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
00100 }
00101 else
00102 {
00103
00104 const scalar invDet = 1/det;
00105 s *= invDet;
00106 t *= invDet;
00107 }
00108 }
00109 else
00110 {
00111 if (s < 0)
00112 {
00113
00114 const scalar tmp0 = b + d;
00115 const scalar tmp1 = c + e;
00116 if (tmp1 > tmp0)
00117 {
00118
00119 const scalar numer = tmp1 - tmp0;
00120 const scalar denom = a-2*b+c;
00121 s = (numer >= denom ? 1 : numer/denom);
00122 t = 1 - s;
00123 }
00124 else
00125 {
00126
00127 s = 0;
00128 t = (tmp1 <= 0 ? 1 : (e >= 0 ? 0 : - e/c));
00129 }
00130 }
00131 else if (t < 0)
00132 {
00133
00134 const scalar tmp0 = b + d;
00135 const scalar tmp1 = c + e;
00136 if (tmp1 > tmp0)
00137 {
00138
00139 const scalar numer = tmp1 - tmp0;
00140 const scalar denom = a-2*b+c;
00141 s = (numer >= denom ? 1 : numer/denom);
00142 t = 1 - s;
00143 }
00144 else
00145 {
00146
00147 t = 0;
00148 s = (tmp1 <= 0 ? 1 : (d >= 0 ? 0 : - d/a));
00149 }
00150 }
00151 else
00152 {
00153
00154 const scalar numer = c+e-(b+d);
00155 if (numer <= 0)
00156 {
00157 s = 0;
00158 }
00159 else
00160 {
00161 const scalar denom = a-2*b+c;
00162 s = (numer >= denom ? 1 : numer/denom);
00163 }
00164 }
00165 t = 1 - s;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 const scalar f = D & D;
00175 return Foam::mag(a*s*s + 2*b*s*t + c*t*t + 2*d*s + 2*e*t + f);
00176 }
00177
00178
00179
00180
00181
00182 Foam::treeDataTriSurface::treeDataTriSurface(const triSurface& surface)
00183 :
00184 surface_(surface)
00185 {}
00186
00187
00188
00189
00190 Foam::pointField Foam::treeDataTriSurface::points() const
00191 {
00192 const pointField& points = surface_.points();
00193
00194 pointField centres(surface_.size());
00195
00196 forAll(surface_, triI)
00197 {
00198 centres[triI] = surface_[triI].centre(points);
00199 }
00200 return centres;
00201 }
00202
00203
00204
00205 Foam::label Foam::treeDataTriSurface::getVolumeType
00206 (
00207 const indexedOctree<treeDataTriSurface>& tree,
00208 const point& sample
00209 ) const
00210 {
00211
00212 const treeBoundBox& treeBb = tree.bb();
00213
00214 pointIndexHit pHit = tree.findNearest
00215 (
00216 sample,
00217 max
00218 (
00219 Foam::sqr(GREAT),
00220 Foam::magSqr(treeBb.span())
00221 )
00222 );
00223
00224 if (!pHit.hit())
00225 {
00226 FatalErrorIn("treeDataTriSurface::getVolumeType(..)")
00227 << "treeBb:" << treeBb
00228 << " sample:" << sample
00229 << " pHit:" << pHit
00230 << abort(FatalError);
00231 }
00232
00233 triSurfaceTools::sideType t = triSurfaceTools::surfaceSide
00234 (
00235 surface_,
00236 sample,
00237 pHit.index(),
00238 pHit.hitPoint(),
00239 indexedOctree<treeDataTriSurface>::perturbTol()
00240 );
00241
00242 if (t == triSurfaceTools::UNKNOWN)
00243 {
00244 return indexedOctree<treeDataTriSurface>::UNKNOWN;
00245 }
00246 else if (t == triSurfaceTools::INSIDE)
00247 {
00248 return indexedOctree<treeDataTriSurface>::INSIDE;
00249 }
00250 else if (t == triSurfaceTools::OUTSIDE)
00251 {
00252 return indexedOctree<treeDataTriSurface>::OUTSIDE;
00253 }
00254 else
00255 {
00256 FatalErrorIn("treeDataTriSurface::getVolumeType(..)")
00257 << "problem" << abort(FatalError);
00258 return indexedOctree<treeDataTriSurface>::UNKNOWN;
00259 }
00260 }
00261
00262
00263
00264 bool Foam::treeDataTriSurface::overlaps
00265 (
00266 const label index,
00267 const treeBoundBox& cubeBb
00268 ) const
00269 {
00270 const pointField& points = surface_.points();
00271 const labelledTri& f = surface_[index];
00272
00273
00274 const point& p0 = points[f[0]];
00275 const point& p1 = points[f[1]];
00276 const point& p2 = points[f[2]];
00277
00278 treeBoundBox triBb(p0, p0);
00279 triBb.min() = min(triBb.min(), p1);
00280 triBb.min() = min(triBb.min(), p2);
00281
00282 triBb.max() = max(triBb.max(), p1);
00283 triBb.max() = max(triBb.max(), p2);
00284
00285
00286
00287
00288
00289
00290
00291
00292 if (!cubeBb.overlaps(triBb))
00293 {
00294 return false;
00295 }
00296
00297
00298 if (cubeBb.contains(p0) || cubeBb.contains(p1) || cubeBb.contains(p2))
00299 {
00300
00301 return true;
00302 }
00303
00304
00305
00306
00307
00308 return triangleFuncs::intersectBb(p0, p1, p2, cubeBb);
00309 }
00310
00311
00312
00313
00314 void Foam::treeDataTriSurface::findNearest
00315 (
00316 const labelList& indices,
00317 const point& sample,
00318
00319 scalar& nearestDistSqr,
00320 label& minIndex,
00321 point& nearestPoint
00322 ) const
00323 {
00324 const pointField& points = surface_.points();
00325
00326 forAll(indices, i)
00327 {
00328 label index = indices[i];
00329 const labelledTri& f = surface_[index];
00330
00331
00332 const point& p0 = points[f[0]];
00333 const point& p1 = points[f[1]];
00334 const point& p2 = points[f[2]];
00335
00336
00340
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 {
00356
00357 vector base(p1);
00358 vector E0(p0 - p1);
00359 vector E1(p2 - p1);
00360
00361 scalar a(E0& E0);
00362 scalar b(E0& E1);
00363 scalar c(E1& E1);
00364
00365
00366
00367 scalar s;
00368 scalar t;
00369
00370 scalar distSqr = nearestCoords
00371 (
00372 base,
00373 E0,
00374 E1,
00375 a,
00376 b,
00377 c,
00378 sample,
00379
00380 s,
00381 t
00382 );
00383
00384 if (distSqr < nearestDistSqr)
00385 {
00386 nearestDistSqr = distSqr;
00387 minIndex = index;
00388 nearestPoint = base + s*E0 + t*E1;
00389 }
00390 }
00391 }
00392 }
00393
00394
00395
00396
00397 void Foam::treeDataTriSurface::findNearest
00398 (
00399 const labelList& indices,
00400 const linePointRef& ln,
00401
00402 treeBoundBox& tightest,
00403 label& minIndex,
00404 point& linePoint,
00405 point& nearestPoint
00406 ) const
00407 {
00408 notImplemented
00409 (
00410 "treeDataTriSurface::findNearest(const labelList&"
00411 ", const linePointRef&, treeBoundBox&, label&, point&, point&) const"
00412 );
00413 }
00414
00415
00416 bool Foam::treeDataTriSurface::intersects
00417 (
00418 const label index,
00419 const point& start,
00420 const point& end,
00421 point& intersectionPoint
00422 ) const
00423 {
00424 const pointField& points = surface_.points();
00425
00426 const labelledTri& f = surface_[index];
00427
00428
00429 treeBoundBox triBb(points[f[0]], points[f[0]]);
00430 triBb.min() = min(triBb.min(), points[f[1]]);
00431 triBb.max() = max(triBb.max(), points[f[1]]);
00432 triBb.min() = min(triBb.min(), points[f[2]]);
00433 triBb.max() = max(triBb.max(), points[f[2]]);
00434
00435 const direction startBits(triBb.posBits(start));
00436 const direction endBits(triBb.posBits(end));
00437
00438 if ((startBits & endBits) != 0)
00439 {
00440
00441 return false;
00442 }
00443
00444 const triPointRef tri(points[f[0]], points[f[1]], points[f[2]]);
00445
00446 const vector dir(end - start);
00447
00448
00449
00450 pointHit inter = tri.intersection
00451 (
00452 start,
00453 dir,
00454 intersection::HALF_RAY,
00455 indexedOctree<treeDataTriSurface>::perturbTol()
00456 );
00457
00458 if (inter.hit() && inter.distance() <= 1)
00459 {
00460
00461
00462 intersectionPoint = inter.hitPoint();
00463
00464 return true;
00465 }
00466 else
00467 {
00468 return false;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 }
00481
00482
00483