46 const scalar surfaceFeatures::parallelTolerance =
sin(
degToRad(1.0));
53 const point& a = line.start();
54 const point&
b = line.end();
58 (
p.x() <
min(a.x(),
b.x()) ||
p.x() >
max(a.x(),
b.x()))
59 || (
p.y() <
min(a.y(),
b.y()) ||
p.y() >
max(a.y(),
b.y()))
60 || (
p.z() <
min(a.z(),
b.z()) ||
p.z() >
max(a.z(),
b.z()))
100 mag(eHit.rawPoint() - start)
101 <
mag(eHit.rawPoint() -
end)
120 List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
123 for (label i = 0; i < externalStart_; i++)
125 edgeStat[featureEdges_[i]] = REGION;
129 for (label i = externalStart_; i < internalStart_; i++)
131 edgeStat[featureEdges_[i]] = EXTERNAL;
135 for (label i = internalStart_; i < featureEdges_.size(); i++)
137 edgeStat[featureEdges_[i]] = INTERNAL;
148 const scalar includedAngle
159 if (edgeStat[edgeI] == REGION)
163 else if (edgeStat[edgeI] == EXTERNAL)
167 else if (edgeStat[edgeI] == INTERNAL)
173 externalStart_ = nRegion;
174 internalStart_ = externalStart_ + nExternal;
179 featureEdges_.setSize(internalStart_ + nInternal);
182 label externalI = externalStart_;
183 label internalI = internalStart_;
187 if (edgeStat[edgeI] == REGION)
189 featureEdges_[regionI++] = edgeI;
191 else if (edgeStat[edgeI] == EXTERNAL)
193 featureEdges_[externalI++] = edgeI;
195 else if (edgeStat[edgeI] == INTERNAL)
197 featureEdges_[internalI++] = edgeI;
203 calcFeatPoints(edgeStat, minCos);
208 void Foam::surfaceFeatures::calcFeatPoints
210 const List<edgeStatus>& edgeStat,
214 DynamicList<label> featurePoints(surf_.nPoints()/1000);
217 const edgeList& edges = surf_.edges();
218 const pointField& localPoints = surf_.localPoints();
220 forAll(pointEdges, pointi)
222 const labelList& pEdges = pointEdges[pointi];
224 label nFeatEdges = 0;
228 if (edgeStat[pEdges[i]] != NONE)
236 featurePoints.
append(pointi);
238 else if (nFeatEdges == 2)
241 DynamicList<vector> edgeVecs(2);
245 const label edgeI = pEdges[i];
247 if (edgeStat[edgeI] != NONE)
249 vector vec = edges[edgeI].vec(localPoints);
250 scalar magVec =
mag(vec);
253 edgeVecs.append(vec/magVec);
258 if (edgeVecs.size() == 2 &&
mag(edgeVecs[0] & edgeVecs[1]) < minCos)
260 featurePoints.
append(pointi);
265 featurePoints_.transfer(featurePoints);
269 void Foam::surfaceFeatures::classifyFeatureAngles
272 List<edgeStatus>& edgeStat,
274 const bool geometricTestOnly
281 bool selectAll = (
mag(minCos-1.0) < SMALL);
285 const labelList& eFaces = edgeFaces[edgeI];
287 if (eFaces.size() != 2)
290 edgeStat[edgeI] = REGION;
294 label face0 = eFaces[0];
295 label face1 = eFaces[1];
300 && surf_[face0].region() != surf_[face1].region()
303 edgeStat[edgeI] = REGION;
319 edgeStat[edgeI] = INTERNAL;
323 edgeStat[edgeI] = EXTERNAL;
332 Foam::label Foam::surfaceFeatures::nextFeatEdge
334 const List<edgeStatus>& edgeStat,
336 const label unsetVal,
337 const label prevEdgeI,
341 const labelList& pEdges = surf_.pointEdges()[vertI];
343 label nextEdgeI = -1;
347 label edgeI = pEdges[i];
352 && edgeStat[edgeI] != NONE
353 && featVisited[edgeI] == unsetVal
380 Foam::surfaceFeatures::labelScalar Foam::surfaceFeatures::walkSegment
383 const List<edgeStatus>& edgeStat,
384 const label startEdgeI,
385 const label startPointi,
386 const label currentFeatI,
390 label edgeI = startEdgeI;
392 label vertI = startPointi;
394 scalar visitedLength = 0.0;
398 if (featurePoints_.found(startPointi))
402 return labelScalar(nVisited, visitedLength);
422 unsetVal = currentFeatI;
428 edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
430 if (edgeI == -1 || edgeI == startEdgeI)
439 featVisited[edgeI] = currentFeatI;
443 featVisited[edgeI] = -2;
448 const edge&
e = surf_.edges()[edgeI];
450 vertI =
e.otherVertex(vertI);
454 visitedLength +=
e.mag(surf_.localPoints());
458 if (nVisited > surf_.nEdges())
460 Warning<<
"walkSegment : reached iteration limit in walking "
461 <<
"feature edges on surface from edge:" << startEdgeI
462 <<
" vertex:" << startPointi <<
nl
463 <<
"Returning with large length" <<
endl;
465 return labelScalar(nVisited, GREAT);
470 return labelScalar(nVisited, visitedLength);
483 Foam::surfaceFeatures::surfaceFeatures::checkFlatRegionEdge
486 const scalar includedAngle,
490 const triSurface& surf = surf_;
492 const edge&
e = surf.edges()[edgeI];
493 const labelList& eFaces = surf.edgeFaces()[edgeI];
497 DynamicList<vector> normals(2);
498 DynamicList<labelList> bins(2);
502 const vector&
n = surf.faceNormals()[eFaces[eFacei]];
508 if (
mag(
n & normals[normalI]) > (1-tol))
517 bins[index].append(eFacei);
519 else if (normals.size() >= 2)
537 if (bins.size() == 1)
559 if (includedAngle >= 0)
565 const vector& ni = surf.faceNormals()[eFaces[i]];
566 for (label j=i+1; j<eFaces.size(); j++)
568 const vector& nj = surf.faceNormals()[eFaces[j]];
569 if (
mag(ni & nj) < minCos)
591 const labelledTri& t = surf.localFaces()[eFaces[bin0[i]]];
592 int dir = t.edgeDirection(
e);
596 regionAndNormal[i] = t.region()+1;
605 regionAndNormal[i] = -(t.region()+1);
614 const labelledTri& t = surf.localFaces()[eFaces[bin1[i]]];
615 int dir = t.edgeDirection(
e);
617 label myRegionAndNormal;
620 myRegionAndNormal = t.region()+1;
624 myRegionAndNormal = -(t.region()+1);
627 regionAndNormal1[i] = myRegionAndNormal;
629 label index = regionAndNormal.find(-myRegionAndNormal);
667 const label externalStart,
668 const label internalStart
672 featurePoints_(featurePoints),
673 featureEdges_(featureEdges),
674 externalStart_(externalStart),
675 internalStart_(externalStart)
683 const scalar includedAngle,
685 const label minElems,
686 const bool geometricTestOnly
697 if (minLen > 0 || minElems > 0)
711 featurePoints_(featInfoDict.
lookup(
"featurePoints")),
712 featureEdges_(featInfoDict.
lookup(
"featureEdges")),
713 externalStart_(featInfoDict.
get<label>(
"externalStart")),
714 internalStart_(featInfoDict.
get<label>(
"internalStart"))
734 featInfoDict.
readEntry(
"featureEdges", featureEdges_);
735 featInfoDict.
readEntry(
"featurePoints", featurePoints_);
736 featInfoDict.
readEntry(
"externalStart", externalStart_);
737 featInfoDict.
readEntry(
"internalStart", internalStart_);
746 const scalar mergeTol,
747 const bool geometricTestOnly
761 scalar mergeTolSqr =
sqr(mergeTol);
779 const label sEdge = edgeLabel[sEdgeI];
787 dynFeatureEdgeFaces.
append(surfEdgeFaces[sEdge]);
791 List<edgeStatus> edgeStat(dynFeatEdges.
size(),
NONE);
793 classifyFeatureAngles
803 List<edgeStatus> allEdgeStat(surf_.
nEdges(),
NONE);
807 const auto iter = dynFeatEdges.
cfind(surfEdges[eI]);
811 allEdgeStat[eI] = edgeStat[iter.val()];
816 dynFeatEdges.
clear();
825 featurePoints_(sf.featurePoints()),
826 featureEdges_(sf.featureEdges()),
827 externalStart_(sf.externalStart()),
828 internalStart_(sf.internalStart())
836 const bool regionEdges,
837 const bool externalEdges,
838 const bool internalEdges
845 selectedEdges.
setCapacity(selectedEdges.size() + nRegionEdges());
847 for (label i = 0; i < externalStart_; i++)
849 selectedEdges.
append(featureEdges_[i]);
855 selectedEdges.
setCapacity(selectedEdges.size() + nExternalEdges());
857 for (label i = externalStart_; i < internalStart_; i++)
859 selectedEdges.
append(featureEdges_[i]);
865 selectedEdges.
setCapacity(selectedEdges.size() + nInternalEdges());
867 for (label i = internalStart_; i < featureEdges_.size(); i++)
869 selectedEdges.
append(featureEdges_[i]);
873 return selectedEdges.
shrink();
879 const scalar includedAngle,
880 const bool geometricTestOnly
888 classifyFeatureAngles
896 setFromStatus(edgeStat, includedAngle);
905 const label minElems,
906 const scalar includedAngle
923 label startEdgeI = 0;
928 for (; startEdgeI < edgeStat.size(); startEdgeI++)
932 edgeStat[startEdgeI] != NONE
933 && featLines[startEdgeI] == -1
941 if (startEdgeI == edgeStat.size())
948 featLines[startEdgeI] = featI;
950 const edge& startEdge = surf_.edges()[startEdgeI];
953 labelScalar leftPath =
964 labelScalar rightPath =
980 + startEdge.
mag(surf_.localPoints())
983 || (leftPath.n_ + rightPath.n_ + 1 < minElems)
989 featLines[startEdgeI] = -2;
1021 label edgeI = featureEdges_[i];
1023 if (featLines[edgeI] == -2)
1025 edgeStat[edgeI] = NONE;
1030 setFromStatus(edgeStat, includedAngle);
1042 deleteBox(edgeStat, bb,
true);
1052 deleteBox(edgeStat, bb,
false);
1060 const bool removeInside
1063 const edgeList& surfEdges = surf_.edges();
1064 const pointField& surfLocalPoints = surf_.localPoints();
1068 const point eMid = surfEdges[edgei].centre(surfLocalPoints);
1081 const plane& cutPlane
1084 const edgeList& surfEdges = surf_.edges();
1086 const labelList& meshPoints = surf_.meshPoints();
1090 const edge&
e = surfEdges[edgei];
1092 const point&
p0 = pts[meshPoints[
e.start()]];
1093 const point& p1 = pts[meshPoints[
e.end()]];
1099 point featPoint = intersect * (p1 -
p0) +
p0;
1101 if (!onLine(featPoint,
line))
1116 if (surf_.edgeFaces()[edgei].size() == 1)
1128 void Foam::surfaceFeatures::checkFlatRegionEdge
1132 const scalar includedAngle
1139 const labelList& eFaces = surf_.edgeFaces()[edgei];
1141 if (eFaces.size() > 2 && (eFaces.size() % 2) == 0)
1143 edgeStat[edgei] = checkFlatRegionEdge
1158 featInfoDict.
add(
"externalStart", externalStart_);
1159 featInfoDict.
add(
"internalStart", internalStart_);
1160 featInfoDict.
add(
"featureEdges", featureEdges_);
1161 featInfoDict.
add(
"featurePoints", featurePoints_);
1176 OFstream regionStr(prefix +
"_regionEdges.obj");
1177 Pout<<
"Writing region edges to " << regionStr.
name() <<
endl;
1180 for (label i = 0; i < externalStart_; i++)
1182 const edge&
e = surf_.edges()[featureEdges_[i]];
1186 regionStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
1190 OFstream externalStr(prefix +
"_externalEdges.obj");
1191 Pout<<
"Writing external edges to " << externalStr.
name() <<
endl;
1194 for (label i = externalStart_; i < internalStart_; i++)
1196 const edge&
e = surf_.edges()[featureEdges_[i]];
1200 externalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
1203 OFstream internalStr(prefix +
"_internalEdges.obj");
1204 Pout<<
"Writing internal edges to " << internalStr.
name() <<
endl;
1207 for (label i = internalStart_; i < featureEdges_.size(); i++)
1209 const edge&
e = surf_.edges()[featureEdges_[i]];
1213 internalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
1216 OFstream pointStr(prefix +
"_points.obj");
1217 Pout<<
"Writing feature points to " << pointStr.
name() <<
endl;
1219 for (
const label pointi : featurePoints_)
1228 os <<
"Feature set:" <<
nl
1229 <<
" points : " << this->featurePoints().size() <<
nl
1230 <<
" edges : " << this->featureEdges().size() <<
nl
1231 <<
" of which" <<
nl
1232 <<
" region edges : " << this->nRegionEdges() <<
nl
1233 <<
" external edges : " << this->nExternalEdges() <<
nl
1234 <<
" internal edges : " << this->nInternalEdges() <<
endl;
1263 const pointField& surfPoints = surf_.localPoints();
1269 const point& surfPt = surfPoints[surfPointi];
1280 <<
"Problem for point "
1281 << surfPointi <<
" in tree " << ppTree.
bb()
1285 label sampleI = info.
index();
1287 if (
magSqr(
samples[sampleI] - surfPt) < maxDistSqr[sampleI])
1289 nearest.insert(sampleI, surfPointi);
1300 Pout<<
"Dumping nearest surface feature points to nearestSamples.obj"
1303 OFstream objStream(
"nearestSamples.obj");
1310 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1326 const scalar minSampleDist
1329 const pointField& surfPoints = surf_.localPoints();
1330 const edgeList& surfEdges = surf_.edges();
1332 scalar maxSearchSqr =
max(maxDistSqr);
1351 label surfEdgeI = selectedEdges[i];
1353 const edge&
e = surfEdges[surfEdgeI];
1355 if (
debug && (i % 1000) == 0)
1357 Pout<<
"looking at surface feature edge " << surfEdgeI
1358 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1359 <<
' ' << surfPoints[
e[1]] <<
endl;
1363 vector eVec =
e.vec(surfPoints);
1364 scalar eMag =
mag(eVec);
1379 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1393 label sampleI = info.
index();
1397 nearest.insert(sampleI, surfEdgeI);
1407 s +=
max(minSampleDist*eMag, sampleDist[sampleI]);
1409 if (
s >= (1-minSampleDist)*eMag)
1424 Pout<<
"Dumping nearest surface edges to nearestEdges.obj"
1427 OFstream objStream(
"nearestEdges.obj");
1432 const label sampleI = iter.key();
1434 const edge&
e = surfEdges[iter.val()];
1439 e.line(surfPoints).nearestDist(
samples[sampleI]).rawPoint();
1443 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1464 const scalar minSampleDist
1483 const pointField& surfPoints = surf_.localPoints();
1484 const edgeList& surfEdges = surf_.edges();
1486 scalar maxSearchSqr =
max(maxDistSqr);
1497 label surfEdgeI = selectedEdges[i];
1499 const edge&
e = surfEdges[surfEdgeI];
1501 if (
debug && (i % 1000) == 0)
1503 Pout<<
"looking at surface feature edge " << surfEdgeI
1504 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1505 <<
' ' << surfPoints[
e[1]] <<
endl;
1509 vector eVec =
e.vec(surfPoints);
1510 scalar eMag =
mag(eVec);
1525 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1539 label index = info.
index();
1541 label sampleEdgeI = ppTree.
shapes().edgeLabels()[index];
1543 const edge&
e = sampleEdges[sampleEdgeI];
1564 if (
s >= (1-minSampleDist)*eMag)
1578 Pout<<
"Dumping nearest surface feature edges to nearestEdges.obj"
1581 OFstream objStream(
"nearestEdges.obj");
1586 const label sampleEdgeI = iter.key();
1588 const edge& sampleEdge = sampleEdges[sampleEdgeI];
1597 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1611 scalar searchSpanSqr,
1619 edgePoint.setSize(
samples.size());
1621 const pointField& localPoints = surf_.localPoints();
1657 edgeLabel[i] = selectedEdges[info.
index()];
1660 const edge&
e = surf_.edges()[edgeLabel[i]];
1664 localPoints[
e.start()],
1665 localPoints[
e.end()],
1670 edgeEndPoint[i] = pHit.
index();
1685 const vector& searchSpan,
1691 edgeLabel.
setSize(selectedSampleEdges.size());
1692 pointOnEdge.setSize(selectedSampleEdges.size());
1693 pointOnFeature.setSize(selectedSampleEdges.size());
1703 surf_.localPoints(),
1712 forAll(selectedSampleEdges, i)
1714 const edge&
e = sampleEdges[selectedSampleEdges[i]];
1720 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1735 edgeLabel[i] = selectedEdges[info.
index()];
1737 pointOnFeature[i] = info.
hitPoint();
1747 scalar searchSpanSqr,
1751 edgeLabel =
labelList(surf_.nEdges(), -1);
1771 const edgeList& surfEdges = surf_.edges();
1772 const pointField& surfLocalPoints = surf_.localPoints();
1778 const point& startPoint = surfLocalPoints[
sample.start()];
1791 const edge& featEdge = edges[infoMid.
index()];
1795 if (
mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
1797 edgeLabel[edgeI] = edgeI;
1816 <<
"Operating on different surfaces"