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 <meshTools/octreeDataTriSurface.H>
00029
00030 #include <OpenFOAM/labelList.H>
00031 #include <meshTools/treeBoundBox.H>
00032 #include <OpenFOAM/faceList.H>
00033 #include <OpenFOAM/triPointRef.H>
00034 #include <meshTools/octree.H>
00035 #include <meshTools/triSurfaceTools.H>
00036 #include <meshTools/triangleFuncs.H>
00037
00038
00039
00040 defineTypeNameAndDebug(Foam::octreeDataTriSurface, 0);
00041
00042 Foam::scalar Foam::octreeDataTriSurface::tol(1E-6);
00043
00044
00045
00046
00047
00048
00049
00050
00051 void Foam::octreeDataTriSurface::nearestCoords
00052 (
00053 const point& base,
00054 const point& E0,
00055 const point& E1,
00056 const scalar a,
00057 const scalar b,
00058 const scalar c,
00059 const point& P,
00060 scalar& s,
00061 scalar& t
00062 )
00063 {
00064
00065 const vector D(base - P);
00066
00067
00068 const scalar d = E0 & D;
00069 const scalar e = E1 & D;
00070
00071
00072 const scalar det = a*c - b*b;
00073
00074 s = b*e - c*d;
00075 t = b*d - a*e;
00076
00077 if (s+t < det)
00078 {
00079 if (s < 0)
00080 {
00081 if (t < 0)
00082 {
00083
00084 if (e > 0)
00085 {
00086
00087 t = 0;
00088 s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
00089 }
00090 else
00091 {
00092
00093 s = 0;
00094 t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
00095 }
00096 }
00097 else
00098 {
00099
00100 s = 0;
00101 t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
00102 }
00103 }
00104 else if (t < 0)
00105 {
00106
00107 t = 0;
00108 s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
00109 }
00110 else
00111 {
00112
00113 const scalar invDet = 1/det;
00114 s *= invDet;
00115 t *= invDet;
00116 }
00117 }
00118 else
00119 {
00120 if (s < 0)
00121 {
00122
00123 const scalar tmp0 = b + d;
00124 const scalar tmp1 = c + e;
00125 if (tmp1 > tmp0)
00126 {
00127
00128 const scalar numer = tmp1 - tmp0;
00129 const scalar denom = a-2*b+c;
00130 s = (numer >= denom ? 1 : numer/denom);
00131 t = 1 - s;
00132 }
00133 else
00134 {
00135
00136 s = 0;
00137 t = (tmp1 <= 0 ? 1 : (e >= 0 ? 0 : - e/c));
00138 }
00139 }
00140 else if (t < 0)
00141 {
00142
00143 const scalar tmp0 = b + d;
00144 const scalar tmp1 = c + e;
00145 if (tmp1 > tmp0)
00146 {
00147
00148 const scalar numer = tmp1 - tmp0;
00149 const scalar denom = a-2*b+c;
00150 s = (numer >= denom ? 1 : numer/denom);
00151 t = 1 - s;
00152 }
00153 else
00154 {
00155
00156 t = 0;
00157 s = (tmp1 <= 0 ? 1 : (d >= 0 ? 0 : - d/a));
00158 }
00159 }
00160 else
00161 {
00162
00163 const scalar numer = c+e-(b+d);
00164 if (numer <= 0)
00165 {
00166 s = 0;
00167 }
00168 else
00169 {
00170 const scalar denom = a-2*b+c;
00171 s = (numer >= denom ? 1 : numer/denom);
00172 }
00173 }
00174 t = 1 - s;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 }
00187
00188
00189 Foam::point Foam::octreeDataTriSurface::nearestPoint
00190 (
00191 const label index,
00192 const point& p
00193 ) const
00194 {
00195 scalar s;
00196 scalar t;
00197
00198 nearestCoords
00199 (
00200 base_[index],
00201 E0_[index],
00202 E1_[index],
00203 a_[index],
00204 b_[index],
00205 c_[index],
00206 p,
00207 s,
00208 t
00209 );
00210
00211 return base_[index] + s*E0_[index] + t*E1_[index];
00212 }
00213
00214
00215
00216 Foam::treeBoundBoxList Foam::octreeDataTriSurface::calcBb
00217 (
00218 const triSurface& surf
00219 )
00220 {
00221 treeBoundBoxList allBb(surf.size(), treeBoundBox::invertedBox);
00222
00223 const labelListList& pointFcs = surf.pointFaces();
00224 const pointField& localPts = surf.localPoints();
00225
00226 forAll(pointFcs, pointI)
00227 {
00228 const labelList& myFaces = pointFcs[pointI];
00229 const point& vertCoord = localPts[pointI];
00230
00231 forAll(myFaces, myFaceI)
00232 {
00233
00234 label faceI = myFaces[myFaceI];
00235
00236 treeBoundBox& bb = allBb[faceI];
00237
00238 bb.min() = min(bb.min(), vertCoord);
00239 bb.max() = max(bb.max(), vertCoord);
00240 }
00241 }
00242
00243 return allBb;
00244 }
00245
00246
00247
00248
00249
00250 Foam::octreeDataTriSurface::octreeDataTriSurface(const triSurface& surface)
00251 :
00252 surface_(surface),
00253 allBb_(calcBb(surface_)),
00254 base_(surface_.size()),
00255 E0_(surface_.size()),
00256 E1_(surface_.size()),
00257 a_(surface_.size()),
00258 b_(surface_.size()),
00259 c_(surface_.size())
00260 {
00261
00262 const pointField& points = surface_.points();
00263
00264 forAll(surface_, faceI)
00265 {
00266 const labelledTri& f = surface_[faceI];
00267
00268
00269 base_[faceI] = points[f[1]];
00270 E0_[faceI] = points[f[0]] - points[f[1]];
00271 E1_[faceI] = points[f[2]] - points[f[1]];
00272
00273 a_[faceI] = E0_[faceI] & E0_[faceI];
00274 b_[faceI] = E0_[faceI] & E1_[faceI];
00275 c_[faceI] = E1_[faceI] & E1_[faceI];
00276 }
00277 }
00278
00279
00280
00281 Foam::octreeDataTriSurface::octreeDataTriSurface
00282 (
00283 const triSurface& surface,
00284 const treeBoundBoxList& allBb
00285 )
00286 :
00287 surface_(surface),
00288 allBb_(allBb),
00289 base_(surface_.size()),
00290 E0_(surface_.size()),
00291 E1_(surface_.size()),
00292 a_(surface_.size()),
00293 b_(surface_.size()),
00294 c_(surface_.size())
00295 {
00296 const pointField& points = surface_.points();
00297
00298 forAll(surface_, faceI)
00299 {
00300 const labelledTri& f = surface_[faceI];
00301
00302
00303 base_[faceI] = points[f[1]];
00304 E0_[faceI] = points[f[0]] - points[f[1]];
00305 E1_[faceI] = points[f[2]] - points[f[1]];
00306
00307 a_[faceI] = E0_[faceI] & E0_[faceI];
00308 b_[faceI] = E0_[faceI] & E1_[faceI];
00309 c_[faceI] = E1_[faceI] & E1_[faceI];
00310 }
00311 }
00312
00313
00314
00315
00316 Foam::label Foam::octreeDataTriSurface::getSampleType
00317 (
00318 const octree<octreeDataTriSurface>& oc,
00319 const point& sample
00320 ) const
00321
00322 {
00323 treeBoundBox tightest(treeBoundBox::greatBox);
00324 scalar tightestDist(treeBoundBox::great);
00325
00326
00327 label faceI = oc.findNearest(sample, tightest, tightestDist);
00328
00329 if (debug & 2)
00330 {
00331 Pout<< "getSampleType : sample:" << sample
00332 << " nearest face:" << faceI;
00333 }
00334
00335 if (faceI == -1)
00336 {
00337 FatalErrorIn
00338 (
00339 "octreeDataTriSurface::getSampleType"
00340 "(octree<octreeDataTriSurface>&, const point&)"
00341 ) << "Could not find " << sample << " in octree."
00342 << abort(FatalError);
00343 }
00344
00345 const pointField& pts = surface_.points();
00346 const labelledTri& f = surface_[faceI];
00347
00348 pointHit curHit = triPointRef
00349 (
00350 pts[f[0]],
00351 pts[f[1]],
00352 pts[f[2]]
00353 ).nearestPoint(sample);
00354
00355
00356
00357 vector n
00358 (
00359 triSurfaceTools::surfaceNormal
00360 (
00361 surface_,
00362 faceI,
00363 curHit.rawPoint()
00364 )
00365 );
00366
00367 return
00368 octree<octreeDataTriSurface>::getVolType(n, sample - curHit.rawPoint());
00369 }
00370
00371
00372
00373 bool Foam::octreeDataTriSurface::overlaps
00374 (
00375 const label index,
00376 const treeBoundBox& cubeBb
00377 ) const
00378 {
00379
00380
00381
00382
00383
00384 if (!cubeBb.overlaps(allBb_[index]))
00385 {
00386 return false;
00387 }
00388
00389
00390 const pointField& points = surface_.points();
00391 const labelledTri& f = surface_[index];
00392 const point& p0 = points[f[0]];
00393 const point& p1 = points[f[1]];
00394 const point& p2 = points[f[2]];
00395
00396
00397 if (cubeBb.contains(p0) || cubeBb.contains(p1) || cubeBb.contains(p2))
00398 {
00399
00400 return true;
00401 }
00402
00403
00404
00405
00406 return triangleFuncs::intersectBb(p0, p1, p2, cubeBb);
00407 }
00408
00409
00410 bool Foam::octreeDataTriSurface::contains
00411 (
00412 const label,
00413 const point&
00414 ) const
00415 {
00416 notImplemented
00417 (
00418 "octreeDataTriSurface::contains(const label, const point&)"
00419 );
00420
00421 return false;
00422 }
00423
00424
00425 bool Foam::octreeDataTriSurface::intersects
00426 (
00427 const label index,
00428 const point& start,
00429 const point& end,
00430 point& intersectionPoint
00431 ) const
00432 {
00433 if (mag(surface_.faceNormals()[index]) < VSMALL)
00434 {
00435 return false;
00436 }
00437
00438 const pointField& points = surface_.points();
00439
00440 const labelledTri& f = surface_[index];
00441
00442 triPointRef tri(points[f[0]], points[f[1]], points[f[2]]);
00443
00444 const vector dir(end - start);
00445
00446
00447 scalar oldTol = intersection::setPlanarTol(0.0);
00448
00449 pointHit inter = tri.ray(start, dir, intersection::HALF_RAY);
00450
00451 intersection::setPlanarTol(oldTol);
00452
00453 if (inter.hit() && inter.distance() <= mag(dir))
00454 {
00455
00456
00457
00458 intersectionPoint = inter.hitPoint();
00459
00460 return true;
00461 }
00462 else
00463 {
00464 return false;
00465 }
00466 }
00467
00468
00469 bool Foam::octreeDataTriSurface::findTightest
00470 (
00471 const label index,
00472 const point& sample,
00473 treeBoundBox& tightest
00474 ) const
00475 {
00476
00477
00478 point myNear, myFar;
00479 allBb_[index].calcExtremities(sample, myNear, myFar);
00480
00481 const point dist = myFar - sample;
00482 scalar myFarDist = mag(dist);
00483
00484 point tightestNear, tightestFar;
00485 tightest.calcExtremities(sample, tightestNear, tightestFar);
00486
00487 scalar tightestFarDist = mag(tightestFar - sample);
00488
00489 if (tightestFarDist < myFarDist)
00490 {
00491
00492 return false;
00493 }
00494 else
00495 {
00496
00497 const point dist2(fabs(dist.x()), fabs(dist.y()), fabs(dist.z()));
00498
00499 tightest.min() = sample - dist2;
00500 tightest.max() = sample + dist2;
00501
00502 return true;
00503 }
00504 }
00505
00506
00507
00508 Foam::scalar Foam::octreeDataTriSurface::calcSign
00509 (
00510 const label index,
00511 const point& sample,
00512 vector& n
00513 ) const
00514 {
00515 n = surface_.faceNormals()[index];
00516
00517 const labelledTri& tri = surface_[index];
00518
00519
00520 vector vec = sample - surface_.points()[tri[0]];
00521
00522 vec /= mag(vec) + VSMALL;
00523
00524 return n & vec;
00525 }
00526
00527
00528
00529 Foam::scalar Foam::octreeDataTriSurface::calcNearest
00530 (
00531 const label index,
00532 const point& sample,
00533 point&
00534 ) const
00535 {
00536 return mag(nearestPoint(index, sample) - sample);
00537 }
00538
00539
00540
00541 Foam::scalar Foam::octreeDataTriSurface::calcNearest
00542 (
00543 const label index,
00544 const linePointRef& ln,
00545 point& linePt,
00546 point& shapePt
00547 ) const
00548 {
00549 notImplemented
00550 (
00551 "octreeDataTriSurface::calcNearest"
00552 "(const label, const linePointRef&, point& linePt, point&)"
00553 );
00554 return GREAT;
00555 }
00556
00557
00558 void Foam::octreeDataTriSurface::write
00559 (
00560 Ostream& os,
00561 const label index
00562 ) const
00563 {
00564 os << surface_[index] << token::SPACE << allBb_[index];
00565 }
00566
00567
00568