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 "treeDataPrimitivePatch.H"
00027 #include <meshTools/indexedOctree.H>
00028 #include <meshTools/triangleFuncs.H>
00029
00030
00031
00032 template
00033 <
00034 class Face,
00035 template<class> class FaceList,
00036 class PointField,
00037 class PointType
00038 >
00039 Foam::scalar
00040 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00041 tolSqr = sqr(1E-6);
00042
00043
00044
00045
00046 template
00047 <
00048 class Face,
00049 template<class> class FaceList,
00050 class PointField,
00051 class PointType
00052 >
00053 Foam::treeBoundBox
00054 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00055 calcBb
00056 (
00057 const pointField& points,
00058 const face& f
00059 )
00060 {
00061 treeBoundBox bb(points[f[0]], points[f[0]]);
00062
00063 for (label fp = 1; fp < f.size(); fp++)
00064 {
00065 const point& p = points[f[fp]];
00066
00067 bb.min() = min(bb.min(), p);
00068 bb.max() = max(bb.max(), p);
00069 }
00070 return bb;
00071 }
00072
00073
00074 template
00075 <
00076 class Face,
00077 template<class> class FaceList,
00078 class PointField,
00079 class PointType
00080 >
00081 void Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00082 update()
00083 {
00084 if (cacheBb_)
00085 {
00086 bbs_.setSize(patch_.size());
00087
00088 forAll(patch_, i)
00089 {
00090 bbs_[i] = calcBb(patch_.points(), patch_[i]);
00091 }
00092 }
00093 }
00094
00095
00096
00097
00098
00099 template
00100 <
00101 class Face,
00102 template<class> class FaceList,
00103 class PointField,
00104 class PointType
00105 >
00106 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00107 treeDataPrimitivePatch
00108 (
00109 const bool cacheBb,
00110 const PrimitivePatch<Face, FaceList, PointField, PointType>& patch
00111 )
00112 :
00113 patch_(patch),
00114 cacheBb_(cacheBb)
00115 {
00116 update();
00117 }
00118
00119
00120
00121
00122 template
00123 <
00124 class Face,
00125 template<class> class FaceList,
00126 class PointField,
00127 class PointType
00128 >
00129 Foam::pointField
00130 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00131 points() const
00132 {
00133 pointField cc(patch_.size());
00134
00135 forAll(patch_, i)
00136 {
00137 cc[i] = patch_[i].centre(patch_.points());
00138 }
00139
00140 return cc;
00141 }
00142
00143
00144
00145
00146 template
00147 <
00148 class Face,
00149 template<class> class FaceList,
00150 class PointField,
00151 class PointType
00152 >
00153 Foam::label
00154 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00155 getVolumeType
00156 (
00157 const indexedOctree
00158 <
00159 treeDataPrimitivePatch
00160 <
00161 Face,
00162 FaceList,
00163 PointField,
00164 PointType
00165 >
00166 >& oc,
00167 const point& sample
00168 ) const
00169 {
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 pointIndexHit info = oc.findNearest(sample, sqr(GREAT));
00183
00184 if (info.index() == -1)
00185 {
00186 FatalErrorIn
00187 (
00188 "treeDataPrimitivePatch::getSampleType"
00189 "(indexedOctree<treeDataPrimitivePatch>&, const point&)"
00190 ) << "Could not find " << sample << " in octree."
00191 << abort(FatalError);
00192 }
00193
00194
00195
00196 label faceI = info.index();
00197
00198 if (debug & 2)
00199 {
00200 Pout<< "getSampleType : sample:" << sample
00201 << " nearest face:" << faceI;
00202 }
00203
00204 const pointField& points = patch_.localPoints();
00205 const face& f = patch_.localFaces()[faceI];
00206
00207
00208
00209
00210 pointHit curHit = f.nearestPoint(sample, points);
00211 const vector area = f.normal(points);
00212 const point& curPt = curHit.rawPoint();
00213
00214
00215
00216
00217
00218 if (curHit.hit())
00219 {
00220
00221
00222 if (debug & 2)
00223 {
00224 Pout<< " -> face hit:" << curPt
00225 << " comparing to face normal " << area << endl;
00226 }
00227 return indexedOctree<treeDataPrimitivePatch>::getSide
00228 (
00229 area,
00230 sample - curPt
00231 );
00232 }
00233
00234 if (debug & 2)
00235 {
00236 Pout<< " -> face miss:" << curPt;
00237 }
00238
00239
00240
00241
00242
00243
00244 const scalar typDimSqr = mag(area) + VSMALL;
00245
00246 forAll(f, fp)
00247 {
00248 if ((magSqr(points[f[fp]] - curPt)/typDimSqr) < tolSqr)
00249 {
00250
00251
00252
00253
00254
00255 return indexedOctree<treeDataPrimitivePatch>::getSide
00256 (
00257 patch_.pointNormals()[f[fp]],
00258 sample - curPt
00259 );
00260 }
00261 }
00262
00263 const point fc(f.centre(points));
00264
00265 if ((magSqr(fc - curPt)/typDimSqr) < tolSqr)
00266 {
00267
00268
00269
00270 if (debug & 2)
00271 {
00272 Pout<< " -> centre hit:" << fc
00273 << " distance:" << magSqr(fc - curPt)/typDimSqr << endl;
00274 }
00275
00276 return indexedOctree<treeDataPrimitivePatch>::getSide
00277 (
00278 area,
00279 sample - curPt
00280 );
00281 }
00282
00283
00284
00285
00286
00287
00288
00289 const labelList& fEdges = patch_.faceEdges()[faceI];
00290
00291 forAll(fEdges, fEdgeI)
00292 {
00293 label edgeI = fEdges[fEdgeI];
00294 const edge& e = patch_.edges()[edgeI];
00295
00296 pointHit edgeHit = e.line(points).nearestDist(sample);
00297
00298 if ((magSqr(edgeHit.rawPoint() - curPt)/typDimSqr) < tolSqr)
00299 {
00300
00301
00302
00303
00304 const labelList& eFaces = patch_.edgeFaces()[edgeI];
00305
00306 vector edgeNormal(vector::zero);
00307
00308 forAll(eFaces, i)
00309 {
00310 edgeNormal += patch_.faceNormal()[eFaces[i]];
00311 }
00312
00313 if (debug & 2)
00314 {
00315 Pout<< " -> real edge hit point:" << edgeHit.rawPoint()
00316 << " comparing to edge normal:" << edgeNormal
00317 << endl;
00318 }
00319
00320
00321
00322 return indexedOctree<treeDataPrimitivePatch>::getSide
00323 (
00324 edgeNormal,
00325 sample - curPt
00326 );
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335 forAll(f, fp)
00336 {
00337 pointHit edgeHit = linePointRef
00338 (
00339 points[f[fp]],
00340 fc
00341 ).nearestDist(sample);
00342
00343 if ((magSqr(edgeHit.rawPoint() - curPt)/typDimSqr) < tolSqr)
00344 {
00345
00346
00347
00348 vector e = points[f[fp]] - fc;
00349 vector ePrev = points[f[f.rcIndex(fp)]] - fc;
00350 vector eNext = points[f[f.fcIndex(fp)]] - fc;
00351
00352 vector nLeft = ePrev ^ e;
00353 nLeft /= mag(nLeft) + VSMALL;
00354
00355 vector nRight = e ^ eNext;
00356 nRight /= mag(nRight) + VSMALL;
00357
00358 if (debug & 2)
00359 {
00360 Pout<< " -> internal edge hit point:" << edgeHit.rawPoint()
00361 << " comparing to edge normal "
00362 << 0.5*(nLeft + nRight)
00363 << endl;
00364 }
00365
00366
00367
00368 return indexedOctree<treeDataPrimitivePatch>::getSide
00369 (
00370 0.5*(nLeft + nRight),
00371 sample - curPt
00372 );
00373 }
00374 }
00375
00376 if (debug & 2)
00377 {
00378 Pout<< "Did not find sample " << sample
00379 << " anywhere related to nearest face " << faceI << endl
00380 << "Face:";
00381
00382 forAll(f, fp)
00383 {
00384 Pout<< " vertex:" << f[fp] << " coord:" << points[f[fp]]
00385 << endl;
00386 }
00387 }
00388
00389
00390
00391
00392
00393
00394 return indexedOctree<treeDataPrimitivePatch>::UNKNOWN;
00395 }
00396
00397
00398
00399 template
00400 <
00401 class Face,
00402 template<class> class FaceList,
00403 class PointField,
00404 class PointType
00405 >
00406 bool
00407 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00408 overlaps
00409 (
00410 const label index,
00411 const treeBoundBox& cubeBb
00412 ) const
00413 {
00414
00415 if (cacheBb_)
00416 {
00417 if (!cubeBb.overlaps(bbs_[index]))
00418 {
00419 return false;
00420 }
00421 }
00422 else
00423 {
00424 if (!cubeBb.overlaps(calcBb(patch_.points(), patch_[index])))
00425 {
00426 return false;
00427 }
00428 }
00429
00430
00431
00432
00433 const pointField& points = patch_.points();
00434 const face& f = patch_[index];
00435
00436 forAll(f, fp)
00437 {
00438 if (cubeBb.contains(points[f[fp]]))
00439 {
00440 return true;
00441 }
00442 }
00443
00444
00445
00446 const point fc = f.centre(points);
00447
00448 forAll(f, fp)
00449 {
00450 bool triIntersects = triangleFuncs::intersectBb
00451 (
00452 points[f[fp]],
00453 points[f[f.fcIndex(fp)]],
00454 fc,
00455 cubeBb
00456 );
00457
00458 if (triIntersects)
00459 {
00460 return true;
00461 }
00462 }
00463 return false;
00464 }
00465
00466
00467
00468
00469 template
00470 <
00471 class Face,
00472 template<class> class FaceList,
00473 class PointField,
00474 class PointType
00475 >
00476 void
00477 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00478 findNearest
00479 (
00480 const labelList& indices,
00481 const point& sample,
00482
00483 scalar& nearestDistSqr,
00484 label& minIndex,
00485 point& nearestPoint
00486 ) const
00487 {
00488 const pointField& points = patch_.points();
00489
00490 forAll(indices, i)
00491 {
00492 label index = indices[i];
00493
00494 const face& f = patch_[index];
00495
00496 pointHit nearHit = f.nearestPoint(sample, points);
00497 scalar distSqr = sqr(nearHit.distance());
00498
00499 if (distSqr < nearestDistSqr)
00500 {
00501 nearestDistSqr = distSqr;
00502 minIndex = index;
00503 nearestPoint = nearHit.rawPoint();
00504 }
00505 }
00506 }
00507
00508
00509 template
00510 <
00511 class Face,
00512 template<class> class FaceList,
00513 class PointField,
00514 class PointType
00515 >
00516 bool
00517 Foam::treeDataPrimitivePatch<Face, FaceList, PointField, PointType>::
00518 intersects
00519 (
00520 const label index,
00521 const point& start,
00522 const point& end,
00523 point& intersectionPoint
00524 ) const
00525 {
00526
00527 if (cacheBb_)
00528 {
00529 const treeBoundBox& faceBb = bbs_[index];
00530
00531 if ((faceBb.posBits(start) & faceBb.posBits(end)) != 0)
00532 {
00533
00534 return false;
00535 }
00536 }
00537
00538 const pointField& points = patch_.points();
00539 const face& f = patch_[index];
00540 const point fc = f.centre(points);
00541 const vector dir(end - start);
00542
00543 pointHit inter = patch_[index].intersection
00544 (
00545 start,
00546 dir,
00547 fc,
00548 points,
00549 intersection::HALF_RAY
00550 );
00551
00552 if (inter.hit() && inter.distance() <= 1)
00553 {
00554
00555
00556 intersectionPoint = inter.hitPoint();
00557 return true;
00558 }
00559 else
00560 {
00561 return false;
00562 }
00563 }
00564
00565
00566