Go to the documentation of this file.
27 #include "triSurface.H"
124 const scalar includedAngle
135 if (edgeStat[edgeI] == REGION)
139 else if (edgeStat[edgeI] == EXTERNAL)
143 else if (edgeStat[edgeI] == INTERNAL)
149 externalStart_ = nRegion;
150 internalStart_ = externalStart_ + nExternal;
155 featureEdges_.setSize(internalStart_ + nInternal);
158 label externalI = externalStart_;
159 label internalI = internalStart_;
163 if (edgeStat[edgeI] == REGION)
165 featureEdges_[regionI++] = edgeI;
167 else if (edgeStat[edgeI] == EXTERNAL)
169 featureEdges_[externalI++] = edgeI;
171 else if (edgeStat[edgeI] == INTERNAL)
173 featureEdges_[internalI++] = edgeI;
179 calcFeatPoints(edgeStat, minCos);
193 const edgeList& edges = surf_.edges();
194 const pointField& localPoints = surf_.localPoints();
196 forAll(pointEdges, pointI)
198 const labelList& pEdges = pointEdges[pointI];
200 label nFeatEdges = 0;
204 if (edgeStat[pEdges[i]] != NONE)
212 featurePoints.
append(pointI);
214 else if (nFeatEdges == 2)
221 const label edgeI = pEdges[i];
223 if (edgeStat[edgeI] != NONE)
225 edgeVecs.
append(edges[edgeI].vec(localPoints));
226 edgeVecs.last() /=
mag(edgeVecs.last());
230 if (
mag(edgeVecs[0] & edgeVecs[1]) < minCos)
232 featurePoints.
append(pointI);
237 featurePoints_.transfer(featurePoints);
246 const bool geometricTestOnly
249 const vectorField& faceNormals = surf_.faceNormals();
253 bool selectAll = (
mag(minCos-1.0) < SMALL);
257 const labelList& eFaces = edgeFaces[edgeI];
259 if (eFaces.
size() != 2)
262 edgeStat[edgeI] = REGION;
266 label face0 = eFaces[0];
267 label face1 = eFaces[1];
272 && surf_[face0].region() != surf_[face1].region()
275 edgeStat[edgeI] = REGION;
280 || ((faceNormals[face0] & faceNormals[face1]) < minCos)
289 if ((f0Tof1 & faceNormals[face0]) >= 0.0)
291 edgeStat[edgeI] = INTERNAL;
295 edgeStat[edgeI] = EXTERNAL;
308 const label unsetVal,
309 const label prevEdgeI,
313 const labelList& pEdges = surf_.pointEdges()[vertI];
315 label nextEdgeI = -1;
319 label edgeI = pEdges[i];
324 && edgeStat[edgeI] != NONE
325 && featVisited[edgeI] == unsetVal
356 const label startEdgeI,
357 const label startPointI,
358 const label currentFeatI,
362 label edgeI = startEdgeI;
364 label vertI = startPointI;
366 scalar visitedLength = 0.0;
370 if (
findIndex(featurePoints_, startPointI) >= 0)
394 unsetVal = currentFeatI;
400 edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
402 if (edgeI == -1 || edgeI == startEdgeI)
411 featVisited[edgeI] = currentFeatI;
415 featVisited[edgeI] = -2;
420 const edge&
e = surf_.edges()[edgeI];
422 vertI =
e.otherVertex(vertI);
426 visitedLength +=
e.mag(surf_.localPoints());
430 if (nVisited > surf_.nEdges())
432 Warning<<
"walkSegment : reached iteration limit in walking "
433 <<
"feature edges on surface from edge:" << startEdgeI
434 <<
" vertex:" << startPointI <<
nl
435 <<
"Returning with large length" <<
endl;
464 const label externalStart,
465 const label internalStart
469 featurePoints_(featurePoints),
470 featureEdges_(featureEdges),
471 externalStart_(externalStart),
472 internalStart_(externalStart)
480 const scalar includedAngle,
482 const label minElems,
483 const bool geometricTestOnly
492 findFeatures(includedAngle, geometricTestOnly);
494 if (minLen > 0 || minElems > 0)
496 trimFeatures(minLen, minElems, includedAngle);
509 featurePoints_(featInfoDict.
lookup(
"featurePoints")),
510 featureEdges_(featInfoDict.
lookup(
"featureEdges")),
545 const scalar mergeTol,
546 const bool geometricTestOnly
558 const edgeList& surfEdges = surf_.edges();
560 scalar mergeTolSqr =
sqr(mergeTol);
578 const label sEdge = edgeLabel[sEdgeI];
585 dynFeatEdges.
insert(surfEdges[sEdge], count++);
586 dynFeatureEdgeFaces.
append(surfEdgeFaces[sEdge]);
592 classifyFeatureAngles
608 if (iter != dynFeatEdges.end())
610 allEdgeStat[eI] = edgeStat[iter()];
615 dynFeatEdges.
clear();
617 setFromStatus(allEdgeStat, GREAT);
625 featurePoints_(
sf.featurePoints()),
626 featureEdges_(
sf.featureEdges()),
627 externalStart_(
sf.externalStart()),
628 internalStart_(
sf.internalStart())
636 const bool regionEdges,
637 const bool externalEdges,
638 const bool internalEdges
645 selectedEdges.
setCapacity(selectedEdges.size() + nRegionEdges());
647 for (
label i = 0; i < externalStart_; i++)
649 selectedEdges.
append(featureEdges_[i]);
655 selectedEdges.
setCapacity(selectedEdges.size() + nExternalEdges());
657 for (
label i = externalStart_; i < internalStart_; i++)
659 selectedEdges.
append(featureEdges_[i]);
665 selectedEdges.
setCapacity(selectedEdges.size() + nInternalEdges());
667 for (
label i = internalStart_; i < featureEdges_.size(); i++)
669 selectedEdges.
append(featureEdges_[i]);
673 return selectedEdges.
shrink();
679 const scalar includedAngle,
680 const bool geometricTestOnly
688 classifyFeatureAngles
696 setFromStatus(edgeStat, includedAngle);
705 const label minElems,
706 const scalar includedAngle
723 label startEdgeI = 0;
728 for (; startEdgeI < edgeStat.
size(); startEdgeI++)
732 edgeStat[startEdgeI] != NONE
733 && featLines[startEdgeI] == -1
741 if (startEdgeI == edgeStat.
size())
748 featLines[startEdgeI] = featI;
750 const edge& startEdge = surf_.edges()[startEdgeI];
780 + startEdge.
mag(surf_.localPoints())
783 || (leftPath.
n_ + rightPath.
n_ + 1 < minElems)
789 featLines[startEdgeI] = -2;
821 label edgeI = featureEdges_[i];
823 if (featLines[edgeI] == -2)
825 edgeStat[edgeI] = NONE;
830 setFromStatus(edgeStat, includedAngle);
840 featInfoDict.
add(
"externalStart", externalStart_);
841 featInfoDict.
add(
"internalStart", internalStart_);
842 featInfoDict.
add(
"featureEdges", featureEdges_);
843 featInfoDict.
add(
"featurePoints", featurePoints_);
845 featInfoDict.
write(writeFile);
859 OFstream regionStr(prefix +
"_regionEdges.obj");
860 Pout<<
"Writing region edges to " << regionStr.
name() <<
endl;
863 for (
label i = 0; i < externalStart_; i++)
865 const edge&
e = surf_.edges()[featureEdges_[i]];
869 regionStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
873 OFstream externalStr(prefix +
"_externalEdges.obj");
874 Pout<<
"Writing external edges to " << externalStr.
name() <<
endl;
877 for (
label i = externalStart_; i < internalStart_; i++)
879 const edge&
e = surf_.edges()[featureEdges_[i]];
883 externalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
886 OFstream internalStr(prefix +
"_internalEdges.obj");
887 Pout<<
"Writing internal edges to " << internalStr.
name() <<
endl;
890 for (
label i = internalStart_; i < featureEdges_.size(); i++)
892 const edge&
e = surf_.edges()[featureEdges_[i]];
896 internalStr <<
"l " << verti-1 <<
' ' << verti <<
endl;
899 OFstream pointStr(prefix +
"_points.obj");
900 Pout<<
"Writing feature points to " << pointStr.
name() <<
endl;
904 label pointI = featurePoints_[i];
936 const pointField& surfPoints = surf_.localPoints();
942 const point& surfPt = surfPoints[surfPointI];
953 <<
"Problem for point "
954 << surfPointI <<
" in tree " << ppTree.
bb()
962 nearest.insert(sampleI, surfPointI);
974 <<
"Dumping nearest surface feature points to nearestSamples.obj"
976 <<
"View this Lightwave-OBJ file with e.g. javaview" <<
endl
979 OFstream objStream(
"nearestSamples.obj");
986 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1002 const scalar minSampleDist
1005 const pointField& surfPoints = surf_.localPoints();
1006 const edgeList& surfEdges = surf_.edges();
1008 scalar maxSearchSqr =
max(maxDistSqr);
1027 label surfEdgeI = selectedEdges[i];
1029 const edge&
e = surfEdges[surfEdgeI];
1031 if (debug && (i % 1000) == 0)
1033 Pout<<
"looking at surface feature edge " << surfEdgeI
1034 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1035 <<
' ' << surfPoints[
e[1]] <<
endl;
1039 vector eVec =
e.vec(surfPoints);
1040 scalar eMag =
mag(eVec);
1055 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1073 nearest.insert(sampleI, surfEdgeI);
1083 s +=
max(minSampleDist*eMag, sampleDist[sampleI]);
1085 if (
s >= (1-minSampleDist)*eMag)
1100 Pout<<
"Dumping nearest surface edges to nearestEdges.obj\n"
1101 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1103 OFstream objStream(
"nearestEdges.obj");
1108 const label sampleI = iter.key();
1112 const edge&
e = surfEdges[iter()];
1115 e.line(surfPoints).nearestDist(
samples[sampleI]).rawPoint();
1119 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1140 const scalar minSampleDist
1159 const pointField& surfPoints = surf_.localPoints();
1160 const edgeList& surfEdges = surf_.edges();
1162 scalar maxSearchSqr =
max(maxDistSqr);
1173 label surfEdgeI = selectedEdges[i];
1175 const edge&
e = surfEdges[surfEdgeI];
1177 if (debug && (i % 1000) == 0)
1179 Pout<<
"looking at surface feature edge " << surfEdgeI
1180 <<
" verts:" <<
e <<
" points:" << surfPoints[
e[0]]
1181 <<
' ' << surfPoints[
e[1]] <<
endl;
1185 vector eVec =
e.vec(surfPoints);
1186 scalar eMag =
mag(eVec);
1201 point edgePoint(surfPoints[
e.start()] +
s*eVec);
1217 label sampleEdgeI = ppTree.
shapes().edgeLabels()[index];
1219 const edge&
e = sampleEdges[sampleEdgeI];
1240 if (
s >= (1-minSampleDist)*eMag)
1254 Pout<<
"Dumping nearest surface feature edges to nearestEdges.obj\n"
1255 <<
"View this Lightwave-OBJ file with e.g. javaview\n" <<
endl;
1257 OFstream objStream(
"nearestEdges.obj");
1262 const label sampleEdgeI = iter.key();
1264 const edge& sampleEdge = sampleEdges[sampleEdgeI];
1273 objStream<<
"l " << vertI-1 <<
' ' << vertI <<
endl;
1287 scalar searchSpanSqr,
1295 edgePoint.setSize(
samples.size());
1297 const pointField& localPoints = surf_.localPoints();
1333 edgeLabel[i] = selectedEdges[info.
index()];
1336 const edge&
e = surf_.edges()[edgeLabel[i]];
1340 localPoints[
e.start()],
1341 localPoints[
e.end()],
1346 edgeEndPoint[i] = pHit.
index();
1361 const vector& searchSpan,
1368 pointOnEdge.setSize(selectedSampleEdges.
size());
1369 pointOnFeature.setSize(selectedSampleEdges.
size());
1379 surf_.localPoints(),
1388 forAll(selectedSampleEdges, i)
1390 const edge&
e = sampleEdges[selectedSampleEdges[i]];
1396 treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1411 edgeLabel[i] = selectedEdges[info.
index()];
1413 pointOnFeature[i] = info.
hitPoint();
1423 scalar searchSpanSqr,
1427 edgeLabel =
labelList(surf_.nEdges(), -1);
1447 const edgeList& surfEdges = surf_.edges();
1448 const pointField& surfLocalPoints = surf_.localPoints();
1452 const edge& sample = surfEdges[edgeI];
1454 const point& startPoint = surfLocalPoints[sample.
start()];
1467 const edge& featEdge = edges[infoMid.
index()];
1471 if (
mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
1473 edgeLabel[edgeI] = edgeI;
1488 <<
"Attempted assignment to self"
1495 <<
"Operating on different surfaces"
Point centre() const
Return centre (centroid)
static pointIndexHit edgeNearest(const point &start, const point &end, const point &sample)
Return nearest point on edge (start..end). Also classify nearest:
const triSurface & surf_
Reference to surface.
label internalStart() const
Start of internal edges.
void writeDict(Ostream &) const
Write as dictionary.
label index() const
Return index.
static const scalar parallelTolerance
Tolerance for determining whether two vectors are parallel.
void nearestFeatEdge(const edgeList &edges, const pointField &points, scalar searchSpanSqr, labelList &edgeLabel) const
Find nearest feature edge to each surface edge. Uses the.
label externalStart_
Start of external edges in featureEdges_.
bool hit() const
Is there a hit.
Map< label > nearestSamples(const labelList &selectedPoints, const pointField &samples, const scalarField &maxDistSqr) const
Find nearest sample for selected surface points.
A class for handling file names.
labelList selectFeatureEdges(const bool regionEdges, const bool externalEdges, const bool internalEdges) const
Helper function: select a subset of featureEdges_.
List< label > labelList
A List of labels.
List< edgeStatus > toStatus() const
From member feature edges to status per edge.
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.
#define forAll(list, i)
Loop across all elements in list.
This class describes the interaction of a face and a point. It carries the info of a successful hit a...
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
scalar mag(const pointField &) const
Return scalar magnitude.
vector vec(const pointField &) const
Return the vector (end - start)
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
dimensionedScalar sin(const dimensionedScalar &ds)
const Point & rawPoint() const
Return point with no checking.
label nEdges() const
Return number of edges in patch.
Standard boundBox + extra functionality for use in octree.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
bool hit() const
Is there a hit.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
A HashTable to objects of type <T> with a label key.
Unit conversion functions.
Mid-point interpolation (weighting factors = 0.5) scheme class.
const Type & shapes() const
Reference to shape.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< scalar > mag(const dimensioned< Type > &)
point centre(const pointField &) const
Return centre (centroid)
void calcFeatPoints(const List< edgeStatus > &edgeStat, const scalar minCos)
Construct feature points where more than 2 feature edges meet.
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
labelList featureEdges_
Labels of edges that are features.
const labelList & featurePoints() const
Return feature point list.
surfaceFeatures(const triSurface &)
Construct from surface.
scalarField samples(nIntervals, 0)
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
const Point & rawPoint() const
Return point with no checking.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Pre-declare SubField and related Field type.
Triangulated surface description with patch information.
const Point & hitPoint() const
Return hit point.
void setCapacity(const label)
Alter the size of the underlying storage.
Holds feature edges/points of surface.
Non-pointer based hierarchical recursive searching.
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt > > &) const
Return *this (used for point which is a typedef to Vector<scalar>.
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.
Holds data for octree to work on an edges subset.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
const labelList & featureEdges() const
Return feature edge list.
label nextFeatEdge(const List< edgeStatus > &edgeStat, const labelList &featVisited, const label unsetVal, const label prevEdgeI, const label vertI) const
Choose next unset feature edge.
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
void operator=(const surfaceFeatures &)
A list of keyword definitions, which are a keyword followed by any number of values (e....
label size() const
Return number of elements in table.
labelScalar walkSegment(const bool mark, const List< edgeStatus > &edgeStat, const label startEdgeI, const label startPointI, const label currentFeatI, labelList &featVisited)
Walk connected feature edges. Marks edges in featVisited.
void writeObj(const fileName &prefix) const
Write to separate OBJ files (region, external, internal edges,.
errorManip< error > abort(error &err)
volScalarField sf(fieldObject, mesh)
const double e
Elementary charge.
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))
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
void setFromStatus(const List< edgeStatus > &edgeStat, const scalar includedAngle)
Set from status per edge.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
errorManipArg< error, int > exit(error &err, const int errNo=1)
labelList trimFeatures(const scalar minLen, const label minElems, const scalar includedAngle)
Delete small sets of edges. Edges are stringed up and any.
const treeBoundBox & bb() const
Top bounding box.
const triSurface & surface() const
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
void setSize(const label)
Reset size of List.
line< point, const point & > linePointRef
Line using referred points.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
PointIndexHit< point > pointIndexHit
label start() const
Return start vertex label.
prefixOSstream Pout(cout, "Pout")
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 clear()
Clear the list, i.e. set size to zero.
label readLabel(Istream &is)
Label and scalar; used in path walking.
label internalStart_
Start of internal edges in featureEdges_.
void findNearest(const label nodeI, const linePointRef &ln, treeBoundBox &tightest, label &nearestShapeI, point &linePoint, point &nearestPoint, const FindNearestOp &fnOp) const
Find nearest point to line.
void write(const fileName &fName) const
Write as dictionary to file.
const fileName & name() const
Return the name of the stream.
void size(const label)
Override size to be inconsistent with allocated storage.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
void classifyFeatureAngles(const labelListList &edgeFaces, List< edgeStatus > &edgeStat, const scalar minCos, const bool geometricTestOnly) const
Classify the angles of the feature edges.
void findFeatures(const scalar includedAngle, const bool geometricTestOnly)
Find feature edges using provided included angle.
defineTypeNameAndDebug(combustionModel, 0)
labelList pointLabels(nPoints, -1)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
bool add(entry *, bool mergeEntry=false)
Add a new entry.
void write(Ostream &, const bool subDict=true) const
Write dictionary, normally with sub-dictionary formatting.
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
dimensionedScalar cos(const dimensionedScalar &ds)
label externalStart() const
Start of external edges.