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