Go to the documentation of this file.
40 #include "triSurface.H"
90 const point& refPt =
p.refPoint();
95 const scalar perturbX = refPt.
x() + 1
e-3;
96 const scalar perturbY = refPt.
y() + 1
e-3;
97 const scalar perturbZ = refPt.
z() + 1
e-3;
99 if (
mag(planeCoeffs[2]) < SMALL)
101 if (
mag(planeCoeffs[1]) < SMALL)
107 + planeCoeffs[1]*perturbY
108 + planeCoeffs[2]*perturbZ
123 + planeCoeffs[0]*perturbX
124 + planeCoeffs[2]*perturbZ
140 + planeCoeffs[0]*perturbX
141 + planeCoeffs[1]*perturbY
185 pointCoordSys[meshPointMap[pI]] =
triad(dir1, dir2,
normal);
188 return pointCoordSys;
197 Info<<
"Calculating vertex normals" <<
endl;
224 pointNormals[pI] += weight*fN;
227 pointNormals[pI] /=
mag(pointNormals[pI]) + VSMALL;
243 Info<<
"Calculating face curvature" <<
endl;
284 const edge&
e = fEdges[feI];
286 edgeVectors[feI] =
e.vec(
points);
287 normalDifferences[feI] =
288 pointNormals[meshPointMap[
e[0]]]
289 - pointNormals[meshPointMap[
e[1]]];
293 const vector& e0 = edgeVectors[0];
295 const vector e1 = (e0 ^ eN);
297 if (
magSqr(eN) < ROOTVSMALL)
302 triad faceCoordSys(e0, e1, eN);
310 for (
label i = 0; i < 3; ++i)
312 scalar
x = edgeVectors[i] & faceCoordSys[0];
313 scalar
y = edgeVectors[i] & faceCoordSys[1];
321 scalar dndx = normalDifferences[i] & faceCoordSys[0];
322 scalar dndy = normalDifferences[i] & faceCoordSys[1];
325 Z[1] += dndx*
y + dndy*
x;
338 const label patchPointIndex = meshPointMap[
f[fpI]];
340 const triad& ptCoordSys = pointCoordSys[patchPointIndex];
342 if (!ptCoordSys.
set())
349 triad rotatedFaceCoordSys = rotTensor &
tensor(faceCoordSys);
355 ptCoordSys[0] & rotatedFaceCoordSys[0],
356 ptCoordSys[0] & rotatedFaceCoordSys[1]
360 ptCoordSys[1] & rotatedFaceCoordSys[0],
361 ptCoordSys[1] & rotatedFaceCoordSys[1]
372 projTensor.
x() & (secondFundamentalTensor & projTensor.
x()),
373 projTensor.
x() & (secondFundamentalTensor & projTensor.
y()),
374 projTensor.
y() & (secondFundamentalTensor & projTensor.
y())
382 meshPoints[patchPointIndex],
388 pointFundamentalTensors[patchPointIndex] +=
389 weight*projectedFundamentalTensor;
391 accumulatedWeights[patchPointIndex] += weight;
399 Info<<
"edgeVecs = " << edgeVectors[0] <<
" "
400 << edgeVectors[1] <<
" "
401 << edgeVectors[2] <<
endl;
402 Info<<
"normDiff = " << normalDifferences[0] <<
" "
403 << normalDifferences[1] <<
" "
404 << normalDifferences[2] <<
endl;
405 Info<<
"faceCoordSys = " << faceCoordSys <<
endl;
411 forAll(curvaturePointField, pI)
413 pointFundamentalTensors[pI] /= (accumulatedWeights[pI] + SMALL);
419 scalar curvature =
max
421 mag(principalCurvatures[0]),
422 mag(principalCurvatures[1])
426 curvaturePointField[meshPoints[pI]] = curvature;
429 return curvaturePointField;
453 const scalar defaultCellSize
456 scalar minDist = defaultCellSize;
461 hI1 < hitList.
size() - 1;
472 hI2 < hitList.
size();
482 minDist =
min(curDist, minDist);
496 const scalar defaultCellSize
499 scalar minDist = defaultCellSize;
504 hI1 < hitList.
size() - 1;
517 hI2 < hitList.
size();
533 minDist =
min(curDist, minDist);
548 Info<<
"Dumping bounding box " << bb <<
" as lines to obj file "
563 str<<
"l " <<
e[0]+1 <<
' ' <<
e[1]+1 <<
nl;
573 const bool removeInside,
596 (
p.x() <
min(a.
x(),
b.x()) ||
p.x() >
max(a.
x(),
b.x()) )
597 || (
p.y() <
min(a.
y(),
b.y()) ||
p.y() >
max(a.
y(),
b.y()) )
598 || (
p.z() <
min(a.
z(),
b.z()) ||
p.z() >
max(a.
z(),
b.z()) )
612 const plane& cutPlane,
649 Info<<
nl <<
"# findLineAll did not hit its own face."
650 <<
nl <<
"# fI " << fI
651 <<
nl <<
"# start " << start[fI]
652 <<
nl <<
"# f centre " << faceCentres[fI]
653 <<
nl <<
"# end " << end[fI]
654 <<
nl <<
"# hitInfo " << hitInfo
671 label hFI = hitInfo[hI].index();
690 const scalar includedAngle,
700 const labelList& eFaces = edgeFaces[edgeI];
702 if (eFaces.
size() > 2)
704 label i0 = eFaces[0];
712 for (
label i = 1; i < eFaces.
size(); i++)
719 if (
mag(
n&n0) < minCos)
743 const scalar includedAngle,
763 if (
mag(
n&normals[normalI]) > (1-tol))
772 bins[index].
append(eFaceI);
774 else if (normals.size() >= 2)
792 if (bins.size() == 1)
814 if (includedAngle >= 0)
824 if (
mag(ni & nj) < minCos)
852 regionAndNormal[i] = t.
region()+1;
861 regionAndNormal[i] = -(t.
region()+1);
873 label myRegionAndNormal;
876 myRegionAndNormal = t.
region()+1;
880 myRegionAndNormal = -(t.
region()+1);
883 regionAndNormal1[i] = myRegionAndNormal;
907 os <<
" points : " << fem.
points().size() <<
nl
919 <<
" external edges : "
921 <<
" internal edges : "
927 <<
" multiply connected : "
933 int main(
int argc,
char *argv[])
937 "extract and write surface features to file"
955 if (!iter().isDict())
960 const dictionary& surfaceDict = iter().dict();
962 if (!surfaceDict.
found(
"extractionMethod"))
967 const word extractionMethod = surfaceDict.
lookup(
"extractionMethod");
969 const fileName surfFileName = iter().keyword();
972 Info<<
"Surface : " << surfFileName <<
nl <<
endl;
981 const Switch featureProximity =
987 Info<<
nl <<
"Feature line extraction is only valid on closed manifold "
988 <<
"surfaces." <<
endl;
1003 faces[fI] = surf[fI].triFaceFace();
1012 scalar includedAngle = 0.0;
1014 if (extractionMethod ==
"extractFromFile")
1017 surfaceDict.
subDict(
"extractFromFileCoeffs");
1020 extractFromFileDict.
lookup(
"featureEdgeFile");
1022 const Switch geometricTestOnly =
1025 "geometricTestOnly",
1034 Info<<
nl <<
"Reading existing feature edges from file "
1035 << featureEdgeFile <<
nl
1036 <<
"Selecting edges purely based on geometric tests: "
1051 else if (extractionMethod ==
"extractFromSurface")
1054 surfaceDict.
subDict(
"extractFromSurfaceCoeffs");
1059 const Switch geometricTestOnly =
1062 "geometricTestOnly",
1067 <<
"Constructing feature set from included angle "
1068 << includedAngle <<
nl
1069 <<
"Selecting edges purely based on geometric tests: "
1087 <<
"No initial feature set. Provide either one"
1088 <<
" of extractFromFile (to read existing set)" <<
nl
1089 <<
" or extractFromSurface (to construct new set from angle)"
1097 if (surfaceDict.
isDict(
"trimFeatures"))
1107 if (minElem > 0 || minLen > 0)
1109 Info<<
"Removing features of length < "
1111 Info<<
"Removing features with number of edges < "
1114 set().trimFeatures(minLen, minElem, includedAngle);
1125 if (surfaceDict.
isDict(
"subsetFeatures"))
1132 if (subsetDict.
found(
"insideBox"))
1136 Info<<
"Removing all edges outside bb " << bb <<
endl;
1141 else if (subsetDict.
found(
"outsideBox"))
1145 Info<<
"Removing all edges inside bb " << bb <<
endl;
1151 const Switch nonManifoldEdges =
1154 if (!nonManifoldEdges)
1156 Info<<
"Removing all non-manifold edges"
1157 <<
" (edges with > 2 connected faces) unless they"
1158 <<
" cross multiple regions" <<
endl;
1168 && (eFaces.
size() % 2) == 0
1187 Info<<
"Removing all open edges"
1188 <<
" (edges with 1 connected face)" <<
endl;
1199 if (subsetDict.
found(
"plane"))
1205 Info<<
"Only edges that intersect the plane with normal "
1207 <<
" and base point " << cutPlane.
refPoint()
1208 <<
" will be included as feature edges."<<
endl;
1217 <<
"Initial feature set:" <<
nl
1220 <<
" of which" <<
nl
1243 surfBaffleRegions[pI] =
true;
1252 sFeatFileName +
".extendedFeatureEdgeMesh",
1257 if (surfaceDict.
isDict(
"addFeatures"))
1259 const word addFeName = surfaceDict.
subDict(
"addFeatures")[
"name"];
1260 Info<<
"Adding (without merging) features from " << addFeName
1269 "extendedFeatureEdgeMesh",
1278 feMesh.
add(addFeMesh);
1283 <<
"Final feature set:" <<
nl;
1286 Info<<
nl <<
"Writing extendedFeatureEdgeMesh to "
1315 Info<<
nl <<
"Writing featureEdgeMesh to "
1318 bfeMesh.regIOobject::write();
1389 Info<<
nl <<
"Extracting internal and external closeness of "
1390 <<
"surface." <<
endl;
1397 sFeatFileName +
".closeness",
1414 scalar span = searchSurf.
bounds().
mag();
1416 scalar externalAngleTolerance = 10;
1417 scalar externalToleranceCosAngle =
1420 degToRad(180 - externalAngleTolerance)
1423 scalar internalAngleTolerance = 45;
1424 scalar internalToleranceCosAngle =
1427 degToRad(180 - internalAngleTolerance)
1430 Info<<
"externalToleranceCosAngle: " << externalToleranceCosAngle
1432 <<
"internalToleranceCosAngle: " << internalToleranceCosAngle
1446 scalarField internalCloseness(start.size(), GREAT);
1447 scalarField externalCloseness(start.size(), GREAT);
1453 if (hitInfo.
size() < 1)
1461 else if (hitInfo.
size() == 1)
1463 if (!hitInfo[0].hit())
1469 else if (hitInfo[0].index() != fI)
1494 if (hitInfo[hI].index() == fI)
1518 else if (ownHitI == 0)
1527 & normals[hitInfo[ownHitI + 1].index()]
1529 < externalToleranceCosAngle
1532 externalCloseness[fI] =
1536 - hitInfo[ownHitI + 1].hitPoint()
1540 else if (ownHitI == hitInfo.
size() - 1)
1549 & normals[hitInfo[ownHitI - 1].index()]
1551 < internalToleranceCosAngle
1554 internalCloseness[fI] =
1558 - hitInfo[ownHitI - 1].hitPoint()
1568 & normals[hitInfo[ownHitI + 1].index()]
1570 < externalToleranceCosAngle
1573 externalCloseness[fI] =
1577 - hitInfo[ownHitI + 1].hitPoint()
1585 & normals[hitInfo[ownHitI - 1].index()]
1587 < internalToleranceCosAngle
1590 internalCloseness[fI] =
1594 - hitInfo[ownHitI - 1].hitPoint()
1605 sFeatFileName +
".internalCloseness",
1617 internalClosenessField.write();
1623 sFeatFileName +
".externalCloseness",
1635 externalClosenessField.write();
1645 "internalCloseness",
1657 "externalCloseness",
1668 Info<<
nl <<
"Extracting curvature of surface at the points."
1702 if (featureProximity)
1704 Info<<
nl <<
"Extracting proximity of close feature points and "
1705 <<
"edges to the surface" <<
endl;
1707 const scalar searchDistance =
1717 const scalar radiusSqr =
min
1727 featureProximity[fI] =
1732 featureProximity[fI]
1737 featureProximity[fI] =
1741 featureProximity[fI]
1749 sFeatFileName +
".featureProximity",
1761 featureProximityField.write();
void add(const extendedEdgeMesh &)
Add extendedEdgeMesh. No filtering of duplicates.
void LUsolve(scalarSquareMatrix &matrix, List< Type > &source)
Solve the matrix using LU decomposition with pivoting.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
const vector & normal() const
Return plane normal.
const boundBox & bounds() const
Return const reference to boundBox.
const labelListList & pointFaces() const
Return point-face addressing.
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
label index() const
Return index.
fileName constantPath() const
Return constant path.
scalar mag() const
The magnitude of the bounding box span.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
const Field< PointType > & points() const
Return reference to global points.
const labelListList & edgeFaces() const
Return edge-face addressing.
void writeStats(Ostream &) const
Write some statistics.
A class for handling words, derived from string.
A class for handling file names.
List< label > labelList
A List of labels.
virtual fileName write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const bool verbose=false) const
Write single surface geometry to file.
void allNearestFeatureEdges(const point &sample, const scalar searchRadiusSqr, List< pointIndexHit > &info) const
Find all the feature edges within searchDistSqr of sample.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
static void addNote(const string &)
Add extra notes for the usage information.
#define forAll(list, i)
Loop across all elements in list.
tmp< pointField > points() const
Vertex coordinates. In octant coding.
label nExternalEdges() const
Return number of external edges.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Templated 2D symmetric tensor derived from VectorSpace adding construction from 4 components,...
Tensor< scalar > tensor
Tensor of scalars.
Standard boundBox + extra functionality for use in octree.
const Time & time() const
Return time.
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.
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
Unit conversion functions.
void normalize()
Normalize each set axis vector to have a unit magnitude.
IOoject and searching on triSurface.
Ostream & endl(Ostream &os)
Add newline and flush stream.
static const edgeList edges
Edge to point addressing.
label multipleStart() const
Return the index of the start of the multiply-connected feature.
PointRef start() const
Return first vertex.
fileName lessExt() const
Return file name without extension (part before last .)
PointRef end() const
Return second vertex.
dimensioned< scalar > mag(const dimensioned< Type > &)
const geometricSurfacePatchList & patches() const
bool isDict(const word &) const
Check if entry is a sub-dictionary.
word name() const
Return file name (part beyond last /)
void writeVTK(OFstream &os, const Type &value)
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Templated 2D tensor derived from VectorSpace adding construction from 4 components,...
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
fileName objectPath() const
Return complete path + object name.
label end() const
Return end vertex label.
const word dictName("particleTrackDict")
A triangle primitive used to calculate face normals and swept volumes.
const labelList & featurePoints() const
Return feature point list.
label nonFeatureStart() const
Return the index of the start of the non-feature points.
label concaveStart() const
Return the index of the start of the concave feature points.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Pre-declare SubField and related Field type.
static const SymmTensor2D zero
Triangulated surface description with patch information.
dimensionedVector eigenValues(const dimensionedTensor &dt)
const Point & hitPoint() const
Return hit point.
Vector2D< Cmpt > x() const
const pointField & points() const
Return points.
void set(T *)
Set pointer to that given.
Holds feature edges/points of surface.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const word & name() const
Return name.
Vector2D< Cmpt > y() const
const labelList & featureEdges() const
Return feature edge list.
double elapsedCpuTime() const
Return CPU time (in seconds) from the start.
Raster intersect(const Raster &rast1, const Raster &rast2)
const edgeList & edges() const
Return edges.
label nPoints() const
Return number of points supporting patch faces.
A list of keyword definitions, which are a keyword followed by any number of values (e....
scalar lineIntersect(const line< Point, PointRef > &l) const
Return the cutting point between the plane and.
label nInternalEdges() const
Return number of internal edges.
label internalStart() const
Return the index of the start of the internal feature edges.
scalar circumRadius() const
Return circum-radius.
void writeObj(Ostream &os, const pointField &points)
const char * asText() const
Return a text representation of the Switch.
errorManip< error > abort(error &err)
const double e
Elementary charge.
label mixedStart() const
Return the index of the start of the mixed type feature points.
A templated 2D square symmetric matrix of objects of <T>, where the n x n matrix dimension is known a...
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)
Representation of a 3D Cartesian coordinate system as a Vector of vectors.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
label openStart() const
Return the index of the start of the open feature edges.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
virtual void findLineAll(const pointField &start, const pointField &end, List< List< pointIndexHit > > &) const
Get all intersections in order from start to end.
bool contains(const vector &dir, const point &) const
Contains point (inside or on edge) and moving in direction.
label start() const
Return start vertex label.
A triangular face using a FixedList of labels corresponding to mesh vertices.
label region() const
Return region label.
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
const Field< PointType > & faceNormals() const
Return face normals for patch.
Point circumCentre() const
Return circum-centre.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
const word & constant() const
Return constant name.
A 1D vector of objects of type <T> with a fixed size <Size>.
const Field< PointType > & faceCentres() const
Return face centres for patch.
TIME_T elapsedClockTime() const
Returns wall-clock time from clock instantiation.
label k
Boltzmann constant.
const point & refPoint() const
Return or return plane base point.
Triangle with additional region number.
label nRegionEdges() const
Return number of region edges.
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
int edgeDirection(const edge &) const
Return the edge direction on the face.
A surfaceWriter for VTK legacy format.
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,...
tensor rotationTensor(const vector &n1, const vector &n2)
vector point
Point is a vector.
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
static void noParallel()
Remove the parallel options.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
void writeObj(const fileName &prefix) const
Write all components of the extendedEdgeMesh as obj files.
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
void allNearestFeaturePoints(const point &sample, scalar searchRadiusSqr, List< pointIndexHit > &info) const
Find all the feature points within searchDistSqr of sample.
fileName path() const
Return complete path.
virtual bool write() const
Give precedence to the regIOobject write.
Points connected by edges.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
IOobject dictIO(dictName, runTime.constant(), mesh, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE)
word name(const complex &)
Return a string representation of a complex.
label flatStart() const
Return the index of the start of the flat feature edges.
A normal distribution model.
bool set(const direction d) const
Is the vector in the direction d set.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
T lookupOrAddDefault(const word &, const T &, bool recursive=false, bool patternMatch=true)
Find and return a T, if not found return the given.
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
dimensionedScalar cos(const dimensionedScalar &ds)