ENH: add input surface scaling (issue #514)

- surfaceFeatureExtract
  * dictionary "scale" entry

- triSurface
- triSurfaceLoader
  * optional scaleFactor on reading

- surfaceAdd
- surfaceBooleanFeatures
- surfaceClean
- surfaceCoarsen
  * scale option

- surfaceTransformPoints, transformPoints
  * scale option as scalar or vector quantity
This commit is contained in:
Mark Olesen
2017-08-14 09:18:15 +02:00
parent aad962a0e4
commit 139edb2468
24 changed files with 305 additions and 169 deletions

View File

@ -41,10 +41,15 @@ using namespace Foam;
autoPtr<triSurface> loadSurface
(
const Foam::Time& runTime,
const fileName& surfName
const fileName& surfName,
const scalar scaleFactor
)
{
Info<< "Reading surface " << surfName << endl;
Info<< "Reading surface " << surfName << nl;
if (scaleFactor > 0)
{
Info<<"Scaling : " << scaleFactor << nl;
}
const fileName fallback =
runTime.constantPath()/triSurfaceMesh::meshSubDir/surfName;
@ -52,11 +57,11 @@ autoPtr<triSurface> loadSurface
autoPtr<triSurface> surfPtr;
if (isFile(surfName))
{
surfPtr.set(new triSurface(surfName));
surfPtr.set(new triSurface(surfName, scaleFactor));
}
else if (isFile(fallback))
{
surfPtr.set(new triSurface(fallback));
surfPtr.set(new triSurface(fallback, scaleFactor));
}
else
{
@ -102,6 +107,12 @@ int main(int argc, char *argv[])
"mergeTol",
"merge points (and edges) using the specified tolerance"
);
argList::addOption
(
"scale",
"factor",
"geometry scaling factor"
);
#include "addDictOption.H"
@ -117,16 +128,18 @@ int main(int argc, char *argv[])
#include "setRootCase.H"
#include "createTime.H"
const scalar scaleFactor = args.optionLookupOrDefault<scalar>("scale", -1);
const word outputFile(args.executable() + ".obj");
const fileName surf1Name(args[1]);
triSurface surf1 = loadSurface(runTime, surf1Name)();
triSurface surf1 = loadSurface(runTime, surf1Name, scaleFactor)();
Info<< surf1Name << " statistics:" << endl;
surf1.writeStats(Info);
Info<< endl;
const fileName surf2Name(args[2]);
triSurface surf2 = loadSurface(runTime, surf2Name)();
triSurface surf2 = loadSurface(runTime, surf2Name, scaleFactor)();
Info<< surf2Name << " statistics:" << endl;
surf2.writeStats(Info);
Info<< endl;

View File

@ -91,7 +91,7 @@ int main(int argc, char *argv[])
// ~~~~~~~~~~~~~~~~~~~~~
fileFormats::FIREMeshWriter::binary = !args.optionFound("ascii");
// default: rescale from [m] to [mm]
// Default: no rescaling
scalar scaleFactor = 1;
if (args.optionReadIfPresent("scale", scaleFactor))
{

View File

@ -43,8 +43,8 @@ Usage
or -yawPitchRoll (yawdegrees pitchdegrees rolldegrees)
or -rollPitchYaw (rolldegrees pitchdegrees yawdegrees)
-scale vector
Scales the points by the given vector.
-scale scalar|vector
Scales the points by the given scalar or vector.
The any or all of the three options may be specified and are processed
in the above order.
@ -182,9 +182,9 @@ int main(int argc, char *argv[])
argList::addOption
(
"scale",
"vector",
"scale by the specified amount - eg, '(0.001 0.001 0.001)' for a "
"uniform [mm] to [m] scaling"
"scalar | vector",
"scale by the specified amount - eg, for a uniform [mm] to [m] scaling "
"use either (0.001 0.001 0.001)' or simply '0.001'"
);
#include "addRegionOption.H"
@ -262,10 +262,10 @@ int main(int argc, char *argv[])
<< " pitch " << v.y() << nl
<< " yaw " << v.z() << nl;
// Convert to radians
// degToRad
v *= pi/180.0;
quaternion R(quaternion::rotationSequence::XYZ, v);
const quaternion R(quaternion::rotationSequence::XYZ, v);
Info<< "Rotating points by quaternion " << R << endl;
points = transform(R, points);
@ -282,16 +282,10 @@ int main(int argc, char *argv[])
<< " pitch " << v.y() << nl
<< " roll " << v.z() << nl;
// Convert to radians
// degToRad
v *= pi/180.0;
scalar yaw = v.x();
scalar pitch = v.y();
scalar roll = v.z();
quaternion R = quaternion(vector(0, 0, 1), yaw);
R *= quaternion(vector(0, 1, 0), pitch);
R *= quaternion(vector(1, 0, 0), roll);
const quaternion R(quaternion::rotationSequence::ZYX, v);
Info<< "Rotating points by quaternion " << R << endl;
points = transform(R, points);
@ -302,13 +296,34 @@ int main(int argc, char *argv[])
}
}
if (args.optionReadIfPresent("scale", v))
if (args.optionFound("scale"))
{
Info<< "Scaling points by " << v << endl;
// Use readList to handle single or multiple values
const List<scalar> scaling = args.optionReadList<scalar>("scale");
points.replace(vector::X, v.x()*points.component(vector::X));
points.replace(vector::Y, v.y()*points.component(vector::Y));
points.replace(vector::Z, v.z()*points.component(vector::Z));
if (scaling.size() == 1)
{
Info<< "Scaling points uniformly by " << scaling[0] << nl;
points *= scaling[0];
}
else if (scaling.size() == 3)
{
Info<< "Scaling points by ("
<< scaling[0] << " "
<< scaling[1] << " "
<< scaling[2] << ")" << nl;
points.replace(vector::X, scaling[0]*points.component(vector::X));
points.replace(vector::Y, scaling[1]*points.component(vector::Y));
points.replace(vector::Z, scaling[2]*points.component(vector::Z));
}
else
{
FatalError
<< "-scale with 1 or 3 components only" << nl
<< "given: " << args["scale"] << endl
<< exit(FatalError);
}
}
// Set the precision of the points data to 10

View File

@ -71,6 +71,12 @@ int main(int argc, char *argv[])
"mergeRegions",
"combine regions from both surfaces"
);
argList::addOption
(
"scale",
"factor",
"geometry scaling factor on input surfaces"
);
argList args(argc, argv);
@ -81,6 +87,8 @@ int main(int argc, char *argv[])
const bool addPoint = args.optionFound("points");
const bool mergeRegions = args.optionFound("mergeRegions");
const scalar scaleFactor = args.optionLookupOrDefault<scalar>("scale", -1);
if (addPoint)
{
Info<< "Reading a surface and adding points from a file"
@ -117,8 +125,12 @@ int main(int argc, char *argv[])
<< "Writing : " << outFileName << nl << endl;
}
const triSurface surface1(inFileName1);
if (scaleFactor > 0)
{
Info<< "Scaling : " << scaleFactor << nl;
}
const triSurface surface1(inFileName1, scaleFactor);
Info<< "Surface1:" << endl;
surface1.writeStats(Info);
Info<< endl;
@ -131,7 +143,7 @@ int main(int argc, char *argv[])
if (addPoint)
{
IFstream pointsFile(args["points"]);
pointField extraPoints(pointsFile);
const pointField extraPoints(pointsFile);
Info<< "Additional Points:" << extraPoints.size() << endl;
@ -139,17 +151,16 @@ int main(int argc, char *argv[])
label pointi = pointsAll.size();
pointsAll.setSize(pointsAll.size() + extraPoints.size());
forAll(extraPoints, i)
for (const auto& pt : extraPoints)
{
pointsAll[pointi++] = extraPoints[i];
pointsAll[pointi++] = pt;
}
combinedSurf = triSurface(surface1, surface1.patches(), pointsAll);
}
else
{
const triSurface surface2(inFileName2);
const triSurface surface2(inFileName2, scaleFactor);
Info<< "Surface2:" << endl;
surface2.writeStats(Info);
Info<< endl;
@ -165,21 +176,19 @@ int main(int argc, char *argv[])
label pointi = 0;
// Copy points1 into pointsAll
forAll(points1, point1i)
for (const auto& pt : points1)
{
pointsAll[pointi++] = points1[point1i];
pointsAll[pointi++] = pt;
}
// Add surface2 points
forAll(points2, point2i)
for (const auto& pt : points2)
{
pointsAll[pointi++] = points2[point2i];
pointsAll[pointi++] = pt;
}
label trianglei = 0;
// Determine map for both regions
label nNewPatches = 0;
labelList patch1Map(surface1.patches().size());
@ -192,17 +201,17 @@ int main(int argc, char *argv[])
forAll(surface1.patches(), i)
{
const word& name = surface1.patches()[i].name();
HashTable<label>::iterator iter = nameToPatch.find(name);
auto iter = nameToPatch.find(name);
label combinedi;
if (iter == nameToPatch.end())
if (iter.found())
{
combinedi = nameToPatch.size();
nameToPatch.insert(name, combinedi);
combinedi = iter.object();
}
else
{
combinedi = iter();
combinedi = nameToPatch.size();
nameToPatch.insert(name, combinedi);
}
patch1Map[i] = combinedi;
}
@ -212,17 +221,17 @@ int main(int argc, char *argv[])
forAll(surface2.patches(), i)
{
const word& name = surface2.patches()[i].name();
HashTable<label>::iterator iter = nameToPatch.find(name);
auto iter = nameToPatch.find(name);
label combinedi;
if (iter == nameToPatch.end())
if (iter.found())
{
combinedi = nameToPatch.size();
nameToPatch.insert(name, combinedi);
combinedi = iter.object();
}
else
{
combinedi = iter();
combinedi = nameToPatch.size();
nameToPatch.insert(name, combinedi);
}
patch2Map[i] = combinedi;
}
@ -245,11 +254,9 @@ int main(int argc, char *argv[])
}
// Copy triangles1 into trianglesAll
forAll(surface1, facei)
for (const labelledTri& tri : surface1)
{
const labelledTri& tri = surface1[facei];
labelledTri& destTri = facesAll[trianglei++];
destTri.triFace::operator=(tri);
@ -257,10 +264,8 @@ int main(int argc, char *argv[])
}
// Add (renumbered) surface2 triangles
forAll(surface2, facei)
for (const labelledTri& tri : surface2)
{
const labelledTri& tri = surface2[facei];
labelledTri& destTri = facesAll[trianglei++];
destTri[0] = tri[0] + points1.size();
destTri[1] = tri[1] + points1.size();

View File

@ -1517,6 +1517,12 @@ int main(int argc, char *argv[])
argList::validArgs.append("surfaceFile1");
argList::validArgs.append("surfaceFile2");
argList::addOption
(
"scale",
"factor",
"Geometry scaling factor (both surfaces)"
);
argList::addBoolOption
(
"surf1Baffle",
@ -1587,6 +1593,10 @@ int main(int argc, char *argv[])
}
// Scale factor for both surfaces:
const scalar scaleFactor
= args.optionLookupOrDefault<scalar>("scale", -1);
const word surf1Name(args[2]);
Info<< "Reading surface " << surf1Name << endl;
triSurfaceMesh surf1
@ -1599,6 +1609,11 @@ int main(int argc, char *argv[])
runTime
)
);
if (scaleFactor > 0)
{
Info<< "Scaling : " << scaleFactor << nl;
surf1.scalePoints(scaleFactor);
}
Info<< surf1Name << " statistics:" << endl;
surf1.writeStats(Info);
@ -1616,6 +1631,11 @@ int main(int argc, char *argv[])
runTime
)
);
if (scaleFactor > 0)
{
Info<< "Scaling : " << scaleFactor << nl;
surf2.scalePoints(scaleFactor);
}
Info<< surf2Name << " statistics:" << endl;
surf2.writeStats(Info);
@ -1627,7 +1647,7 @@ int main(int argc, char *argv[])
edgeIntersections edgeCuts1;
edgeIntersections edgeCuts2;
bool invertedSpace = args.optionFound("invertedSpace");
const bool invertedSpace = args.optionFound("invertedSpace");
if (invertedSpace && validActions[action] == booleanSurface::DIFFERENCE)
{
@ -1736,9 +1756,7 @@ int main(int argc, char *argv[])
const extendedFeatureEdgeMesh& feMesh = feMeshPtr();
feMesh.writeStats(Info);
feMesh.write();
feMesh.writeObj(feMesh.path()/sFeatFileName);
{

View File

@ -60,7 +60,13 @@ int main(int argc, char *argv[])
argList::addBoolOption
(
"noClean",
"suppress surface checking/cleanup on the input surface"
"Suppress surface checking/cleanup on the input surface"
);
argList::addOption
(
"scale",
"factor",
"Input geometry scaling factor"
);
argList args(argc, argv);
@ -77,7 +83,12 @@ int main(int argc, char *argv[])
Info<< "Reading surface from " << inFileName << " ..." << nl << endl;
triSurface surf(inFileName);
triSurface surf
(
inFileName,
args.optionLookupOrDefault<scalar>("scale", -1)
);
surf.writeStats(Info);
if (!args.optionFound("noClean"))
@ -90,7 +101,7 @@ int main(int argc, char *argv[])
while (true)
{
label nEdgeCollapse = collapseEdge(surf, minLen);
const label nEdgeCollapse = collapseEdge(surf, minLen);
if (nEdgeCollapse == 0)
{
@ -99,7 +110,7 @@ int main(int argc, char *argv[])
}
while (true)
{
label nSplitEdge = collapseBase(surf, minLen, minQuality);
const label nSplitEdge = collapseBase(surf, minLen, minQuality);
if (nSplitEdge == 0)
{

View File

@ -28,7 +28,7 @@ Group
grpSurfaceUtilities
Description
Surface coarsening using `bunnylod'
Surface coarsening using 'bunnylod'
Reference:
\verbatim
@ -75,6 +75,13 @@ int main(int argc, char *argv[])
argList::validArgs.append("surfaceFile");
argList::validArgs.append("reductionFactor");
argList::validArgs.append("output surfaceFile");
argList::addOption
(
"scale",
"factor",
"input geometry scaling factor"
);
argList args(argc, argv);
const fileName inFileName = args[1];
@ -90,40 +97,39 @@ int main(int argc, char *argv[])
<< exit(FatalError);
}
Info<< "Input surface :" << inFileName << endl
<< "Reduction factor:" << reduction << endl
<< "Output surface :" << outFileName << endl << endl;
const scalar scaleFactor = args.optionLookupOrDefault<scalar>("scale", -1);
const triSurface surf(inFileName);
Info<< "Input surface :" << inFileName << nl
<< "Scaling factor :" << scaleFactor << nl
<< "Reduction factor:" << reduction << nl
<< "Output surface :" << outFileName << nl
<< endl;
const triSurface surf(inFileName, scaleFactor);
Info<< "Surface:" << endl;
surf.writeStats(Info);
Info<< endl;
::List< ::Vector> vert; // global list of vertices
::List< ::tridata> tri; // global list of triangles
::List<::Vector> vert; // global list of vertices
::List<::tridata> tri; // global list of triangles
// Convert triSurface to progmesh format. Note: can use global point
// numbering since surface read in from file.
const pointField& pts = surf.points();
forAll(pts, ptI)
for (const point& pt : pts)
{
const point& pt = pts[ptI];
vert.Add( ::Vector(pt.x(), pt.y(), pt.z()));
vert.Add(::Vector(pt.x(), pt.y(), pt.z()));
}
forAll(surf, facei)
for (const labelledTri& f : surf)
{
const labelledTri& f = surf[facei];
tridata td;
td.v[0]=f[0];
td.v[1]=f[1];
td.v[2]=f[2];
td.v[0] = f[0];
td.v[1] = f[1];
td.v[2] = f[2];
tri.Add(td);
}
@ -133,20 +139,20 @@ int main(int argc, char *argv[])
::ProgressiveMesh(vert,tri,collapse_map,permutation);
// rearrange the vertex list
::List< ::Vector> temp_list;
for (int i=0;i<vert.num;i++)
::List<::Vector> temp_list;
for (int i=0; i<vert.num; i++)
{
temp_list.Add(vert[i]);
}
for (int i=0;i<vert.num;i++)
for (int i=0; i<vert.num; i++)
{
vert[permutation[i]]=temp_list[i];
vert[permutation[i]] = temp_list[i];
}
// update the changes in the entries in the triangle list
for (int i=0;i<tri.num;i++)
for (int i=0; i<tri.num; i++)
{
for (int j=0;j<3;j++)
for (int j=0; j<3; j++)
{
tri[i].v[j] = permutation[tri[i].v[j]];
}

View File

@ -74,24 +74,24 @@ int main(int argc, char *argv[])
argList::addBoolOption
(
"clean",
"perform some surface checking/cleanup on the input surface"
"Perform some surface checking/cleanup on the input surface"
);
argList::addBoolOption
(
"group",
"reorder faces into groups; one per region"
"Reorder faces into groups; one per region"
);
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1"
"Input geometry scaling factor"
);
argList::addOption
(
"writePrecision",
"label",
"write to output with the specified precision"
"Write to output with the specified precision"
);
argList args(argc, argv);
@ -116,8 +116,10 @@ int main(int argc, char *argv[])
<< exit(FatalError);
}
const scalar scaleFactor = args.optionLookupOrDefault<scalar>("scale", -1);
Info<< "Reading : " << importName << endl;
triSurface surf(importName);
triSurface surf(importName, scaleFactor);
Info<< "Read surface:" << endl;
surf.writeStats(Info);
@ -144,13 +146,6 @@ int main(int argc, char *argv[])
}
Info<< "writing " << exportName;
scalar scaleFactor = 0;
if (args.optionReadIfPresent("scale", scaleFactor) && scaleFactor > 0)
{
Info<< " with scaling " << scaleFactor;
surf.scalePoints(scaleFactor);
}
Info<< endl;
surf.write(exportName, sortByRegion);

View File

@ -339,8 +339,15 @@ int main(int argc, char *argv[])
<< " writeObj=" << writeObj
<< " writeVTK=" << writeVTK << nl;
scalar scaleFactor = -1;
// Allow rescaling of the surface points (eg, mm -> m)
if (surfaceDict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
{
Info<<"Scaling : " << scaleFactor << nl;
}
// Load a single file, or load and combine multiple selected files
autoPtr<triSurface> surfPtr = loader.load(loadingOption);
autoPtr<triSurface> surfPtr = loader.load(loadingOption, scaleFactor);
if (!surfPtr.valid() || surfPtr().empty())
{
FatalErrorInFunction

View File

@ -50,6 +50,9 @@ outputName1
surfaces (surface1.stl surface2.nas);
// mm -> m scaling
// scale 0.001;
// Generate additional intersection features (none | self | region)
intersectionMethod self;

View File

@ -123,9 +123,8 @@ int main(int argc, char *argv[])
Info<< " " << points[f[fp]] << "\n";
}
Info<< endl;
Info<< "End\n" << endl;
Info<< nl
<< "End\n" << endl;
return 0;
}

View File

@ -90,7 +90,7 @@ int main(int argc, char *argv[])
vector refPt = Zero;
bool calcAroundRefPt = args.optionReadIfPresent("referencePoint", refPt);
triSurface surf(surfFileName);
const triSurface surf(surfFileName);
scalar m = 0.0;
vector cM = Zero;

View File

@ -44,7 +44,7 @@ Usage
Specify a feature angle
E.g. inflate surface by 2cm with 1.5 safety factor:
E.g. inflate surface by 20mm with 1.5 safety factor:
surfaceInflate DTC-scaled.obj 0.02 1.5 -featureAngle 45 -nSmooth 2
\*---------------------------------------------------------------------------*/

View File

@ -87,7 +87,7 @@ int main(int argc, char *argv[])
(
"scale",
"factor",
"geometry scaling factor - default is 1"
"input geometry scaling factor"
);
argList::addBoolOption
(
@ -119,10 +119,10 @@ int main(int argc, char *argv[])
// use UnsortedMeshedSurface, not MeshedSurface to maintain ordering
UnsortedMeshedSurface<face> surf(importName);
scalar scaling = 0;
if (args.optionReadIfPresent("scale", scaling) && scaling > 0)
const scalar scaling = args.optionLookupOrDefault<scalar>("scale", -1);
if (scaling > 0)
{
Info<< " -scale " << scaling << endl;
Info<< " -scale " << scaling << nl;
surf.scalePoints(scaling);
}

View File

@ -63,6 +63,12 @@ int main(int argc, char *argv[])
"usePierceTest",
"determine orientation by counting number of intersections"
);
argList::addOption
(
"scale",
"factor",
"input geometry scaling factor"
);
argList args(argc, argv);
@ -86,11 +92,14 @@ int main(int argc, char *argv[])
Info<< "outside" << endl;
}
const scalar scaling = args.optionLookupOrDefault<scalar>("scale", -1);
if (scaling > 0)
{
Info<< "Input scaling: " << scaling << nl;
}
// Load surface
triSurface surf(surfFileName);
triSurface surf(surfFileName, scaling);
bool anyFlipped = false;
@ -118,11 +127,11 @@ int main(int argc, char *argv[])
if (anyFlipped)
{
Info<< "Flipped orientation of (part of) surface." << endl;
Info<< "Flipped orientation of (part of) surface." << nl;
}
else
{
Info<< "Did not flip orientation of any triangle of surface." << endl;
Info<< "Did not flip orientation of any triangle of surface." << nl;
}
Info<< "Writing new surface to " << outFileName << endl;

View File

@ -46,31 +46,47 @@ using namespace Foam;
int main(int argc, char *argv[])
{
argList::addNote
(
"Merge points on surface if they are within absolute distance [m]."
);
argList::noParallel();
argList::validArgs.append("surfaceFile");
argList::validArgs.append("merge distance");
argList::validArgs.append("output surfaceFile");
argList::addOption
(
"scale",
"factor",
"input geometry scaling factor"
);
argList args(argc, argv);
const fileName surfFileName = args[1];
const scalar mergeTol = args.argRead<scalar>(2);
const fileName outFileName = args[3];
Info<< "Reading surface from " << surfFileName << " ..." << endl;
Info<< "Merging points within " << mergeTol << " metre." << endl;
const scalar scaling = args.optionLookupOrDefault<scalar>("scale", -1);
triSurface surf1(surfFileName);
Info<< "Reading surface from " << surfFileName << " ..." << nl
<< "Merging points within " << mergeTol << " metre." << nl;
if (scaling > 0)
{
Info<< "input scaling " << scaling << nl;
}
Info<< "Original surface:" << endl;
const triSurface surf1(surfFileName, scaling);
Info<< "Original surface:" << nl;
surf1.writeStats(Info);
triSurface cleanSurf(surf1);
while (true)
{
label nOldVert = cleanSurf.nPoints();
const label nOldVert = cleanSurf.nPoints();
cleanSurf = triSurfaceTools::mergePoints(cleanSurf, mergeTol);

View File

@ -105,7 +105,8 @@ int main(int argc, char *argv[])
argList::addNote
(
"Redistribute a triSurface. "
"The specified surface must be located in the constant/triSurface directory"
"The specified surface must be located in the constant/triSurface "
"directory"
);
argList::validArgs.append("triSurfaceMesh");

View File

@ -85,9 +85,9 @@ int main(int argc, char *argv[])
argList::addOption
(
"scale",
"vector",
"scale by the specified amount - eg, '(0.001 0.001 0.001)' for a "
"uniform [mm] to [m] scaling"
"scalar | vector",
"scale by the specified amount - eg, for a uniform [mm] to [m] scaling "
"use either (0.001 0.001 0.001)' or simply '0.001'"
);
argList::addOption
(
@ -138,7 +138,7 @@ int main(int argc, char *argv[])
n1n2[0] /= mag(n1n2[0]);
n1n2[1] /= mag(n1n2[1]);
tensor T = rotationTensor(n1n2[0], n1n2[1]);
const tensor T = rotationTensor(n1n2[0], n1n2[1]);
Info<< "Rotating points by " << T << endl;
@ -151,10 +151,10 @@ int main(int argc, char *argv[])
<< " pitch " << v.y() << nl
<< " yaw " << v.z() << nl;
// Convert to radians
// degToRad
v *= pi/180.0;
quaternion R(quaternion::rotationSequence::XYZ, v);
const quaternion R(quaternion::rotationSequence::XYZ, v);
Info<< "Rotating points by quaternion " << R << endl;
points = transform(R, points);
@ -166,29 +166,43 @@ int main(int argc, char *argv[])
<< " pitch " << v.y() << nl
<< " roll " << v.z() << nl;
// Convert to radians
// degToRad
v *= pi/180.0;
scalar yaw = v.x();
scalar pitch = v.y();
scalar roll = v.z();
quaternion R = quaternion(vector(0, 0, 1), yaw);
R *= quaternion(vector(0, 1, 0), pitch);
R *= quaternion(vector(1, 0, 0), roll);
const quaternion R(quaternion::rotationSequence::ZYX, v);
Info<< "Rotating points by quaternion " << R << endl;
points = transform(R, points);
}
if (args.optionReadIfPresent("scale", v))
if (args.optionFound("scale"))
{
Info<< "Scaling points by " << v << endl;
// Use readList to handle single or multiple values
const List<scalar> scaling = args.optionReadList<scalar>("scale");
points.replace(vector::X, v.x()*points.component(vector::X));
points.replace(vector::Y, v.y()*points.component(vector::Y));
points.replace(vector::Z, v.z()*points.component(vector::Z));
if (scaling.size() == 1)
{
Info<< "Scaling points uniformly by " << scaling[0] << nl;
points *= scaling[0];
}
else if (scaling.size() == 3)
{
Info<< "Scaling points by ("
<< scaling[0] << " "
<< scaling[1] << " "
<< scaling[2] << ")" << nl;
points.replace(vector::X, scaling[0]*points.component(vector::X));
points.replace(vector::Y, scaling[1]*points.component(vector::Y));
points.replace(vector::Z, scaling[2]*points.component(vector::Z));
}
else
{
FatalError
<< "-scale with 1 or 3 components only" << nl
<< "given: " << args["scale"] << endl
<< exit(FatalError);
}
}
surf1.movePoints(points);

View File

@ -125,7 +125,8 @@ public:
// Constructors
//- Create a writer object with given output scaling
//- Create a writer object with given output scaling.
// Treats a zero or negative scale factor as unity scaling.
meshWriter
(
const polyMesh&,

View File

@ -97,7 +97,8 @@ public:
// Constructors
//- Prepare for writing, optionally with scaling
//- Prepare for writing, optionally with scaling.
// Treats a zero or negative scale factor as unity scaling.
FIREMeshWriter(const polyMesh&, const scalar scaleFactor = 1.0);

View File

@ -218,7 +218,8 @@ Foam::label Foam::triSurfaceLoader::select(const wordReList& matcher)
Foam::autoPtr<Foam::triSurface> Foam::triSurfaceLoader::load
(
const enum loadingOption opt
const enum loadingOption opt,
const scalar scaleFactor
) const
{
autoPtr<triSurface> output;
@ -229,7 +230,8 @@ Foam::autoPtr<Foam::triSurface> Foam::triSurfaceLoader::load
}
else if (selected_.size() == 1)
{
output.set(new triSurface(directory_/selected_[0]));
// Use scaling (if any)
output.set(new triSurface(directory_/selected_[0], scaleFactor));
triSurface& surf = output();
@ -392,6 +394,12 @@ Foam::autoPtr<Foam::triSurface> Foam::triSurfaceLoader::load
}
}
// Apply scaling (if any)
if (scaleFactor > VSMALL)
{
points *= scaleFactor;
}
output.set(new triSurface(faces, patches, points, true));
return output;

View File

@ -154,9 +154,12 @@ public:
label select(const wordReList& matcher);
//- Load a single file, or load and combine multiple selected files
// Optionally scale the surface(s) on input, with a zero or negative
// scale factor treated as no scaling.
autoPtr<triSurface> load
(
const enum loadingOption opt = loadingOption::OFFSET_REGION
const enum loadingOption opt = loadingOption::OFFSET_REGION,
const scalar scaleFactor = -1
) const;
};

View File

@ -760,17 +760,19 @@ Foam::triSurface::triSurface
}
Foam::triSurface::triSurface(const fileName& name)
Foam::triSurface::triSurface(const fileName& name, const scalar scaleFactor)
:
ParentType(List<Face>(), pointField()),
patches_(),
sortedEdgeFacesPtr_(nullptr),
edgeOwnerPtr_(nullptr)
{
word ext = name.ext();
const word ext = name.ext();
read(name, ext);
scalePoints(scaleFactor);
setDefaultPatches();
}
@ -886,8 +888,8 @@ void Foam::triSurface::movePoints(const pointField& newPoints)
void Foam::triSurface::scalePoints(const scalar scaleFactor)
{
// avoid bad scaling
if (scaleFactor > 0 && scaleFactor != 1.0)
// Avoid bad scaling
if (scaleFactor > VSMALL && scaleFactor != 1.0)
{
// Remove all geometry dependent data
clearTopology();

View File

@ -264,46 +264,55 @@ public:
//- Construct from triangles, patches, points.
triSurface
(
const List<labelledTri>&,
const geometricSurfacePatchList&,
const pointField&
const List<labelledTri>& triangles,
const geometricSurfacePatchList& patches,
const pointField& points
);
//- Construct from triangles, patches, points. Reuse storage.
triSurface
(
List<labelledTri>&,
const geometricSurfacePatchList&,
pointField&,
List<labelledTri>& triangles,
const geometricSurfacePatchList& patches,
pointField& points,
const bool reuse
);
//- Construct by transferring (triangles, points) components.
triSurface
(
const Xfer<List<labelledTri>>&,
const geometricSurfacePatchList&,
const Xfer<List<point>>&
const Xfer<List<labelledTri>>& triangles,
const geometricSurfacePatchList& patches,
const Xfer<List<point>>& points
);
//- Construct from triangles, points. Set patch names to default.
triSurface(const List<labelledTri>&, const pointField&);
triSurface
(
const List<labelledTri>& triangles,
const pointField& points
);
//- Construct from triangles, points. Set region to 0 and default
// patchName.
triSurface(const triFaceList&, const pointField&);
triSurface
(
const triFaceList& triangles,
const pointField& points
);
//- Construct from file name (uses extension to determine type)
triSurface(const fileName&);
//- Construct from file name (uses extension to determine type).
// Optional (positive, non-zero) point scaling is possible.
triSurface(const fileName& name, const scalar scaleFactor = -1);
//- Construct from Istream
triSurface(Istream&);
triSurface(Istream& is);
//- Construct from objectRegistry
triSurface(const Time& d);
//- Construct as copy
triSurface(const triSurface&);
triSurface(const triSurface& ts);
//- Destructor
@ -382,10 +391,10 @@ public:
// Edit
//- Move points
virtual void movePoints(const pointField&);
virtual void movePoints(const pointField& newPoints);
//- Scale points. A non-positive factor is ignored
virtual void scalePoints(const scalar);
//- Scale points. A non-positive factor is ignored.
virtual void scalePoints(const scalar scaleFactor);
//- Check/remove duplicate/degenerate triangles
void checkTriangles(const bool verbose);
@ -447,13 +456,13 @@ public:
// Write
//- Write to Ostream in simple FOAM format
void write(Ostream&) const;
void write(Ostream& os) const;
//- Generic write routine. Chooses writer based on extension.
void write(const fileName&, const bool sortByRegion = false) const;
//- Write to database
void write(const Time&) const;
void write(const Time& d) const;
//- Write some statistics
void writeStats(Ostream& os) const;