Go to the documentation of this file.
118 pointNormals[pI] += weight*fN;
121 pointNormals[pI] /=
mag(pointNormals[pI]) + VSMALL;
124 return tpointNormals;
149 const edge&
e =
s.edges()[edgeI];
152 if (!isFeaturePoint[
e[i]])
164 const labelList& eFaces = edgeFaces[edgeI];
170 n +=
s.faceNormals()[eFaces[i]];
176 const edge&
e =
s.edges()[edgeI];
179 if (!isFeaturePoint[
e[i]])
181 pointNormals[
e[i]] +=
n;
190 if (nNormals[pointI] > 0)
192 pointNormals[pointI] /=
mag(pointNormals[pointI]);
198 forAll(pointNormals, pointI)
200 if (
mag(
mag(pointNormals[pointI])-1) > SMALL)
208 return tpointNormals;
212 void detectSelfIntersections
224 isEdgeIntersecting =
false;
228 const edge&
e = edges[edgeI];
242 isEdgeIntersecting[edgeI] =
true;
248 label detectIntersectionPoints
250 const scalar tolerance,
253 const scalar extendFactor,
257 const bool checkSelfIntersect,
264 const pointField initialLocalPoints(initialPoints,
s.meshPoints());
269 isPointOnHitEdge.
setSize(
s.nPoints());
270 isPointOnHitEdge =
false;
275 scalar tol =
max(tolerance, 10*
s.tolerance());
281 pointField start(initialLocalPoints+tol*displacement);
282 pointField end(initialLocalPoints+extendFactor*displacement);
285 s.findLineAny(start, end, hits);
292 &&
findIndex(localFaces[hits[pointI].index()], pointI) == -1
295 scale[pointI] =
max(0.0, scale[pointI]-0.2);
297 isPointOnHitEdge[pointI] =
true;
305 if (checkSelfIntersect)
308 detectSelfIntersections(
s, isEdgeIntersecting);
315 const edge&
e = edges[edgeI];
317 if (isEdgeIntersecting[edgeI] && !initialIsEdgeIntersecting[edgeI])
319 if (isPointOnHitEdge.
set(
e[0]))
321 label start =
s.meshPoints()[
e[0]];
324 Pout<<
"Additional self intersection at "
328 scale[
e[0]] =
max(0.0, scale[
e[0]]-0.2);
331 if (isPointOnHitEdge.
set(
e[1]))
333 label end =
s.meshPoints()[
e[1]];
336 Pout<<
"Additional self intersection at "
340 scale[
e[1]] =
max(0.0, scale[
e[1]]-0.2);
367 const edge&
e = edges[edgeI];
368 const scalar
w = edgeWeights[edgeI];
371 sumWeight[
e[0]] +=
w;
374 sumWeight[
e[1]] +=
w;
382 if (
mag(sumWeight[pointI]) < VSMALL)
385 res[pointI] =
fld[pointI];
389 res[pointI] /= sumWeight[pointI];
413 const edge&
e = edges[edgeI];
416 edgeWeights[edgeI] = 1.0/(
max(
w, SMALL));
425 if (isAffectedPoint.
get(pointI) == 1)
430 0.5*
fld[pointI] + 0.5*avgFld[pointI]
457 const edge&
e = edges[edgeI];
458 if (isSmoothPoint[
e[0]])
460 newIsSmoothPoint[
e[1]] =
true;
462 if (isSmoothPoint[
e[1]])
464 newIsSmoothPoint[
e[0]] =
true;
467 Info<<
"From points-to-smooth " << isSmoothPoint.count()
468 <<
" to " << newIsSmoothPoint.count()
470 isSmoothPoint.transfer(newIsSmoothPoint);
474 for (
label i = 0; i < nSmooth; i++)
480 forAll(isSmoothPoint, pointI)
482 if (isSmoothPoint[pointI] && !isFeaturePoint[pointI])
489 avg += faceCentres[
pFaces[pFaceI]];
492 newPoints[meshPoints[pointI]] = avg;
508 const edge&
e = edges[edgeI];
511 point eMid = 0.5*(start+end);
512 pointSum[
e[0]] += eMid;
514 pointSum[
e[1]] += eMid;
523 isSmoothPoint[pointI]
524 && isFeaturePoint[pointI]
525 && nPointSum[pointI] >= 2
528 newPoints[meshPoints[pointI]] =
529 pointSum[pointI]/nPointSum[pointI];
534 s.movePoints(newPoints);
542 const edge&
e = edges[edgeI];
543 if (isSmoothPoint[
e[0]])
545 newIsSmoothPoint[
e[1]] =
true;
547 if (isSmoothPoint[
e[1]])
549 newIsSmoothPoint[
e[0]] =
true;
552 Info<<
"From points-to-smooth " << isSmoothPoint.count()
553 <<
" to " << newIsSmoothPoint.count()
555 isSmoothPoint.transfer(newIsSmoothPoint);
564 int main(
int argc,
char *argv[])
571 "Creates inflated version of surface using point normals."
572 " Takes surface, distance to inflate and additional safety factor"
576 "checkSelfIntersection",
577 "also check for self-intersection"
583 "number of smoothing iterations (default 20)"
594 "switch on additional debug information"
603 runTime.functionObjects().off();
607 const scalar extendFactor(
args.
argRead<scalar>(3));
608 const bool checkSelfIntersect =
args.
optionFound(
"checkSelfIntersection");
618 Info<<
"Inflating surface " << inputName
619 <<
" according to point normals" <<
nl
621 <<
" safety factor : " << extendFactor <<
nl
622 <<
" self intersection test : " << checkSelfIntersect <<
nl
623 <<
" smoothing iterations : " << nSmooth <<
nl
624 <<
" feature angle : " << featureAngle <<
nl
628 if (extendFactor < 1 || extendFactor > 10)
631 <<
"Illegal safety factor " << extendFactor
632 <<
". It is usually 1..2"
655 Info<<
"Detected features:" <<
nl
656 <<
" feature points : " << features.featurePoints().size()
657 <<
" out of " <<
s.nPoints() <<
nl
658 <<
" feature edges : " << features.featureEdges().size()
659 <<
" out of " <<
s.nEdges() <<
nl
663 forAll(features.featurePoints(), i)
665 label pointI = features.featurePoints()[i];
666 isFeaturePoint[pointI] =
true;
677 Info<<
"Constructing field scale\n" <<
endl;
695 Info<<
"Calculating vertex normals\n" <<
endl;
708 Info<<
"Constructing field pointDisplacement\n" <<
endl;
734 if (checkSelfIntersect)
736 detectSelfIntersections(
s, initialIsEdgeIntersecting);
742 initialIsEdgeIntersecting.
setSize(
s.nEdges(),
true);
747 while (runTime.loop())
749 Info<<
"Time = " << runTime.timeName() <<
nl <<
endl;
755 newPoints[meshPoints[i]] += pointDisplacement[i];
757 s.movePoints(newPoints);
758 Info<<
"Bounding box : " <<
s.bounds() <<
endl;
764 if (
s.pointFaces()[pointI].size())
766 scale[pointI] =
mag(pointDisplacement[pointI])/
distance;
782 label nIntersections = detectIntersectionPoints
791 initialIsEdgeIntersecting,
796 Info<<
"Detected " << nIntersections <<
" intersections" <<
nl
799 if (nIntersections == 0)
807 forAll(isAffectedPoint, pointI)
809 if (isAffectedPoint[pointI])
811 isScaledPoint[pointI] =
true;
817 for (
label i = 0; i < nSmooth; i++)
820 oldScale.rename(
"oldScale");
832 pointDisplacement *=
distance*scale/
mag(pointDisplacement);
836 lloydsSmoothing(nSmooth,
s, isFeaturePoint, edgeStat, isAffectedPoint);
843 label meshPointI = meshPoints[i];
844 pointDisplacement[i] = pts[meshPointI]-initialPoints[meshPointI];
851 Info<<
"ExecutionTime = " << runTime.elapsedCpuTime() <<
" s"
852 <<
" ClockTime = " << runTime.elapsedClockTime() <<
" s"
857 Info<<
"Detected overall intersecting points " << isScaledPoint.count()
858 <<
" out of " <<
s.nPoints() <<
nl <<
endl;
863 OBJstream str(runTime.path()/
"isScaledPoint.obj");
864 forAll(isScaledPoint, pointI)
866 if (isScaledPoint[pointI])
868 str.write(initialPoints[meshPoints[pointI]]);
static SLList< string > validArgs
A list of valid (mandatory) arguments.
vectorField pointField
pointField is a vectorField.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
const dimensionedScalar mp
Proton mass.
const labelListList & pointFaces() const
Return point-face addressing.
volScalarField w(IOobject("w", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE), mesh, dimensionedScalar("w", dimensionSet(0, 0, 0, 0, 0, 0, 0), 0.0))
const Field< PointType > & points() const
Return reference to global points.
A class for handling words, derived from string.
const stringList & args() const
Return arguments.
OFstream which keeps track of vertices.
static void addOption(const word &opt, const string ¶m="", const string &usage="")
Add to an option to validOptions with usage information.
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.
A class for managing temporary objects.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Type gAverage(const FieldField< Field, Type > &f)
void set(const PackedList< 1 > &)
Set specified bits.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
IOoject and searching on triSurface.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< scalar > mag(const dimensioned< Type > &)
void setSize(const label, const unsigned int &val=0u)
Alias for resize()
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]
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.
Pre-declare SubField and related Field type.
Triangulated surface description with patch information.
pointIndexHit findLine(const bool findAny, const point &treeStart, const point &treeEnd, const label startNodeI, const direction startOctantI, const FindIntersectOp &fiOp, const bool verbose=false) const
Find any or nearest intersection.
virtual Ostream & write(const token &)=0
Write next token to stream.
Holds feature edges/points of surface.
Non-pointer based hierarchical recursive searching.
int main(int argc, char *argv[])
T optionLookupOrDefault(const word &opt, const T &deflt) const
Read a value from the named option if present.
label nPoints() const
Return number of points supporting patch faces.
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){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Generic dimensioned Type class.
errorManip< error > abort(error &err)
unsigned int get(const label) const
Get value at index I.
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))
scalar distance(const vector &p1, const vector &p2)
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
A triangular face using a FixedList of labels corresponding to mesh vertices.
prefixOSstream Pout(cout, "Pout")
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
bool optionFound(const word &opt) const
Return true if the named option is found.
T argRead(const label index) const
Read a value from the argument at index.
void size(const label)
Override size to be inconsistent with allocated storage.
static void noParallel()
Remove the parallel options.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Foam::argList args(argc, argv)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...