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 "octreeDataFace.H"
00027 #include <OpenFOAM/labelList.H>
00028 #include <OpenFOAM/polyMesh.H>
00029 #include "octree.H"
00030 #include <OpenFOAM/polyPatch.H>
00031 #include <meshTools/triangleFuncs.H>
00032 #include <OpenFOAM/linePointRef.H>
00033
00034
00035
00036 defineTypeNameAndDebug(Foam::octreeDataFace, 0);
00037
00038 Foam::scalar Foam::octreeDataFace::tol(1E-6);
00039
00040
00041
00042
00043 void Foam::octreeDataFace::calcBb()
00044 {
00045 allBb_.setSize(meshFaces_.size());
00046 allBb_ = treeBoundBox::invertedBox;
00047
00048 forAll (meshFaces_, i)
00049 {
00050
00051 treeBoundBox& myBb = allBb_[i];
00052
00053 const face& f = mesh_.faces()[meshFaces_[i]];
00054
00055 forAll(f, faceVertexI)
00056 {
00057 const point& coord = mesh_.points()[f[faceVertexI]];
00058
00059 myBb.min() = min(myBb.min(), coord);
00060 myBb.max() = max(myBb.max(), coord);
00061 }
00062 }
00063 }
00064
00065
00066
00067
00068
00069 Foam::octreeDataFace::octreeDataFace
00070 (
00071 const primitiveMesh& mesh,
00072 const labelList& meshFaces,
00073 const treeBoundBoxList& allBb
00074 )
00075 :
00076 mesh_(mesh),
00077 meshFaces_(meshFaces),
00078 allBb_(allBb)
00079 {}
00080
00081
00082
00083 Foam::octreeDataFace::octreeDataFace
00084 (
00085 const primitiveMesh& mesh,
00086 const labelList& meshFaces
00087 )
00088 :
00089 mesh_(mesh),
00090 meshFaces_(meshFaces),
00091 allBb_(meshFaces_.size())
00092 {
00093
00094 calcBb();
00095 }
00096
00097
00098
00099 Foam::octreeDataFace::octreeDataFace
00100 (
00101 const primitiveMesh& mesh,
00102 const UList<const labelList*>& meshFaceListPtrs,
00103 const UList<const treeBoundBoxList*>& bbListPtrs
00104 )
00105 :
00106 mesh_(mesh),
00107 meshFaces_(0),
00108 allBb_(0)
00109 {
00110 label faceI = 0;
00111
00112 forAll(meshFaceListPtrs, listI)
00113 {
00114 faceI += meshFaceListPtrs[listI]->size();
00115 }
00116
00117 meshFaces_.setSize(faceI);
00118 allBb_.setSize(faceI);
00119
00120 faceI = 0;
00121
00122 forAll(meshFaceListPtrs, listI)
00123 {
00124 const labelList& meshFaces = *meshFaceListPtrs[listI];
00125 const treeBoundBoxList& allBb = *bbListPtrs[listI];
00126
00127 forAll(meshFaces, meshFaceI)
00128 {
00129 meshFaces_[faceI] = meshFaces[meshFaceI];
00130 allBb_[faceI] = allBb[meshFaceI];
00131 faceI++;
00132 }
00133 }
00134 }
00135
00136
00137
00138 Foam::octreeDataFace::octreeDataFace
00139 (
00140 const primitiveMesh& mesh,
00141 const UList<const labelList*>& meshFaceListPtrs
00142 )
00143 :
00144 mesh_(mesh),
00145 meshFaces_(0)
00146 {
00147 label faceI = 0;
00148
00149 forAll(meshFaceListPtrs, listI)
00150 {
00151 faceI += meshFaceListPtrs[listI]->size();
00152 }
00153
00154 meshFaces_.setSize(faceI);
00155
00156 faceI = 0;
00157
00158 forAll(meshFaceListPtrs, listI)
00159 {
00160 const labelList& meshFaces = *meshFaceListPtrs[listI];
00161
00162 forAll(meshFaces, meshFaceI)
00163 {
00164 meshFaces_[faceI++] = meshFaces[meshFaceI];
00165 }
00166 }
00167
00168
00169 calcBb();
00170 }
00171
00172
00173
00174 Foam::octreeDataFace::octreeDataFace(const polyPatch& patch)
00175 :
00176 mesh_(patch.boundaryMesh().mesh()),
00177 meshFaces_(patch.size())
00178 {
00179 forAll(patch, patchFaceI)
00180 {
00181 meshFaces_[patchFaceI] = patch.start() + patchFaceI;
00182 }
00183
00184
00185 calcBb();
00186 }
00187
00188
00189
00190 Foam::octreeDataFace::octreeDataFace(const primitiveMesh& mesh)
00191 :
00192 mesh_(mesh),
00193 meshFaces_(0),
00194 allBb_(0)
00195 {
00196
00197 meshFaces_.setSize(mesh_.nFaces() - mesh_.nInternalFaces());
00198
00199
00200 label boundaryFaceI = 0;
00201
00202 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
00203 {
00204 meshFaces_[boundaryFaceI++] = faceI;
00205 }
00206
00207
00208 calcBb();
00209 }
00210
00211
00212
00213 Foam::octreeDataFace::octreeDataFace(const octreeDataFace& shapes)
00214 :
00215 mesh_(shapes.mesh()),
00216 meshFaces_(shapes.meshFaces()),
00217 allBb_(shapes.allBb())
00218 {}
00219
00220
00221
00222
00223 Foam::octreeDataFace::~octreeDataFace()
00224 {}
00225
00226
00227
00228
00229 Foam::label Foam::octreeDataFace::getSampleType
00230 (
00231 const octree<octreeDataFace>& oc,
00232 const point& sample
00233 ) const
00234 {
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 treeBoundBox tightest(treeBoundBox::greatBox);
00246 scalar tightestDist(treeBoundBox::great);
00247
00248 label index = oc.findNearest(sample, tightest, tightestDist);
00249
00250 if (index == -1)
00251 {
00252 FatalErrorIn
00253 (
00254 "octreeDataFace::getSampleType"
00255 "(octree<octreeDataFace>&, const point&)"
00256 ) << "Could not find " << sample << " in octree."
00257 << abort(FatalError);
00258 }
00259
00260
00261
00262 label faceI = meshFaces_[index];
00263
00264 if (debug & 2)
00265 {
00266 Pout<< "getSampleType : sample:" << sample
00267 << " nearest face:" << faceI;
00268 }
00269
00270 const face& f = mesh_.faces()[faceI];
00271
00272 const pointField& points = mesh_.points();
00273
00274 pointHit curHit = f.nearestPoint(sample, points);
00275
00276
00277
00278
00279
00280 if (curHit.hit())
00281 {
00282
00283
00284 if (debug & 2)
00285 {
00286 Pout<< " -> face hit:" << curHit.hitPoint()
00287 << " comparing to face normal " << mesh_.faceAreas()[faceI]
00288 << endl;
00289 }
00290 return octree<octreeDataFace>::getVolType
00291 (
00292 mesh_.faceAreas()[faceI],
00293 sample - curHit.hitPoint()
00294 );
00295 }
00296
00297 if (debug & 2)
00298 {
00299 Pout<< " -> face miss:" << curHit.missPoint();
00300 }
00301
00302
00303
00304
00305
00306
00307 scalar typDim = sqrt(mag(mesh_.faceAreas()[faceI])) + VSMALL;
00308
00309 forAll(f, fp)
00310 {
00311 if ((mag(points[f[fp]] - curHit.missPoint())/typDim) < tol)
00312 {
00313
00314
00315
00316
00317 const labelList& myFaces = mesh_.pointFaces()[f[fp]];
00318
00319 vector pointNormal(vector::zero);
00320
00321 forAll(myFaces, myFaceI)
00322 {
00323 if (myFaces[myFaceI] >= mesh_.nInternalFaces())
00324 {
00325 vector n = mesh_.faceAreas()[myFaces[myFaceI]];
00326 n /= mag(n) + VSMALL;
00327
00328 pointNormal += n;
00329 }
00330 }
00331
00332 if (debug & 2)
00333 {
00334 Pout<< " -> face point hit :" << points[f[fp]]
00335 << " point normal:" << pointNormal
00336 << " distance:"
00337 << mag(points[f[fp]] - curHit.missPoint())/typDim
00338 << endl;
00339 }
00340 return octree<octreeDataFace>::getVolType
00341 (
00342 pointNormal,
00343 sample - curHit.missPoint()
00344 );
00345 }
00346 }
00347 if ((mag(mesh_.faceCentres()[faceI] - curHit.missPoint())/typDim) < tol)
00348 {
00349
00350
00351
00352 if (debug & 2)
00353 {
00354 Pout<< " -> centre hit:" << mesh_.faceCentres()[faceI]
00355 << " distance:"
00356 << mag(mesh_.faceCentres()[faceI] - curHit.missPoint())/typDim
00357 << endl;
00358 }
00359
00360 return octree<octreeDataFace>::getVolType
00361 (
00362 mesh_.faceAreas()[faceI],
00363 sample - curHit.missPoint()
00364 );
00365 }
00366
00367
00368
00369
00370
00371
00372 const labelList& myEdges = mesh_.faceEdges()[faceI];
00373
00374 forAll(myEdges, myEdgeI)
00375 {
00376 const edge& e = mesh_.edges()[myEdges[myEdgeI]];
00377
00378 pointHit edgeHit = line<point, const point&>
00379 (
00380 points[e.start()],
00381 points[e.end()]
00382 ).nearestDist(sample);
00383
00384
00385 if ((mag(edgeHit.rawPoint() - curHit.missPoint())/typDim) < tol)
00386 {
00387
00388
00389
00390
00391 const labelList& myFaces = mesh_.edgeFaces()[myEdges[myEdgeI]];
00392
00393 vector edgeNormal(vector::zero);
00394
00395 forAll(myFaces, myFaceI)
00396 {
00397 if (myFaces[myFaceI] >= mesh_.nInternalFaces())
00398 {
00399 vector n = mesh_.faceAreas()[myFaces[myFaceI]];
00400 n /= mag(n) + VSMALL;
00401
00402 edgeNormal += n;
00403 }
00404 }
00405
00406 if (debug & 2)
00407 {
00408 Pout<< " -> real edge hit point:" << edgeHit.rawPoint()
00409 << " comparing to edge normal:" << edgeNormal
00410 << endl;
00411 }
00412
00413
00414
00415 return octree<octreeDataFace>::getVolType
00416 (
00417 edgeNormal,
00418 sample - curHit.missPoint()
00419 );
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428 forAll(f, fp)
00429 {
00430 pointHit edgeHit =
00431 line<point, const point&>
00432 (
00433 points[f[fp]],
00434 mesh_.faceCentres()[faceI]
00435 ).nearestDist(sample);
00436
00437 if ((mag(edgeHit.rawPoint() - curHit.missPoint())/typDim) < tol)
00438 {
00439
00440
00441
00442 const label fpPrev = f.rcIndex(fp);
00443 const label fpNext = f.fcIndex(fp);
00444
00445 vector e = points[f[fp]] - mesh_.faceCentres()[faceI];
00446 vector ePrev = points[f[fpPrev]] - mesh_.faceCentres()[faceI];
00447 vector eNext = points[f[fpNext]] - mesh_.faceCentres()[faceI];
00448
00449 vector nLeft = ePrev ^ e;
00450 nLeft /= mag(nLeft) + VSMALL;
00451
00452 vector nRight = e ^ eNext;
00453 nRight /= mag(nRight) + VSMALL;
00454
00455 if (debug & 2)
00456 {
00457 Pout<< " -> internal edge hit point:" << edgeHit.rawPoint()
00458 << " comparing to edge normal "
00459 << 0.5*(nLeft + nRight)
00460 << endl;
00461 }
00462
00463
00464
00465 return octree<octreeDataFace>::getVolType
00466 (
00467 0.5*(nLeft + nRight),
00468 sample - curHit.missPoint()
00469 );
00470 }
00471 }
00472
00473 if (debug & 2)
00474 {
00475 Pout<< "Did not find sample " << sample
00476 << " anywhere related to nearest face " << faceI << endl
00477 << "Face:";
00478
00479 forAll(f, fp)
00480 {
00481 Pout<< " vertex:" << f[fp] << " coord:" << points[f[fp]]
00482 << endl;
00483 }
00484 }
00485
00486
00487
00488
00489
00490
00491 return octree<octreeDataFace>::UNKNOWN;
00492 }
00493
00494
00495 bool Foam::octreeDataFace::overlaps
00496 (
00497 const label index,
00498 const treeBoundBox& sampleBb
00499 ) const
00500 {
00501
00502
00503
00504
00505
00506 if (!sampleBb.overlaps(allBb_[index]))
00507 {
00508 return false;
00509 }
00510
00511
00512 label faceI = meshFaces_[index];
00513
00514 const face& f = mesh_.faces()[faceI];
00515
00516 const pointField& points = mesh_.points();
00517
00518 forAll(f, fp)
00519 {
00520 if (sampleBb.contains(points[f[fp]]))
00521 {
00522 return true;
00523 }
00524 }
00525
00526
00527
00528 const point& fc = mesh_.faceCentres()[faceI];
00529
00530 forAll(f, fp)
00531 {
00532 const label fp1 = f.fcIndex(fp);
00533
00534 bool triIntersects = triangleFuncs::intersectBb
00535 (
00536 points[f[fp]],
00537 points[f[fp1]],
00538 fc,
00539 sampleBb
00540 );
00541
00542 if (triIntersects)
00543 {
00544 return true;
00545 }
00546 }
00547 return false;
00548 }
00549
00550
00551 bool Foam::octreeDataFace::contains(const label, const point&) const
00552 {
00553 notImplemented
00554 (
00555 "octreeDataFace::contains(const label, const point&)"
00556 );
00557 return false;
00558 }
00559
00560
00561 bool Foam::octreeDataFace::intersects
00562 (
00563 const label index,
00564 const point& start,
00565 const point& end,
00566 point& intersectionPoint
00567 ) const
00568 {
00569 label faceI = meshFaces_[index];
00570
00571 const face& f = mesh_.faces()[faceI];
00572
00573 const vector dir(end - start);
00574
00575
00576 scalar oldTol = intersection::setPlanarTol(0.0);
00577
00578 pointHit inter = f.ray
00579 (
00580 start,
00581 dir,
00582 mesh_.points(),
00583 intersection::HALF_RAY,
00584 intersection::VECTOR
00585 );
00586
00587 intersection::setPlanarTol(oldTol);
00588
00589 if (inter.hit() && inter.distance() <= mag(dir))
00590 {
00591 intersectionPoint = inter.hitPoint();
00592
00593 return true;
00594 }
00595 else
00596 {
00597 return false;
00598 }
00599 }
00600
00601
00602 bool Foam::octreeDataFace::findTightest
00603 (
00604 const label index,
00605 const point& sample,
00606 treeBoundBox& tightest
00607 ) const
00608 {
00609
00610 point myNear, myFar;
00611 allBb_[index].calcExtremities(sample, myNear, myFar);
00612
00613 const point dist = myFar - sample;
00614 scalar myFarDist = mag(dist);
00615
00616 point tightestNear, tightestFar;
00617 tightest.calcExtremities(sample, tightestNear, tightestFar);
00618
00619 scalar tightestFarDist = mag(tightestFar - sample);
00620
00621 if (tightestFarDist < myFarDist)
00622 {
00623
00624 return false;
00625 }
00626 else
00627 {
00628
00629 const point dist2(fabs(dist.x()), fabs(dist.y()), fabs(dist.z()));
00630
00631 tightest.min() = sample - dist2;
00632 tightest.max() = sample + dist2;
00633
00634 return true;
00635 }
00636 }
00637
00638
00639
00640 Foam::scalar Foam::octreeDataFace::calcSign
00641 (
00642 const label index,
00643 const point& sample,
00644 point& n
00645 ) const
00646 {
00647 label faceI = meshFaces_[index];
00648
00649 n = mesh_.faceAreas()[faceI];
00650
00651 n /= mag(n) + VSMALL;
00652
00653 vector vec = sample - mesh_.faceCentres()[faceI];
00654
00655 vec /= mag(vec) + VSMALL;
00656
00657 return n & vec;
00658 }
00659
00660
00661
00662 Foam::scalar Foam::octreeDataFace::calcNearest
00663 (
00664 const label index,
00665 const point& sample,
00666 point& nearest
00667 ) const
00668 {
00669 label faceI = meshFaces_[index];
00670
00671 const face& f = mesh_.faces()[faceI];
00672
00673 pointHit nearHit = f.nearestPoint(sample, mesh_.points());
00674
00675 nearest = nearHit.rawPoint();
00676
00677 if (debug & 1)
00678 {
00679 const point& ctr = mesh_.faceCentres()[faceI];
00680
00681 scalar sign = mesh_.faceAreas()[faceI] & (sample - nearest);
00682
00683 Pout<< "octreeDataFace::calcNearest : "
00684 << "sample:" << sample
00685 << " index:" << index
00686 << " faceI:" << faceI
00687 << " ctr:" << ctr
00688 << " sign:" << sign
00689 << " nearest point:" << nearest
00690 << " distance to face:" << nearHit.distance()
00691 << endl;
00692 }
00693 return nearHit.distance();
00694 }
00695
00696
00697
00698 Foam::scalar Foam::octreeDataFace::calcNearest
00699 (
00700 const label index,
00701 const linePointRef& ln,
00702 point& linePt,
00703 point& shapePt
00704 ) const
00705 {
00706 notImplemented
00707 (
00708 "octreeDataFace::calcNearest(const label, const linePointRef&"
00709 ", point&, point&)"
00710 );
00711 return GREAT;
00712 }
00713
00714
00715 void Foam::octreeDataFace::write(Ostream& os, const label index) const
00716 {
00717 os << meshFaces_[index] << " " << allBb_[index];
00718 }
00719
00720
00721