Go to the documentation of this file.
68 scalar calcVertexNormalWeight
76 label index =
f.find(pI);
96 auto& pointNormals = tpointNormals.ref();
108 const label faceI =
pFaces[fI];
113 scalar weight = calcVertexNormalWeight
121 pointNormals[pI] += weight * areaNorm;
124 pointNormals[pI].normalise();
127 return tpointNormals;
134 const bitSet& isFeaturePoint,
152 const edge&
e =
s.edges()[edgeI];
155 if (!isFeaturePoint.
test(
e[i]))
157 pointNormals[
e[i]] =
Zero;
167 const labelList& eFaces = edgeFaces[edgeI];
171 for (
const label facei : eFaces)
173 n +=
s.faceNormals()[facei];
179 const edge&
e =
s.edges()[edgeI];
182 if (!isFeaturePoint.
test(
e[i]))
184 pointNormals[
e[i]] +=
n;
193 if (nNormals[pointI] > 0)
195 pointNormals[pointI].normalise();
201 forAll(pointNormals, pointI)
203 if (
mag(
mag(pointNormals[pointI])-1) > SMALL)
211 return tpointNormals;
215 void detectSelfIntersections
218 bitSet& isEdgeIntersecting
226 isEdgeIntersecting.
setSize(edges.size());
227 isEdgeIntersecting =
false;
231 const edge&
e = edges[edgeI];
245 isEdgeIntersecting.
set(edgeI);
251 label detectIntersectionPoints
253 const scalar tolerance,
256 const scalar extendFactor,
260 const bool checkSelfIntersect,
261 const bitSet& initialIsEdgeIntersecting,
267 const pointField initialLocalPoints(initialPoints,
s.meshPoints());
272 isPointOnHitEdge.
setSize(
s.nPoints());
273 isPointOnHitEdge =
false;
278 scalar tol =
max(tolerance, 10*
s.tolerance());
284 pointField start(initialLocalPoints+tol*displacement);
285 pointField end(initialLocalPoints+extendFactor*displacement);
288 s.findLineAny(start,
end, hits);
295 && !localFaces[hits[pointI].index()].
found(pointI)
298 scale[pointI] =
max(0.0, scale[pointI]-0.2);
300 isPointOnHitEdge.
set(pointI);
308 if (checkSelfIntersect)
310 bitSet isEdgeIntersecting;
311 detectSelfIntersections(
s, isEdgeIntersecting);
318 const edge&
e = edges[edgeI];
320 if (isEdgeIntersecting[edgeI] && !initialIsEdgeIntersecting[edgeI])
322 if (isPointOnHitEdge.
set(
e[0]))
324 label start =
s.meshPoints()[
e[0]];
327 Pout<<
"Additional self intersection at "
331 scale[
e[0]] =
max(0.0, scale[
e[0]]-0.2);
334 if (isPointOnHitEdge.
set(
e[1]))
336 label
end =
s.meshPoints()[
e[1]];
339 Pout<<
"Additional self intersection at "
343 scale[
e[1]] =
max(0.0, scale[
e[1]]-0.2);
370 const edge&
e = edges[edgeI];
371 const scalar w = edgeWeights[edgeI];
373 res[
e[0]] += w*
fld[
e[1]];
374 sumWeight[
e[0]] += w;
376 res[
e[1]] += w*
fld[
e[0]];
377 sumWeight[
e[1]] += w;
385 if (
mag(sumWeight[pointI]) < VSMALL)
388 res[pointI] =
fld[pointI];
392 res[pointI] /= sumWeight[pointI];
403 const bitSet& isAffectedPoint,
416 const edge&
e = edges[edgeI];
419 edgeWeights[edgeI] = 1.0/(
max(w, SMALL));
428 if (isAffectedPoint.
test(pointI))
433 0.5*
fld[pointI] + 0.5*avgFld[pointI]
445 const bitSet& isFeaturePoint,
447 const bitSet& isAffectedPoint
454 bitSet isSmoothPoint(isAffectedPoint);
457 bitSet newIsSmoothPoint(isSmoothPoint);
460 const edge&
e = edges[edgeI];
461 if (isSmoothPoint.test(
e[0]))
463 newIsSmoothPoint.
set(
e[1]);
465 if (isSmoothPoint.test(
e[1]))
467 newIsSmoothPoint.set(
e[0]);
470 Info<<
"From points-to-smooth " << isSmoothPoint.count()
471 <<
" to " << newIsSmoothPoint.count()
473 isSmoothPoint.transfer(newIsSmoothPoint);
477 for (label i = 0; i < nSmooth; i++)
483 forAll(isSmoothPoint, pointI)
485 if (isSmoothPoint[pointI] && !isFeaturePoint[pointI])
492 avg += faceCentres[
pFaces[pFaceI]];
495 newPoints[meshPoints[pointI]] = avg;
511 const edge&
e = edges[edgeI];
515 pointSum[
e[0]] += eMid;
517 pointSum[
e[1]] += eMid;
526 isSmoothPoint[pointI]
527 && isFeaturePoint[pointI]
528 && nPointSum[pointI] >= 2
531 newPoints[meshPoints[pointI]] =
532 pointSum[pointI]/nPointSum[pointI];
537 s.movePoints(newPoints);
542 bitSet newIsSmoothPoint(isSmoothPoint);
545 const edge&
e = edges[edgeI];
546 if (isSmoothPoint[
e[0]])
548 newIsSmoothPoint.
set(
e[1]);
550 if (isSmoothPoint[
e[1]])
552 newIsSmoothPoint.set(
e[0]);
555 Info<<
"From points-to-smooth " << isSmoothPoint.count()
556 <<
" to " << newIsSmoothPoint.count()
558 isSmoothPoint.transfer(newIsSmoothPoint);
567 int main(
int argc,
char *argv[])
571 "Inflates surface according to point normals."
577 "Creates inflated version of surface using point normals. "
578 "Takes surface, distance to inflate and additional safety factor"
582 "checkSelfIntersection",
583 "Also check for self-intersection"
589 "Number of smoothing iterations (default 20)"
600 "Switch on additional debug information"
614 const auto extendFactor =
args.
get<scalar>(3);
615 const bool checkSelfIntersect =
args.
found(
"checkSelfIntersection");
621 Info<<
"Inflating surface " << inputName
622 <<
" according to point normals" <<
nl
624 <<
" safety factor : " << extendFactor <<
nl
625 <<
" self intersection test : " << checkSelfIntersect <<
nl
626 <<
" smoothing iterations : " << nSmooth <<
nl
627 <<
" feature angle : " << featureAngle <<
nl
631 if (extendFactor < 1 || extendFactor > 10)
634 <<
"Illegal safety factor " << extendFactor
635 <<
". It is usually 1..2"
658 Info<<
"Detected features:" <<
nl
659 <<
" feature points : " << features.featurePoints().size()
660 <<
" out of " <<
s.nPoints() <<
nl
661 <<
" feature edges : " << features.featureEdges().size()
662 <<
" out of " <<
s.nEdges() <<
nl
665 bitSet isFeaturePoint(
s.nPoints(), features.featurePoints());
674 Info<<
"Constructing field scale\n" <<
endl;
692 Info<<
"Calculating vertex normals\n" <<
endl;
705 Info<<
"Constructing field pointDisplacement\n" <<
endl;
726 bitSet isScaledPoint(
s.nPoints());
730 bitSet initialIsEdgeIntersecting;
731 if (checkSelfIntersect)
733 detectSelfIntersections(
s, initialIsEdgeIntersecting);
739 initialIsEdgeIntersecting.
setSize(
s.nEdges(),
true);
752 newPoints[meshPoints[i]] += pointDisplacement[i];
754 s.movePoints(newPoints);
755 Info<<
"Bounding box : " <<
s.bounds() <<
endl;
761 if (
s.pointFaces()[pointI].size())
763 scale[pointI] =
mag(pointDisplacement[pointI])/
distance;
779 label nIntersections = detectIntersectionPoints
788 initialIsEdgeIntersecting,
793 Info<<
"Detected " << nIntersections <<
" intersections" <<
nl
796 if (nIntersections == 0)
804 forAll(isAffectedPoint, pointI)
806 if (isAffectedPoint.
test(pointI))
808 isScaledPoint.set(pointI);
814 for (label i = 0; i < nSmooth; i++)
817 oldScale.rename(
"oldScale");
829 pointDisplacement *=
distance*scale/
mag(pointDisplacement);
833 lloydsSmoothing(nSmooth,
s, isFeaturePoint, edgeStat, isAffectedPoint);
840 label meshPointI = meshPoints[i];
841 pointDisplacement[i] = pts[meshPointI]-initialPoints[meshPointI];
852 Info<<
"Detected overall intersecting points " << isScaledPoint.count()
853 <<
" out of " <<
s.nPoints() <<
nl <<
endl;
859 forAll(isScaledPoint, pointI)
861 if (isScaledPoint[pointI])
863 str.write(initialPoints[meshPoints[pointI]]);
const Field< point_type > & points() const noexcept
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
const dimensionedScalar mp
const labelListList & pointFaces() const
A class for handling words, derived from Foam::string.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.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))
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
OFstream that keeps track of vertices.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
T getOrDefault(const word &optName, const T &deflt) const
A class for managing temporary objects.
static constexpr const zero Zero
Type gAverage(const FieldField< Field, Type > &f)
static word timeName(const scalar t, const int precision=precision_)
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
static void addNote(const string ¬e)
void set(const bitSet &bitset)
IOoject and searching on triSurface.
Ostream & endl(Ostream &os)
Vector< Cmpt > & normalise()
bool test(const label pos) const
T get(const label index) const
label min(const labelHashSet &set, label minValue=labelMax)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
static void addArgument(const string &argName, const string &usage="")
Ostream & printExecutionTime(OSstream &os) const
static void noFunctionObjects(bool addWithOption=false)
@ NONE
Not a classified feature edge.
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Generic templated field type.
virtual bool write(const bool valid=true) const
Triangulated surface description with patch information.
Holds feature edges/points of surface.
Non-pointer based hierarchical recursive searching.
label max(const labelHashSet &set, label maxValue=labelMin)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
void setSize(const label n, unsigned int val=0u)
Generic dimensioned Type class.
constexpr auto end(C &c) -> decltype(c.end())
errorManip< error > abort(error &err)
scalar distance(const vector &p1, const vector &p2)
errorManipArg< error, int > exit(error &err, const int errNo=1)
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
#define FatalErrorInFunction
A triangular face using a FixedList of labels corresponding to mesh vertices.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
const dimensionedScalar e
static tmp< T > New(Args &&... args)
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
const labelList & meshPoints() const
const word & constant() const
static void addOption(const word &optName, const string ¶m="", const string &usage="", bool advanced=false)
Foam::argList args(argc, argv)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::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].reset(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]
bool found(const word &optName) const