From 7ea185b0b559f86ba277d63bf350155ee287373f Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 18 Aug 2022 11:07:53 +0200
Subject: [PATCH] ENH: support rotationCentre for surface output formats
 (#2565)

- as an alternative output transform (supplementary to the regular
  coordinate system specification - issue #2505) it is now possible to
  specify the rotation centre directly.

  Example:

      formatOptions
      {
          vtk
          {
              scale 1000;  // m -> mm
              transform
              {
                  origin  (0 0 0);
                  rotationCentre  (1 0 0);
                  rotation axisAngle;
                  axis    (0 0 1);
                  angle   -45;
              }
          }
      }

   This behaves like the transformPoints and surfaceTransformPoints
   '-centre' option (formerly '-origin') in that it removes the
   specified amount from the point locations, applies the rotation and
   finally adds the specified amount back to the newly rotated point
   locations.

   The results of specifying a `rotationCentre` and a non-zero
   coordinate system `origin` may not be intuitively evident.
---
 src/surfMesh/writers/common/surfaceWriter.C   | 53 +++++++++++++------
 src/surfMesh/writers/common/surfaceWriter.H   |  9 +++-
 .../squareBend/system/samplingDebug           | 15 ++++++
 3 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/src/surfMesh/writers/common/surfaceWriter.C b/src/surfMesh/writers/common/surfaceWriter.C
index 402a70ad083..bcc4c535363 100644
--- a/src/surfMesh/writers/common/surfaceWriter.C
+++ b/src/surfMesh/writers/common/surfaceWriter.C
@@ -144,6 +144,7 @@ Foam::surfaceWriter::surfaceWriter()
     adjustedSurf_(),
     mergeDim_(defaultMergeDim),
     geometryScale_(1),
+    geometryCentre_(Zero),
     geometryTransform_(),
     upToDate_(false),
     wroteGeom_(false),
@@ -168,6 +169,7 @@ Foam::surfaceWriter::surfaceWriter(const dictionary& options)
     options.readIfPresent("verbose", verbose_);
 
     geometryScale_ = 1;
+    geometryCentre_ = Zero;
     geometryTransform_.clear();
 
     options.readIfPresent("scale", geometryScale_);
@@ -175,8 +177,9 @@ Foam::surfaceWriter::surfaceWriter(const dictionary& options)
     const dictionary* dictptr;
 
     // Optional cartesian coordinate system transform
-    if ((dictptr = options.findDict("transform", keyType::LITERAL))!= nullptr)
+    if ((dictptr = options.findDict("transform", keyType::LITERAL)) != nullptr)
     {
+        dictptr->readIfPresent("rotationCentre", geometryCentre_);
         geometryTransform_ = coordSystem::cartesian(*dictptr);
     }
 
@@ -471,23 +474,43 @@ const Foam::meshedSurfRef& Foam::surfaceWriter::adjustSurface() const
     {
         adjustedSurf_.reset(surface());
 
-        if
-        (
-            geometryTransform_.valid()
-         &&
-            (
-                (magSqr(geometryTransform_.origin()) > ROOTVSMALL)
-             || !geometryTransform_.R().is_identity()
-            )
-        )
+        tmp<pointField> tpts;
+
+        if (geometryTransform_.valid())
         {
-            // Forward transform
-            adjustedSurf_.movePoints
-            (
-                geometryTransform_.globalPosition(adjustedSurf_.points0())
-            );
+            if (!geometryTransform_.R().is_identity())
+            {
+                if (magSqr(geometryCentre_) > ROOTVSMALL)
+                {
+                    // Set centre of rotation,
+                    // followed by forward transform (local -> global)
+                    tpts =
+                        geometryTransform_.globalPosition
+                        (
+                            adjustedSurf_.points0() - geometryCentre_
+                        );
+
+                    // Unset centre of rotation
+                    tpts.ref() += geometryCentre_;
+                }
+                else
+                {
+                    // Forward transform (local -> global)
+                    tpts =
+                        geometryTransform_.globalPosition
+                        (
+                            adjustedSurf_.points0()
+                        );
+                }
+            }
+            else if (magSqr(geometryTransform_.origin()) > ROOTVSMALL)
+            {
+                // Translate only (local -> global)
+                tpts = (adjustedSurf_.points0() + geometryTransform_.origin());
+            }
         }
 
+        adjustedSurf_.movePoints(tpts);
         adjustedSurf_.scalePoints(geometryScale_);
     }
 
diff --git a/src/surfMesh/writers/common/surfaceWriter.H b/src/surfMesh/writers/common/surfaceWriter.H
index f867b34a892..c4535a01548 100644
--- a/src/surfMesh/writers/common/surfaceWriter.H
+++ b/src/surfMesh/writers/common/surfaceWriter.H
@@ -62,11 +62,11 @@ Description
             transform
             {
                 origin  (0 0 0);
+                rotationCentre  (0 0 0);
                 rotation axisAngle;
                 axis    (1 0 0);
                 angle   45;
             }
-
         }
     }
     \endverbatim
@@ -82,6 +82,10 @@ Description
     \endtable
 
 Note
+    The \c transform sub-dictionary also supports a \c rotationCentre
+    keyword which applies \em untranslate by that amount prior to the rotation,
+    and subsequently followed by a \em translate.
+
     For surface formats that require geometry in a separate file,
     it is the responsibility of the implementation (not the caller)
     to ensure that this occurs.
@@ -147,6 +151,9 @@ protected:
         //- Output geometry scaling after rotate/translate
         scalar geometryScale_;
 
+        //- The centre of rotation (untranslate, translate)
+        point geometryCentre_;
+
         //- Local coordinate system transformation
         coordSystem::cartesian geometryTransform_;
 
diff --git a/tutorials/compressible/rhoSimpleFoam/squareBend/system/samplingDebug b/tutorials/compressible/rhoSimpleFoam/squareBend/system/samplingDebug
index 791fd7568f8..a8138d0be59 100644
--- a/tutorials/compressible/rhoSimpleFoam/squareBend/system/samplingDebug
+++ b/tutorials/compressible/rhoSimpleFoam/squareBend/system/samplingDebug
@@ -111,6 +111,21 @@ debug
             isoValue    1e5;
             regularise  true;
             interpolate true;
+
+            formatOptions
+            {
+                ensight
+                {
+                    transform
+                    {
+                        origin  (0 0 0);
+                        rotationCentre  (0.025 0 0);
+                        rotation axisAngle;
+                        axis    (0 1 0);
+                        angle   90;
+                    }
+                }
+            }
         }
 
         // Top channel
-- 
GitLab