44 const scalar surfaceFeatures::parallelTolerance =
sin(
degToRad(1.0));
75 mag(eHit.rawPoint() - start)
76 <
mag(eHit.rawPoint() - end)
98 for (
label i = 0; i < externalStart_; i++)
100 edgeStat[featureEdges_[i]] = REGION;
104 for (
label i = externalStart_; i < internalStart_; i++)
106 edgeStat[featureEdges_[i]] = EXTERNAL;
110 for (
label i = internalStart_; i < featureEdges_.size(); i++)
112 edgeStat[featureEdges_[i]] = INTERNAL;
123 const scalar includedAngle
134 if (edgeStat[edgeI] == REGION)
138 else if (edgeStat[edgeI] == EXTERNAL)
142 else if (edgeStat[edgeI] == INTERNAL)
148 externalStart_ = nRegion;
149 internalStart_ = externalStart_ + nExternal;
154 featureEdges_.setSize(internalStart_ + nInternal);
157 label externalI = externalStart_;
158 label internalI = internalStart_;
162 if (edgeStat[edgeI] == REGION)
164 featureEdges_[regionI++] = edgeI;
166 else if (edgeStat[edgeI] == EXTERNAL)
168 featureEdges_[externalI++] = edgeI;
170 else if (edgeStat[edgeI] == INTERNAL)
172 featureEdges_[internalI++] = edgeI;
178 calcFeatPoints(edgeStat, minCos);
183 void Foam::surfaceFeatures::calcFeatPoints
192 const edgeList& edges = surf_.edges();
193 const pointField& localPoints = surf_.localPoints();
195 forAll(pointEdges, pointi)
197 const labelList& pEdges = pointEdges[pointi];
199 label nFeatEdges = 0;
203 if (edgeStat[pEdges[i]] != NONE)
211 featurePoints.append(pointi);
213 else if (nFeatEdges == 2)
216 DynamicList<vector> edgeVecs(2);
220 const label edgeI = pEdges[i];
222 if (edgeStat[edgeI] != NONE)
224 edgeVecs.
append(edges[edgeI].vec(localPoints));
225 edgeVecs.last() /=
mag(edgeVecs.last());
229 if (
mag(edgeVecs[0] & edgeVecs[1]) < minCos)
231 featurePoints.append(pointi);
236 featurePoints_.transfer(featurePoints);
240 void Foam::surfaceFeatures::classifyFeatureAngles
243 List<edgeStatus>& edgeStat,
245 const bool geometricTestOnly
248 const vectorField& faceNormals = surf_.faceNormals();
252 bool selectAll = (
mag(minCos-1.0) < small);
256 const labelList& eFaces = edgeFaces[edgeI];
258 if (eFaces.size() != 2)
261 edgeStat[edgeI] = REGION;
265 label face0 = eFaces[0];
266 label face1 = eFaces[1];
271 && surf_[face0].region() != surf_[face1].region()
274 edgeStat[edgeI] = REGION;
279 || ((faceNormals[face0] & faceNormals[face1]) < minCos)
288 if ((f0Tof1 & faceNormals[face0]) >= 0.0)
290 edgeStat[edgeI] = INTERNAL;
294 edgeStat[edgeI] = EXTERNAL;
305 const List<edgeStatus>& edgeStat,
307 const label unsetVal,
308 const label prevEdgeI,
312 const labelList& pEdges = surf_.pointEdges()[vertI];
314 label nextEdgeI = -1;
318 label edgeI = pEdges[i];
323 && edgeStat[edgeI] != NONE
324 && featVisited[edgeI] == unsetVal
351 Foam::surfaceFeatures::labelScalar Foam::surfaceFeatures::walkSegment
354 const List<edgeStatus>& edgeStat,
355 const label startEdgeI,
356 const label startPointi,
357 const label currentFeatI,
361 label edgeI = startEdgeI;
363 label vertI = startPointi;
365 scalar visitedLength = 0.0;
369 if (
findIndex(featurePoints_, startPointi) >= 0)
373 return labelScalar(nVisited, visitedLength);
393 unsetVal = currentFeatI;
399 edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
401 if (edgeI == -1 || edgeI == startEdgeI)
410 featVisited[edgeI] = currentFeatI;
414 featVisited[edgeI] = -2;
419 const edge&
e = surf_.edges()[edgeI];
421 vertI =
e.otherVertex(vertI);
425 visitedLength +=
e.mag(surf_.localPoints());
429 if (nVisited > surf_.nEdges())
431 Warning<<
"walkSegment : reached iteration limit in walking "
432 <<
"feature edges on surface from edge:" << startEdgeI
433 <<
" vertex:" << startPointi <<
nl
434 <<
"Returning with large length" <<
endl;
436 return labelScalar(nVisited, great);
441 return labelScalar(nVisited, visitedLength);
463 const label externalStart,
464 const label internalStart
468 featurePoints_(featurePoints),
469 featureEdges_(featureEdges),
470 externalStart_(externalStart),
471 internalStart_(externalStart)
479 const scalar includedAngle,
481 const label minElems,
482 const bool geometricTestOnly
493 if (minLen > 0 || minElems > 0)
507 featurePoints_(featInfoDict.lookup(
"featurePoints")),
508 featureEdges_(featInfoDict.lookup(
"featureEdges")),
509 externalStart_(featInfoDict.lookup<
label>(
"externalStart")),
510 internalStart_(featInfoDict.lookup<
label>(
"internalStart"))
532 externalStart_ = featInfoDict.
lookup<
label>(
"externalStart");
533 internalStart_ = featInfoDict.
lookup<
label>(
"internalStart");
542 const scalar mergeTol,
543 const bool geometricTestOnly
557 scalar mergeTolSqr =
sqr(mergeTol);
575 const label sEdge = edgeLabel[sEdgeI];
583 dynFeatureEdgeFaces.
append(surfEdgeFaces[sEdge]);
589 classifyFeatureAngles
605 if (iter != dynFeatEdges.
end())
607 allEdgeStat[eI] = edgeStat[iter()];
612 dynFeatEdges.
clear();
621 featurePoints_(
sf.featurePoints()),
622 featureEdges_(
sf.featureEdges()),
623 externalStart_(
sf.externalStart()),
624 internalStart_(
sf.internalStart())
632 const bool regionEdges,
633 const bool externalEdges,
634 const bool internalEdges
643 for (
label i = 0; i < externalStart_; i++)
645 selectedEdges.
append(featureEdges_[i]);
653 for (
label i = externalStart_; i < internalStart_; i++)
655 selectedEdges.
append(featureEdges_[i]);
663 for (
label i = internalStart_; i < featureEdges_.size(); i++)
665 selectedEdges.
append(featureEdges_[i]);
669 return selectedEdges.
shrink();
675 const scalar includedAngle,
676 const bool geometricTestOnly
684 classifyFeatureAngles
692 setFromStatus(edgeStat, includedAngle);
701 const label minElems,
702 const scalar includedAngle
719 label startEdgeI = 0;
724 for (; startEdgeI < edgeStat.
size(); startEdgeI++)
728 edgeStat[startEdgeI] != NONE
729 && featLines[startEdgeI] == -1
737 if (startEdgeI == edgeStat.
size())
744 featLines[startEdgeI] = featI;
746 const edge& startEdge = surf_.edges()[startEdgeI];
749 labelScalar leftPath =
760 labelScalar rightPath =
776 + startEdge.
mag(surf_.localPoints())
779 || (leftPath.n_ + rightPath.n_ + 1 < minElems)
785 featLines[startEdgeI] = -2;
817 label edgeI = featureEdges_[i];
819 if (featLines[edgeI] == -2)
821 edgeStat[edgeI] = NONE;
826 setFromStatus(edgeStat, includedAngle);
835 featInfoDict.
add(
"externalStart", externalStart_);
836 featInfoDict.
add(
"internalStart", internalStart_);
837 featInfoDict.
add(
"featureEdges", featureEdges_);
838 featInfoDict.
add(
"featurePoints", featurePoints_);
840 featInfoDict.
write(writeFile);
854 OFstream regionStr(prefix +
"_regionEdges.obj");
855 Pout<<
"Writing region edges to " << regionStr.
name() <<
endl;
858 for (
label i = 0; i < externalStart_; i++)
860 const edge&
e = surf_.edges()[featureEdges_[i]];
864 regionStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
868 OFstream externalStr(prefix +
"_externalEdges.obj");
869 Pout<<
"Writing external edges to " << externalStr.
name() <<
endl;
872 for (
label i = externalStart_; i < internalStart_; i++)
874 const edge&
e = surf_.edges()[featureEdges_[i]];
878 externalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
881 OFstream internalStr(prefix +
"_internalEdges.obj");
882 Pout<<
"Writing internal edges to " << internalStr.
name() <<
endl;
885 for (
label i = internalStart_; i < featureEdges_.size(); i++)
887 const edge&
e = surf_.edges()[featureEdges_[i]];
891 internalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
894 OFstream pointStr(prefix +
"_points.obj");
895 Pout<<
"Writing feature points to " << pointStr.
name() <<
endl;
899 label pointi = featurePoints_[i];
931 const pointField& surfPoints = surf_.localPoints();
937 const point& surfPt = surfPoints[surfPointi];
948 <<
"Problem for point "
949 << surfPointi <<
" in tree " << ppTree.
bb()
957 nearest.
insert(sampleI, surfPointi);
969 <<
"Dumping nearest surface feature points to nearestSamples.obj"
971 <<
"View this Lightwave-OBJ file with e.g. javaview" <<
endl
974 OFstream objStream(
"nearestSamples.obj");
981 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
997 const scalar minSampleDist
1000 const pointField& surfPoints = surf_.localPoints();
1001 const edgeList& surfEdges = surf_.edges();
1003 scalar maxSearchSqr =
max(maxDistSqr);
1022 label surfEdgeI = selectedEdges[i];
1024 const edge&
e = surfEdges[surfEdgeI];
1026 if (debug && (i % 1000) == 0)
1028 Pout<<
"looking at surface feature edge " << surfEdgeI
1029 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1030 <<
' ' << surfPoints[
e[1]] <<
endl;
1034 vector eVec =
e.vec(surfPoints);
1035 scalar eMag =
mag(eVec);
1050 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1068 nearest.
insert(sampleI, surfEdgeI);
1078 s +=
max(minSampleDist*eMag, sampleDist[sampleI]);
1080 if (
s >= (1-minSampleDist)*eMag)
1095 Pout<<
"Dumping nearest surface edges to nearestEdges.obj\n"
1096 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1098 OFstream objStream(
"nearestEdges.obj");
1103 const label sampleI = iter.key();
1107 const edge&
e = surfEdges[iter()];
1110 e.line(surfPoints).nearestDist(
samples[sampleI]).rawPoint();
1114 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1135 const scalar minSampleDist
1154 const pointField& surfPoints = surf_.localPoints();
1155 const edgeList& surfEdges = surf_.edges();
1157 scalar maxSearchSqr =
max(maxDistSqr);
1168 label surfEdgeI = selectedEdges[i];
1170 const edge&
e = surfEdges[surfEdgeI];
1172 if (debug && (i % 1000) == 0)
1174 Pout<<
"looking at surface feature edge " << surfEdgeI
1175 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1176 <<
' ' << surfPoints[
e[1]] <<
endl;
1180 vector eVec =
e.vec(surfPoints);
1181 scalar eMag =
mag(eVec);
1196 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1212 label sampleEdgeI = ppTree.
shapes().edgeLabels()[index];
1214 const edge&
e = sampleEdges[sampleEdgeI];
1235 if (
s >= (1-minSampleDist)*eMag)
1249 Pout<<
"Dumping nearest surface feature edges to nearestEdges.obj\n"
1250 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1252 OFstream objStream(
"nearestEdges.obj");
1257 const label sampleEdgeI = iter.key();
1259 const edge& sampleEdge = sampleEdges[sampleEdgeI];
1268 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1282 scalar searchSpanSqr,
1292 const pointField& localPoints = surf_.localPoints();
1328 edgeLabel[i] = selectedEdges[info.
index()];
1331 const edge&
e = surf_.edges()[edgeLabel[i]];
1335 localPoints[
e.start()],
1336 localPoints[
e.end()],
1341 edgeEndPoint[i] = pHit.
index();
1356 const vector& searchSpan,
1364 pointOnFeature.
setSize(selectedSampleEdges.
size());
1374 surf_.localPoints(),
1383 forAll(selectedSampleEdges, i)
1385 const edge&
e = sampleEdges[selectedSampleEdges[i]];
1391 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1406 edgeLabel[i] = selectedEdges[info.
index()];
1408 pointOnFeature[i] = info.
hitPoint();
1418 scalar searchSpanSqr,
1422 edgeLabel =
labelList(surf_.nEdges(), -1);
1442 const edgeList& surfEdges = surf_.edges();
1443 const pointField& surfLocalPoints = surf_.localPoints();
1447 const edge& sample = surfEdges[edgeI];
1449 const point& startPoint = surfLocalPoints[sample.
start()];
1462 const edge& featEdge = edges[infoMid.
index()];
1466 if (
mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
1468 edgeLabel[edgeI] = edgeI;
1483 <<
"Attempted assignment to self"
1490 <<
"Operating on different surfaces"
1526 const plane& cutPlane,
1542 if (intersect < 0 || intersect > 1)
1554 const scalar includedAngle,
1574 if (
mag(
n&normals[normalI]) > (1-tol))
1583 bins[index].
append(eFacei);
1585 else if (normals.
size() >= 2)
1602 if (bins.
size() == 1)
1624 if (includedAngle >= 0)
1634 if (
mag(ni & nj) < minCos)
1662 regionAndNormal[i] = t.
region()+1;
1671 regionAndNormal[i] = -(t.
region()+1);
1683 label myRegionAndNormal;
1686 myRegionAndNormal = t.
region()+1;
1690 myRegionAndNormal = -(t.
region()+1);
1693 regionAndNormal1[i] = myRegionAndNormal;
1715 const scalar includedAngle,
1727 && (eFaces.
size() % 2) == 0
#define forAll(list, i)
Loop across all elements in list.
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
void setCapacity(const label)
Alter the size of the underlying storage.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
label size() const
Return number of elements in table.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
void clear()
Clear all entries from table.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
void append(const T &)
Append an element at the end of the list.
void size(const label)
Override size to be inconsistent with allocated storage.
void clear()
Clear the list, i.e. set size to zero.
void setSize(const label)
Reset size of List.
A HashTable to objects of type <T> with a label key.
const fileName & name() const
Return the name of the stream.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
const Point & hitPoint() const
Return hit point.
const Point & rawPoint() const
Return point with no checking.
label index() const
Return index.
bool hit() const
Is there a hit.
label nEdges() const
Return number of edges in patch.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
const Field< PointType > & points() const
Return reference to global points.
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
const labelListList & edgeFaces() const
Return edge-face addressing.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const Field< PointType > & faceNormals() const
Return face normals for patch.
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt >> &) const
Return *this (used for point which is a typedef to Vector<scalar>.
A bounding box defined in terms of the points at its extremities.
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
bool contains(const point &) const
Contains point? (inside or on edge)
A list of keyword definitions, which are a keyword followed by any number of values (e....
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
void write(Ostream &, const bool subDict=true) const
Write dictionary, normally with sub-dictionary formatting.
bool add(entry *, bool mergeEntry=false)
Add a new entry.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
scalar mag(const pointField &) const
Return scalar magnitude.
vector vec(const pointField &) const
Return the vector (end - start)
point centre(const pointField &) const
Return centre (centroid)
label start() const
Return start vertex label.
A class for handling file names.
Non-pointer based hierarchical recursive searching.
const Type & shapes() const
Reference to shape.
const treeBoundBox & bb() const
Top bounding box.
Triangle with additional region number.
label region() const
Return region label.
Point centre() const
Return centre (centroid)
Mid-point interpolation (weighting factors = 0.5) scheme class.
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
scalar lineIntersect(const line< Point, PointRef > &l) const
Return the cutting point between the plane and.
Holds feature edges/points of surface.
void findFeatures(const scalar includedAngle, const bool geometricTestOnly)
Find feature edges using provided included angle.
surfaceFeatures(const triSurface &)
Construct from surface.
labelList selectFeatureEdges(const bool regionEdges, const bool externalEdges, const bool internalEdges) const
Helper function: select a subset of featureEdges_.
const labelList & featureEdges() const
Return feature edge list.
void setFromStatus(const List< edgeStatus > &edgeStat, const scalar includedAngle)
Set from status per edge.
void write(const fileName &fName) const
Write as dictionary to file.
const labelList & featurePoints() const
Return feature point list.
void writeObj(const fileName &prefix) const
Write to separate OBJ files (region, external, internal edges,.
Map< pointIndexHit > nearestEdges(const labelList &selectedEdges, const edgeList &sampleEdges, const labelList &selectedSampleEdges, const pointField &samplePoints, const scalarField &sampleDist, const scalarField &maxDistSqr, const scalar minSampleDist=0.1) const
Like nearestSamples but now gets nearest point on.
List< edgeStatus > toStatus() const
From member feature edges to status per edge.
void writeDict(Ostream &) const
Write as dictionary.
void nearestSurfEdge(const labelList &selectedEdges, const pointField &samples, scalar searchSpanSqr, labelList &edgeLabel, labelList &edgeEndPoint, pointField &edgePoint) const
Find nearest surface edge (out of selectedEdges) for.
label internalStart() const
Start of internal edges.
label externalStart() const
Start of external edges.
const triSurface & surface() const
Map< label > nearestSamples(const labelList &selectedPoints, const pointField &samples, const scalarField &maxDistSqr) const
Find nearest sample for selected surface points.
void nearestFeatEdge(const edgeList &edges, const pointField &points, scalar searchSpanSqr, labelList &edgeLabel) const
Find nearest feature edge to each surface edge. Uses the.
void operator=(const surfaceFeatures &)
labelList trimFeatures(const scalar minLen, const label minElems, const scalar includedAngle)
Delete small sets of edges. Edges are stringed up and any.
Standard boundBox + extra functionality for use in octree.
Holds data for octree to work on an edges subset.
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
int edgeDirection(const edge &) const
Return the edge direction on the face.
Triangulated surface description with patch information.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
volScalarField sf(fieldObject, mesh)
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
errorManipArg< error, int > exit(error &err, const int errNo=1)
scalar degToRad(const scalar deg)
Convert degrees to radians.
List< label > labelList
A List of labels.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
PointIndexHit< point > pointIndexHit
Ostream & endl(Ostream &os)
Add newline and flush stream.
line< point, const point & > linePointRef
Line using referred points.
surfaceFeatures::edgeStatus checkNonManifoldEdge(const triSurface &surf, const scalar tol, const scalar includedAngle, const label edgei)
Divide into multiple normal bins.
void selectBox(const triSurface &surf, const boundBox &bb, const bool removeInside, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges inside or outside bounding box.
errorManip< error > abort(error &err)
dimensionedScalar sin(const dimensionedScalar &ds)
vectorField pointField
pointField is a vectorField.
vector point
Point is a vector.
Vector< scalar > vector
A scalar version of the templated Vector.
List< labelList > labelListList
A List of labelList.
dimensioned< scalar > mag(const dimensioned< Type > &)
void selectManifoldEdges(const triSurface &surf, const scalar tol, const scalar includedAngle, List< surfaceFeatures::edgeStatus > &edgeStat)
Select manifold edges.
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
PointHit< point > pointHit
Field< vector > vectorField
Specialisation of Field<T> for vector.
prefixOSstream Pout(cout, "Pout")
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
void selectCutEdges(const triSurface &surf, const plane &cutPlane, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges that are intersected by the given plane.
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
dimensionedScalar cos(const dimensionedScalar &ds)
labelList pointLabels(nPoints, -1)
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
scalarField samples(nIntervals, 0)