1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 \*---------------------------------------------------------------------------*/
29 #include "surfaceFeatures.H"
30 #include "triSurface.H"
32 #include "octreeDataEdges.H"
33 #include "octreeDataPoint.H"
34 #include "meshTools.H"
35 #include "linePointRef.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 defineTypeNameAndDebug(Foam::surfaceFeatures, 0);
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 //- Get nearest point on edge and classify position on edge.
47 Foam::pointIndexHit Foam::surfaceFeatures::edgeNearest
54 pointHit eHit = linePointRef(start, end).nearestDist(sample);
56 // Classification of position on edge.
61 // Nearest point is on edge itself.
62 // Note: might be at or very close to endpoint. We should use tolerance
68 // Nearest point has to be one of the end points. Find out
72 mag(eHit.rawPoint() - start)
73 < mag(eHit.rawPoint() - end)
84 return pointIndexHit(eHit.hit(), eHit.rawPoint(), endPoint);
88 // Go from selected edges only to a value for every edge
89 Foam::List<Foam::surfaceFeatures::edgeStatus> Foam::surfaceFeatures::toStatus()
92 List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
95 for (label i = 0; i < externalStart_; i++)
97 edgeStat[featureEdges_[i]] = REGION;
101 for (label i = externalStart_; i < internalStart_; i++)
103 edgeStat[featureEdges_[i]] = EXTERNAL;
107 for (label i = internalStart_; i < featureEdges_.size(); i++)
109 edgeStat[featureEdges_[i]] = INTERNAL;
116 // Set from value for every edge
117 void Foam::surfaceFeatures::setFromStatus(const List<edgeStatus>& edgeStat)
125 forAll(edgeStat, edgeI)
127 if (edgeStat[edgeI] == REGION)
131 else if (edgeStat[edgeI] == EXTERNAL)
135 else if (edgeStat[edgeI] == INTERNAL)
141 externalStart_ = nRegion;
142 internalStart_ = externalStart_ + nExternal;
147 featureEdges_.setSize(internalStart_ + nInternal);
150 label externalI = externalStart_;
151 label internalI = internalStart_;
153 forAll(edgeStat, edgeI)
155 if (edgeStat[edgeI] == REGION)
157 featureEdges_[regionI++] = edgeI;
159 else if (edgeStat[edgeI] == EXTERNAL)
161 featureEdges_[externalI++] = edgeI;
163 else if (edgeStat[edgeI] == INTERNAL)
165 featureEdges_[internalI++] = edgeI;
169 // Calculate consistent feature points
170 calcFeatPoints(edgeStat);
174 //construct feature points where more than 2 feature edges meet
175 void Foam::surfaceFeatures::calcFeatPoints(const List<edgeStatus>& edgeStat)
177 DynamicList<label> featurePoints(surf_.nPoints()/1000);
179 const labelListList& pointEdges = surf_.pointEdges();
181 forAll(pointEdges, pointI)
183 const labelList& pEdges = pointEdges[pointI];
185 label nFeatEdges = 0;
189 if (edgeStat[pEdges[i]] != NONE)
197 featurePoints.append(pointI);
201 featurePoints_.transfer(featurePoints);
205 // Returns next feature edge connected to pointI with correct value.
206 Foam::label Foam::surfaceFeatures::nextFeatEdge
208 const List<edgeStatus>& edgeStat,
209 const labelList& featVisited,
210 const label unsetVal,
211 const label prevEdgeI,
215 const labelList& pEdges = surf_.pointEdges()[vertI];
217 label nextEdgeI = -1;
221 label edgeI = pEdges[i];
226 && edgeStat[edgeI] != NONE
227 && featVisited[edgeI] == unsetVal
236 // More than one feature edge to choose from. End of segment.
246 // Finds connected feature edges by walking from prevEdgeI in direction of
247 // prevPointI. Marks feature edges visited in featVisited by assigning them
248 // the current feature line number. Returns cumulative length of edges walked.
249 // Works in one of two modes:
250 // - mark : step to edges with featVisited = -1.
251 // Mark edges visited with currentFeatI.
252 // - clear : step to edges with featVisited = currentFeatI
253 // Mark edges visited with -2 and erase from feature edges.
254 Foam::surfaceFeatures::labelScalar Foam::surfaceFeatures::walkSegment
257 const List<edgeStatus>& edgeStat,
258 const label startEdgeI,
259 const label startPointI,
260 const label currentFeatI,
261 labelList& featVisited
264 label edgeI = startEdgeI;
266 label vertI = startPointI;
271 // edgeI : first edge on this segment
272 // vertI : one of the endpoints of this segment
274 // Start walking, marking off edges (in featVisited)
286 unsetVal = currentFeatI;
290 scalar visitedLength = 0.0;
296 // Step to next feature edge with value unsetVal
297 edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
299 if (edgeI == -1 || edgeI == startEdgeI)
304 // Mark with current value. If in clean mode also remove feature edge.
308 featVisited[edgeI] = currentFeatI;
312 featVisited[edgeI] = -2;
316 // Step to next vertex on edge
317 const edge& e = surf_.edges()[edgeI];
319 vertI = e.otherVertex(vertI);
322 // Update cumulative length
323 visitedLength += e.mag(surf_.localPoints());
327 if (nVisited > surf_.nEdges())
329 Warning<< "walkSegment : reached iteration limit in walking "
330 << "feature edges on surface from edge:" << startEdgeI
331 << " vertex:" << startPointI << nl
332 << "Returning with large length" << endl;
334 return labelScalar(nVisited, GREAT);
339 return labelScalar(nVisited, visitedLength);
343 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
345 Foam::surfaceFeatures::surfaceFeatures(const triSurface& surf)
355 // Construct from components.
356 Foam::surfaceFeatures::surfaceFeatures
358 const triSurface& surf,
359 const labelList& featurePoints,
360 const labelList& featureEdges,
361 const label externalStart,
362 const label internalStart
366 featurePoints_(featurePoints),
367 featureEdges_(featureEdges),
368 externalStart_(externalStart),
369 internalStart_(externalStart)
373 // Construct from surface, angle and min length
374 Foam::surfaceFeatures::surfaceFeatures
376 const triSurface& surf,
377 const scalar includedAngle,
388 findFeatures(includedAngle);
390 if (minLen > 0 || minElems > 0)
392 trimFeatures(minLen, minElems);
397 //- Construct from dictionary
398 Foam::surfaceFeatures::surfaceFeatures
400 const triSurface& surf,
401 const dictionary& featInfoDict
405 featurePoints_(featInfoDict.lookup("featurePoints")),
406 featureEdges_(featInfoDict.lookup("featureEdges")),
407 externalStart_(readLabel(featInfoDict.lookup("externalStart"))),
408 internalStart_(readLabel(featInfoDict.lookup("internalStart")))
412 //- Construct from file
413 Foam::surfaceFeatures::surfaceFeatures
415 const triSurface& surf,
416 const fileName& fName
427 dictionary featInfoDict(str);
429 featureEdges_ = labelList(featInfoDict.lookup("featureEdges"));
430 featurePoints_ = labelList(featInfoDict.lookup("featurePoints"));
431 externalStart_ = readLabel(featInfoDict.lookup("externalStart"));
432 internalStart_ = readLabel(featInfoDict.lookup("internalStart"));
436 //- Construct as copy
437 Foam::surfaceFeatures::surfaceFeatures(const surfaceFeatures& sf)
440 featurePoints_(sf.featurePoints()),
441 featureEdges_(sf.featureEdges()),
442 externalStart_(sf.externalStart()),
443 internalStart_(sf.internalStart())
447 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
449 Foam::labelList Foam::surfaceFeatures::selectFeatureEdges
451 const bool regionEdges,
452 const bool externalEdges,
453 const bool internalEdges
456 DynamicList<label> selectedEdges;
460 selectedEdges.setCapacity(selectedEdges.size() + nRegionEdges());
462 for (label i = 0; i < externalStart_; i++)
464 selectedEdges.append(featureEdges_[i]);
470 selectedEdges.setCapacity(selectedEdges.size() + nExternalEdges());
472 for (label i = externalStart_; i < internalStart_; i++)
474 selectedEdges.append(featureEdges_[i]);
480 selectedEdges.setCapacity(selectedEdges.size() + nInternalEdges());
482 for (label i = internalStart_; i < featureEdges_.size(); i++)
484 selectedEdges.append(featureEdges_[i]);
488 return selectedEdges.shrink();
492 void Foam::surfaceFeatures::findFeatures(const scalar includedAngle)
497 (180.0-includedAngle)
498 * mathematicalConstant::pi/180.0
501 const labelListList& edgeFaces = surf_.edgeFaces();
502 const vectorField& faceNormals = surf_.faceNormals();
503 const pointField& points = surf_.points();
505 // Per edge whether is feature edge.
506 List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
508 forAll(edgeFaces, edgeI)
510 const labelList& eFaces = edgeFaces[edgeI];
512 if (eFaces.size() != 2)
514 // Non-manifold. What to do here? Is region edge? external edge?
515 edgeStat[edgeI] = REGION;
519 label face0 = eFaces[0];
520 label face1 = eFaces[1];
522 if (surf_[face0].region() != surf_[face1].region())
524 edgeStat[edgeI] = REGION;
528 if ((faceNormals[face0] & faceNormals[face1]) < minCos)
531 // Check if convex or concave by looking at angle
532 // between face centres and normal
534 surf_[face1].centre(points)
535 - surf_[face0].centre(points);
537 if ((f0Tof1 & faceNormals[face0]) > 0.0)
539 edgeStat[edgeI] = INTERNAL;
543 edgeStat[edgeI] = EXTERNAL;
550 setFromStatus(edgeStat);
554 // Remove small strings of edges. First assigns string number to
555 // every edge and then works out the length of them.
556 void Foam::surfaceFeatures::trimFeatures
562 // Convert feature edge list to status per edge.
563 List<edgeStatus> edgeStat(toStatus());
566 // Mark feature edges according to connected lines.
568 // -2: part of too small a feature line
569 // >0: feature line number
570 labelList featLines(surf_.nEdges(), -1);
572 // Current featureline number.
575 // Current starting edge
576 label startEdgeI = 0;
580 // Find unset featureline
581 for (; startEdgeI < edgeStat.size(); startEdgeI++)
585 edgeStat[startEdgeI] != NONE
586 && featLines[startEdgeI] == -1
589 // Found unassigned feature edge.
594 if (startEdgeI == edgeStat.size())
596 // No unset feature edge found. All feature edges have line number
601 featLines[startEdgeI] = featI;
603 const edge& startEdge = surf_.edges()[startEdgeI];
605 // Walk 'left' and 'right' from startEdge.
606 labelScalar leftPath =
611 startEdgeI, // edge, not yet assigned to a featureLine
612 startEdge[0], // start of edge
614 featLines // Mark for all edges
617 labelScalar rightPath =
623 startEdge[1], // end of edge
630 (leftPath.len_ + rightPath.len_ < minLen)
631 || (leftPath.n_ + rightPath.n_ < minElems)
634 // Rewalk same route (recognizable by featLines == featI)
635 // to reset featLines.
637 featLines[startEdgeI] = -2;
641 false, // 'clean' mode
643 startEdgeI, // edge, not yet assigned to a featureLine
644 startEdge[0], // start of edge
645 featI, // Unset value
646 featLines // Mark for all edges
654 startEdge[1], // end of edge
666 // Unmark all feature lines that have featLines=-2
667 forAll(featureEdges_, i)
669 label edgeI = featureEdges_[i];
671 if (featLines[edgeI] == -2)
673 edgeStat[edgeI] = NONE;
677 // Convert back to edge labels
678 setFromStatus(edgeStat);
682 void Foam::surfaceFeatures::writeDict(Ostream& writeFile) const
685 dictionary featInfoDict;
686 featInfoDict.add("externalStart", externalStart_);
687 featInfoDict.add("internalStart", internalStart_);
688 featInfoDict.add("featureEdges", featureEdges_);
689 featInfoDict.add("featurePoints", featurePoints_);
691 featInfoDict.write(writeFile);
695 void Foam::surfaceFeatures::write(const fileName& fName) const
703 void Foam::surfaceFeatures::writeObj(const fileName& prefix) const
705 OFstream regionStr(prefix + "_regionEdges.obj");
706 Pout<< "Writing region edges to " << regionStr.name() << endl;
709 for (label i = 0; i < externalStart_; i++)
711 const edge& e = surf_.edges()[featureEdges_[i]];
713 meshTools::writeOBJ(regionStr, surf_.localPoints()[e[0]]); verti++;
714 meshTools::writeOBJ(regionStr, surf_.localPoints()[e[1]]); verti++;
715 regionStr << "l " << verti-1 << ' ' << verti << endl;
719 OFstream externalStr(prefix + "_externalEdges.obj");
720 Pout<< "Writing external edges to " << externalStr.name() << endl;
723 for (label i = externalStart_; i < internalStart_; i++)
725 const edge& e = surf_.edges()[featureEdges_[i]];
727 meshTools::writeOBJ(externalStr, surf_.localPoints()[e[0]]); verti++;
728 meshTools::writeOBJ(externalStr, surf_.localPoints()[e[1]]); verti++;
729 externalStr << "l " << verti-1 << ' ' << verti << endl;
732 OFstream internalStr(prefix + "_internalEdges.obj");
733 Pout<< "Writing internal edges to " << internalStr.name() << endl;
736 for (label i = internalStart_; i < featureEdges_.size(); i++)
738 const edge& e = surf_.edges()[featureEdges_[i]];
740 meshTools::writeOBJ(internalStr, surf_.localPoints()[e[0]]); verti++;
741 meshTools::writeOBJ(internalStr, surf_.localPoints()[e[1]]); verti++;
742 internalStr << "l " << verti-1 << ' ' << verti << endl;
745 OFstream pointStr(prefix + "_points.obj");
746 Pout<< "Writing feature points to " << pointStr.name() << endl;
748 forAll(featurePoints_, i)
750 label pointI = featurePoints_[i];
752 meshTools::writeOBJ(pointStr, surf_.localPoints()[pointI]);
757 // Get nearest vertex on patch for every point of surf in pointSet.
758 Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
760 const labelList& pointLabels,
761 const pointField& samples,
762 const scalarField& maxDist
765 // Build tree out of all samples.
766 treeBoundBox bb(samples);
768 octree<octreeDataPoint> ppTree
770 bb, // overall search domain
771 octreeDataPoint(samples), // all information needed to do checks
773 20.0, // maximum ratio of cubes v.s. cells
774 100.0 // max. duplicity; n/a since no bounding boxes.
777 // From patch point to surface point
778 Map<label> nearest(2*pointLabels.size());
780 const pointField& surfPoints = surf_.localPoints();
782 forAll(pointLabels, i)
784 label surfPointI = pointLabels[i];
786 const point& surfPt = surfPoints[surfPointI];
788 point maxDistPt(maxDist[i], maxDist[i], maxDist[i]);
790 treeBoundBox tightest(surfPt - maxDistPt, surfPt + maxDistPt);
791 scalar tightestDist = Foam::GREAT;
793 label sampleI = ppTree.findNearest
802 FatalErrorIn("surfaceFeatures::nearestSamples")
803 << "Problem for point "
804 << surfPointI << " in tree " << ppTree.octreeBb()
805 << abort(FatalError);
810 magSqr(samples[sampleI] - surfPt)
811 < Foam::sqr(maxDist[sampleI])
814 nearest.insert(sampleI, surfPointI);
826 << "Dumping nearest surface feature points to nearestSamples.obj"
828 << "View this Lightwave-OBJ file with e.g. javaview" << endl
831 OFstream objStream("nearestSamples.obj");
836 Map<label>::const_iterator iter = nearest.begin();
837 iter != nearest.end();
841 meshTools::writeOBJ(objStream, samples[iter.key()]); vertI++;
842 meshTools::writeOBJ(objStream, surfPoints[iter()]); vertI++;
843 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
851 // Get nearest sample point for regularly sampled points along
852 // selected edges. Return map from sample to edge label
853 Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
855 const labelList& selectedEdges,
856 const pointField& samples,
857 const scalarField& sampleDist,
858 const scalarField& maxDist,
859 const scalar minSampleDist
862 const pointField& surfPoints = surf_.localPoints();
863 const edgeList& surfEdges = surf_.edges();
865 scalar maxSearch = max(maxDist);
866 vector span(maxSearch, maxSearch, maxSearch);
868 // octree.shapes holds reference!
869 treeBoundBox bb(samples);
871 octree<octreeDataPoint> ppTree
873 bb, // overall search domain
874 octreeDataPoint(samples), // all information needed to do checks
876 20.0, // maximum ratio of cubes v.s. cells
877 100.0 // max. duplicity; n/a since no bounding boxes.
880 // From patch point to surface edge.
881 Map<label> nearest(2*selectedEdges.size());
883 forAll(selectedEdges, i)
885 label surfEdgeI = selectedEdges[i];
887 const edge& e = surfEdges[surfEdgeI];
889 if (debug && (i % 1000) == 0)
891 Pout<< "looking at surface feature edge " << surfEdgeI
892 << " verts:" << e << " points:" << surfPoints[e[0]]
893 << ' ' << surfPoints[e[1]] << endl;
896 // Normalized edge vector
897 vector eVec = e.vec(surfPoints);
898 scalar eMag = mag(eVec);
908 // Coordinate along edge (0 .. eMag)
913 point edgePoint(surfPoints[e.start()] + s*eVec);
915 treeBoundBox tightest(edgePoint - span, edgePoint + span);
916 scalar tightestDist = Foam::GREAT;
918 label sampleI = ppTree.findNearest
927 // No point close enough to surface edge.
930 if (tightestDist < maxDist[sampleI])
932 nearest.insert(sampleI, surfEdgeI);
940 // Step to next sample point using local distance.
941 // Truncate to max 1/minSampleDist samples per feature edge.
942 s += max(minSampleDist*eMag, sampleDist[sampleI]);
944 if (s >= (1-minSampleDist)*eMag)
946 // Do one more sample, at edge endpoint
959 Pout<< "Dumping nearest surface edges to nearestEdges.obj\n"
960 << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
962 OFstream objStream("nearestEdges.obj");
967 Map<label>::const_iterator iter = nearest.begin();
968 iter != nearest.end();
972 label sampleI = iter.key();
974 meshTools::writeOBJ(objStream, samples[sampleI]); vertI++;
976 const edge& e = surfEdges[iter()];
979 e.line(surfPoints).nearestDist(samples[sampleI]).rawPoint();
981 meshTools::writeOBJ(objStream, nearPt); vertI++;
983 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
991 // Get nearest edge on patch for regularly sampled points along the feature
992 // edges. Return map from patch edge to feature edge.
994 // Q: using point-based sampleDist and maxDist (distance to look around
995 // each point). Should they be edge-based e.g. by averaging or max()?
996 Foam::Map<Foam::pointIndexHit> Foam::surfaceFeatures::nearestEdges
998 const labelList& selectedEdges,
999 const edgeList& sampleEdges,
1000 const labelList& selectedSampleEdges,
1001 const pointField& samplePoints,
1002 const scalarField& sampleDist,
1003 const scalarField& maxDist,
1004 const scalar minSampleDist
1007 // Build tree out of selected sample edges.
1008 octree<octreeDataEdges> ppTree
1010 treeBoundBox(samplePoints), // overall search domain
1016 ), // geometric info container for edges
1018 20.0, // maximum ratio of cubes v.s. cells
1019 10.0 // max. duplicity
1022 const pointField& surfPoints = surf_.localPoints();
1023 const edgeList& surfEdges = surf_.edges();
1025 scalar maxSearch = max(maxDist);
1026 vector span(maxSearch, maxSearch, maxSearch);
1029 Map<pointIndexHit> nearest(2*sampleEdges.size());
1032 // Loop over all selected edges. Sample at regular intervals. Find nearest
1033 // sampleEdges (using octree)
1036 forAll(selectedEdges, i)
1038 label surfEdgeI = selectedEdges[i];
1040 const edge& e = surfEdges[surfEdgeI];
1042 if (debug && (i % 1000) == 0)
1044 Pout<< "looking at surface feature edge " << surfEdgeI
1045 << " verts:" << e << " points:" << surfPoints[e[0]]
1046 << ' ' << surfPoints[e[1]] << endl;
1049 // Normalized edge vector
1050 vector eVec = e.vec(surfPoints);
1051 scalar eMag = mag(eVec);
1056 // Sample along edge
1061 // Coordinate along edge (0 .. eMag)
1066 point edgePoint(surfPoints[e.start()] + s*eVec);
1068 treeBoundBox tightest(edgePoint - span, edgePoint + span);
1069 scalar tightestDist = Foam::GREAT;
1071 label index = ppTree.findNearest
1080 // No edge close enough to surface edge.
1084 label sampleEdgeI = ppTree.shapes().edgeLabels()[index];
1086 const edge& e = sampleEdges[sampleEdgeI];
1088 if (tightestDist < maxDist[e.start()])
1093 pointIndexHit(true, edgePoint, surfEdgeI)
1102 // Step to next sample point using local distance.
1103 // Truncate to max 1/minSampleDist samples per feature edge.
1104 // s += max(minSampleDist*eMag, sampleDist[e.start()]);
1107 if (s >= (1-minSampleDist)*eMag)
1109 // Do one more sample, at edge endpoint
1121 Pout<< "Dumping nearest surface feature edges to nearestEdges.obj\n"
1122 << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
1124 OFstream objStream("nearestEdges.obj");
1129 Map<pointIndexHit>::const_iterator iter = nearest.begin();
1130 iter != nearest.end();
1134 label sampleEdgeI = iter.key();
1136 const edge& sampleEdge = sampleEdges[sampleEdgeI];
1138 // Write line from edgeMid to point on feature edge
1139 meshTools::writeOBJ(objStream, sampleEdge.centre(samplePoints));
1142 meshTools::writeOBJ(objStream, iter().rawPoint());
1145 objStream<< "l " << vertI-1 << ' ' << vertI << endl;
1153 // Get nearest surface edge for every sample. Return in form of
1154 // labelLists giving surfaceEdge label&intersectionpoint.
1155 void Foam::surfaceFeatures::nearestSurfEdge
1157 const labelList& selectedEdges,
1158 const pointField& samples,
1159 const vector& searchSpan, // Search span
1160 labelList& edgeLabel,
1161 labelList& edgeEndPoint,
1162 pointField& edgePoint
1165 edgeLabel.setSize(samples.size());
1166 edgeEndPoint.setSize(samples.size());
1167 edgePoint.setSize(samples.size());
1169 const pointField& localPoints = surf_.localPoints();
1171 octree<octreeDataEdges> ppTree
1173 treeBoundBox(localPoints), // overall search domain
1179 ), // all information needed to do geometric checks
1181 20.0, // maximum ratio of cubes v.s. cells
1182 10.0 // max. duplicity
1188 const point& sample = samples[i];
1190 treeBoundBox tightest(sample - searchSpan, sample + searchSpan);
1192 scalar tightestDist = magSqr(searchSpan);
1209 edgeLabel[i] = selectedEdges[index];
1211 // Unfortunately findNearest does not return nearest point so
1213 const edge& e = surf_.edges()[edgeLabel[i]];
1215 pointIndexHit pHit =
1218 localPoints[e.start()],
1219 localPoints[e.end()],
1223 edgePoint[i] = pHit.rawPoint();
1224 edgeEndPoint[i] = pHit.index();
1230 // Get nearest point on nearest feature edge for every sample (is edge)
1231 void Foam::surfaceFeatures::nearestSurfEdge
1233 const labelList& selectedEdges,
1235 const edgeList& sampleEdges,
1236 const labelList& selectedSampleEdges,
1237 const pointField& samplePoints,
1239 const vector& searchSpan, // Search span
1240 labelList& edgeLabel, // label of surface edge or -1
1241 pointField& pointOnEdge, // point on above edge
1242 pointField& pointOnFeature // point on sample edge
1245 edgeLabel.setSize(selectedSampleEdges.size());
1246 pointOnEdge.setSize(selectedSampleEdges.size());
1247 pointOnFeature.setSize(selectedSampleEdges.size());
1250 octree<octreeDataEdges> ppTree
1252 treeBoundBox(surf_.localPoints()), // overall search domain
1256 surf_.localPoints(),
1258 ), // all information needed to do geometric checks
1260 10.0, // maximum ratio of cubes v.s. cells
1261 10.0 // max. duplicity
1265 forAll(selectedSampleEdges, i)
1267 const edge& e = sampleEdges[selectedSampleEdges[i]];
1269 linePointRef edgeLine = e.line(samplePoints);
1271 point eMid(edgeLine.centre());
1273 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1291 edgeLabel[i] = featureEdges_[index];
1297 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1299 void Foam::surfaceFeatures::operator=(const surfaceFeatures& rhs)
1301 // Check for assignment to self
1306 "Foam::surfaceFeatures::operator=(const Foam::surfaceFeatures&)"
1307 ) << "Attempted assignment to self"
1308 << abort(FatalError);
1311 if (&surf_ != &rhs.surface())
1315 "Foam::surfaceFeatures::operator=(const Foam::surfaceFeatures&)"
1316 ) << "Operating on different surfaces"
1317 << abort(FatalError);
1320 featurePoints_ = rhs.featurePoints();
1321 featureEdges_ = rhs.featureEdges();
1322 externalStart_ = rhs.externalStart();
1323 internalStart_ = rhs.internalStart();
1327 // ************************************************************************* //