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 "surfaceFeatures.H"
00029 #include <triSurface/triSurface.H>
00030 #include <meshTools/octree.H>
00031 #include <meshTools/octreeDataEdges.H>
00032 #include <meshTools/octreeDataPoint.H>
00033 #include <meshTools/meshTools.H>
00034 #include <OpenFOAM/linePointRef.H>
00035 #include <OpenFOAM/OFstream.H>
00036 #include <OpenFOAM/IFstream.H>
00037
00038
00039
00040 defineTypeNameAndDebug(Foam::surfaceFeatures, 0);
00041
00042
00043
00044
00045
00046 Foam::pointIndexHit Foam::surfaceFeatures::edgeNearest
00047 (
00048 const point& start,
00049 const point& end,
00050 const point& sample
00051 )
00052 {
00053 pointHit eHit = linePointRef(start, end).nearestDist(sample);
00054
00055
00056 label endPoint;
00057
00058 if (eHit.hit())
00059 {
00060
00061
00062
00063 endPoint = -1;
00064 }
00065 else
00066 {
00067
00068
00069 if
00070 (
00071 mag(eHit.rawPoint() - start)
00072 < mag(eHit.rawPoint() - end)
00073 )
00074 {
00075 endPoint = 0;
00076 }
00077 else
00078 {
00079 endPoint = 1;
00080 }
00081 }
00082
00083 return pointIndexHit(eHit.hit(), eHit.rawPoint(), endPoint);
00084 }
00085
00086
00087
00088 Foam::List<Foam::surfaceFeatures::edgeStatus> Foam::surfaceFeatures::toStatus()
00089 const
00090 {
00091 List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
00092
00093
00094 for (label i = 0; i < externalStart_; i++)
00095 {
00096 edgeStat[featureEdges_[i]] = REGION;
00097 }
00098
00099
00100 for (label i = externalStart_; i < internalStart_; i++)
00101 {
00102 edgeStat[featureEdges_[i]] = EXTERNAL;
00103 }
00104
00105
00106 for (label i = internalStart_; i < featureEdges_.size(); i++)
00107 {
00108 edgeStat[featureEdges_[i]] = INTERNAL;
00109 }
00110
00111 return edgeStat;
00112 }
00113
00114
00115
00116 void Foam::surfaceFeatures::setFromStatus(const List<edgeStatus>& edgeStat)
00117 {
00118
00119
00120 label nRegion = 0;
00121 label nExternal = 0;
00122 label nInternal = 0;
00123
00124 forAll(edgeStat, edgeI)
00125 {
00126 if (edgeStat[edgeI] == REGION)
00127 {
00128 nRegion++;
00129 }
00130 else if (edgeStat[edgeI] == EXTERNAL)
00131 {
00132 nExternal++;
00133 }
00134 else if (edgeStat[edgeI] == INTERNAL)
00135 {
00136 nInternal++;
00137 }
00138 }
00139
00140 externalStart_ = nRegion;
00141 internalStart_ = externalStart_ + nExternal;
00142
00143
00144
00145
00146 featureEdges_.setSize(internalStart_ + nInternal);
00147
00148 label regionI = 0;
00149 label externalI = externalStart_;
00150 label internalI = internalStart_;
00151
00152 forAll(edgeStat, edgeI)
00153 {
00154 if (edgeStat[edgeI] == REGION)
00155 {
00156 featureEdges_[regionI++] = edgeI;
00157 }
00158 else if (edgeStat[edgeI] == EXTERNAL)
00159 {
00160 featureEdges_[externalI++] = edgeI;
00161 }
00162 else if (edgeStat[edgeI] == INTERNAL)
00163 {
00164 featureEdges_[internalI++] = edgeI;
00165 }
00166 }
00167
00168
00169 calcFeatPoints(edgeStat);
00170 }
00171
00172
00173
00174 void Foam::surfaceFeatures::calcFeatPoints(const List<edgeStatus>& edgeStat)
00175 {
00176 DynamicList<label> featurePoints(surf_.nPoints()/1000);
00177
00178 const labelListList& pointEdges = surf_.pointEdges();
00179
00180 forAll(pointEdges, pointI)
00181 {
00182 const labelList& pEdges = pointEdges[pointI];
00183
00184 label nFeatEdges = 0;
00185
00186 forAll(pEdges, i)
00187 {
00188 if (edgeStat[pEdges[i]] != NONE)
00189 {
00190 nFeatEdges++;
00191 }
00192 }
00193
00194 if (nFeatEdges > 2)
00195 {
00196 featurePoints.append(pointI);
00197 }
00198 }
00199
00200 featurePoints_.transfer(featurePoints);
00201 }
00202
00203
00204
00205 Foam::label Foam::surfaceFeatures::nextFeatEdge
00206 (
00207 const List<edgeStatus>& edgeStat,
00208 const labelList& featVisited,
00209 const label unsetVal,
00210 const label prevEdgeI,
00211 const label vertI
00212 ) const
00213 {
00214 const labelList& pEdges = surf_.pointEdges()[vertI];
00215
00216 label nextEdgeI = -1;
00217
00218 forAll(pEdges, i)
00219 {
00220 label edgeI = pEdges[i];
00221
00222 if
00223 (
00224 edgeI != prevEdgeI
00225 && edgeStat[edgeI] != NONE
00226 && featVisited[edgeI] == unsetVal
00227 )
00228 {
00229 if (nextEdgeI == -1)
00230 {
00231 nextEdgeI = edgeI;
00232 }
00233 else
00234 {
00235
00236 return -1;
00237 }
00238 }
00239 }
00240
00241 return nextEdgeI;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 Foam::surfaceFeatures::labelScalar Foam::surfaceFeatures::walkSegment
00254 (
00255 const bool mark,
00256 const List<edgeStatus>& edgeStat,
00257 const label startEdgeI,
00258 const label startPointI,
00259 const label currentFeatI,
00260 labelList& featVisited
00261 )
00262 {
00263 label edgeI = startEdgeI;
00264
00265 label vertI = startPointI;
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 label unsetVal;
00278
00279 if (mark)
00280 {
00281 unsetVal = -1;
00282 }
00283 else
00284 {
00285 unsetVal = currentFeatI;
00286 }
00287
00288
00289 scalar visitedLength = 0.0;
00290
00291 label nVisited = 0;
00292
00293 do
00294 {
00295
00296 edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
00297
00298 if (edgeI == -1 || edgeI == startEdgeI)
00299 {
00300 break;
00301 }
00302
00303
00304
00305 if (mark)
00306 {
00307 featVisited[edgeI] = currentFeatI;
00308 }
00309 else
00310 {
00311 featVisited[edgeI] = -2;
00312 }
00313
00314
00315
00316 const edge& e = surf_.edges()[edgeI];
00317
00318 vertI = e.otherVertex(vertI);
00319
00320
00321
00322 visitedLength += e.mag(surf_.localPoints());
00323
00324 nVisited++;
00325
00326 if (nVisited > surf_.nEdges())
00327 {
00328 Warning<< "walkSegment : reached iteration limit in walking "
00329 << "feature edges on surface from edge:" << startEdgeI
00330 << " vertex:" << startPointI << nl
00331 << "Returning with large length" << endl;
00332
00333 return labelScalar(nVisited, GREAT);
00334 }
00335 }
00336 while (true);
00337
00338 return labelScalar(nVisited, visitedLength);
00339 }
00340
00341
00342
00343
00344 Foam::surfaceFeatures::surfaceFeatures(const triSurface& surf)
00345 :
00346 surf_(surf),
00347 featurePoints_(0),
00348 featureEdges_(0),
00349 externalStart_(0),
00350 internalStart_(0)
00351 {}
00352
00353
00354
00355 Foam::surfaceFeatures::surfaceFeatures
00356 (
00357 const triSurface& surf,
00358 const labelList& featurePoints,
00359 const labelList& featureEdges,
00360 const label externalStart,
00361 const label internalStart
00362 )
00363 :
00364 surf_(surf),
00365 featurePoints_(featurePoints),
00366 featureEdges_(featureEdges),
00367 externalStart_(externalStart),
00368 internalStart_(externalStart)
00369 {}
00370
00371
00372
00373 Foam::surfaceFeatures::surfaceFeatures
00374 (
00375 const triSurface& surf,
00376 const scalar includedAngle,
00377 const scalar minLen,
00378 const label minElems
00379 )
00380 :
00381 surf_(surf),
00382 featurePoints_(0),
00383 featureEdges_(0),
00384 externalStart_(0),
00385 internalStart_(0)
00386 {
00387 findFeatures(includedAngle);
00388
00389 if (minLen > 0 || minElems > 0)
00390 {
00391 trimFeatures(minLen, minElems);
00392 }
00393 }
00394
00395
00396
00397 Foam::surfaceFeatures::surfaceFeatures
00398 (
00399 const triSurface& surf,
00400 const dictionary& featInfoDict
00401 )
00402 :
00403 surf_(surf),
00404 featurePoints_(featInfoDict.lookup("featurePoints")),
00405 featureEdges_(featInfoDict.lookup("featureEdges")),
00406 externalStart_(readLabel(featInfoDict.lookup("externalStart"))),
00407 internalStart_(readLabel(featInfoDict.lookup("internalStart")))
00408 {}
00409
00410
00411
00412 Foam::surfaceFeatures::surfaceFeatures
00413 (
00414 const triSurface& surf,
00415 const fileName& fName
00416 )
00417 :
00418 surf_(surf),
00419 featurePoints_(0),
00420 featureEdges_(0),
00421 externalStart_(0),
00422 internalStart_(0)
00423 {
00424 IFstream str(fName);
00425
00426 dictionary featInfoDict(str);
00427
00428 featureEdges_ = labelList(featInfoDict.lookup("featureEdges"));
00429 featurePoints_ = labelList(featInfoDict.lookup("featurePoints"));
00430 externalStart_ = readLabel(featInfoDict.lookup("externalStart"));
00431 internalStart_ = readLabel(featInfoDict.lookup("internalStart"));
00432 }
00433
00434
00435
00436 Foam::surfaceFeatures::surfaceFeatures(const surfaceFeatures& sf)
00437 :
00438 surf_(sf.surface()),
00439 featurePoints_(sf.featurePoints()),
00440 featureEdges_(sf.featureEdges()),
00441 externalStart_(sf.externalStart()),
00442 internalStart_(sf.internalStart())
00443 {}
00444
00445
00446
00447
00448 Foam::labelList Foam::surfaceFeatures::selectFeatureEdges
00449 (
00450 const bool regionEdges,
00451 const bool externalEdges,
00452 const bool internalEdges
00453 ) const
00454 {
00455 DynamicList<label> selectedEdges;
00456
00457 if (regionEdges)
00458 {
00459 selectedEdges.setCapacity(selectedEdges.size() + nRegionEdges());
00460
00461 for (label i = 0; i < externalStart_; i++)
00462 {
00463 selectedEdges.append(featureEdges_[i]);
00464 }
00465 }
00466
00467 if (externalEdges)
00468 {
00469 selectedEdges.setCapacity(selectedEdges.size() + nExternalEdges());
00470
00471 for (label i = externalStart_; i < internalStart_; i++)
00472 {
00473 selectedEdges.append(featureEdges_[i]);
00474 }
00475 }
00476
00477 if (internalEdges)
00478 {
00479 selectedEdges.setCapacity(selectedEdges.size() + nInternalEdges());
00480
00481 for (label i = internalStart_; i < featureEdges_.size(); i++)
00482 {
00483 selectedEdges.append(featureEdges_[i]);
00484 }
00485 }
00486
00487 return selectedEdges.shrink();
00488 }
00489
00490
00491 void Foam::surfaceFeatures::findFeatures(const scalar includedAngle)
00492 {
00493 scalar minCos =
00494 Foam::cos
00495 (
00496 (180.0-includedAngle)
00497 * mathematicalConstant::pi/180.0
00498 );
00499
00500 const labelListList& edgeFaces = surf_.edgeFaces();
00501 const vectorField& faceNormals = surf_.faceNormals();
00502 const pointField& points = surf_.points();
00503
00504
00505 List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
00506
00507 forAll(edgeFaces, edgeI)
00508 {
00509 const labelList& eFaces = edgeFaces[edgeI];
00510
00511 if (eFaces.size() != 2)
00512 {
00513
00514 edgeStat[edgeI] = REGION;
00515 }
00516 else
00517 {
00518 label face0 = eFaces[0];
00519 label face1 = eFaces[1];
00520
00521 if (surf_[face0].region() != surf_[face1].region())
00522 {
00523 edgeStat[edgeI] = REGION;
00524 }
00525 else
00526 {
00527 if ((faceNormals[face0] & faceNormals[face1]) < minCos)
00528 {
00529
00530
00531
00532 vector f0Tof1 =
00533 surf_[face1].centre(points)
00534 - surf_[face0].centre(points);
00535
00536 if ((f0Tof1 & faceNormals[face0]) > 0.0)
00537 {
00538 edgeStat[edgeI] = INTERNAL;
00539 }
00540 else
00541 {
00542 edgeStat[edgeI] = EXTERNAL;
00543 }
00544 }
00545 }
00546 }
00547 }
00548
00549 setFromStatus(edgeStat);
00550 }
00551
00552
00553
00554
00555 void Foam::surfaceFeatures::trimFeatures
00556 (
00557 const scalar minLen,
00558 const label minElems
00559 )
00560 {
00561
00562 List<edgeStatus> edgeStat(toStatus());
00563
00564
00565
00566
00567
00568
00569 labelList featLines(surf_.nEdges(), -1);
00570
00571
00572 label featI = 0;
00573
00574
00575 label startEdgeI = 0;
00576
00577 do
00578 {
00579
00580 for (; startEdgeI < edgeStat.size(); startEdgeI++)
00581 {
00582 if
00583 (
00584 edgeStat[startEdgeI] != NONE
00585 && featLines[startEdgeI] == -1
00586 )
00587 {
00588
00589 break;
00590 }
00591 }
00592
00593 if (startEdgeI == edgeStat.size())
00594 {
00595
00596
00597 break;
00598 }
00599
00600 featLines[startEdgeI] = featI;
00601
00602 const edge& startEdge = surf_.edges()[startEdgeI];
00603
00604
00605 labelScalar leftPath =
00606 walkSegment
00607 (
00608 true,
00609 edgeStat,
00610 startEdgeI,
00611 startEdge[0],
00612 featI,
00613 featLines
00614 );
00615
00616 labelScalar rightPath =
00617 walkSegment
00618 (
00619 true,
00620 edgeStat,
00621 startEdgeI,
00622 startEdge[1],
00623 featI,
00624 featLines
00625 );
00626
00627 if
00628 (
00629 (leftPath.len_ + rightPath.len_ < minLen)
00630 || (leftPath.n_ + rightPath.n_ < minElems)
00631 )
00632 {
00633
00634
00635
00636 featLines[startEdgeI] = -2;
00637
00638 walkSegment
00639 (
00640 false,
00641 edgeStat,
00642 startEdgeI,
00643 startEdge[0],
00644 featI,
00645 featLines
00646 );
00647
00648 walkSegment
00649 (
00650 false,
00651 edgeStat,
00652 startEdgeI,
00653 startEdge[1],
00654 featI,
00655 featLines
00656 );
00657 }
00658 else
00659 {
00660 featI++;
00661 }
00662 }
00663 while (true);
00664
00665
00666 forAll(featureEdges_, i)
00667 {
00668 label edgeI = featureEdges_[i];
00669
00670 if (featLines[edgeI] == -2)
00671 {
00672 edgeStat[edgeI] = NONE;
00673 }
00674 }
00675
00676
00677 setFromStatus(edgeStat);
00678 }
00679
00680
00681 void Foam::surfaceFeatures::writeDict(Ostream& writeFile) const
00682 {
00683
00684 dictionary featInfoDict;
00685 featInfoDict.add("externalStart", externalStart_);
00686 featInfoDict.add("internalStart", internalStart_);
00687 featInfoDict.add("featureEdges", featureEdges_);
00688 featInfoDict.add("featurePoints", featurePoints_);
00689
00690 featInfoDict.write(writeFile);
00691 }
00692
00693
00694 void Foam::surfaceFeatures::write(const fileName& fName) const
00695 {
00696 OFstream str(fName);
00697
00698 writeDict(str);
00699 }
00700
00701
00702 void Foam::surfaceFeatures::writeObj(const fileName& prefix) const
00703 {
00704 OFstream regionStr(prefix + "_regionEdges.obj");
00705 Pout<< "Writing region edges to " << regionStr.name() << endl;
00706
00707 label verti = 0;
00708 for (label i = 0; i < externalStart_; i++)
00709 {
00710 const edge& e = surf_.edges()[featureEdges_[i]];
00711
00712 meshTools::writeOBJ(regionStr, surf_.localPoints()[e[0]]); verti++;
00713 meshTools::writeOBJ(regionStr, surf_.localPoints()[e[1]]); verti++;
00714 regionStr << "l " << verti-1 << ' ' << verti << endl;
00715 }
00716
00717
00718 OFstream externalStr(prefix + "_externalEdges.obj");
00719 Pout<< "Writing external edges to " << externalStr.name() << endl;
00720
00721 verti = 0;
00722 for (label i = externalStart_; i < internalStart_; i++)
00723 {
00724 const edge& e = surf_.edges()[featureEdges_[i]];
00725
00726 meshTools::writeOBJ(externalStr, surf_.localPoints()[e[0]]); verti++;
00727 meshTools::writeOBJ(externalStr, surf_.localPoints()[e[1]]); verti++;
00728 externalStr << "l " << verti-1 << ' ' << verti << endl;
00729 }
00730
00731 OFstream internalStr(prefix + "_internalEdges.obj");
00732 Pout<< "Writing internal edges to " << internalStr.name() << endl;
00733
00734 verti = 0;
00735 for (label i = internalStart_; i < featureEdges_.size(); i++)
00736 {
00737 const edge& e = surf_.edges()[featureEdges_[i]];
00738
00739 meshTools::writeOBJ(internalStr, surf_.localPoints()[e[0]]); verti++;
00740 meshTools::writeOBJ(internalStr, surf_.localPoints()[e[1]]); verti++;
00741 internalStr << "l " << verti-1 << ' ' << verti << endl;
00742 }
00743
00744 OFstream pointStr(prefix + "_points.obj");
00745 Pout<< "Writing feature points to " << pointStr.name() << endl;
00746
00747 forAll(featurePoints_, i)
00748 {
00749 label pointI = featurePoints_[i];
00750
00751 meshTools::writeOBJ(pointStr, surf_.localPoints()[pointI]);
00752 }
00753 }
00754
00755
00756
00757 Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
00758 (
00759 const labelList& pointLabels,
00760 const pointField& samples,
00761 const scalarField& maxDist
00762 ) const
00763 {
00764
00765
00766
00767 treeBoundBox bb(samples);
00768
00769 octree<octreeDataPoint> ppTree
00770 (
00771 bb,
00772 octreeDataPoint(samples),
00773 1,
00774 20.0,
00775 100.0
00776 );
00777
00778
00779 Map<label> nearest(2*pointLabels.size());
00780
00781 const pointField& surfPoints = surf_.localPoints();
00782
00783 forAll(pointLabels, i)
00784 {
00785 label surfPointI = pointLabels[i];
00786
00787 const point& surfPt = surfPoints[surfPointI];
00788
00789 point maxDistPt(maxDist[i], maxDist[i], maxDist[i]);
00790
00791 treeBoundBox tightest(surfPt - maxDistPt, surfPt + maxDistPt);
00792 scalar tightestDist = Foam::GREAT;
00793
00794 label sampleI = ppTree.findNearest
00795 (
00796 surfPt,
00797 tightest,
00798 tightestDist
00799 );
00800
00801 if (sampleI == -1)
00802 {
00803 FatalErrorIn("surfaceFeatures::nearestSamples")
00804 << "Problem for point "
00805 << surfPointI << " in tree " << ppTree.octreeBb()
00806 << abort(FatalError);
00807 }
00808
00809 if
00810 (
00811 magSqr(samples[sampleI] - surfPt)
00812 < Foam::sqr(maxDist[sampleI])
00813 )
00814 {
00815 nearest.insert(sampleI, surfPointI);
00816 }
00817 }
00818
00819
00820 if (debug)
00821 {
00822
00823
00824
00825
00826 Pout<< endl
00827 << "Dumping nearest surface feature points to nearestSamples.obj"
00828 << endl
00829 << "View this Lightwave-OBJ file with e.g. javaview" << endl
00830 << endl;
00831
00832 OFstream objStream("nearestSamples.obj");
00833
00834 label vertI = 0;
00835 for
00836 (
00837 Map<label>::const_iterator iter = nearest.begin();
00838 iter != nearest.end();
00839 ++iter
00840 )
00841 {
00842 meshTools::writeOBJ(objStream, samples[iter.key()]); vertI++;
00843 meshTools::writeOBJ(objStream, surfPoints[iter()]); vertI++;
00844 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
00845 }
00846 }
00847
00848 return nearest;
00849 }
00850
00851
00852
00853
00854 Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
00855 (
00856 const labelList& selectedEdges,
00857 const pointField& samples,
00858 const scalarField& sampleDist,
00859 const scalarField& maxDist,
00860 const scalar minSampleDist
00861 ) const
00862 {
00863 const pointField& surfPoints = surf_.localPoints();
00864 const edgeList& surfEdges = surf_.edges();
00865
00866 scalar maxSearch = max(maxDist);
00867 vector span(maxSearch, maxSearch, maxSearch);
00868
00869
00870 treeBoundBox bb(samples);
00871
00872 octree<octreeDataPoint> ppTree
00873 (
00874 bb,
00875 octreeDataPoint(samples),
00876 1,
00877 20.0,
00878 100.0
00879 );
00880
00881
00882 Map<label> nearest(2*selectedEdges.size());
00883
00884 forAll(selectedEdges, i)
00885 {
00886 label surfEdgeI = selectedEdges[i];
00887
00888 const edge& e = surfEdges[surfEdgeI];
00889
00890 if (debug && (i % 1000) == 0)
00891 {
00892 Pout<< "looking at surface feature edge " << surfEdgeI
00893 << " verts:" << e << " points:" << surfPoints[e[0]]
00894 << ' ' << surfPoints[e[1]] << endl;
00895 }
00896
00897
00898 vector eVec = e.vec(surfPoints);
00899 scalar eMag = mag(eVec);
00900 eVec /= eMag;
00901
00902
00903
00904
00905
00906
00907 bool exit = false;
00908
00909
00910 scalar s = 0.0;
00911
00912 while (true)
00913 {
00914 point edgePoint(surfPoints[e.start()] + s*eVec);
00915
00916 treeBoundBox tightest(edgePoint - span, edgePoint + span);
00917 scalar tightestDist = Foam::GREAT;
00918
00919 label sampleI = ppTree.findNearest
00920 (
00921 edgePoint,
00922 tightest,
00923 tightestDist
00924 );
00925
00926 if (sampleI == -1)
00927 {
00928
00929 break;
00930 }
00931 if (tightestDist < maxDist[sampleI])
00932 {
00933 nearest.insert(sampleI, surfEdgeI);
00934 }
00935
00936 if (exit)
00937 {
00938 break;
00939 }
00940
00941
00942
00943 s += max(minSampleDist*eMag, sampleDist[sampleI]);
00944
00945 if (s >= (1-minSampleDist)*eMag)
00946 {
00947
00948 s = eMag;
00949 exit = true;
00950 }
00951 }
00952 }
00953
00954
00955
00956 if (debug)
00957 {
00958
00959
00960 Pout<< "Dumping nearest surface edges to nearestEdges.obj\n"
00961 << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
00962
00963 OFstream objStream("nearestEdges.obj");
00964
00965 label vertI = 0;
00966 for
00967 (
00968 Map<label>::const_iterator iter = nearest.begin();
00969 iter != nearest.end();
00970 ++iter
00971 )
00972 {
00973 label sampleI = iter.key();
00974
00975 meshTools::writeOBJ(objStream, samples[sampleI]); vertI++;
00976
00977 const edge& e = surfEdges[iter()];
00978
00979 point nearPt =
00980 e.line(surfPoints).nearestDist(samples[sampleI]).rawPoint();
00981
00982 meshTools::writeOBJ(objStream, nearPt); vertI++;
00983
00984 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
00985 }
00986 }
00987
00988 return nearest;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997 Foam::Map<Foam::pointIndexHit> Foam::surfaceFeatures::nearestEdges
00998 (
00999 const labelList& selectedEdges,
01000 const edgeList& sampleEdges,
01001 const labelList& selectedSampleEdges,
01002 const pointField& samplePoints,
01003 const scalarField& sampleDist,
01004 const scalarField& maxDist,
01005 const scalar minSampleDist
01006 ) const
01007 {
01008
01009 octree<octreeDataEdges> ppTree
01010 (
01011 treeBoundBox(samplePoints),
01012 octreeDataEdges
01013 (
01014 sampleEdges,
01015 samplePoints,
01016 selectedSampleEdges
01017 ),
01018 1,
01019 20.0,
01020 10.0
01021 );
01022
01023 const pointField& surfPoints = surf_.localPoints();
01024 const edgeList& surfEdges = surf_.edges();
01025
01026 scalar maxSearch = max(maxDist);
01027 vector span(maxSearch, maxSearch, maxSearch);
01028
01029
01030 Map<pointIndexHit> nearest(2*sampleEdges.size());
01031
01032
01033
01034
01035
01036
01037 forAll(selectedEdges, i)
01038 {
01039 label surfEdgeI = selectedEdges[i];
01040
01041 const edge& e = surfEdges[surfEdgeI];
01042
01043 if (debug && (i % 1000) == 0)
01044 {
01045 Pout<< "looking at surface feature edge " << surfEdgeI
01046 << " verts:" << e << " points:" << surfPoints[e[0]]
01047 << ' ' << surfPoints[e[1]] << endl;
01048 }
01049
01050
01051 vector eVec = e.vec(surfPoints);
01052 scalar eMag = mag(eVec);
01053 eVec /= eMag;
01054
01055
01056
01057
01058
01059
01060 bool exit = false;
01061
01062
01063 scalar s = 0.0;
01064
01065 while (true)
01066 {
01067 point edgePoint(surfPoints[e.start()] + s*eVec);
01068
01069 treeBoundBox tightest(edgePoint - span, edgePoint + span);
01070 scalar tightestDist = Foam::GREAT;
01071
01072 label index = ppTree.findNearest
01073 (
01074 edgePoint,
01075 tightest,
01076 tightestDist
01077 );
01078
01079 if (index == -1)
01080 {
01081
01082 break;
01083 }
01084
01085 label sampleEdgeI = ppTree.shapes().edgeLabels()[index];
01086
01087 const edge& e = sampleEdges[sampleEdgeI];
01088
01089 if (tightestDist < maxDist[e.start()])
01090 {
01091 nearest.insert
01092 (
01093 sampleEdgeI,
01094 pointIndexHit(true, edgePoint, surfEdgeI)
01095 );
01096 }
01097
01098 if (exit)
01099 {
01100 break;
01101 }
01102
01103
01104
01105
01106 s += 0.01*eMag;
01107
01108 if (s >= (1-minSampleDist)*eMag)
01109 {
01110
01111 s = eMag;
01112 exit = true;
01113 }
01114 }
01115 }
01116
01117
01118 if (debug)
01119 {
01120
01121
01122 Pout<< "Dumping nearest surface feature edges to nearestEdges.obj\n"
01123 << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
01124
01125 OFstream objStream("nearestEdges.obj");
01126
01127 label vertI = 0;
01128 for
01129 (
01130 Map<pointIndexHit>::const_iterator iter = nearest.begin();
01131 iter != nearest.end();
01132 ++iter
01133 )
01134 {
01135 label sampleEdgeI = iter.key();
01136
01137 const edge& sampleEdge = sampleEdges[sampleEdgeI];
01138
01139
01140 meshTools::writeOBJ(objStream, sampleEdge.centre(samplePoints));
01141 vertI++;
01142
01143 meshTools::writeOBJ(objStream, iter().rawPoint());
01144 vertI++;
01145
01146 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
01147 }
01148 }
01149
01150 return nearest;
01151 }
01152
01153
01154
01155
01156 void Foam::surfaceFeatures::nearestSurfEdge
01157 (
01158 const labelList& selectedEdges,
01159 const pointField& samples,
01160 const vector& searchSpan,
01161 labelList& edgeLabel,
01162 labelList& edgeEndPoint,
01163 pointField& edgePoint
01164 ) const
01165 {
01166 edgeLabel.setSize(samples.size());
01167 edgeEndPoint.setSize(samples.size());
01168 edgePoint.setSize(samples.size());
01169
01170 const pointField& localPoints = surf_.localPoints();
01171
01172 octree<octreeDataEdges> ppTree
01173 (
01174 treeBoundBox(localPoints),
01175 octreeDataEdges
01176 (
01177 surf_.edges(),
01178 localPoints,
01179 selectedEdges
01180 ),
01181 1,
01182 20.0,
01183 10.0
01184 );
01185
01186
01187 forAll(samples, i)
01188 {
01189 const point& sample = samples[i];
01190
01191 treeBoundBox tightest(sample - searchSpan, sample + searchSpan);
01192
01193 scalar tightestDist = magSqr(searchSpan);
01194
01195 label index =
01196 ppTree.findNearest
01197 (
01198 sample,
01199 tightest,
01200 tightestDist
01201 );
01202
01203
01204 if (index == -1)
01205 {
01206 edgeLabel[i] = -1;
01207 }
01208 else
01209 {
01210 edgeLabel[i] = selectedEdges[index];
01211
01212
01213
01214 const edge& e = surf_.edges()[edgeLabel[i]];
01215
01216 pointIndexHit pHit =
01217 edgeNearest
01218 (
01219 localPoints[e.start()],
01220 localPoints[e.end()],
01221 sample
01222 );
01223
01224 edgePoint[i] = pHit.rawPoint();
01225 edgeEndPoint[i] = pHit.index();
01226 }
01227 }
01228 }
01229
01230
01231
01232 void Foam::surfaceFeatures::nearestSurfEdge
01233 (
01234 const labelList& selectedEdges,
01235
01236 const edgeList& sampleEdges,
01237 const labelList& selectedSampleEdges,
01238 const pointField& samplePoints,
01239
01240 const vector& searchSpan,
01241 labelList& edgeLabel,
01242 pointField& pointOnEdge,
01243 pointField& pointOnFeature
01244 ) const
01245 {
01246 edgeLabel.setSize(selectedSampleEdges.size());
01247 pointOnEdge.setSize(selectedSampleEdges.size());
01248 pointOnFeature.setSize(selectedSampleEdges.size());
01249
01250
01251 octree<octreeDataEdges> ppTree
01252 (
01253 treeBoundBox(surf_.localPoints()),
01254 octreeDataEdges
01255 (
01256 surf_.edges(),
01257 surf_.localPoints(),
01258 selectedEdges
01259 ),
01260 1,
01261 10.0,
01262 10.0
01263 );
01264
01265
01266 forAll(selectedSampleEdges, i)
01267 {
01268 const edge& e = sampleEdges[selectedSampleEdges[i]];
01269
01270 linePointRef edgeLine = e.line(samplePoints);
01271
01272 point eMid(edgeLine.centre());
01273
01274 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
01275
01276 label index =
01277 ppTree.findNearest
01278 (
01279 edgeLine,
01280 tightest,
01281 pointOnEdge[i],
01282 pointOnFeature[i]
01283 );
01284
01285
01286 if (index == -1)
01287 {
01288 edgeLabel[i] = -1;
01289 }
01290 else
01291 {
01292 edgeLabel[i] = featureEdges_[index];
01293 }
01294 }
01295 }
01296
01297
01298
01299
01300 void Foam::surfaceFeatures::operator=(const surfaceFeatures& rhs)
01301 {
01302
01303 if (this == &rhs)
01304 {
01305 FatalErrorIn
01306 (
01307 "Foam::surfaceFeatures::operator=(const Foam::surfaceFeatures&)"
01308 ) << "Attempted assignment to self"
01309 << abort(FatalError);
01310 }
01311
01312 if (&surf_ != &rhs.surface())
01313 {
01314 FatalErrorIn
01315 (
01316 "Foam::surfaceFeatures::operator=(const Foam::surfaceFeatures&)"
01317 ) << "Operating on different surfaces"
01318 << abort(FatalError);
01319 }
01320
01321 featurePoints_ = rhs.featurePoints();
01322 featureEdges_ = rhs.featureEdges();
01323 externalStart_ = rhs.externalStart();
01324 internalStart_ = rhs.internalStart();
01325 }
01326
01327
01328