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)
220 const label edgeI = pEdges[i];
222 if (edgeStat[edgeI] != NONE)
224 edgeVecs.
append(edges[edgeI].vec(localPoints));
229 if (
mag(edgeVecs[0] & edgeVecs[1]) < minCos)
231 featurePoints.
append(pointi);
236 featurePoints_.transfer(featurePoints);
240 void Foam::surfaceFeatures::classifyFeatureAngles
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)
285 surf_[face1].
centre(points)
286 - surf_[face0].
centre(points);
288 if ((f0Tof1 & faceNormals[face0]) >= 0.0)
290 edgeStat[edgeI] = INTERNAL;
294 edgeStat[edgeI] = EXTERNAL;
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
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];
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];
582 dynFeatEdges.
insert(surfEdges[sEdge], count++);
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
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 =
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;
836 featInfoDict.
add(
"externalStart", externalStart_);
837 featInfoDict.
add(
"internalStart", internalStart_);
838 featInfoDict.
add(
"featureEdges", featureEdges_);
839 featInfoDict.
add(
"featurePoints", featurePoints_);
841 featInfoDict.
write(writeFile);
855 OFstream regionStr(prefix +
"_regionEdges.obj");
856 Pout<<
"Writing region edges to " << regionStr.
name() <<
endl;
859 for (
label i = 0; i < externalStart_; i++)
861 const edge&
e = surf_.
edges()[featureEdges_[i]];
865 regionStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
869 OFstream externalStr(prefix +
"_externalEdges.obj");
870 Pout<<
"Writing external edges to " << externalStr.
name() <<
endl;
873 for (
label i = externalStart_; i < internalStart_; i++)
875 const edge&
e = surf_.
edges()[featureEdges_[i]];
879 externalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
882 OFstream internalStr(prefix +
"_internalEdges.obj");
883 Pout<<
"Writing internal edges to " << internalStr.
name() <<
endl;
886 for (
label i = internalStart_; i < featureEdges_.
size(); i++)
888 const edge&
e = surf_.
edges()[featureEdges_[i]];
892 internalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
895 OFstream pointStr(prefix +
"_points.obj");
896 Pout<<
"Writing feature points to " << pointStr.
name() <<
endl;
900 label pointi = featurePoints_[i];
936 label surfPointi = pointLabels[i];
938 const point& surfPt = surfPoints[surfPointi];
949 <<
"Problem for point " 950 << surfPointi <<
" in tree " << ppTree.
bb()
956 if (
magSqr(samples[sampleI] - surfPt) < maxDistSqr[sampleI])
958 nearest.insert(sampleI, surfPointi);
970 <<
"Dumping nearest surface feature points to nearestSamples.obj" 972 <<
"View this Lightwave-OBJ file with e.g. javaview" <<
endl 975 OFstream objStream(
"nearestSamples.obj");
982 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
998 const scalar minSampleDist
1004 scalar maxSearchSqr =
max(maxDistSqr);
1023 label surfEdgeI = selectedEdges[i];
1025 const edge&
e = surfEdges[surfEdgeI];
1027 if (debug && (i % 1000) == 0)
1029 Pout<<
"looking at surface feature edge " << surfEdgeI
1030 <<
" verts:" << e <<
" points:" << surfPoints[e[0]]
1031 <<
' ' << surfPoints[e[1]] <<
endl;
1036 scalar eMag =
mag(eVec);
1051 point edgePoint(surfPoints[e.
start()] + s*eVec);
1065 label sampleI = info.index();
1067 if (
magSqr(info.hitPoint() - edgePoint) < maxDistSqr[sampleI])
1069 nearest.insert(sampleI, surfEdgeI);
1079 s +=
max(minSampleDist*eMag, sampleDist[sampleI]);
1081 if (s >= (1-minSampleDist)*eMag)
1096 Pout<<
"Dumping nearest surface edges to nearestEdges.obj\n" 1097 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1099 OFstream objStream(
"nearestEdges.obj");
1104 const label sampleI = iter.key();
1108 const edge&
e = surfEdges[iter()];
1115 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1136 const scalar minSampleDist
1158 scalar maxSearchSqr =
max(maxDistSqr);
1169 label surfEdgeI = selectedEdges[i];
1171 const edge&
e = surfEdges[surfEdgeI];
1173 if (debug && (i % 1000) == 0)
1175 Pout<<
"looking at surface feature edge " << surfEdgeI
1176 <<
" verts:" << e <<
" points:" << surfPoints[e[0]]
1177 <<
' ' << surfPoints[e[1]] <<
endl;
1182 scalar eMag =
mag(eVec);
1197 point edgePoint(surfPoints[e.
start()] + s*eVec);
1211 label index = info.index();
1213 label sampleEdgeI = ppTree.
shapes().edgeLabels()[index];
1215 const edge& e = sampleEdges[sampleEdgeI];
1217 if (
magSqr(info.hitPoint() - edgePoint) < maxDistSqr[e.
start()])
1236 if (s >= (1-minSampleDist)*eMag)
1250 Pout<<
"Dumping nearest surface feature edges to nearestEdges.obj\n" 1251 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1253 OFstream objStream(
"nearestEdges.obj");
1258 const label sampleEdgeI = iter.key();
1260 const edge& sampleEdge = sampleEdges[sampleEdgeI];
1269 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1283 scalar searchSpanSqr,
1315 const point& sample = samples[i];
1329 edgeLabel[i] = selectedEdges[info.
index()];
1336 localPoints[e.
start()],
1337 localPoints[e.
end()],
1342 edgeEndPoint[i] = pHit.
index();
1357 const vector& searchSpan,
1365 pointOnFeature.
setSize(selectedSampleEdges.
size());
1384 forAll(selectedSampleEdges, i)
1386 const edge&
e = sampleEdges[selectedSampleEdges[i]];
1392 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1407 edgeLabel[i] = selectedEdges[info.
index()];
1409 pointOnFeature[i] = info.
hitPoint();
1419 scalar searchSpanSqr,
1426 searchDomain.inflate(0.1);
1448 const edge& sample = surfEdges[edgeI];
1450 const point& startPoint = surfLocalPoints[sample.
start()];
1461 const vector surfEdgeDir = midPoint - startPoint;
1463 const edge& featEdge = edges[infoMid.
index()];
1464 const vector featEdgeDir = featEdge.
vec(points);
1467 if (
mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
1469 edgeLabel[edgeI] = edgeI;
1484 <<
"Attempted assignment to self" 1491 <<
"Operating on different surfaces" 1527 const plane& cutPlane,
1537 const point& p0 = points[meshPoints[e.
start()]];
1538 const point& p1 = points[meshPoints[e.
end()]];
1543 if (intersect < 0 || intersect > 1)
1555 const scalar includedAngle,
1575 if (
mag(n&normals[normalI]) > (1-tol))
1584 bins[index].
append(eFacei);
1586 else if (normals.
size() >= 2)
1603 if (bins.
size() == 1)
1625 if (includedAngle >= 0)
1635 if (
mag(ni & nj) < minCos)
1663 regionAndNormal[i] = t.
region()+1;
1672 regionAndNormal[i] = -(t.
region()+1);
1684 label myRegionAndNormal;
1687 myRegionAndNormal = t.
region()+1;
1691 myRegionAndNormal = -(t.
region()+1);
1694 regionAndNormal1[i] = myRegionAndNormal;
1716 const scalar includedAngle,
1728 && (eFaces.
size() % 2) == 0
void write(Ostream &, const bool subDict=true) const
Write dictionary, normally with sub-dictionary formatting.
#define forAll(list, i)
Loop across all elements in list.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
A class for handling file names.
Holds (reference to) pointField. Encapsulation of data needed for octree searches. Used for searching for nearest point. No bounding boxes around points. Only overlaps and calcNearest are implemented, rest makes little sense.
label nRegionEdges() const
Return number of region edges.
errorManipArg< error, int > exit(error &err, const int errNo=1)
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
void write(const fileName &fName) const
Write as dictionary to file.
A list of keyword definitions, which are a keyword followed by any number of values (e...
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
void selectCutEdges(const triSurface &surf, const plane &cutPlane, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges that are intersected by the given plane.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Unit conversion functions.
void size(const label)
Override size to be inconsistent with allocated storage.
bool contains(const point &) const
Contains point? (inside or on edge)
surfaceFeatures::edgeStatus checkNonManifoldEdge(const triSurface &surf, const scalar tol, const scalar includedAngle, const label edgei)
Divide into multiple normal bins.
Ostream & endl(Ostream &os)
Add newline and flush stream.
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
Holds data for octree to work on an edges subset.
label externalStart() const
Start of external edges.
Map< label > nearestSamples(const labelList &selectedPoints, const pointField &samples, const scalarField &maxDistSqr) const
Find nearest sample for selected surface points.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
void selectBox(const triSurface &surf, const boundBox &bb, const bool removeInside, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges inside or outside bounding box.
A bounding box defined in terms of the points at its extremities.
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.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
PointIndexHit< point > pointIndexHit
const labelList & featureEdges() const
Return feature edge list.
label otherVertex(const label a) const
Given one vertex, return the other.
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
const Field< PointType > & localPoints() const
Return pointField of points in patch.
const fileName & name() const
Return the name of the stream.
void writeObj(const fileName &prefix) const
Write to separate OBJ files (region, external, internal edges,.
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
point centre(const pointField &) const
Return centre (centroid)
bool add(entry *, bool mergeEntry=false)
Add a new entry.
labelList selectFeatureEdges(const bool regionEdges, const bool externalEdges, const bool internalEdges) const
Helper function: select a subset of featureEdges_.
int edgeDirection(const edge &) const
Return the edge direction on the face.
List< edgeStatus > toStatus() const
From member feature edges to status per edge.
bool insert(const edge &, const T &newElmt)
Insert a new hashedEntry.
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt >> &) const
Return *this (used for point which is a typedef to Vector<scalar>.
void selectManifoldEdges(const triSurface &surf, const scalar tol, const scalar includedAngle, List< surfaceFeatures::edgeStatus > &edgeStat)
Select manifold edges.
const Point & hitPoint() const
Return hit point.
labelList trimFeatures(const scalar minLen, const label minElems, const scalar includedAngle)
Delete small sets of edges. Edges are stringed up and any.
label region() const
Return region label.
void operator=(const surfaceFeatures &)
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.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
linePointRef line(const pointField &) const
Return edge line.
dimensionedScalar cos(const dimensionedScalar &ds)
line< point, const point & > linePointRef
Line using referred points.
Mid-point interpolation (weighting factors = 0.5) scheme class.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
void clear()
Clear the list, i.e. set size to zero.
void setFromStatus(const List< edgeStatus > &edgeStat, const scalar includedAngle)
Set from status per edge.
void append(const T &)
Append an element at the end of the list.
void setCapacity(const label)
Alter the size of the underlying storage.
const triSurface & surface() const
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
bool hit() const
Is there a hit.
const Field< PointType > & points() const
Return reference to global points.
const Type & shapes() const
Reference to shape.
surfaceFeatures(const triSurface &)
Construct from surface.
const labelListList & edgeFaces() const
Return edge-face addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
List< label > labelList
A List of labels.
scalar mag(const pointField &) const
Return scalar magnitude.
Triangle with additional region number.
const Field< PointType > & faceNormals() const
Return face normals for patch.
const treeBoundBox & bb() const
Top bounding box.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
errorManip< error > abort(error &err)
const Point & rawPoint() const
Return point with no checking.
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
dimensionedScalar sin(const dimensionedScalar &ds)
vector vec(const pointField &) const
Return the vector (end - start)
label nEdges() const
Return number of edges in patch.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
const labelList & featurePoints() const
Return feature point list.
defineTypeNameAndDebug(combustionModel, 0)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
volScalarField sf(fieldObject, mesh)
scalar lineIntersect(const line< Point, PointRef > &l) const
Return the cutting point between the plane and.
Point centre() const
Return centre (centroid)
void setSize(const label)
Reset size of List.
vector point
Point is a vector.
Non-pointer based hierarchical recursive searching.
void findFeatures(const scalar includedAngle, const bool geometricTestOnly)
Find feature edges using provided included angle.
label end() const
Return end vertex label.
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.
prefixOSstream Pout(cout, "Pout")
const List< FaceType > & localFaces() const
Return patch faces addressing into local point list.
void writeDict(Ostream &) const
Write as dictionary.
void nearestFeatEdge(const edgeList &edges, const pointField &points, scalar searchSpanSqr, labelList &edgeLabel) const
Find nearest feature edge to each surface edge. Uses the.
Standard boundBox + extra functionality for use in octree.
dimensioned< scalar > mag(const dimensioned< Type > &)
label nInternalEdges() const
Return number of internal edges.
const doubleScalar e
Elementary charge.
PointHit< point > pointHit
label internalStart() const
Start of internal edges.
T & last()
Return the last element of the list.
Triangulated surface description with patch information.
label index() const
Return index.
PointHit< Point > nearestDist(const Point &p) const
Return nearest distance to line from a given point.
label start() const
Return start vertex label.
Holds feature edges/points of surface.
label nExternalEdges() const
Return number of external edges.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
A HashTable to objects of type <T> with a label key.