transformPoints.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  transformPoints
29 
30 Group
31  grpMeshManipulationUtilities
32 
33 Description
34  Transforms the mesh points in the polyMesh directory according to the
35  translate, rotate and scale options.
36 
37 Usage
38  Options are:
39 
40  -time value
41  Specify the time to search from and apply the transformation
42  (default is latest)
43 
44  -recentre
45  Recentre using the bounding box centre before other operations
46 
47  -translate vector
48  Translate the points by the given vector before rotations
49 
50  -rotate (vector vector)
51  Rotate the points from the first vector to the second
52 
53  -rotate-angle (vector angle)
54  Rotate angle degrees about vector axis.
55 
56  or -yawPitchRoll (yawdegrees pitchdegrees rolldegrees)
57  or -rollPitchYaw (rolldegrees pitchdegrees yawdegrees)
58 
59  -scale scalar|vector
60  Scale the points by the given scalar or vector on output.
61 
62  The any or all of the three options may be specified and are processed
63  in the above order.
64 
65  With -rotateFields (in combination with -rotate/yawPitchRoll/rollPitchYaw)
66  it will also read & transform vector & tensor fields.
67 
68 Note
69  roll (rotation about x)
70  pitch (rotation about y)
71  yaw (rotation about z)
72 
73 \*---------------------------------------------------------------------------*/
74 
75 #include "argList.H"
76 #include "Time.H"
77 #include "fvMesh.H"
78 #include "volFields.H"
79 #include "surfaceFields.H"
80 #include "pointFields.H"
81 #include "ReadFields.H"
82 #include "regionProperties.H"
83 #include "transformField.H"
85 #include "axisAngleRotation.H"
87 
88 using namespace Foam;
89 using namespace Foam::coordinateRotations;
90 
91 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
92 
93 template<class GeoField>
94 void readAndRotateFields
95 (
96  PtrList<GeoField>& flds,
97  const fvMesh& mesh,
98  const dimensionedTensor& rotT,
99  const IOobjectList& objects
100 )
101 {
102  ReadFields(mesh, objects, flds);
103  for (GeoField& fld : flds)
104  {
105  Info<< "Transforming " << fld.name() << endl;
106  transform(fld, rotT, fld);
107  }
108 }
109 
110 
111 void rotateFields
112 (
113  const word& regionName,
114  const Time& runTime,
115  const tensor& rotT
116 )
117 {
118  // Need dimensionedTensor for geometric fields
119  const dimensionedTensor T(rotT);
120 
121  #include "createRegionMesh.H"
122 
123  // Read objects in time directory
124  IOobjectList objects(mesh, runTime.timeName());
125 
126  // Read vol fields.
127 
129  readAndRotateFields(vsFlds, mesh, T, objects);
130 
132  readAndRotateFields(vvFlds, mesh, T, objects);
133 
135  readAndRotateFields(vstFlds, mesh, T, objects);
136 
137  PtrList<volSymmTensorField> vsymtFlds;
138  readAndRotateFields(vsymtFlds, mesh, T, objects);
139 
141  readAndRotateFields(vtFlds, mesh, T, objects);
142 
143  // Read surface fields.
144 
146  readAndRotateFields(ssFlds, mesh, T, objects);
147 
149  readAndRotateFields(svFlds, mesh, T, objects);
150 
152  readAndRotateFields(sstFlds, mesh, T, objects);
153 
155  readAndRotateFields(ssymtFlds, mesh, T, objects);
156 
158  readAndRotateFields(stFlds, mesh, T, objects);
159 
160  mesh.write();
161 }
162 
163 
164 // Retrieve scaling option
165 // - size 0 : no scaling
166 // - size 1 : uniform scaling
167 // - size 3 : non-uniform scaling
168 List<scalar> getScalingOpt(const word& optName, const argList& args)
169 {
170  // readListIfPresent handles single or multiple values
171  // - accept 1 or 3 values
172 
173  List<scalar> scaling;
174  args.readListIfPresent(optName, scaling);
175 
176  if (scaling.size() == 1)
177  {
178  // Uniform scaling
179  }
180  else if (scaling.size() == 3)
181  {
182  // Non-uniform, but may actually be uniform
183  if
184  (
185  equal(scaling[0], scaling[1])
186  && equal(scaling[0], scaling[2])
187  )
188  {
189  scaling.resize(1);
190  }
191  }
192  else if (!scaling.empty())
193  {
194  FatalError
195  << "Incorrect number of components, must be 1 or 3." << nl
196  << " -" << optName << ' ' << args[optName].c_str() << endl
197  << exit(FatalError);
198  }
199 
200  if (scaling.size() == 1 && equal(scaling[0], 1))
201  {
202  // Scale factor 1 == no scaling
203  scaling.clear();
204  }
205 
206  // Zero and negative scaling are permitted
207 
208  return scaling;
209 }
210 
211 
212 void applyScaling(pointField& points, const List<scalar>& scaling)
213 {
214  if (scaling.size() == 1)
215  {
216  Info<< "Scaling points uniformly by " << scaling[0] << nl;
217  points *= scaling[0];
218  }
219  else if (scaling.size() == 3)
220  {
221  Info<< "Scaling points by ("
222  << scaling[0] << ' '
223  << scaling[1] << ' '
224  << scaling[2] << ')' << nl;
225 
229  }
230 }
231 
232 
233 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
234 
235 int main(int argc, char *argv[])
236 {
238  (
239  "Transform (translate / rotate / scale) mesh points.\n"
240  "Note: roll=rotate about x, pitch=rotate about y, yaw=rotate about z"
241  );
243  (
244  "time",
245  "time",
246  "Specify the time to search from and apply the transformation"
247  " (default is latest)"
248  );
250  (
251  "recentre",
252  "Recentre the bounding box before other operations"
253  );
255  (
256  "translate",
257  "vector",
258  "Translate by specified <vector> before rotations"
259  );
261  (
262  "auto-origin",
263  "Use bounding box centre as origin for rotations"
264  );
266  (
267  "origin",
268  "point",
269  "Use specified <point> as origin for rotations"
270  );
272  (
273  "rotate",
274  "(vectorA vectorB)",
275  "Rotate from <vectorA> to <vectorB> - eg, '((1 0 0) (0 0 1))'"
276  );
278  (
279  "rotate-angle",
280  "(vector scalar)",
281  "Rotate <angle> degrees about <vector> - eg, '((1 0 0) 45)'"
282  );
284  (
285  "rollPitchYaw",
286  "vector",
287  "Rotate by '(roll pitch yaw)' degrees"
288  );
290  (
291  "yawPitchRoll",
292  "vector",
293  "Rotate by '(yaw pitch roll)' degrees"
294  );
296  (
297  "rotateFields",
298  "Read and transform vector and tensor fields too"
299  );
301  (
302  "scale",
303  "scalar | vector",
304  "Scale by the specified amount - Eg, for uniform [mm] to [m] scaling "
305  "use either '(0.001 0.001 0.001)' or simply '0.001'"
306  );
307 
308  // Compatibility with surfaceTransformPoints
309  argList::addOptionCompat("scale", {"write-scale", 0});
310 
311  #include "addAllRegionOptions.H"
312  #include "setRootCase.H"
313 
314  const bool doRotateFields = args.found("rotateFields");
315 
316  // Verify that an operation has been specified
317  {
318  const List<word> operationNames
319  {
320  "recentre",
321  "translate",
322  "rotate",
323  "rotate-angle",
324  "rollPitchYaw",
325  "yawPitchRoll",
326  "scale"
327  };
328 
329  if (!args.count(operationNames))
330  {
331  FatalError
332  << "No operation supplied, "
333  << "use at least one of the following:" << nl
334  << " ";
335 
336  for (const auto& opName : operationNames)
337  {
338  FatalError
339  << " -" << opName;
340  }
341 
342  FatalError
343  << nl << exit(FatalError);
344  }
345  }
346 
347  // ------------------------------------------------------------------------
348 
349  #include "createTime.H"
350 
351  if (args.found("time"))
352  {
353  if (args["time"] == "constant")
354  {
355  runTime.setTime(instant(0, "constant"), 0);
356  }
357  else
358  {
359  const scalar timeValue = args.get<scalar>("time");
360  runTime.setTime(instant(timeValue), 0);
361  }
362  }
363 
364  // Handle -allRegions, -regions, -region
365  #include "getAllRegionOptions.H"
366 
367  // ------------------------------------------------------------------------
368 
369  forAll(regionNames, regioni)
370  {
371  const word& regionName = regionNames[regioni];
372  const word& regionDir =
373  (
375  );
376  const fileName meshDir = regionDir/polyMesh::meshSubDir;
377 
378  if (regionNames.size() > 1)
379  {
380  Info<< "region=" << regionName << nl;
381  }
382 
384  (
385  IOobject
386  (
387  "points",
388  runTime.findInstance(meshDir, "points"),
389  meshDir,
390  runTime,
393  false
394  )
395  );
396 
397 
398  // Begin operations
399 
400  vector v;
401  if (args.found("recentre"))
402  {
403  v = boundBox(points).centre();
404  Info<< "Adjust centre " << v << " -> (0 0 0)" << endl;
405  points -= v;
406  }
407 
408  if (args.readIfPresent("translate", v))
409  {
410  Info<< "Translating points by " << v << endl;
411  points += v;
412  }
413 
414  vector origin;
415  bool useOrigin = args.readIfPresent("origin", origin);
416  if (args.found("auto-origin") && !useOrigin)
417  {
418  useOrigin = true;
419  origin = boundBox(points).centre();
420  }
421 
422  if (useOrigin)
423  {
424  Info<< "Set origin for rotations to " << origin << endl;
425  points -= origin;
426  }
427 
428  if (args.found("rotate"))
429  {
430  Pair<vector> n1n2
431  (
432  args.lookup("rotate")()
433  );
434  n1n2[0].normalise();
435  n1n2[1].normalise();
436 
437  const tensor rot(rotationTensor(n1n2[0], n1n2[1]));
438 
439  Info<< "Rotating points by " << rot << endl;
440  points = transform(rot, points);
441 
442  if (doRotateFields)
443  {
444  rotateFields(regionName, runTime, rot);
445  }
446  }
447  else if (args.found("rotate-angle"))
448  {
449  const Tuple2<vector, scalar> rotAxisAngle
450  (
451  args.lookup("rotate-angle")()
452  );
453 
454  const vector& axis = rotAxisAngle.first();
455  const scalar angle = rotAxisAngle.second();
456 
457  Info<< "Rotating points " << nl
458  << " about " << axis << nl
459  << " angle " << angle << nl;
460 
461  const tensor rot(axisAngle::rotation(axis, angle, true));
462 
463  Info<< "Rotating points by " << rot << endl;
464  points = transform(rot, points);
465 
466  if (doRotateFields)
467  {
468  rotateFields(regionName, runTime, rot);
469  }
470  }
471  else if (args.readIfPresent("rollPitchYaw", v))
472  {
473  Info<< "Rotating points by" << nl
474  << " roll " << v.x() << nl
475  << " pitch " << v.y() << nl
476  << " yaw " << v.z() << nl;
477 
478  const tensor rot(euler::rotation(euler::eulerOrder::XYZ, v, true));
479 
480  Info<< "Rotating points by " << rot << endl;
481  points = transform(rot, points);
482 
483  if (doRotateFields)
484  {
485  rotateFields(regionName, runTime, rot);
486  }
487  }
488  else if (args.readIfPresent("yawPitchRoll", v))
489  {
490  Info<< "Rotating points by" << nl
491  << " yaw " << v.x() << nl
492  << " pitch " << v.y() << nl
493  << " roll " << v.z() << nl;
494 
495  const tensor rot(euler::rotation(euler::eulerOrder::ZYX, v, true));
496 
497  Info<< "Rotating points by " << rot << endl;
498  points = transform(rot, points);
499 
500  if (doRotateFields)
501  {
502  rotateFields(regionName, runTime, rot);
503  }
504  }
505 
506  // Output scaling
507  applyScaling(points, getScalingOpt("scale", args));
508 
509  if (useOrigin)
510  {
511  Info<< "Unset origin for rotations from " << origin << endl;
512  points += origin;
513  }
514 
515 
516  // Set the precision of the points data to 10
518 
519  Info<< "Writing points into directory "
520  << runTime.relativePath(points.path()) << nl
521  << endl;
522  points.write();
523  }
524 
525  Info<< nl << "End" << nl << endl;
526 
527  return 0;
528 }
529 
530 
531 // ************************************************************************* //
Foam::argList::count
label count(const UList< word > &optionNames) const
Definition: argList.C:1748
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:191
volFields.H
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::Tensor
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
Definition: complexI.H:268
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:165
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Foam::Vector< scalar >::Z
@ Z
Definition: Vector.H:77
EulerCoordinateRotation.H
Foam::Vector< scalar >::Y
@ Y
Definition: Vector.H:77
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
regionProperties.H
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: foamVtkLagrangianWriter.H:57
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Definition: fvMesh.C:1034
Foam::List::resize
void resize(const label len)
Definition: ListI.H:132
Foam::polyMesh::defaultRegion
static word defaultRegion
Definition: polyMesh.H:314
Foam::ReadFields
wordList ReadFields(const typename GeoMesh::Mesh &mesh, const IOobjectList &objects, PtrList< GeometricField< Type, PatchField, GeoMesh >> &fields, const bool syncPar=true, const bool readOldTime=false)
transformGeometricField.H
Spatial transformation functions for GeometricField.
Foam::polyMesh::meshSubDir
static word meshSubDir
Definition: polyMesh.H:317
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:773
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::argList::addOptionCompat
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Definition: argList.C:361
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:119
Foam::argList::readListIfPresent
bool readListIfPresent(const word &optName, List< T > &list) const
Definition: argListI.H:387
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
surfaceFields.H
Foam::surfaceFields.
Foam::transform
dimensionSet transform(const dimensionSet &ds)
Definition: dimensionSet.C:514
Foam::argList::get
T get(const label index) const
Definition: argListI.H:271
Foam::argList::readIfPresent
bool readIfPresent(const word &optName, T &val) const
Definition: argListI.H:316
regionNames
wordList regionNames
Definition: getAllRegionOptions.H:31
transformField.H
Spatial transformation functions for primitive fields.
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::TimePaths::relativePath
fileName relativePath(const fileName &input, const bool caseTag=false) const
Definition: TimePathsI.H:80
Foam::argList::lookup
ITstream lookup(const word &optName) const
Definition: argListI.H:177
Foam::coordinateRotations::axisAngle::rotation
static tensor rotation(const vector &axis, const scalar angle, bool degrees=false)
Definition: axisAngleRotation.C:58
Foam::Field
Generic templated field type.
Definition: Field.H:59
Foam::Info
messageStream Info
Foam::coordinateRotations
Namespace for coordinate system rotations.
Definition: axesRotation.C:30
Foam::boundBox::centre
point centre() const
Definition: boundBoxI.H:108
Foam::Vector< scalar >::X
@ X
Definition: Vector.H:77
argList.H
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:51
axisAngleRotation.H
Foam::Field::replace
void replace(const direction, const UList< cmptType > &)
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:55
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Definition: hashSets.C:40
fld
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))
Definition: gmvOutputLagrangian.H:23
Foam::Vector::x
const Cmpt & x() const
Definition: VectorI.H:66
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::dimensioned
Generic dimensioned Type class.
Definition: dimensionedScalarFwd.H:36
createRegionMesh.H
Required Variables.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:81
fvMesh.H
Foam
Definition: atmBoundaryLayer.C:26
Foam::Vector::z
const Cmpt & z() const
Definition: VectorI.H:78
Foam::Field::component
tmp< Field< cmptType > > component(const direction) const
Definition: Field.C:532
Foam::IOobjectList
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:51
Foam::Time::findInstance
word findInstance(const fileName &dir, const word &name=word::null, const IOobject::readOption rOpt=IOobject::MUST_READ, const word &stopInstance=word::null) const
Definition: Time.C:790
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
getAllRegionOptions.H
Priority.
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Definition: argList.C:317
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision() noexcept
Definition: IOstream.H:338
Time.H
setRootCase.H
ReadFields.H
Field reading functions for post-processing utilities.
addAllRegionOptions.H
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:50
Foam::Vector< scalar >
Foam::List< scalar >
Foam::Time::setTime
virtual void setTime(const Time &t)
Definition: Time.C:996
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::List::clear
void clear()
Definition: ListI.H:109
Foam::word::null
static const word null
Definition: word.H:78
createTime.H
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:57
Foam::Vector::y
const Cmpt & y() const
Definition: VectorI.H:72
Foam::coordinateRotations::euler::rotation
static tensor rotation(const vector &angles, bool degrees=false)
Definition: EulerCoordinateRotation.C:232
Foam::instant
An instant of time. Contains the time value and name.
Definition: instant.H:48
Foam::rotationTensor
tensor rotationTensor(const vector &n1, const vector &n2)
Definition: transform.H:47
Foam::Tuple2< vector, scalar >
regionDir
const word & regionDir
Definition: findMeshDefinitionDict.H:28
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
args
Foam::argList args(argc, argv)
Foam::equal
bool equal(const T &s1, const T &s2)
Definition: doubleFloat.H:41
pointFields.H
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171
Foam::IOobject::MUST_READ
@ MUST_READ
Definition: IOobject.H:181