diff --git a/applications/test/syncTools/missing_cell/Allclean b/applications/test/syncTools/missing_cell/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..b44c686537f5c140c2a58cecbb816c6ee6e05332
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/Allclean
@@ -0,0 +1,11 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+cleanCase
+
+# Remove surface and features
+rm -rf constant/triSurface
+
+#------------------------------------------------------------------------------
diff --git a/applications/test/syncTools/missing_cell/Allrun b/applications/test/syncTools/missing_cell/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..740433838365032766c54cacfa2601daf54b91df
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/Allrun
@@ -0,0 +1,27 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+#- Generate 2x2x1 cells
+runApplication blockMesh
+
+#- Remove cell0
+runApplication topoSet
+runApplication subsetMesh c0 -patch exposed0 -overwrite
+
+#- Put exposed faces (2) into separate patches
+runApplication -s face topoSet
+runApplication createPatch -overwrite
+
+#- Decompose - creates one processor without any faces in patches
+runApplication decomposePar
+
+#- Extract inter-patch points. Should include processor that does not
+#- have faces on patch ...
+mkdir -p constant/triSurface
+runParallel surfaceMeshExtract \
+    -patches '(exposed0 exposed1)' -featureAngle 180 \
+    constant/triSurface/blockMesh.obj
+
+#------------------------------------------------------------------------------
diff --git a/applications/test/syncTools/missing_cell/README.txt b/applications/test/syncTools/missing_cell/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..776e9a7483b2a6a19dd0adbb598cd16dc55a3579
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/README.txt
@@ -0,0 +1,7 @@
+- 2x2x1 mesh
+- remove one cell, exposing two faces
+- move exposed faces into two patches
+- decompose onto 3
+- run surfaceMeshExtract -featureAngle 180
+- should also mark points on the processor that has no
+  faces but is coupled
diff --git a/applications/test/syncTools/missing_cell/constant/transportProperties b/applications/test/syncTools/missing_cell/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..81751433add7024256d4bef17106be60be2f9d59
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/constant/transportProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+nu              0.01;
+
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/blockMeshDict b/applications/test/syncTools/missing_cell/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..b0b42b9b088166d3f044ab8747d08382b7bf91ec
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/blockMeshDict
@@ -0,0 +1,88 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    //- Single block
+    (0  0   0)
+    (2  0   0)
+    (2  2   0)
+    (0  2   0)
+    (0  0   2)
+    (2  0   2)
+    (2  2   2)
+    (0  2   2)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (2 2 1) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    topWall
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+    bottomWall
+    {
+        type wall;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    fixedWalls
+    {
+        type wall;
+        faces
+        (
+            (0 4 7 3)
+            (2 6 5 1)
+        );
+    }
+    frontAndBack
+    {
+        type patch;
+        faces
+        (
+            (0 3 2 1)
+            (4 5 6 7)
+        );
+    }
+    exposed0
+    {
+        type patch;
+        faces   ();
+    }
+);
+
+mergePatchPairs
+(
+);
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/controlDict b/applications/test/syncTools/missing_cell/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..67583ffe687146b8c60f6fe72ecd6e53e3193931
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/controlDict
@@ -0,0 +1,48 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     icoFoam;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         0.5;
+
+deltaT          0.005;
+
+writeControl    timeStep;
+
+writeInterval   20;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  16;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/createPatchDict b/applications/test/syncTools/missing_cell/system/createPatchDict
new file mode 100644
index 0000000000000000000000000000000000000000..2b8eb0d7041807418b750e116f98a19adf55b1b2
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/createPatchDict
@@ -0,0 +1,44 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      createPatchDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+pointSync false;
+
+// Patches to create.
+patches
+(
+    // Example of creating mapped patches using geometric matching
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    {
+        // Name of new patch
+        name exposed1;
+
+        // Dictionary to construct new patch from
+        patchInfo
+        {
+            type        patch;
+        }
+
+        // How to select the faces:
+        //  - set : specify faceSet in 'set'
+        //  - patches : specify names in 'patches'
+        //  - autoPatch : attempts automatic patching of the specified
+        //                candidates in 'patches'.
+        constructFrom   set;
+        set             exposed0;
+    }
+);
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/decomposeParDict b/applications/test/syncTools/missing_cell/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..2eb5272d0db72448a16bd13e8c7a7a4cc5c5029a
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/decomposeParDict
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  3;
+
+//- The decomposition method (mandatory)
+method              scotch;
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/fvSchemes b/applications/test/syncTools/missing_cell/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..51748f98addb1124e4052f9f06e625d4b83c752c
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/fvSchemes
@@ -0,0 +1,51 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{
+    default         Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(p)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear orthogonal;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         orthogonal;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/fvSolution b/applications/test/syncTools/missing_cell/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..e19b1d15604c8dce018e3fc4af17f77ddd37a135
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/fvSolution
@@ -0,0 +1,52 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-06;
+        relTol          0.05;
+    }
+
+    pFinal
+    {
+        $p;
+        relTol          0;
+    }
+
+    U
+    {
+        solver          smoothSolver;
+        smoother        symGaussSeidel;
+        tolerance       1e-05;
+        relTol          0;
+    }
+}
+
+PISO
+{
+    nCorrectors     2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell        0;
+    pRefValue       0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/syncTools/missing_cell/system/topoSetDict b/applications/test/syncTools/missing_cell/system/topoSetDict
new file mode 100644
index 0000000000000000000000000000000000000000..b58c9dc308435af3c38727a1dab3c06544970129
--- /dev/null
+++ b/applications/test/syncTools/missing_cell/system/topoSetDict
@@ -0,0 +1,48 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    {
+        name    c0;
+        type    cellSet;
+        action  new;
+        source  labelToCell;
+        value   (0);
+    }
+    {
+        name    c0;
+        type    cellSet;
+        action  invert;
+    }
+
+    {
+        name    exposed0;
+        type    faceSet;
+        action  new;
+        source  patchToFace;
+        patch   exposed0;
+    }
+    {
+        name    exposed0;
+        type    faceSet;
+        action  subset;
+        source  boxToFace;
+        box     (-100 1 -100)(100 100 100);
+    }
+);
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/generation/extrude/extrudeMesh/extrudeMesh.C b/applications/utilities/mesh/generation/extrude/extrudeMesh/extrudeMesh.C
index aed6edfbea3609967611fb628c3db5cd2bb4cb1d..9023c4f1642f518de12e59fed5189616434f484c 100644
--- a/applications/utilities/mesh/generation/extrude/extrudeMesh/extrudeMesh.C
+++ b/applications/utilities/mesh/generation/extrude/extrudeMesh/extrudeMesh.C
@@ -99,21 +99,21 @@ label findPatchID(const polyBoundaryMesh& patches, const word& name)
 }
 
 
-labelList patchFaces(const polyBoundaryMesh& patches, const wordList& names)
+labelList patchFaces(const polyBoundaryMesh& patches, const wordRes& names)
 {
+    const labelList patchIDs(patches.indices(names));
+
     label n = 0;
 
-    forAll(names, i)
+    for (label patchi : patchIDs)
     {
-        const polyPatch& pp = patches[findPatchID(patches, names[i])];
-
-        n += pp.size();
+        n += patches[patchi].size();
     }
     labelList faceLabels(n);
     n = 0;
-    forAll(names, i)
+    for (label patchi : patchIDs)
     {
-        const polyPatch& pp = patches[findPatchID(patches, names[i])];
+        const polyPatch& pp = patches[patchi];
 
         forAll(pp, j)
         {
@@ -128,24 +128,25 @@ labelList patchFaces(const polyBoundaryMesh& patches, const wordList& names)
 void zoneFaces
 (
     const faceZoneMesh& fzs,
-    const wordList& names,
+    const wordRes& names,
     labelList& faceLabels,
     bitSet& faceFlip
 )
 {
+    const labelList zoneIDs(fzs.indices(names));
+
     label n = 0;
 
-    forAll(names, i)
+    for (label zonei : zoneIDs)
     {
-        const auto& pp = fzs[fzs.findZoneID(names[i])];
-        n += pp.size();
+        n += fzs[zonei].size();
     }
     faceLabels.setSize(n);
     faceFlip.setSize(n);
     n = 0;
-    forAll(names, i)
+    for (label zonei : zoneIDs)
     {
-        const auto& pp = fzs[fzs.findZoneID(names[i])];
+        const auto& pp = fzs[zonei];
         const boolList& ppFlip = pp.flipMap();
         forAll(pp, i)
         {
@@ -345,8 +346,8 @@ int main(int argc, char *argv[])
             sourceCaseDir =
                 sourceCaseDir/("processor" + Foam::name(Pstream::myProcNo()));
         }
-        wordList sourcePatches;
-        wordList sourceFaceZones;
+        wordRes sourcePatches;
+        wordRes sourceFaceZones;
         if
         (
             dict.readIfPresent
@@ -868,13 +869,13 @@ int main(int argc, char *argv[])
         frontPatchFaces = patchFaces
         (
             meshFromSurface().boundaryMesh(),
-            wordList(1, frontPatchName)
+            wordRes(1, frontPatchName)
         );
         backPatchName = "otherSide";
         backPatchFaces = patchFaces
         (
             meshFromSurface().boundaryMesh(),
-            wordList(1, backPatchName)
+            wordRes(1, backPatchName)
         );
     }
 
diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index 2002149f2255a6b077bd4c902ce178367b7242bc..2cec08501cc23bd6a86e5867285be78065ceffdb 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -825,6 +825,17 @@ int main(int argc, char *argv[])
     #include "setSystemMeshDictionaryIO.H"
     const IOdictionary meshDict(dictIO);
 
+    // Overall mesh generation mode
+    const meshRefinement::MeshType meshType
+    (
+        meshRefinement::MeshTypeNames.getOrDefault
+        (
+            "type",
+            meshDict,
+            meshRefinement::CASTELLATED
+        )
+    );
+
 
     // all surface geometry
     const dictionary& geometryDict =
@@ -1339,6 +1350,7 @@ int main(int argc, char *argv[])
         shells,             // for volume (inside/outside) refinement
         limitShells,        // limit of volume refinement
         labelList(),        // initial faces to test
+        meshType,           // how to operate
         dryRun
     );
 
diff --git a/applications/utilities/mesh/manipulation/subsetMesh/subsetMesh.C b/applications/utilities/mesh/manipulation/subsetMesh/subsetMesh.C
index 1a195e360067a55c75931ae294c340663fd467d1..1b195acc0322956076116ac4dd7f71335a82c787 100644
--- a/applications/utilities/mesh/manipulation/subsetMesh/subsetMesh.C
+++ b/applications/utilities/mesh/manipulation/subsetMesh/subsetMesh.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -220,7 +220,7 @@ PtrList<FieldType> subsetFields
     const pointMesh& pMesh
 )
 {
-    const fvMesh& baseMesh = subsetter.baseMesh();
+    //const fvMesh& baseMesh = subsetter.baseMesh();
 
     const UPtrList<const IOobject> fieldObjects
     (
@@ -247,8 +247,8 @@ PtrList<FieldType> subsetFields
             IOobject
             (
                 io.name(),
-                baseMesh.time().timeName(),
-                baseMesh,
+                pMesh.thisDb().time().timeName(),
+                pMesh.thisDb(),
                 IOobjectOption::MUST_READ,
                 IOobjectOption::NO_WRITE,
                 IOobjectOption::NO_REGISTER
@@ -382,6 +382,8 @@ int main(int argc, char *argv[])
     #include "createTime.H"
 
     #include "createNamedMesh.H"
+    // Make sure pointMesh gets constructed/read as well
+    (void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
 
     // arg[1] = word (cellSet) or wordRes (cellZone)
     // const word selectionName = args[1];
@@ -583,7 +585,7 @@ int main(int argc, char *argv[])
     // Read point fields and subset
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    const pointMesh& pMesh = pointMesh::New(mesh);
+    const pointMesh& pMesh = pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
 
     #undef  createSubsetFields
     #define createSubsetFields(FieldType, Variable)             \
@@ -663,6 +665,18 @@ int main(int argc, char *argv[])
     subsetter.subMesh().write();
     processorMeshes::removeFiles(subsetter.subMesh());
 
+    auto* subPointMeshPtr =
+        subsetter.subMesh().thisDb().findObject<pointMesh>
+        (
+            pointMesh::typeName
+        );
+    if (subPointMeshPtr)
+    {
+        pointMesh& subPointMesh = const_cast<pointMesh&>(*subPointMeshPtr);
+        subPointMesh.setInstance(subsetter.subMesh().facesInstance());
+        subPointMesh.write();
+    }
+
 
     // Volume fields
     for (const auto& fld : vScalarFlds)     { fld.write(); }
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index df9c6d9ce26e724e70d30bde22ac4ed68fa15b7d..43222468845d083d27f36ed94df32ce6d54a8ae9 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2022 OpenCFD Ltd.
+    Copyright (C) 2016-2022,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -666,6 +666,9 @@ int main(int argc, char *argv[])
             ),
             decompDictFile
         );
+        // Make sure pointMesh gets read as well
+        (void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
+
 
         // Decompose the mesh
         if (!decomposeFieldsOnly)
@@ -785,6 +788,7 @@ int main(int argc, char *argv[])
             PtrList<labelIOList> cellProcAddressingList(mesh.nProcs());
             PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs());
             PtrList<labelIOList> pointProcAddressingList(mesh.nProcs());
+            PtrList<labelIOList> pointBoundaryProcAddressingList(mesh.nProcs());
 
             PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs());
             PtrList<pointFieldDecomposer> pointFieldDecomposerList
@@ -869,7 +873,10 @@ int main(int argc, char *argv[])
 
                 // Point fields
                 // ~~~~~~~~~~~~
-                const pointMesh& pMesh = pointMesh::New(mesh);
+
+                // Read decomposed pointMesh
+                const pointMesh& pMesh =
+                    pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
 
                 pointFieldDecomposer::fieldsCache pointFieldCache;
 
@@ -1138,7 +1145,34 @@ int main(int argc, char *argv[])
                             pointProcAddressingList
                         );
 
-                        const pointMesh& procPMesh = pointMesh::New(procMesh);
+                        const pointMesh& procPMesh =
+                            pointMesh::New(procMesh, IOobject::READ_IF_PRESENT);
+
+                        if (!pointBoundaryProcAddressingList.set(proci))
+                        {
+                            pointBoundaryProcAddressingList.set
+                            (
+                                proci,
+                                autoPtr<labelIOList>::New
+                                (
+                                    IOobject
+                                    (
+                                        "boundaryProcAddressing",
+                                        procMesh.facesInstance(),
+                                        polyMesh::meshSubDir
+                                       /pointMesh::meshSubDir,
+                                        procPMesh.thisDb(),
+                                        IOobject::READ_IF_PRESENT,
+                                        IOobject::NO_WRITE,
+                                        IOobject::NO_REGISTER
+                                    ),
+                                    boundaryProcAddressing
+                                )
+                            );
+                        }
+                        const auto& pointBoundaryProcAddressing =
+                            pointBoundaryProcAddressingList[proci];
+
 
                         if (!pointFieldDecomposerList.set(proci))
                         {
@@ -1150,7 +1184,7 @@ int main(int argc, char *argv[])
                                     pMesh,
                                     procPMesh,
                                     pointProcAddressing,
-                                    boundaryProcAddressing
+                                    pointBoundaryProcAddressing
                                 )
                             );
                         }
@@ -1162,6 +1196,12 @@ int main(int argc, char *argv[])
 
                         if (times.size() == 1)
                         {
+                            // Early deletion
+                            pointBoundaryProcAddressingList.set
+                            (
+                                proci,
+                                nullptr
+                            );
                             pointProcAddressingList.set(proci, nullptr);
                             pointFieldDecomposerList.set(proci, nullptr);
                         }
diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
index 2158e2a19e45b638270f05a9d76332919b247db2..c3d8ca5f8d94b507b2da4419defa9bcd96efbf48 100644
--- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
+++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C
@@ -44,6 +44,12 @@ License
 #include "decompositionModel.H"
 #include "hexRef8Data.H"
 
+// For handling pointMeshes with additional patches
+#include "pointMesh.H"
+#include "meshPointPatch.H"
+#include "processorPointPatch.H"
+#include "DynamicField.H"
+
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 void Foam::domainDecomposition::mark
@@ -740,6 +746,101 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
 
         procMesh.write();
 
+        // Add pointMesh if it was available
+        const auto* pMeshPtr =
+            thisDb().cfindObject<pointMesh>(pointMesh::typeName);
+        if (pMeshPtr)
+        {
+            const auto& pMesh = *pMeshPtr;
+            const auto& pMeshBoundary = pMesh.boundary();
+
+
+            // 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
+            //    any additional patches
+            const auto& procPointMesh = pointMesh::New(procMesh);
+
+            pointBoundaryMesh& procBoundary =
+                const_cast<pointBoundaryMesh&>(procPointMesh.boundary());
+
+
+            // 2. Explicitly add subsetted meshPointPatches
+            forAll(pMeshBoundary, patchi)
+            {
+                const auto* mppPtr = isA<meshPointPatch>(pMeshBoundary[patchi]);
+                if (mppPtr && (procBoundary.findPatchID(mppPtr->name()) == -1))
+                {
+                    const auto& mpp = *mppPtr;
+
+                    DynamicList<label> procMeshPoints(mpp.size());
+                    DynamicField<vector> procNormals(mpp.size());
+                    forAll(mpp.meshPoints(), i)
+                    {
+                        const label pointi = mpp.meshPoints()[i];
+                        const label procPointi = pointLookup[pointi];
+                        if (procPointi != -1)
+                        {
+                            procMeshPoints.append(procPointi);
+                            procNormals.append(mpp.pointNormals()[i]);
+                        }
+                    }
+
+                    procBoundary.push_back
+                    (
+                        new meshPointPatch
+                        (
+                            mpp.name(),
+                            procMeshPoints,
+                            procNormals,
+                            procBoundary.size(),
+                            procBoundary,
+                            meshPointPatch::typeName
+                        )
+                    );
+                }
+            }
+
+            // 3. Shuffle new patches before any processor patches
+            labelList oldToNew(procBoundary.size());
+            label newPatchi = 0;
+            forAll(procBoundary, patchi)
+            {
+                if (!isA<processorPointPatch>(procBoundary[patchi]))
+                {
+                    oldToNew[patchi] = newPatchi;
+                    newPatchi++;
+                }
+            }
+
+            // decomposed-to-undecomposed patch numbering
+            labelList boundaryProcAddressing(identity(newPatchi));
+            boundaryProcAddressing.setSize(procBoundary.size(), -1);
+
+            forAll(procBoundary, patchi)
+            {
+                if (isA<processorPointPatch>(procBoundary[patchi]))
+                {
+                    oldToNew[patchi] = newPatchi++;
+                }
+            }
+            procBoundary.reorder(oldToNew, true);
+
+            // Write pointMesh/boundary
+            procBoundary.write();
+
+            // Write pointMesh/boundaryProcAddressing
+            IOobject ioAddr
+            (
+                "boundaryProcAddressing",
+                procMesh.facesInstance(),
+                polyMesh::meshSubDir/pointMesh::meshSubDir,
+                procPointMesh.thisDb(),
+                IOobject::NO_READ,
+                IOobject::NO_WRITE,
+                IOobject::NO_REGISTER
+            );
+            IOListRef<label>(ioAddr, boundaryProcAddressing).write();
+        }
+
         // Write points if pointsInstance differing from facesInstance
         if (facesInstancePointsPtr_)
         {
diff --git a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
index 4d2910373d9c06e24d5444dee3ef0ff928fbe6c3..0e8f7f7b39cddf1a346702878af331a307517393 100644
--- a/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
+++ b/applications/utilities/parallelProcessing/reconstructPar/reconstructPar.C
@@ -427,24 +427,18 @@ int main(int argc, char *argv[])
             {
                 Info<< "Reconstructing point fields" << nl << endl;
 
-                const pointMesh& pMesh = pointMesh::New(mesh);
-                PtrList<pointMesh> pMeshes(procMeshes.meshes().size());
-
-                forAll(pMeshes, proci)
-                {
-                    pMeshes.set
-                    (
-                        proci,
-                        new pointMesh(procMeshes.meshes()[proci])
-                    );
-                }
+                const pointMesh& pMesh = pointMesh::New
+                (
+                    mesh,
+                    IOobject::READ_IF_PRESENT
+                );
 
                 pointFieldReconstructor reconstructor
                 (
                     pMesh,
-                    pMeshes,
+                    procMeshes.pointMeshes(),
                     procMeshes.pointProcAddressing(),
-                    procMeshes.boundaryProcAddressing()
+                    procMeshes.pointMeshBoundaryProcAddressing()
                 );
 
                 reconstructor.reconstructAllFields(objects, selectedFields);
diff --git a/applications/utilities/surface/surfaceMeshExtract/Make/options b/applications/utilities/surface/surfaceMeshExtract/Make/options
index 5ae72ebd31bdf7500846ee0dca7a4c123ff4fb43..09d94545a79d41316204b2dad2085ce4c5c22b21 100644
--- a/applications/utilities/surface/surfaceMeshExtract/Make/options
+++ b/applications/utilities/surface/surfaceMeshExtract/Make/options
@@ -1,7 +1,9 @@
 EXE_INC = \
     -I$(LIB_SRC)/surfMesh/lnInclude \
+    -I$(LIB_SRC)/fileFormats/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude
 
 EXE_LIBS = \
     -lsurfMesh \
+    -lfileFormats \
     -lmeshTools
diff --git a/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C b/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
index 3387ad26411d3504e2bbd384a540e8dec8a2488f..6f276914579981810a6e6fe31eb2ca43f0a6725d 100644
--- a/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
+++ b/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2017-2023 OpenCFD Ltd.
+    Copyright (C) 2017-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,13 +34,39 @@ Description
     Extract patch or faceZone surfaces from a polyMesh.
     Depending on output surface format triangulates faces.
 
-    Region numbers on faces no guaranteed to be the same as the patch indices.
+    Region numbers on faces not guaranteed to be the same as the patch indices.
 
     Optionally only extracts named patches.
 
+    Optionally filters out points on faceZones, feature-edges and
+    featurePoints and generates pointPatches
+    for these - written to pointMesh/boundary.
+
     If run in parallel, processor patches get filtered out by default and
     the mesh is merged (based on topology).
 
+Usage
+    \b surfaceMeshExtract [OPTION] \<surfacefile\>
+
+    Options:
+      - \par -patches NAME | LIST
+        Specify single patch or multiple patches (name or regex) to extract
+
+      - \par -faceZones NAME | LIST
+        Specify single zone or multiple face zones (name or regex) to extract
+
+      - \par -exclude-patches NAME | LIST
+        Exclude single or multiple patches (name or regex) from extraction
+
+      - \par -excludeProcPatches
+        Exclude processor patches (default if parallel)
+
+      - \par -featureAngle \<angle\>
+        Extract feature edges/points and put into separate point-patches
+
+      - \par -extractZonePoints
+        Extract all face zone points and put into separate point-patches
+
 \*---------------------------------------------------------------------------*/
 
 #include "MeshedSurface.H"
@@ -48,6 +74,7 @@ Description
 #include "argList.H"
 #include "Time.H"
 #include "polyMesh.H"
+#include "pointMesh.H"
 #include "emptyPolyPatch.H"
 #include "processorPolyPatch.H"
 #include "ListListOps.H"
@@ -56,11 +83,79 @@ Description
 #include "globalMeshData.H"
 #include "globalIndex.H"
 #include "timeSelector.H"
+#include "meshPointPatch.H"
+#include "unitConversion.H"
+#include "dummyTransform.H"
+#include "syncTools.H"
+#include "processorPointPatch.H"
+#include "pointMeshTools.H"
+#include "OBJstream.H"
 
 using namespace Foam;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+void writeOBJ
+(
+    const fileName& path,
+    const pointPatch& pp
+)
+{
+    const meshPointPatch& ppp = refCast<const meshPointPatch>(pp);
+    const polyMesh& mesh = ppp.boundaryMesh().mesh().mesh();
+
+    // Count constraints
+    label maxConstraint = 0;
+    const auto& constraints = ppp.constraints();
+    forAll(constraints, i)
+    {
+        maxConstraint = max(maxConstraint, constraints[i].first());
+    }
+    reduce(maxConstraint, maxOp<label>());
+
+    const pointField localPoints(mesh.points(), ppp.meshPoints());
+
+    if (maxConstraint == 3)
+    {
+        OBJstream os
+        (
+            path
+          / ppp.name()+"_fixedPoints.obj"
+        );
+        os.write(localPoints);
+        Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
+            << endl;
+    }
+    else if (maxConstraint == 2)
+    {
+        OBJstream os
+        (
+            path
+          / ppp.name()+"_slidingPoints.obj"
+        );
+        forAll(localPoints, i)
+        {
+            os.write(localPoints[i], constraints[i].second());
+        }
+        Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
+            << " as coordinates and normals"
+            << endl;
+    }
+    else if (maxConstraint == 1)
+    {
+        OBJstream os
+        (
+            path
+          / ppp.name()+"_surfacePoints.obj"
+        );
+        os.write(localPoints);
+        Info<< "Written pointPatch " << ppp.name() << " to " << os.name()
+            << " as coordinates"
+            << endl;
+    }
+}
+
+
 labelList getSelectedPatches
 (
     const polyBoundaryMesh& patches,
@@ -107,6 +202,286 @@ labelList getSelectedPatches
 }
 
 
+label addMeshPointPatches
+(
+    const polyMesh& mesh,
+    const pointMesh& pMesh,
+
+    const uindirectPrimitivePatch& allBoundary,
+    const labelUList& faceToZone,
+    const surfZoneIdentifierList& surfZones,
+    const labelList& faceZoneToCompactZone,
+
+    const scalar edgeFeatureAngle,
+    const scalar pointFeatureAngle,
+    const bool verbose = true,
+    const bool writePoints = false
+)
+{
+    const auto& pointBm = pMesh.boundary();
+    const auto& fzs = mesh.faceZones();
+    const label nPointPatches = pointBm.size();
+    const pointField& points = mesh.points();
+
+
+    // Feature edge(points) internal to a zone
+    labelListList zoneToMeshPoints;
+    List<pointConstraintList> zoneToConstraints;
+
+    // Feature edge(points) in between zones
+    labelList twoZoneMeshPoints;
+    pointConstraintList twoZoneConstraints;
+
+    // Feature points on > 2 zones
+    labelList multiZoneMeshPoints;
+    pointConstraintList multiZoneConstraints;
+
+    pointMeshTools::featurePointsEdges
+    (
+        mesh,
+        allBoundary,
+        // Per boundary face to zone
+        faceToZone,
+        // Number of zones
+        surfZones.size(),
+        edgeFeatureAngle,
+        //const scalar pointFeatureAngle, //not yet done
+
+        // Feature edge(points) internal to a zone
+        zoneToMeshPoints,
+        zoneToConstraints,
+
+        // Feature edge(points) in between zones
+        twoZoneMeshPoints,
+        twoZoneConstraints,
+
+        // Feature points on > 2 zones
+        multiZoneMeshPoints,
+        multiZoneConstraints
+    );
+
+
+    // Add per-zone patches
+    if (faceZoneToCompactZone.size())
+    {
+        // Calculate point normals consistent across whole patch
+        const pointField pointNormals
+        (
+            PatchTools::pointNormals
+            (
+                mesh,
+                allBoundary
+            )
+        );
+
+        forAll(faceZoneToCompactZone, zonei)
+        {
+            const label compacti = faceZoneToCompactZone[zonei];
+            if (compacti != -1)
+            {
+                const word patchName(surfZones[compacti].name());
+
+                if (pointBm.findPatchID(patchName) == -1)
+                {
+                    // Extract the points originating from the faceZone. Can
+                    //  - re-call featurePointsEdges with 0 feature angle so
+                    //    all points go into the feature edges
+                    //  - mark using faceToZone the correct points
+                    //  - or assume the whole faceZone was extracted:
+                    const uindirectPrimitivePatch fzPatch
+                    (
+                        UIndirectList<face>
+                        (
+                            mesh.faces(),
+                            fzs[zonei].addressing()
+                        ),
+                        points
+                    );
+                    const auto& mp = fzPatch.meshPoints();
+
+                    const vector nullVector(vector::uniform(0));
+
+                    // Extract pointNormal (or 0) on all patch/connected points
+                    vectorField meshPointNormals(mesh.nPoints(), nullVector);
+                    for (const label pointi : mp)
+                    {
+                        const label allPointi =
+                            allBoundary.meshPointMap()[pointi];
+                        meshPointNormals[pointi] = pointNormals[allPointi];
+                    }
+                    syncTools::syncPointList
+                    (
+                        mesh,
+                        meshPointNormals,
+                        maxMagSqrEqOp<vector>(),
+                        nullVector
+                    );
+
+                    // Extract indices with non-zero pointNormal
+                    DynamicList<label> meshPoints(mp.size());
+                    forAll(meshPointNormals, pointi)
+                    {
+                        if (meshPointNormals[pointi] != nullVector)
+                        {
+                            meshPoints.append(pointi);
+                        }
+                    }
+
+                    const_cast<pointBoundaryMesh&>(pointBm).push_back
+                    (
+                        new meshPointPatch
+                        (
+                            patchName,
+                            meshPoints,
+                            vectorField(meshPointNormals, meshPoints),
+                            pointBm.size(),
+                            pointBm,
+                            meshPointPatch::typeName
+                        )
+                    );
+
+                    if (verbose)
+                    {
+                        const auto& ppp = pointBm.last();
+                        Info<< "Added zone pointPatch " << ppp.name()
+                            << " with "
+                            << returnReduce(meshPoints.size(), sumOp<label>())
+                            << " points" << endl;
+                    }
+                    if (writePoints)
+                    {
+                        writeOBJ(mesh.path(), pointBm.last());
+                    }
+                }
+            }
+        }
+    }
+
+
+    // Add per-patch feature-edges
+    forAll(zoneToMeshPoints, zonei)
+    {
+        const label nPoints =
+            returnReduce(zoneToMeshPoints[zonei].size(), sumOp<label>());
+
+        const word patchName(surfZones[zonei].name() + "Edges");
+
+        if (nPoints && (pointBm.findPatchID(patchName) == -1))
+        {
+            const_cast<pointBoundaryMesh&>(pointBm).push_back
+            (
+                new meshPointPatch
+                (
+                    patchName,
+                    zoneToMeshPoints[zonei],
+                    zoneToConstraints[zonei],
+                    pointBm.size(),
+                    pointBm,
+                    meshPointPatch::typeName
+                )
+            );
+
+            if (verbose)
+            {
+                const auto& ppp = pointBm.last();
+                Info<< "Added feature-edges pointPatch " << ppp.name()
+                    << " with " << nPoints << " points" << endl;
+            }
+            if (writePoints)
+            {
+                writeOBJ(mesh.path(), pointBm.last());
+            }
+        }
+    }
+
+
+    // Add inter-patch points
+
+    const word allEdgePatchName("boundaryEdges");
+    const label nPatchEdgePoints =
+        returnReduce(twoZoneMeshPoints.size(), sumOp<label>());
+    if (nPatchEdgePoints && (pointBm.findPatchID(allEdgePatchName) == -1))
+    {
+        const_cast<pointBoundaryMesh&>(pointBm).push_back
+        (
+            new meshPointPatch
+            (
+                allEdgePatchName,
+                twoZoneMeshPoints,
+                twoZoneConstraints,
+                pointBm.size(),
+                pointBm,
+                meshPointPatch::typeName
+            )
+        );
+
+        if (verbose)
+        {
+            const auto& ppp = pointBm.last();
+            Info<< "Added inter-patch pointPatch " << ppp.name()
+                << " with " << nPatchEdgePoints << " points" << endl;
+        }
+        if (writePoints)
+        {
+            writeOBJ(mesh.path(), pointBm.last());
+        }
+    }
+
+
+    const word allPointPatchName("boundaryPoints");
+    const label nMultiPoints =
+        returnReduce(multiZoneMeshPoints.size(), sumOp<label>());
+    if (nMultiPoints && (pointBm.findPatchID(allPointPatchName) == -1))
+    {
+        const_cast<pointBoundaryMesh&>(pointBm).push_back
+        (
+            new meshPointPatch
+            (
+                allPointPatchName,
+                multiZoneMeshPoints,
+                multiZoneConstraints,
+                pointBm.size(),
+                pointBm,
+                meshPointPatch::typeName
+            )
+        );
+
+        if (verbose)
+        {
+            const auto& ppp = pointBm.last();
+            Info<< "Added multi-patch pointPatch " << ppp.name()
+                << " with " << nMultiPoints << " points" << endl;
+        }
+        if (writePoints)
+        {
+            writeOBJ(mesh.path(), pointBm.last());
+        }
+    }
+
+
+    // Shuffle into order
+    labelList oldToNew(pointBm.size());
+    label newPatchi = 0;
+    forAll(pointBm, patchi)
+    {
+        if (!isA<processorPointPatch>(pointBm[patchi]))
+        {
+            oldToNew[patchi] = newPatchi++;
+        }
+    }
+    forAll(pointBm, patchi)
+    {
+        if (isA<processorPointPatch>(pointBm[patchi]))
+        {
+            oldToNew[patchi] = newPatchi++;
+        }
+    }
+    const_cast<pointBoundaryMesh&>(pointBm).reorder(oldToNew, true);
+
+    return pointBm.size() - nPointPatches;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 int main(int argc, char *argv[])
@@ -114,8 +489,6 @@ int main(int argc, char *argv[])
     argList::addNote
     (
         "Extract patch or faceZone surfaces from a polyMesh."
-        " The name is historical, it only triangulates faces"
-        " when the output format requires it."
     );
     timeSelector::addOptions();
 
@@ -153,6 +526,22 @@ int main(int argc, char *argv[])
         true  // mark as an advanced option
     );
     argList::addOptionCompat("exclude-patches", {"excludePatches", 2306});
+    argList::addOption
+    (
+        "featureAngle",
+        "angle",
+        "Auto-extract feature edges/points and put into separate point-patches"
+    );
+    argList::addBoolOption
+    (
+        "extractZonePoints",
+        "Extract point-patches for selected faceZones"
+    );
+    argList::addBoolOption
+    (
+        "writeOBJ",
+        "Write added pointPatch points to .obj files"
+    );
 
     #include "setRootCase.H"
     #include "createTime.H"
@@ -200,9 +589,37 @@ int main(int argc, char *argv[])
             << nl << endl;
     }
 
+    scalar featureAngle = 180.0;
+    const bool specifiedFeature = args.readIfPresent
+    (
+        "featureAngle",
+        featureAngle
+    );
+
+    const bool extractZonePoints = args.found("extractZonePoints");
+    const bool writeOBJ = args.found("writeOBJ");
+
     Info<< "Reading mesh from time " << runTime.value() << endl;
 
     #include "createNamedPolyMesh.H"
+    if (specifiedFeature)
+    {
+        Info<< "Detecting all sharp (>" << featureAngle
+            << " degrees) patch edges." << nl << endl;
+
+        if (extractZonePoints)
+        {
+            Info<< "Extracting all faceZone points as pointPatches."
+                << nl << endl;
+        }
+
+        //#include "createNamedPointMesh.H"
+        // Do not read constant/pointMesh - construct from polyMesh only
+        Info<< "Create pointMesh for time = "
+             << runTime.timeName() << Foam::nl << Foam::endl;
+        (void)pointMesh::New(mesh);
+    }
+
 
     // User specified times
     instantList timeDirs = timeSelector::select0(runTime, args);
@@ -249,7 +666,7 @@ int main(int argc, char *argv[])
         // Construct table of patches to include.
         const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
 
-        labelList patchIds =
+        const labelList patchIds =
         (
             (includePatches.size() || excludePatches.size())
           ? getSelectedPatches(bMesh, includePatches, excludePatches)
@@ -276,7 +693,13 @@ int main(int argc, char *argv[])
         // Mesh face and compact zone indx
         DynamicList<label> faceLabels;
         DynamicList<label> compactZones;
+        // Per compact 'zone' index the name and location
+        surfZoneIdentifierList surfZones;
 
+        // Per local patch to compact 'zone' index (or -1)
+        labelList patchToCompactZone(bMesh.size(), -1);
+        // Per local faceZone to compact 'zone' index (or -1)
+        labelList faceZoneToCompactZone(bMesh.size(), -1);
         {
             // Collect sizes. Hash on names to handle local-only patches (e.g.
             //  processor patches)
@@ -317,9 +740,18 @@ int main(int argc, char *argv[])
             Pstream::broadcast(compactZoneID);
 
 
+            // Zones
+            surfZones.resize_nocopy(compactZoneID.size());
+            forAllConstIters(compactZoneID, iter)
+            {
+                surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
+                Info<< "surfZone " << *iter
+                    <<  " : "      << surfZones[*iter].name()
+                    << endl;
+            }
+
+
             // Rework HashTable into labelList just for speed of conversion
-            labelList patchToCompactZone(bMesh.size(), -1);
-            labelList faceZoneToCompactZone(bMesh.size(), -1);
             forAllConstIters(compactZoneID, iter)
             {
                 label patchi = bMesh.findPatchID(iter.key());
@@ -362,7 +794,7 @@ int main(int argc, char *argv[])
 
 
         // Addressing engine for all faces
-        uindirectPrimitivePatch allBoundary
+        const uindirectPrimitivePatch allBoundary
         (
             UIndirectList<face>(mesh.faces(), faceLabels),
             mesh.points()
@@ -400,7 +832,7 @@ int main(int argc, char *argv[])
 
         // Gather all ZoneIDs
         List<labelList> gatheredZones(Pstream::nProcs());
-        gatheredZones[Pstream::myProcNo()].transfer(compactZones);
+        gatheredZones[Pstream::myProcNo()] = compactZones;
         Pstream::gatherList(gatheredZones);
 
         // On master combine all points, faces, zones
@@ -428,16 +860,6 @@ int main(int argc, char *argv[])
             gatheredZones.clear();
 
 
-            // Zones
-            surfZoneIdentifierList surfZones(compactZoneID.size());
-            forAllConstIters(compactZoneID, iter)
-            {
-                surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
-                Info<< "surfZone " << *iter
-                    <<  " : "      << surfZones[*iter].name()
-                    << endl;
-            }
-
             UnsortedMeshedSurface<face> unsortedFace
             (
                 std::move(allPoints),
@@ -464,6 +886,39 @@ int main(int argc, char *argv[])
 
             sortedFace.write(globalCasePath);
         }
+
+
+        if (specifiedFeature)
+        {
+            // Add edge patches
+            const auto& pMesh = pointMesh::New(mesh);
+
+            const label nAdded = addMeshPointPatches
+            (
+                mesh,
+                pMesh,
+
+                allBoundary,    // all patches together
+                compactZones,   // originating compactZone
+                surfZones,      // per compactZone the index
+                (
+                    extractZonePoints
+                  ? faceZoneToCompactZone   // per faceZone the compactZone
+                  : labelList::null()
+                ),
+
+                featureAngle,
+                featureAngle,
+
+                true,
+                writeOBJ
+            );
+
+            if (nAdded)
+            {
+                pMesh.boundary().write();
+            }
+        }
     }
 
     Info<< "End\n" << endl;
diff --git a/etc/caseDicts/annotated/extrudeMeshDict b/etc/caseDicts/annotated/extrudeMeshDict
index 6832d739bb120399487b474470cc1d0447f8a331..a6ce6d7303f0d1337901258b085675f65da59946 100644
--- a/etc/caseDicts/annotated/extrudeMeshDict
+++ b/etc/caseDicts/annotated/extrudeMeshDict
@@ -26,6 +26,7 @@ constructFrom patch;
 // If construct from patch/mesh:
 sourceCase      "<case>";
 // and one of sourcePatches or sourceFaceZones (but not both):
+// (note: wildcards allowed)
 sourceFaceZones (someFacesZone);
 sourcePatches   (movingWall);
 
diff --git a/etc/caseDicts/annotated/snappyHexMeshDict b/etc/caseDicts/annotated/snappyHexMeshDict
index c45b2bfa65ee8a3d5d418466321bf9bb533dc91f..1cd48e0f394840113d10801a30f6a3424607d10a 100644
--- a/etc/caseDicts/annotated/snappyHexMeshDict
+++ b/etc/caseDicts/annotated/snappyHexMeshDict
@@ -14,6 +14,12 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Type of mesh generation:
+//  - castellated (default)
+//  - castellatedBufferLayer
+//type            castellatedBufferLayer;
+
+
 // Which of the steps to run
 castellatedMesh true;
 snap            true;
@@ -267,6 +273,10 @@ castellatedMeshControls
             //    these can be done with feature edge snapping (so can leave
             //    level (0 0))
             //curvatureLevel (10 0 10 -1);
+
+            // Optional disabling of buffer layer addition (if switched on by
+            // type = castellatedBufferLayer)
+            addBufferLayers false;
         }
     }
 
@@ -605,6 +615,18 @@ snapControls
         //- Attract points only to the surface they originate from. Default
         //  false. This can improve snapping of intersecting surfaces.
         //  strictRegionSnap true;
+
+
+    // Choice of mesh motion algorithm to inflate layers (only used for mode
+    // castellatedBufferLayer)
+
+        //solver  displacementPointSmoothing;
+        //displacementPointSmoothingCoeffs
+        //{
+        //    // Use laplacian to untangle problem areas
+        //    pointSmoother           laplacian;
+        //    nPointSmootherIter      10;
+        //}
 }
 
 // Settings for the layer addition.
diff --git a/etc/caseDicts/annotated/topoSetSourcesDict b/etc/caseDicts/annotated/topoSetSourcesDict
index 58727baa7e3fa6a61731f581188855d5fc2058ea..9021d8d94dbd99ee20bd18aae05de0ebd49cacdd 100644
--- a/etc/caseDicts/annotated/topoSetSourcesDict
+++ b/etc/caseDicts/annotated/topoSetSourcesDict
@@ -501,6 +501,15 @@ pointSet_doc
     }
 
 
+    //- All points of pointpatch
+    {
+        source  patchToPoint;
+        patches ("patch.*");
+        // or
+        patch   somePatch;
+    }
+
+
     //- Copy elements from pointSet
     {
         source  pointToPoint;
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index f8df675d93d013772900428798bb6ff33d568eb8..b19173cddc1f881a3ce7d63b9ba4e533f3c76ec7 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -715,10 +715,15 @@ pointMeshMapper = $(pointMesh)/pointMeshMapper
 $(pointMeshMapper)/pointMapper.C
 $(pointMeshMapper)/pointPatchMapper.C
 
+pointMeshTools = $(pointMesh)/pointMeshTools
+$(pointMeshTools)/pointMeshTools.C
+
 pointPatches = $(pointMesh)/pointPatches
 $(pointPatches)/pointPatch/pointPatch.C
+$(pointPatches)/pointPatch/pointPatchNew.C
 $(pointPatches)/facePointPatch/facePointPatch.C
 $(pointPatches)/facePointPatch/facePointPatchNew.C
+$(pointPatches)/meshPointPatch/meshPointPatch.C
 
 basicPointPatches = $(pointPatches)/basic
 $(basicPointPatches)/coupled/coupledPointPatch.C
@@ -792,6 +797,7 @@ $(Fields)/fieldTypes.C
 pointPatchFields = fields/pointPatchFields
 $(pointPatchFields)/pointPatchField/pointPatchFieldBase.C
 $(pointPatchFields)/pointPatchField/pointPatchFields.C
+$(pointPatchFields)/pointPatchField/pointConstraint/pointConstraint.C
 
 basicPointPatchFields = $(pointPatchFields)/basic
 $(basicPointPatchFields)/calculated/calculatedPointPatchFields.C
diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.C b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.C
new file mode 100644
index 0000000000000000000000000000000000000000..d1ab3d47ffd7b1f55768ca45a446170fe96180e6
--- /dev/null
+++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.C
@@ -0,0 +1,37 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointConstraint.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    const char* const pTraits<pointConstraint>::typeName = "pointConstraint";
+}
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H
index 932e44ed9a9356d692bcc4c3d7ea115d666c210c..d9adbf158213549ea1265357085bfe0c45cab0aa 100644
--- a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H
+++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraint.H
@@ -73,6 +73,9 @@ public:
         //- Construct from components
         inline pointConstraint(const Tuple2<label, vector>&);
 
+        //- Construct from components
+        inline pointConstraint(const label count, const vector& n);
+
         //- Construct from Istream
         inline pointConstraint(Istream&);
 
@@ -97,8 +100,19 @@ public:
 };
 
 
+//! List of pointConstraint
+typedef List<pointConstraint> pointConstraintList;
+
+
 // * * * * * * * * * * * * * * * * * Traits  * * * * * * * * * * * * * * * * //
 
+//- Template specialisation for pTraits\<pointConstraint\> to enable IO
+template<>
+struct pTraits<pointConstraint>
+{
+    static const char* const typeName;
+};
+
 //- Contiguous data for pointConstraint
 template<> struct is_contiguous<pointConstraint> : std::true_type {};
 
diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H
index c6c1b74dfbcd500460168139a3a08066d39cbf70..324165fe333da25c4738d6f8af65477a63c0a259 100644
--- a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H
+++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointConstraint/pointConstraintI.H
@@ -39,6 +39,16 @@ inline Foam::pointConstraint::pointConstraint(const Tuple2<label, vector>& pc)
 {}
 
 
+inline Foam::pointConstraint::pointConstraint
+(
+    const label count,
+    const vector& n
+)
+:
+    Tuple2<label, vector>(count, n)
+{}
+
+
 inline Foam::pointConstraint::pointConstraint(Istream& is)
 :
     Tuple2<label, vector>(is)
diff --git a/src/OpenFOAM/include/createNamedPointMesh.H b/src/OpenFOAM/include/createNamedPointMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..7c1c4265b7fc200331afe908c073f1a8c9ead467
--- /dev/null
+++ b/src/OpenFOAM/include/createNamedPointMesh.H
@@ -0,0 +1,10 @@
+Foam::Info
+    << "Create pointMesh for time = "
+    << runTime.timeName() << Foam::nl << Foam::endl;
+
+// Register pointMesh on the database
+const Foam::pointMesh& pMesh = pointMesh::New
+(
+    mesh,
+    Foam::IOobject::READ_IF_PRESENT
+);
diff --git a/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.C b/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.C
index 266583000abf2c357680f7c3805c5bdd6c7b6d4a..97990194a2091f524c1b71f76987d1ea9820d013 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2018-2023 OpenCFD Ltd.
+    Copyright (C) 2018-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -33,9 +33,74 @@ License
 #include "PstreamBuffers.H"
 #include "lduSchedule.H"
 #include "globalMeshData.H"
+#include "processorPointPatch.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(pointBoundaryMesh, 0);
+}
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+bool Foam::pointBoundaryMesh::hasGroupIDs() const
+{
+    if (groupIDsPtr_)
+    {
+        // Use existing cache
+        return !groupIDsPtr_->empty();
+    }
+
+    const auto& patches = *this;
+
+    for (const auto& p : patches)
+    {
+        if (!p.inGroups().empty())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+void Foam::pointBoundaryMesh::calcGroupIDs() const
+{
+    if (groupIDsPtr_)
+    {
+        return;  // Or FatalError
+    }
+
+    groupIDsPtr_.emplace(16);
+    auto& groupLookup = *groupIDsPtr_;
+
+    const auto& patches = *this;
+
+    forAll(patches, patchi)
+    {
+        for (const word& groupName : patches[patchi].inGroups())
+        {
+            groupLookup(groupName).push_back(patchi);
+        }
+    }
+
+    // Remove groups that clash with patch names
+    forAll(patches, patchi)
+    {
+        if (groupLookup.erase(patches[patchi].name()))
+        {
+            WarningInFunction
+                << "Removed group '" << patches[patchi].name()
+                << "' which clashes with patch " << patchi
+                << " of the same name."
+                << endl;
+        }
+    }
+}
+
+
 void Foam::pointBoundaryMesh::addPatches(const polyBoundaryMesh& pbm)
 {
     // Set boundary patches
@@ -43,7 +108,7 @@ void Foam::pointBoundaryMesh::addPatches(const polyBoundaryMesh& pbm)
 
     patches.resize_null(pbm.size());
 
-    forAll(patches, patchi)
+    forAll(pbm, patchi)
     {
         // NB: needs ptr() to get *pointPatch instead of *facePointPatch
         patches.set(patchi, facePointPatch::New(pbm[patchi], *this).ptr());
@@ -60,21 +125,301 @@ Foam::pointBoundaryMesh::pointBoundaryMesh
 )
 :
     pointPatchList(),
+    regIOobject
+    (
+        IOobject
+        (
+            "boundary",
+            //m.thisDb().time().findInstance(m.meshDir(), "boundary"),
+            pbm.mesh().facesInstance(),
+            polyMesh::meshSubDir/pointMesh::meshSubDir,
+            m.thisDb(),
+            IOobject::NO_READ,
+            IOobject::NO_WRITE,
+            false                   // Avoid conflict with polyMesh/boundary
+        )
+    ),
     mesh_(m)
 {
     addPatches(pbm);
+
+    if (debug)
+    {
+        pointPatchList& Patches = *this;
+
+        Pout<< "pointBoundaryMesh::pointBoundaryMesh"
+            << "(const pointMesh&, const polyBoundaryMesh&): "
+            << "constructed pointBoundaryMesh:" << endl;
+        Pout<< incrIndent;
+        for (const auto& pp : Patches)
+        {
+            Pout<< indent
+                << "index:" << pp.index() << " patch:" << pp.name()
+                << " type:" << pp.type() << endl;
+        }
+        Pout<< decrIndent;
+    }
+}
+
+
+Foam::pointBoundaryMesh::pointBoundaryMesh
+(
+    const IOobject& io,
+    const pointMesh& m,
+    const polyBoundaryMesh& pbm
+)
+:
+    pointPatchList(),
+    regIOobject
+    (
+        IOobject
+        (
+            "boundary",
+            io.instance(),
+            polyMesh::meshSubDir/pointMesh::meshSubDir,
+            io.db(),
+            io.readOpt(),
+            io.writeOpt(),
+            false   //io.registerObject()     // or always set to false?
+        )
+    ),
+    mesh_(m)
+{
+    pointPatchList& Patches = *this;
+
+    if (isReadRequired() || (isReadOptional() && headerOk()))
+    {
+        if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
+        {
+            WarningInFunction
+                << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
+                << " does not support automatic rereading."
+                << endl;
+        }
+
+        if (debug)
+        {
+            Pout<< "pointBoundaryMesh::pointBoundaryMesh"
+                << "(const IOobject&, const pointMesh&,"
+                << " const polyBoundaryMesh&): "
+                << "Constructing from boundary file " << objectRelPath()
+                << endl;
+        }
+
+        // Read pointPatchList
+        Istream& is = readStream(typeName);
+
+        PtrList<entry> patchEntries(is);
+        Patches.setSize(patchEntries.size());
+
+        forAll(Patches, patchi)
+        {
+            // Try construct-from-dictionary first
+            const word& name = patchEntries[patchi].keyword();
+
+            autoPtr<pointPatch> pPtr
+            (
+                pointPatch::New
+                (
+                    name,
+                    patchEntries[patchi].dict(),
+                    patchi,
+                    *this
+                )
+            );
+
+            if (!pPtr)
+            {
+                const label polyPatchi = pbm.findPatchID(name, false);
+                // Try as facePointPatch from polyPatch
+                pPtr = facePointPatch::New(pbm[polyPatchi], *this);
+                pPtr->index() = patchi;
+            }
+
+            Patches.set(patchi, pPtr);
+        }
+
+        // Check state of IOstream
+        is.check
+        (
+            "pointBoundaryMesh::pointBoundaryMesh"
+            "(const IOobject&, const pointMesh&,"
+            " const polyBoundaryMesh&)"
+        );
+
+        close();
+    }
+    else
+    {
+        if (debug)
+        {
+            Pout<< "pointBoundaryMesh::pointBoundaryMesh"
+                << "(const IOobject&, const pointMesh&,"
+                << " const polyBoundaryMesh&): "
+                << "Constructing from polyBoundaryMesh only"
+                << endl;
+        }
+
+        addPatches(pbm);
+    }
+
+
+    if (debug)
+    {
+        Pout<< "pointBoundaryMesh::pointBoundaryMesh"
+            << "(const IOobject&, const pointMesh&, const polyBoundaryMesh&): "
+            << "constructed pointBoundaryMesh:" << endl;
+        Pout<< incrIndent;
+        for (const auto& pp : Patches)
+        {
+            Pout<< indent
+                << "index:" << pp.index() << " patch:" << pp.name()
+                << " type:" << pp.type() << endl;
+        }
+        Pout<< decrIndent;
+    }
 }
 
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+Foam::label Foam::pointBoundaryMesh::nNonProcessor() const
+{
+    const pointPatchList& patches = *this;
+
+    label count = 0;
+
+    for (const auto& p : patches)
+    {
+        if (isA<processorPointPatch>(p))
+        {
+            break;
+        }
+
+        ++count;
+    }
+
+    return count;
+}
+
+
+Foam::label Foam::pointBoundaryMesh::nProcessorPatches() const
+{
+    const pointPatchList& patches = *this;
+
+    label count = 0;
+
+    for (const auto& p : patches)
+    {
+        if (isA<processorPointPatch>(p))
+        {
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+
+Foam::wordList Foam::pointBoundaryMesh::names() const
+{
+    return PtrListOps::get<word>(*this, nameOp<pointPatch>());
+}
+
+
+Foam::wordList Foam::pointBoundaryMesh::types() const
+{
+    return PtrListOps::get<word>(*this, typeOp<pointPatch>());
+}
+
+
+Foam::wordList Foam::pointBoundaryMesh::physicalTypes() const
+{
+    return
+        PtrListOps::get<word>
+        (
+            *this,
+            [](const pointPatch& p) { return p.physicalType(); }
+        );
+}
+
+
+const Foam::HashTable<Foam::labelList>&
+Foam::pointBoundaryMesh::groupPatchIDs() const
+{
+    if (!groupIDsPtr_)
+    {
+        calcGroupIDs();
+    }
+
+    return *groupIDsPtr_;
+}
+
+
 Foam::labelList Foam::pointBoundaryMesh::indices
 (
     const wordRe& matcher,
     const bool useGroups
 ) const
 {
-    return mesh().boundaryMesh().indices(matcher, useGroups);
+    if (matcher.empty())
+    {
+        return labelList();
+    }
+
+    // Only check groups if requested and they exist
+    const bool checkGroups = (useGroups && this->hasGroupIDs());
+
+    labelHashSet ids(0);
+
+    if (matcher.isPattern())
+    {
+        if (checkGroups)
+        {
+            const auto& groupLookup = groupPatchIDs();
+            forAllConstIters(groupLookup, iter)
+            {
+                if (matcher(iter.key()))
+                {
+                    // Add patch ids associated with the group
+                    ids.insert(iter.val());
+                }
+            }
+        }
+
+        if (ids.empty())
+        {
+            return PtrListOps::findMatching(*this, matcher);
+        }
+        else
+        {
+            ids.insert(PtrListOps::findMatching(*this, matcher));
+        }
+    }
+    else
+    {
+        // Literal string.
+        // Special version of above for reduced memory footprint.
+
+        const label patchId = PtrListOps::firstMatching(*this, matcher);
+
+        if (patchId >= 0)
+        {
+            return labelList(one{}, patchId);
+        }
+        else if (checkGroups)
+        {
+            const auto iter = groupPatchIDs().cfind(matcher);
+
+            if (iter.good())
+            {
+                // Hash ids associated with the group
+                ids.insert(iter.val());
+            }
+        }
+    }
+
+    return ids.sortedToc();
 }
 
 
@@ -84,7 +429,43 @@ Foam::labelList Foam::pointBoundaryMesh::indices
     const bool useGroups
 ) const
 {
-    return mesh().boundaryMesh().indices(matcher, useGroups);
+    if (matcher.empty())
+    {
+        return labelList();
+    }
+    else if (matcher.size() == 1)
+    {
+        return this->indices(matcher.front(), useGroups);
+    }
+
+    labelHashSet ids(0);
+
+    // Only check groups if requested and they exist
+    if (useGroups && this->hasGroupIDs())
+    {
+        ids.reserve(this->size());
+
+        const auto& groupLookup = groupPatchIDs();
+        forAllConstIters(groupLookup, iter)
+        {
+            if (matcher(iter.key()))
+            {
+                // Add patch ids associated with the group
+                ids.insert(iter.val());
+            }
+        }
+    }
+
+    if (ids.empty())
+    {
+        return PtrListOps::findMatching(*this, matcher);
+    }
+    else
+    {
+        ids.insert(PtrListOps::findMatching(*this, matcher));
+    }
+
+    return ids.sortedToc();
 }
 
 
@@ -95,13 +476,91 @@ Foam::labelList Foam::pointBoundaryMesh::indices
     const bool useGroups
 ) const
 {
-    return mesh().boundaryMesh().indices(select, ignore, useGroups);
+    //return mesh().boundaryMesh().indices(select, ignore, useGroups);
+    if (ignore.empty())
+    {
+        return this->indices(select, useGroups);
+    }
+
+    const wordRes::filter matcher(select, ignore);
+
+    labelHashSet ids(0);
+
+    // Only check groups if requested and they exist
+    if (useGroups && this->hasGroupIDs())
+    {
+        ids.reserve(this->size());
+
+        const auto& groupLookup = groupPatchIDs();
+        forAllConstIters(groupLookup, iter)
+        {
+            if (matcher(iter.key()))
+            {
+                // Add patch ids associated with the group
+                ids.insert(iter.val());
+            }
+        }
+    }
+
+    if (ids.empty())
+    {
+        return PtrListOps::findMatching(*this, matcher);
+    }
+    else
+    {
+        ids.insert(PtrListOps::findMatching(*this, matcher));
+    }
+
+    return ids.sortedToc();
 }
 
 
-Foam::label Foam::pointBoundaryMesh::findPatchID(const word& patchName) const
+Foam::label Foam::pointBoundaryMesh::findPatchID
+(
+    const word& patchName,
+    bool allowNotFound
+) const
 {
-    return mesh().boundaryMesh().findPatchID(patchName);
+    //return mesh().boundaryMesh().findPatchID(patchName);
+    if (patchName.empty())
+    {
+        return -1;
+    }
+
+    const label patchId = PtrListOps::firstMatching(*this, patchName);
+
+    if (patchId >= 0)
+    {
+        return patchId;
+    }
+
+    if (!allowNotFound)
+    {
+        FatalErrorInFunction
+            << "Patch '" << patchName << "' not found. "
+            << "Available patch names";
+
+        if (polyMesh::defaultRegion != mesh_.name())
+        {
+            FatalError
+                << " in region '" << mesh_.name() << "'";
+        }
+
+        FatalError
+            << " include: " << names() << endl
+            << exit(FatalError);
+    }
+
+    // Patch not found
+    if (debug)
+    {
+        Pout<< "label pointBoundaryMesh::findPatchID(const word&) const"
+            << " Patch named " << patchName << " not found.  "
+            << "Available patch names: " << names() << endl;
+    }
+
+    // Not found, return -1
+    return -1;
 }
 
 
@@ -243,4 +702,80 @@ void Foam::pointBoundaryMesh::updateMesh()
 }
 
 
+void Foam::pointBoundaryMesh::reorder
+(
+    const labelUList& oldToNew,
+    const bool validBoundary
+)
+{
+    // Change order of patches
+    pointPatchList::reorder(oldToNew);
+
+    // Adapt indices
+    pointPatchList& patches = *this;
+
+    forAll(patches, patchi)
+    {
+        patches[patchi].index() = patchi;
+    }
+
+    // Clear group-to-patch addressing. Note: could re-calculate
+    groupIDsPtr_.reset(nullptr);
+
+    if (validBoundary)
+    {
+        updateMesh();
+    }
+
+    if (debug)
+    {
+        pointPatchList& Patches = *this;
+
+        Pout<< "pointBoundaryMesh::reorder"
+            << "(const labelUList&, const bool): "
+            << "reordered pointBoundaryMesh:" << endl;
+        Pout<< incrIndent;
+        for (const auto& pp : Patches)
+        {
+            Pout<< indent
+                << "index:" << pp.index() << " patch:" << pp.name()
+                << " type:" << pp.type() << endl;
+        }
+        Pout<< decrIndent;
+    }
+}
+
+
+bool Foam::pointBoundaryMesh::writeData(Ostream& os) const
+{
+    const pointPatchList& patches = *this;
+
+    os  << patches.size() << nl << token::BEGIN_LIST << incrIndent << nl;
+
+    forAll(patches, patchi)
+    {
+        os  << indent << patches[patchi].name() << nl
+            << indent << token::BEGIN_BLOCK << nl
+            << incrIndent << patches[patchi] << decrIndent
+            << indent << token::END_BLOCK << endl;
+    }
+
+    os  << decrIndent << token::END_LIST;
+
+    // Check state of IOstream
+    os.check("pointBoundaryMesh::writeData(Ostream& os) const");
+
+    return os.good();
+}
+
+
+//bool Foam::pointBoundaryMesh::writeObject
+//(
+//    IOstreamOption
+//) const
+//{
+//    return regIOobject::writeObject(fmt, ver, IOstream::UNCOMPRESSED);
+//}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.H b/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.H
index 588245038b895debf9b0442310829ec6c6f76b6e..561d75e1725e21f4001f9d5db894ec13b1be8162 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointBoundaryMesh/pointBoundaryMesh.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2013 OpenFOAM Foundation
-    Copyright (C) 2018-2023 OpenCFD Ltd.
+    Copyright (C) 2018-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -39,6 +39,7 @@ SourceFiles
 #define Foam_pointBoundaryMesh_H
 
 #include "pointPatch.H"
+#include "regIOobject.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -56,19 +57,29 @@ class wordRes;
 
 class pointBoundaryMesh
 :
-    public pointPatchList
+    public pointPatchList,
+    public regIOobject
 {
     // Private Data
 
         //- Reference to mesh
         const pointMesh& mesh_;
 
+        //- Demand-driven: list of patch ids per group
+        mutable autoPtr<HashTable<labelList>> groupIDsPtr_;
+
 
     // Private Member Functions
 
         //- Calculate geometry for the patches (transformation tensors etc.)
         void calcGeometry();
 
+        //- Some patches have inGroup entries
+        bool hasGroupIDs() const;
+
+        //- Calculate group name to patch ids lookup
+        void calcGroupIDs() const;
+
         //- Assign facePointPatches corresponding to the given polyBoundaryMesh
         void addPatches(const polyBoundaryMesh& pbm);
 
@@ -85,11 +96,27 @@ public:
     friend class pointMesh;
 
 
+    //- Runtime type information
+    TypeName("pointBoundaryMesh");
+
+
     // Constructors
 
         //- Construct from polyBoundaryMesh
         pointBoundaryMesh(const pointMesh&, const polyBoundaryMesh&);
 
+        //- Construct from IOobject and polyBoundaryMesh
+        pointBoundaryMesh
+        (
+            const IOobject& io,
+            const pointMesh&,
+            const polyBoundaryMesh&
+        );
+
+
+    //- Destructor
+    virtual ~pointBoundaryMesh() = default;
+
 
     // Member Functions
 
@@ -99,6 +126,21 @@ public:
             return mesh_;
         }
 
+        //- The number of patches before the first processor patch.
+        label nNonProcessor() const;
+
+        //- The number of processorPointPatch patches
+        label nProcessorPatches() const;
+
+        //- Return a list of patch names
+        wordList names() const;
+
+        //- Return a list of patch types
+        wordList types() const;
+
+        //- Return a list of physical types
+        wordList physicalTypes() const;
+
         //- Return (sorted) patch indices for all matches.
         //  A no-op (returns empty list) for an empty matcher
         labelList indices(const wordRe& matcher, const bool useGroups) const;
@@ -121,14 +163,31 @@ public:
 
         //- Find patch index given a name
         //  A no-op (returns -1) for an empty patchName
-        label findPatchID(const word& patchName) const;
+        label findPatchID
+        (
+            const word& patchName,
+            const bool allowNotFound = true
+        ) const;
+
+        //- The patch indices per patch group
+        const HashTable<labelList>& groupPatchIDs() const;
 
-        //- Correct polyBoundaryMesh after moving points
+        //- Correct pointBoundaryMesh after moving points
         void movePoints(const pointField&);
 
-        //- Correct polyBoundaryMesh after topology update
+        //- Correct pointBoundaryMesh after topology update
         void updateMesh();
 
+        //- Reorders patches. Ordering does not have to be done in
+        //  ascending or descending order. Reordering has to be unique.
+        //  (is shuffle) If validBoundary calls updateMesh()
+        //  after reordering to recalculate data (so call needs to be parallel
+        //  sync in that case)
+        void reorder(const labelUList& oldToNew, const bool validBoundary);
+
+        //- writeData member function required by regIOobject
+        virtual bool writeData(Ostream&) const;
+
 
     // Housekeeping
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointMesh.C b/src/OpenFOAM/meshes/pointMesh/pointMesh.C
index 3f36c56332a6f6130742e649b9b97a357f2fcd32..7d5d74ab8ffbe059ec4106a4be182d8a6e6d2f3b 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointMesh.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointMesh.C
@@ -40,6 +40,8 @@ namespace Foam
     defineTypeNameAndDebug(pointMesh, 0);
 }
 
+Foam::word Foam::pointMesh::meshSubDir = "pointMesh";
+
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
@@ -89,8 +91,66 @@ Foam::pointMesh::pointMesh(const polyMesh& pMesh)
 }
 
 
+Foam::pointMesh::pointMesh(const polyMesh& pMesh, const IOobject& io)
+:
+    MeshObject<polyMesh, Foam::UpdateableMeshObject, pointMesh>(pMesh),
+    GeoMesh<polyMesh>(pMesh),
+    boundary_(io, *this, pMesh.boundaryMesh())
+{
+    if (debug)
+    {
+        Pout<< "pointMesh::pointMesh(const polyMesh&): "
+            << "Constructing from IO " << io.objectRelPath()
+            << endl;
+    }
+
+    // Calculate the geometry for the patches (transformation tensors etc.)
+    boundary_.calcGeometry();
+}
+
+
+Foam::pointMesh::pointMesh
+(
+    const polyMesh& pMesh,
+    const IOobjectOption::readOption rOpt
+)
+:
+    pointMesh
+    (
+        pMesh,
+        IOobject
+        (
+            pMesh.name(),                // polyMesh region
+            pMesh.facesInstance(),       // polyMesh topology instance
+            pMesh.time(),
+            rOpt,
+            Foam::IOobject::NO_WRITE
+        )
+    )
+{}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+void Foam::pointMesh::setInstance
+(
+    const fileName& inst,
+    const IOobjectOption::writeOption wOpt
+)
+{
+    if (debug)
+    {
+        Pout<< "pointMesh::setInstance(): "
+            << "Setting instance to " << inst << endl;
+    }
+    this->writeOpt(wOpt);
+    this->instance() = inst;
+
+    boundary_.writeOpt(wOpt);
+    boundary_.instance() = inst;
+}
+
+
 bool Foam::pointMesh::movePoints()
 {
     if (debug)
@@ -119,4 +179,19 @@ void Foam::pointMesh::updateMesh(const mapPolyMesh& mpm)
 }
 
 
+bool Foam::pointMesh::writeObject
+(
+    IOstreamOption streamOpt,
+    const bool writeOnProc
+) const
+{
+    if (debug)
+    {
+        Pout<< "pointMesh::writeObject(IOstreamOption, const bool): "
+            << "Writing to " << boundary_.objectRelPath() << endl;
+    }
+    return boundary_.writeObject(streamOpt, writeOnProc);
+}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointMesh.H b/src/OpenFOAM/meshes/pointMesh/pointMesh.H
index 58462132078c368185b71681c61b17bd3ce6a2bf..8aaeb4f698c29acc8b6445972402e5e1c527b401 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointMesh.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointMesh.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2013 OpenFOAM Foundation
-    Copyright (C) 2021-2023 OpenCFD Ltd.
+    Copyright (C) 2021-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -96,12 +96,26 @@ public:
     // Declare name of the class and its debug switch
     ClassName("pointMesh");
 
+    //- Return the mesh sub-directory name (usually "pointMesh")
+    static word meshSubDir;
+
 
     // Constructors
 
         //- Construct from polyMesh
         explicit pointMesh(const polyMesh& pMesh);
 
+        //- Construct from polyMesh and IOobject (used when reading boundary)
+        explicit pointMesh(const polyMesh& pMesh, const IOobject& io);
+
+        //- Construct from polyMesh and readOpt. Takes instance, time etc
+        //- from polyMesh. Used when reading boundary.
+        explicit pointMesh
+        (
+            const polyMesh& pMesh,
+            const IOobjectOption::readOption rOpt
+        );
+
 
     //- Destructor
     ~pointMesh() = default;
@@ -151,6 +165,13 @@ public:
             return GeoMesh<polyMesh>::mesh_.time();
         }
 
+        //- Set the instance for mesh files
+        void setInstance
+        (
+            const fileName& instance,
+            const IOobjectOption::writeOption wOpt = IOobject::AUTO_WRITE
+        );
+
 
     // Volume Mesh
 
@@ -181,6 +202,16 @@ public:
         {
             return &pm == this;
         }
+
+
+    // Write
+
+        //- Write
+        virtual bool writeObject
+        (
+            IOstreamOption streamOpt,
+            const bool writeOnProc = true
+        ) const;
 };
 
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.C b/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.C
new file mode 100644
index 0000000000000000000000000000000000000000..c49189a46e40ddf34e8828db282f2deb472edbf5
--- /dev/null
+++ b/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.C
@@ -0,0 +1,542 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointMeshTools.H"
+#include "syncTools.H"
+#include "PatchTools.H"
+#include "dummyTransform.H"
+#include "unitConversion.H"
+//#include "OFstream.H"
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+void Foam::pointMeshTools::featurePointsEdges
+(
+    const polyMesh& mesh,
+
+    const uindirectPrimitivePatch& allBoundary,
+
+    // Per boundary face to zone
+    const labelUList& faceToZone,
+    // Number of zones
+    const label nZones,
+
+    const scalar edgeFeatureAngle,
+    //const scalar pointFeatureAngle, //not yet done
+
+    // Feature edge(points) internal to a zone
+    labelListList& zoneToMeshPoints,
+    List<pointConstraintList>& zoneToConstraints,
+
+    // Feature edge(points) in between zones
+    labelList& twoZoneMeshPoints,
+    pointConstraintList& twoZoneConstraints,
+
+    // Feature points on > 2 zones
+    labelList& multiZoneMeshPoints,
+    pointConstraintList& multiZoneConstraints
+)
+{
+    // Analyses edges on mesh faces and splits them up according to topology
+    // and geometry:
+    // - edges in between faces on same zone but making a feature angle
+    // - edges in between faces on two different zones
+    // - points on faces on > 2 zones
+
+
+    const globalMeshData& globalData = mesh.globalData();
+    const indirectPrimitivePatch& cpp = globalData.coupledPatch();
+    const mapDistribute& map = globalData.globalEdgeSlavesMap();
+    const auto& mp = allBoundary.meshPoints();
+
+    const vector nullVector(vector::uniform(0));
+    const auto assignNonNull = [&](vector& x, const vector& y)
+    {
+        if (x == nullVector && y != nullVector)
+        {
+            x = y;
+        }
+    };
+
+    // Calculate parallel-consistent point normals (as unweighted average
+    // of faceNormals). Note: only valid on patch points, not on mesh points
+    // that are coupled to these.
+    const pointField pointNormals
+    (
+        PatchTools::pointNormals
+        (
+            mesh,
+            allBoundary
+        )
+    );
+
+
+    // Find correspondence between allBoundary and coupled edges
+    labelList allEdges;
+    labelList coupledEdges;
+    bitSet sameEdgeOrientation;
+    PatchTools::matchEdges
+    (
+        allBoundary,
+        cpp,
+        allEdges,
+        coupledEdges,
+        sameEdgeOrientation
+    );
+
+
+
+    // To construct the patches we need to know per edge:
+    //  - patch on either side (if topological feature edge)
+    //  - faceNormal on either side (if feature angle)
+    // We need to know per point:
+    //  - patches on all connected faces
+    //  - faceNormals on all connected faces? And compare to average?
+    //    or edge normals on all connected edges
+
+
+    typedef Tuple2<label, vector> PN;
+    const PN nullPN(-1, nullVector);
+
+
+
+    // Point-based analysis
+    // ~~~~~~~~~~~~~~~~~~~~
+
+    // Collect per (mesh)point the zones (1, 2 or >2). Note: per mesh to
+    // make it easier to sync. See edge-based code below where we explicitly
+    // have to transfer from patch-edge to mesh-point etc. Note sure which one
+    // fits better....
+    // State:
+    //  (-1, -1)    : initial state
+    //  (-2, -2)    : more than 2 zones
+    //  (>=0, >=0)  : zones from connected faces
+    labelPairList pointToZones(mesh.nPoints(), labelPair(-1, -1));
+    {
+        // Combine zones.
+        const auto combineZones = [&](labelPair& x, const labelPair& y)
+        {
+            if (x == labelPair(-2, -2))
+            {
+                // Already marked as having >2 zones
+            }
+            else if (y == labelPair(-2, -2))
+            {
+                x = y;
+            }
+            else
+            {
+                // Find first free slot
+                if (x[0] == -1)
+                {
+                    if (y[0] != -1)
+                    {
+                        x[0] = y[0];
+                    }
+                    else
+                    {
+                        x[0] = y[1];
+                    }
+                }
+                else if (x[1] == -1)
+                {
+                    if (y[0] != -1 && y[0] != x[0])
+                    {
+                        x[1] = y[0];
+                    }
+                    else if (y[1] != -1 && y[1] != x[1])
+                    {
+                        x[1] = y[1];
+                    }
+                }
+                else
+                {
+                    // Both x slots filled. See if y adds a 3rd element
+                    if (y[0] != -1 && y[0] != x[0] && y[0] != x[1])
+                    {
+                        x = labelPair(-2, -2);
+                    }
+                    else if (y[1] != -1 && y[1] != x[0] && y[1] != x[1])
+                    {
+                        x = labelPair(-2, -2);
+                    }
+                }
+            }
+        };
+
+
+        forAll(allBoundary, facei)
+        {
+            const auto& f = allBoundary[facei];
+            const label zonei = faceToZone[facei];
+            for (const label pointi : f)
+            {
+                auto& pZones = pointToZones[pointi];
+
+                if (pZones != labelPair(-2, -2) && !pZones.contains(zonei))
+                {
+                    if (pZones.first() == -1)
+                    {
+                        pZones.first() = zonei;
+                    }
+                    else if (pZones.second() == -1)
+                    {
+                        pZones.second() = zonei;
+                    }
+                    else
+                    {
+                        // Mark as >2 zones
+                        pZones = labelPair(-2, -2);
+                    }
+                }
+            }
+        }
+
+        syncTools::syncPointList
+        (
+            mesh,
+            pointToZones,
+            combineZones,
+            labelPair(-1, -1),
+            dummyTransform()
+        );
+    }
+
+
+
+
+    // Edge-based analysis
+    // ~~~~~~~~~~~~~~~~~~~~
+
+    // 1. Local analysis
+
+    List<Pair<PN>> allEdgeToFaces
+    (
+        allBoundary.nEdges(),
+        Pair<PN>(nullPN, nullPN)
+    );
+    {
+        const auto& edgeFaces = allBoundary.edgeFaces();
+        const auto& faceNormals = allBoundary.faceNormals();
+
+        forAll(edgeFaces, edgei)
+        {
+            const auto& eFaces = edgeFaces[edgei];
+            const vector& n0 = faceNormals[eFaces[0]];
+            const label zone0 = faceToZone[eFaces[0]];
+            if (eFaces.size() == 1)
+            {
+                allEdgeToFaces[edgei] = Pair<PN>(PN(zone0, n0), nullPN);
+            }
+            else
+            {
+                const vector& n1 = faceNormals[eFaces[1]];
+                const label zone1 = faceToZone[eFaces[1]];
+                allEdgeToFaces[edgei] = Pair<PN>
+                (
+                    PN(zone0, n0),
+                    PN(zone1, n1)
+                );
+            }
+        }
+    }
+
+
+    // 2. Sync across coupled patches
+
+    {
+        // Combine pair of normals
+        const auto vectorPairMax = [&](Pair<PN>& x, const Pair<PN>& y)
+        {
+            if (x[0] == nullPN)
+            {
+                if (y[0] != nullPN)
+                {
+                    x[0] = y[0];
+                }
+                else
+                {
+                    x[0] = y[1];
+                }
+            }
+            else if (x[1] == nullPN)
+            {
+                if (y[0] != nullPN && y[0] != x[0])
+                {
+                    x[1] = y[0];
+                }
+                else
+                {
+                    x[1] = y[1];
+                }
+            }
+        };
+
+        List<Pair<PN>> cppEdgeData
+        (
+            map.constructSize(),
+            Pair<PN>(nullPN, nullPN)
+        );
+        UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges) =
+            UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges);
+
+        globalData.syncData
+        (
+            cppEdgeData,
+            globalData.globalEdgeSlaves(),
+            globalData.globalEdgeTransformedSlaves(),
+            map,
+            globalData.globalTransforms(),
+            vectorPairMax,
+            dummyTransform()
+        );
+
+        UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges) =
+            UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges);
+    }
+
+
+    // Now we have all the per-patch edge information
+    // - do inter-patch edges
+    // - do feature-angle edges
+    // Store on mesh points
+
+    const auto assignNonNullPN = [&](PN& x, const PN& y)
+    {
+        if (x.second() == nullVector && y.second() != nullVector)
+        {
+            x = y;
+        }
+    };
+
+
+    const scalar featEdgeCos = Foam::cos(degToRad(edgeFeatureAngle));
+
+
+    //OFstream os("allBoundary.obj");
+    //Pout<< "Dumping feature edges to " << os.name() << endl;
+    //OFstream interOs("interZoneBoundary.obj");
+    //Pout<< "Dumping inter-zone edges to " << os.name() << endl;
+
+    // Storing the normal for points that are on inter-patch edges
+    vectorField patchEdgeNormal(mesh.nPoints(), nullVector);
+    // Storing the constraint for points that are on patch-internal feat edges
+    List<PN> featEdgeNormal(mesh.nPoints(), nullPN);
+
+    // Use point-based sync
+    {
+        forAll(allEdgeToFaces, edgei)
+        {
+            const edge& e = allBoundary.edges()[edgei];
+            const label mp0 = mp[e[0]];
+            const label mp1 = mp[e[1]];
+
+            const Pair<PN>& facesInfo = allEdgeToFaces[edgei];
+
+            if (facesInfo[1] == nullPN)
+            {
+                // Real boundary edge. On single patch only so no need
+                // to put in separate point patch ... (? tbd)
+            }
+            else
+            {
+                const label zone0 = facesInfo[0].first();
+                const label zone1 = facesInfo[1].first();
+
+                const point& p0 = allBoundary.points()[mp0];
+                const point& p1 = allBoundary.points()[mp1];
+                vector eVec(p1-p0);
+                eVec.normalise();
+
+                if (zone0 != zone1)
+                {
+                    // Inter-patch. TBD: check for feature angle as well?
+
+                    //patchEdgeNormal[mp0] = pointNormals[e[0]];
+                    //patchEdgeNormal[mp1] = pointNormals[e[1]];
+
+                    patchEdgeNormal[mp0] = eVec;
+                    patchEdgeNormal[mp1] = eVec;
+                }
+                else
+                {
+                    // Same patch - check for feature angle
+
+                    const vector& n0 = facesInfo[0].second();
+                    const vector& n1 = facesInfo[1].second();
+
+                    if ((n0 & n1) < featEdgeCos)
+                    {
+                        //Pout<< "** feature edge:" << edgei
+                        //    << " points:" << allBoundary.points()[mp0]
+                        //    << allBoundary.points()[mp1]
+                        //    << nl
+                        //    << " faceNormal0:" << n0
+                        //    << " faceNormal1:" << n1 << nl
+                        //    << " zone0:" << zone0
+                        //    << " zone1:" << zone1 << nl
+                        //    << " pointNormals0:" << pointNormals[e[0]]
+                        //    << " pointNormals1:" << pointNormals[e[1]]
+                        //    << nl
+                        //    << endl;
+
+                        if (patchEdgeNormal[mp0] == nullVector)
+                        {
+                            //featEdgeNormal[mp0] = PN
+                            //(
+                            //    zone0,   // zone
+                            //    pointNormals[e[0]]
+                            //);
+                            featEdgeNormal[mp0].first() = zone0;
+                            // Assign edge direction. TBD: average & parallel
+                            featEdgeNormal[mp0].second() = eVec;
+                        }
+                        if (patchEdgeNormal[mp1] == nullVector)
+                        {
+                            //featEdgeNormal[mp1] = PN
+                            //(
+                            //    zone1,   // zone
+                            //    pointNormals[e[1]]
+                            //);
+                            featEdgeNormal[mp1].first() = zone1;
+                            // Assign edge direction. TBD: average & parallel
+                            featEdgeNormal[mp1].second() = eVec;
+                        }
+                    }
+                }
+            }
+        }
+
+        syncTools::syncPointList
+        (
+            mesh,
+            patchEdgeNormal,
+            assignNonNull,
+            nullVector
+        );
+        syncTools::syncPointList
+        (
+            mesh,
+            featEdgeNormal,
+            assignNonNullPN,
+            nullPN,
+            dummyTransform()
+        );
+    }
+
+    // Make sure that inter-patch points are not also in feature-edge
+    // points. Note: not absolutely necessary since all inter-patch points
+    // will also be in the 'normal' facePointPatches.
+
+    DynamicList<label> dynMultiZoneMeshPoints(allBoundary.nPoints());
+    DynamicList<pointConstraint> dynMultiZoneConstraints(allBoundary.nPoints());
+    forAll(pointToZones, pointi)
+    {
+        if (pointToZones[pointi] == labelPair(-2, -2))
+        {
+            dynMultiZoneMeshPoints.append(pointi);
+            // Note: pointConstraint just a slip constraint for now
+            dynMultiZoneConstraints.append
+            (
+                pointConstraint
+                (
+                    3,                  // feature point
+                    Zero                //meshPointNormals[pointi]
+                )
+            );
+            // Unmark as feature angle point
+            patchEdgeNormal[pointi] = nullVector;
+            featEdgeNormal[pointi] = nullPN;
+        }
+    }
+    multiZoneMeshPoints = std::move(dynMultiZoneMeshPoints);
+    multiZoneConstraints = std::move(dynMultiZoneConstraints);
+
+
+    DynamicList<label> dynTwoZoneMeshPoints(allBoundary.nPoints());
+    DynamicList<pointConstraint> dynTwoZoneConstraints(allBoundary.nPoints());
+    forAll(patchEdgeNormal, pointi)
+    {
+        if (patchEdgeNormal[pointi] != nullVector)
+        {
+            dynTwoZoneMeshPoints.append(pointi);
+            // Note: pointConstraint just a slip constraint for now
+            dynTwoZoneConstraints.append
+            (
+                pointConstraint
+                (
+                    2,                  // feature edge
+                    patchEdgeNormal[pointi]
+                )
+            );
+
+            // Unmark as feature angle point
+            featEdgeNormal[pointi] = nullPN;
+        }
+    }
+    twoZoneMeshPoints = std::move(dynTwoZoneMeshPoints);
+    twoZoneConstraints = std::move(dynTwoZoneConstraints);
+
+
+    // Sort featEdgeNormal according to zone
+    zoneToMeshPoints.resize_nocopy(nZones);
+    zoneToConstraints.resize_nocopy(nZones);
+    {
+        labelList sizes(nZones, 0);
+        forAll(featEdgeNormal, pointi)
+        {
+            const auto& pInfo = featEdgeNormal[pointi];
+            if (pInfo != nullPN)
+            {
+                const label zonei = pInfo.first();
+                sizes[zonei]++;
+            }
+        }
+        forAll(zoneToMeshPoints, zonei)
+        {
+            zoneToMeshPoints[zonei].setSize(sizes[zonei]);
+            zoneToConstraints[zonei].setSize(sizes[zonei]);
+        }
+        sizes = 0;
+        forAll(featEdgeNormal, pointi)
+        {
+            const auto& pInfo = featEdgeNormal[pointi];
+            if (pInfo != nullPN)
+            {
+                const label zonei = pInfo.first();
+                const label index = sizes[zonei]++;
+
+                zoneToMeshPoints[zonei][index] = pointi;
+                zoneToConstraints[zonei][index] =
+                    pointConstraint(2, pInfo.second()); // constrained to slide
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.H b/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.H
new file mode 100644
index 0000000000000000000000000000000000000000..cb5d87dc8a551588333eff49120c8084f08c1345
--- /dev/null
+++ b/src/OpenFOAM/meshes/pointMesh/pointMeshTools/pointMeshTools.H
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::polyMeshTools
+
+Description
+    Collection of static functions operating on pointMesh.
+
+SourceFiles
+    pointMeshTools.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef Foam_pointMeshTools_H
+#define Foam_pointMeshTools_H
+
+#include "pointMesh.H"
+#include "pointConstraint.H"
+#include "uindirectPrimitivePatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class pointMeshTools Declaration
+\*---------------------------------------------------------------------------*/
+
+class pointMeshTools
+{
+public:
+
+    //- Analyse patch for feature edges, feature points. Handles points
+    //- not being on a face of patch but coupled to it.
+    static void featurePointsEdges
+    (
+        const polyMesh& mesh,
+
+        const uindirectPrimitivePatch& boundary,
+        // Per boundary face to zone
+        const labelUList& faceToZone,
+        // Number of zones
+        const label nZones,
+
+        const scalar edgeFeatureAngle,
+        //const scalar pointFeatureAngle, //not yet done
+
+        // Feature edge(points) internal to a zone
+        labelListList& zoneToMeshPoints,
+        List<pointConstraintList>& zoneToConstraints,
+
+        // Feature edge(points) in between zones
+        labelList& twoZoneMeshPoints,
+        pointConstraintList& twoZoneConstraints,
+
+        // Feature points on > 2 zones
+        labelList& multiZoneMeshPoints,
+        pointConstraintList& multiZoneConstraints
+    );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/basic/generic/genericPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/basic/generic/genericPointPatch.H
index fe01c486bde117149f8a8b2027a437075c2dea5f..1ff942519f780afc3efd2094df683e57182a8364 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/basic/generic/genericPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/basic/generic/genericPointPatch.H
@@ -72,6 +72,39 @@ public:
         :
             facePointPatch(patch, bm)
         {}
+
+        //- Construct given the original patch and a map
+        genericPointPatch
+        (
+            const genericPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
+        :
+            facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<genericPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
 };
 
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.C
index ccccd2eb51e23c8ac2b161c0977aa0e9a557d269..479c7233c7fca3f7c9b9455af4ef4dd51fd81bf1 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.C
@@ -91,6 +91,20 @@ Foam::cyclicPointPatch::cyclicPointPatch
 {}
 
 
+Foam::cyclicPointPatch::cyclicPointPatch
+(
+    const cyclicPointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    coupledFacePointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    cyclicPolyPatch_(refCast<const cyclicPolyPatch>(patch.patch()))
+{}
+
+
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 Foam::cyclicPointPatch::~cyclicPointPatch()
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.H
index 493c0dc9d5f2b596c9688e5d6846e05a3f05e1b0..e40fd90e64b9922798cce6c67cc765859ce5ec11 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclic/cyclicPointPatch.H
@@ -105,6 +105,36 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        cyclicPointPatch
+        (
+            const cyclicPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<cyclicPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     //- Destructor
     virtual ~cyclicPointPatch();
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclicSlip/cyclicSlipPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclicSlip/cyclicSlipPointPatch.H
index 7b8d8ec754d5244d764f6c80e91e86d9af136360..d9f6be76df81ee51b026ad9bd55cde4009f11146 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclicSlip/cyclicSlipPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/cyclicSlip/cyclicSlipPointPatch.H
@@ -73,6 +73,39 @@ public:
             cyclicPointPatch(patch, bm)
         {}
 
+        //- Construct given the original patch and a map
+        cyclicSlipPointPatch
+        (
+            const cyclicSlipPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
+        :
+            cyclicPointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<cyclicSlipPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     //- Destructor
     virtual ~cyclicSlipPointPatch() = default;
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/empty/emptyPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/empty/emptyPointPatch.H
index 629cb53f9ac22b3c620b96c30feea11750526d92..6e4a41fe5d1e41d7fa96fdd3f172aeb9eff8f636 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/empty/emptyPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/empty/emptyPointPatch.H
@@ -72,6 +72,39 @@ public:
             facePointPatch(patch, bm)
         {}
 
+        //- Construct given the original patch and a map
+        emptyPointPatch
+        (
+            const emptyPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
+        :
+            facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<emptyPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     // Member Functions
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPointPatch.H
index 215d66170b539a755e3e84fbbd5907f97b53b235..8721152ad715a943cb3f0d3218a2380b378e27ad 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/nonuniformTransformCyclic/nonuniformTransformCyclicPointPatch.H
@@ -73,6 +73,40 @@ public:
             cyclicPointPatch(patch, bm)
         {}
 
+        //- Construct given the original patch and a map
+        nonuniformTransformCyclicPointPatch
+        (
+            const nonuniformTransformCyclicPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
+        :
+            cyclicPointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::
+                NewFrom<nonuniformTransformCyclicPointPatch>
+                (
+                    *this,
+                    bm,
+                    index,
+                    mapAddressing,
+                    reversePointMap
+                );
+        }
+
 
     // Destructor
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.C
index 2190e44f8407add2d9ab9402699a0b421308c183..b81fab03d566f3b6119def2d7a1fe087e7963d17 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.C
@@ -117,4 +117,20 @@ Foam::processorPointPatch::processorPointPatch
 {}
 
 
+Foam::processorPointPatch::processorPointPatch
+(
+    const processorPointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    coupledFacePointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    procPolyPatch_(refCast<const processorPolyPatch>(patch.patch()))
+{
+    //? map reverseMeshPoints_ or leave demand-driven
+}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.H
index df6a488b417bd9645b22800978697affab758cbc..2c59c5c9f357112ae07c81f909a183edcfeb2506 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processor/processorPointPatch.H
@@ -111,6 +111,36 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        processorPointPatch
+        (
+            const processorPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<processorPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     //- Destructor
     virtual ~processorPointPatch() = default;
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.C
index c195173f03926c5450aeef9e2873a5dd60f74226..0b933a27575c47bb3e585361d4b0c17b99bffe33 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.C
@@ -59,6 +59,20 @@ processorCyclicPointPatch::processorCyclicPointPatch
 {}
 
 
+Foam::processorCyclicPointPatch::processorCyclicPointPatch
+(
+    const processorCyclicPointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    processorPointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    procCycPolyPatch_(refCast<const processorCyclicPolyPatch>(patch.patch()))
+{}
+
+
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
 processorCyclicPointPatch::~processorCyclicPointPatch()
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.H
index c24d0324544db53466717ce7562b909d6b5d49bf..1132df269ef4f6c02b401a749486181ada3f97d5 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/processorCyclic/processorCyclicPointPatch.H
@@ -89,6 +89,36 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        processorCyclicPointPatch
+        (
+            const processorCyclicPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<processorCyclicPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     //- Destructor
     virtual ~processorCyclicPointPatch();
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetry/symmetryPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetry/symmetryPointPatch.H
index d1dccb9125e6b8364d1e0d25e4e2f373e17fc956..6061b2aa8265c598b0b6d4b22f17e49288109642 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetry/symmetryPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetry/symmetryPointPatch.H
@@ -75,6 +75,38 @@ public:
             facePointPatch(patch, bm)
         {}
 
+        //- Construct given the original patch and a map
+        symmetryPointPatch
+        (
+            const symmetryPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ):
+            facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<symmetryPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     // Member Functions
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.C
index 57e66e7cc467fb3fae03d7eb2278c1b11efef341..52bfbfe9f010aeff616e339789e7d4b197f9fb34 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.C
@@ -58,6 +58,23 @@ Foam::symmetryPlanePointPatch::symmetryPlanePointPatch
 {}
 
 
+Foam::symmetryPlanePointPatch::symmetryPlanePointPatch
+(
+    const symmetryPlanePointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    symmetryPlanePolyPatch_
+    (
+        refCast<const symmetryPlanePolyPatch>(patch.patch())
+    )
+{}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 void Foam::symmetryPlanePointPatch::applyConstraint
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.H
index cbca7e1f3c86f2ed92bac7587e98b5ab55f34063..869a8725709bf5d9761e859063bf63ed873c75ba 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/symmetryPlane/symmetryPlanePointPatch.H
@@ -74,6 +74,36 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        symmetryPlanePointPatch
+        (
+            const symmetryPlanePointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<symmetryPlanePointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     // Member Functions
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.C
index 13989369045ffb8034e3f5f2c6c74800a9ab2921..84b1181045b43884361a44faa5853fdf7b2f1bf6 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.C
@@ -58,6 +58,20 @@ Foam::wedgePointPatch::wedgePointPatch
 {}
 
 
+Foam::wedgePointPatch::wedgePointPatch
+(
+    const wedgePointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    wedgePolyPatch_(refCast<const wedgePolyPatch>(patch.patch()))
+{}
+
+
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 void Foam::wedgePointPatch::applyConstraint
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.H
index e0100939cd68d5db63019cc5845c8ae0c0253e8e..a21513d04f8d23b1d294ae8153c2d9d8be9c5874 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/constraint/wedge/wedgePointPatch.H
@@ -74,6 +74,36 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        wedgePointPatch
+        (
+            const wedgePointPatch& pp,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<wedgePointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     // Member Functions
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.C
index 40ab33cdd97714dfa3fc48b28da589a2918f9a6e..0dcb653a0523663cd7f7d61a5971f79cf4d0ca67 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.C
@@ -50,4 +50,19 @@ Foam::coupledFacePointPatch::coupledFacePointPatch
 {}
 
 
+Foam::coupledFacePointPatch::coupledFacePointPatch
+(
+    const coupledFacePointPatch& patch,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    facePointPatch(patch, bm, index, mapAddressing, reversePointMap),
+    coupledPointPatch(bm),
+    coupledPolyPatch_(refCast<const coupledPolyPatch>(patch.patch()))
+{}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.H
index e3701771b458f868aaf1f2507bd04057b4205ea1..34724847dd21927a9d9dfd4b4f21913a3b77eeb8 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/coupled/coupledFacePointPatch.H
@@ -91,6 +91,16 @@ public:
             const pointBoundaryMesh& bm
         );
 
+        //- Construct given the original patch and a map
+        coupledFacePointPatch
+        (
+            const coupledFacePointPatch& pp,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
 
     //- Destructor
     virtual ~coupledFacePointPatch() = default;
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/wall/wallPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/wall/wallPointPatch.H
index a69065029fa195e4f1ebb7110cdc3545f62ed68a..bc7b4c0fd0145ee97e8bf472d0fad3d6771af00a 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/wall/wallPointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/derived/wall/wallPointPatch.H
@@ -71,6 +71,39 @@ public:
         :
             facePointPatch(patch, bm)
         {}
+
+        //- Construct given the original patch and a map
+        wallPointPatch
+        (
+            const wallPointPatch& patch,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
+        :
+            facePointPatch(patch, bm, index, mapAddressing, reversePointMap)
+        {}
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<wallPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
 };
 
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.C
index 1025a998fc9f1c1a190201313c728fde364f9191..594061a96f86db8e35047afbb09e93920837fa85 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.C
@@ -84,9 +84,30 @@ Foam::facePointPatch::facePointPatch
     const pointBoundaryMesh& bm
 )
 :
-    pointPatch(bm),
+    pointPatch(p.name(), p.index(), bm, p.physicalType(), p.inGroups()),
     polyPatch_(p)
 {}
 
 
+Foam::facePointPatch::facePointPatch
+(
+    const facePointPatch& pp,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    pointPatch
+    (
+        pp.name(),
+        index,
+        bm,
+        pp.physicalType(),
+        pp.inGroups()
+    ),
+    polyPatch_(pp.patch())
+{}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.H
index efb6c4789956a1af827230db19a9487f4351a1f7..a988d533116e8c38d9ac482fd613296240ed810c 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/facePointPatch/facePointPatch.H
@@ -128,6 +128,36 @@ public:
             const pointBoundaryMesh& pm
         );
 
+        //- Construct given the original patch and a map
+        facePointPatch
+        (
+            const facePointPatch& pp,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<facePointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
 
     // Selectors
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.C
new file mode 100644
index 0000000000000000000000000000000000000000..2e9c845c75cd2eacec46fd6aa351bed7b4938b4f
--- /dev/null
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.C
@@ -0,0 +1,235 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "meshPointPatch.H"
+#include "addToRunTimeSelectionTable.H"
+#include "pointMesh.H"
+#include "pointConstraint.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+defineTypeNameAndDebug(meshPointPatch, 0);
+
+//- Needs run-time selection table on pointPatch, not facePointPatch
+addToRunTimeSelectionTable
+(
+    pointPatch,
+    meshPointPatch,
+    dictionary
+);
+
+static List<pointConstraint> makeConstraints(const vectorField& normals)
+{
+    List<pointConstraint> cs(normals.size());
+
+    forAll(cs, i)
+    {
+        cs[i].applyConstraint(normals[i]);
+    }
+    return cs;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::meshPointPatch::meshPointPatch
+(
+    const word& name,
+    const labelUList& meshPoints,
+    const List<pointConstraint>& constraints,
+    const label index,
+    const pointBoundaryMesh& bm,
+    const word& patchType
+)
+:
+    pointPatch(name, index, bm, word::null, wordList()),
+    meshPoints_(meshPoints),
+    constraints_(constraints)
+{
+    if (meshPoints_.size() != constraints_.size())
+    {
+        FatalErrorInFunction << "patch " << name
+            << " size of meshPoints " << meshPoints_.size()
+            << " differs from size of constraints " << constraints_.size()
+            << exit(FatalError);
+    }
+}
+
+
+Foam::meshPointPatch::meshPointPatch
+(
+    const word& name,
+    const labelUList& meshPoints,
+    const vectorField& pointNormals,
+    const label index,
+    const pointBoundaryMesh& bm,
+    const word& patchType
+)
+:
+    pointPatch(name, index, bm, word::null, wordList()),
+    meshPoints_(meshPoints),
+    constraints_(makeConstraints(pointNormals))
+{
+    if (meshPoints_.size() != pointNormals.size())
+    {
+        FatalErrorInFunction << "patch " << name
+            << " size of meshPoints " << meshPoints_.size()
+            << " differs from size of pointNormals " << pointNormals.size()
+            << exit(FatalError);
+    }
+}
+
+
+Foam::meshPointPatch::meshPointPatch
+(
+    const word& name,
+    const dictionary& dict,
+    const label index,
+    const pointBoundaryMesh& bm,
+    const word& patchType
+)
+:
+    pointPatch(name, dict, index, bm),
+    meshPoints_(dict.get<labelList>("meshPoints")),
+    constraints_(dict.get<List<pointConstraint>>("constraints"))
+{}
+
+
+Foam::meshPointPatch::meshPointPatch
+(
+    const meshPointPatch& pp,
+    const pointBoundaryMesh& bm,
+    const label index,
+    const labelUList& mapAddressing,
+    const labelUList& reversePointMap
+)
+:
+    meshPointPatch
+    (
+        pp.name(),
+        labelList(reversePointMap, labelList(pp.meshPoints(), mapAddressing)),
+        List<pointConstraint>(pp.constraints(), mapAddressing),
+        index,
+        bm,
+        pp.type()
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::meshPointPatch::movePoints(PstreamBuffers&, const pointField& p)
+{
+    localPointsPtr_.reset(nullptr);
+
+    // Recalculate the point normals? Something like
+    //if (owner())
+    //{
+    //    const SubList<face> subFaces
+    //    (
+    //        mesh.faces(),
+    //        mesh.nBoundaryFaces(),
+    //        mesh.nInternalFaces()
+    //    );
+    //    const primitivePatch pp(subFaces, mesh.points());
+    //
+    //
+    //    for (const label pointi : meshPoints())
+    //    {
+    //        const auto fnd(pp.meshPointMap().find(pointi));
+    //        if (fnd)
+    //        {
+    //            const label patchPointi = fnd();
+    //            // Determine point patch equiv
+    //
+    //        const auto& point
+    //
+    //
+
+}
+    
+
+void Foam::meshPointPatch::updateMesh(PstreamBuffers&)
+{
+    localPointsPtr_.reset(nullptr);
+    pointNormalsPtr_.reset(nullptr);
+    // Do what to constraints_? Don't know what the new mesh points are
+}
+
+
+const Foam::pointField& Foam::meshPointPatch::localPoints() const
+{
+    if (!localPointsPtr_)
+    {
+        localPointsPtr_.reset
+        (
+            new pointField
+            (
+                boundaryMesh().mesh().mesh().points(),
+                meshPoints()
+            )
+        );
+    }
+    return localPointsPtr_();
+}
+
+
+const Foam::vectorField& Foam::meshPointPatch::pointNormals() const
+{
+    if (!pointNormalsPtr_)
+    {
+        pointNormalsPtr_.reset(new vectorField(size()));
+        vectorField& pointNormals = pointNormalsPtr_();
+        forAll(constraints_, i)
+        {
+            pointNormals[i] = constraints_[i].second();
+        }
+    }
+    return pointNormalsPtr_();
+}
+
+
+void Foam::meshPointPatch::write(Ostream& os) const
+{
+    pointPatch::write(os);
+    meshPoints().writeEntry("meshPoints", os);
+    constraints().writeEntry("constraints", os);
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.H
new file mode 100644
index 0000000000000000000000000000000000000000..54853d74386ac03f0c404ac8122d87f33c4a404d
--- /dev/null
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/meshPointPatch/meshPointPatch.H
@@ -0,0 +1,213 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::meshPointPatch
+
+Description
+    pointPatch with explicitly provided points instead of using the points
+    of a polyPatch.
+
+    Note: does not constrain displacement - is not a constraint patch.
+
+SourceFiles
+    meshPointPatch.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef meshPointPatch_H
+#define meshPointPatch_H
+
+#include "pointPatch.H"
+#include "polyPatch.H"
+#include "autoPtr.H"
+#include "patchIdentifier.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                  Class meshPointPatch Declaration
+\*---------------------------------------------------------------------------*/
+
+class meshPointPatch
+:
+    public pointPatch
+{
+private:
+
+    // Private Member Functions
+
+        //- No copy construct
+        meshPointPatch(const meshPointPatch&) = delete;
+
+        //- No copy assignment
+        void operator=(const meshPointPatch&) = delete;
+
+
+protected:
+
+    // Protected Member Data
+
+        //- Explicit mesh points
+        const labelList meshPoints_;
+
+        const List<pointConstraint> constraints_;
+
+        //- Demand-driven local points
+        mutable autoPtr<pointField> localPointsPtr_;
+
+        //- Demand-driven local normals (assumes constructed with pointNormals
+        //  or normal-only-constraint)
+        mutable autoPtr<pointField> pointNormalsPtr_;
+
+
+    // Protected Member Functions
+
+        //- Correct patches after moving points
+        virtual void movePoints(PstreamBuffers&, const pointField&);
+
+        //- Update of the patch topology
+        virtual void updateMesh(PstreamBuffers&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("meshPoint");
+
+
+    // Constructors
+
+        //- Construct from components
+        meshPointPatch
+        (
+            const word& name,
+            const labelUList& meshPoints,
+            const List<pointConstraint>& constraints,
+            const label index,
+            const pointBoundaryMesh& bm,
+            const word& patchType
+        );
+
+        //- Construct from single-constraint (i.e. slip, provided normals)
+        meshPointPatch
+        (
+            const word& name,
+            const labelUList& meshPoints,
+            const vectorField& pointNormals,
+            const label index,
+            const pointBoundaryMesh& bm,
+            const word& patchType
+        );
+
+        //- Construct from dictionary
+        meshPointPatch
+        (
+            const word& name,
+            const dictionary& dict,
+            const label index,
+            const pointBoundaryMesh& bm,
+            const word& patchType
+        );
+
+        //- Construct given the original patch and a map
+        meshPointPatch
+        (
+            const meshPointPatch& pp,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        );
+
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const
+        {
+            return autoPtr<pointPatch>::NewFrom<meshPointPatch>
+            (
+                *this,
+                bm,
+                index,
+                mapAddressing,
+                reversePointMap
+            );
+        }
+
+
+    //- Destructor
+    virtual ~meshPointPatch() = default;
+
+
+    // Member Functions
+
+        //- Return size
+        virtual label size() const
+        {
+            return meshPoints().size();
+        }
+
+        //- Return mesh points
+        virtual const labelList& meshPoints() const
+        {
+            return meshPoints_;
+        }
+
+        //- Return constraints
+        virtual const List<pointConstraint>& constraints() const
+        {
+            return constraints_;
+        }
+
+        //- Return pointField of points in patch
+        virtual const pointField& localPoints() const;
+
+        //- Return point unit normals. Assumes single constraint
+        virtual const vectorField& pointNormals() const;
+
+        //- Write the pointPatch data as a dictionary
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.C
index 39bc76279354e5754132d3baace7e19f6d87899a..9e462b02ffb2d7ecf785b81957a2a952b498a391 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.C
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2012 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -31,7 +32,33 @@ License
 
 namespace Foam
 {
-defineTypeNameAndDebug(pointPatch, 0);
+    defineTypeNameAndDebug(pointPatch, 0);
+
+//    int pointPatch::disallowGenericPointPatch
+//    (
+//        debug::debugSwitch("disallowGenericPointPatch", 0)
+//    );
+
+    defineRunTimeSelectionTable(pointPatch, dictionary);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::pointPatch::write(Ostream& os) const
+{
+    os.writeKeyword("type") << type() << token::END_STATEMENT << nl;
+    patchIdentifier::write(os);
+}
+
+
+// * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const pointPatch& p)
+{
+    p.write(os);
+    os.check("Ostream& operator<<(Ostream& os, const pointPatch& p");
+    return os;
 }
 
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.H b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.H
index 22b6e1943836eec073d64710ea03231bcee92a78..6af214b3192ee84b4e2d4bfccb03a461641f79c4 100644
--- a/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.H
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatch.H
@@ -38,6 +38,7 @@ SourceFiles
 #ifndef Foam_pointPatch_H
 #define Foam_pointPatch_H
 
+#include "patchIdentifier.H"
 #include "labelList.H"
 #include "vectorField.H"
 #include "pointField.H"
@@ -54,6 +55,8 @@ class pointConstraint;
 class pointPatch;
 class PstreamBuffers;
 
+Ostream& operator<<(Ostream&, const pointPatch&);
+
 //- Store lists of pointPatch as a PtrList
 typedef PtrList<pointPatch> pointPatchList;
 
@@ -62,6 +65,8 @@ typedef PtrList<pointPatch> pointPatchList;
 \*---------------------------------------------------------------------------*/
 
 class pointPatch
+:
+    public patchIdentifier
 {
     // Private Data
 
@@ -114,14 +119,90 @@ public:
     TypeName("basePatch");
 
 
+    // Declare run-time constructor selection tables
+
+        declareRunTimeSelectionTable
+        (
+            autoPtr,
+            pointPatch,
+            dictionary,
+            (
+                const word& name,
+                const dictionary& dict,
+                const label index,
+                const pointBoundaryMesh& bm,
+                const word& patchType
+            ),
+            (name, dict, index, bm, patchType)
+        );
+
+
     // Constructor
 
-        //- Construct from boundary mesh
-        explicit pointPatch(const pointBoundaryMesh& bm)
+        //- Construct from components
+        explicit pointPatch
+        (
+            const word& name,
+            const label index,
+            const pointBoundaryMesh& bm,
+            const word& physicalType,
+            const wordList& inGroups
+        )
+        :
+            patchIdentifier(name, index, physicalType, inGroups),
+            boundaryMesh_(bm)
+        {}
+
+        //- Construct from dictionary
+        explicit pointPatch
+        (
+            const word& name,
+            const dictionary& dict,
+            const label index,
+            const pointBoundaryMesh& bm
+        )
+        :
+            patchIdentifier(name, dict, index),
+            boundaryMesh_(bm)
+        {}
+
+        //- Construct given the original patch and a map
+        explicit pointPatch
+        (
+            const pointPatch& pp,
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        )
         :
+            patchIdentifier(pp.name(), index, pp.physicalType(), pp.inGroups()),
             boundaryMesh_(bm)
         {}
 
+        //- Construct and return a subset clone,
+        //- resetting the point list and boundary mesh
+        virtual autoPtr<pointPatch> clone
+        (
+            const pointBoundaryMesh& bm,
+            const label index,
+            const labelUList& mapAddressing,
+            const labelUList& reversePointMap
+        ) const = 0;
+
+
+    // Selectors
+
+        //- Return a pointer to a new patch created on freestore. Returns
+        //- null if not found
+        static autoPtr<pointPatch> New
+        (
+            const word& name,
+            const dictionary& dict,
+            const label index,
+            const pointBoundaryMesh&
+        );
+
 
     //- Destructor
     virtual ~pointPatch() = default;
@@ -129,15 +210,9 @@ public:
 
     // Member Functions
 
-        //- Return name
-        virtual const word& name() const = 0;
-
         //- Return size
         virtual label size() const = 0;
 
-        //- Return the index of this patch in the pointBoundaryMesh
-        virtual label index() const = 0;
-
         //- Return boundaryMesh reference
         const pointBoundaryMesh& boundaryMesh() const
         {
@@ -172,6 +247,14 @@ public:
             pointConstraint&
         ) const
         {}
+
+        //- Write the pointPatch data as a dictionary
+        virtual void write(Ostream&) const;
+
+
+    // Ostream Operator
+
+        friend Ostream& operator<<(Ostream&, const pointPatch&);
 };
 
 
diff --git a/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatchNew.C b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatchNew.C
new file mode 100644
index 0000000000000000000000000000000000000000..ce57b873a01618de10b75cdaecb96a7b420cac6e
--- /dev/null
+++ b/src/OpenFOAM/meshes/pointMesh/pointPatches/pointPatch/pointPatchNew.C
@@ -0,0 +1,56 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointPatch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+Foam::autoPtr<Foam::pointPatch> Foam::pointPatch::New
+(
+    const word& name,
+    const dictionary& dict,
+    const label index,
+    const pointBoundaryMesh& bm
+)
+{
+    // Similar to polyPatchNew but no support for generic since we want it
+    // to fall through to the construct-from-polyPatch
+    DebugInFunction << "Constructing pointPatch" << endl;
+
+    const word patchType(dict.lookup("type"));
+    //dict.readIfPresent("geometricType", patchType);
+
+    auto* ctorPtr = dictionaryConstructorTable(patchType);
+
+    if (!ctorPtr)
+    {
+        return nullptr;
+    }
+
+    return autoPtr<pointPatch>(ctorPtr(name, dict, index, bm, patchType));
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
index 3ece63c5e75cc346059f056108ce55dd8514e397..c3e9cd5d6a0c956346be431c386d89f184a2d649 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyBoundaryMesh/polyBoundaryMesh.C
@@ -1418,6 +1418,9 @@ void Foam::polyBoundaryMesh::reorder
         patches[patchi].index() = patchi;
     }
 
+    // Clear group-to-patch addressing. Note: could re-calculate
+    groupIDsPtr_.reset(nullptr);
+
     if (validBoundary)
     {
         updateMesh();
diff --git a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/symmetryPlane/symmetryPlanePolyPatch.C b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/symmetryPlane/symmetryPlanePolyPatch.C
index b71af44be2f36941f2bd0782699728c53cac8624..eda279c964807930fb2ffd58ac73d769a7e220f4 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/symmetryPlane/symmetryPlanePolyPatch.C
+++ b/src/OpenFOAM/meshes/polyMesh/polyPatches/constraint/symmetryPlane/symmetryPlanePolyPatch.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2013-2015 OpenFOAM Foundation
-    Copyright (C) 2022 OpenCFD Ltd.
+    Copyright (C) 2022,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -49,8 +49,12 @@ void Foam::symmetryPlanePolyPatch::calcGeometry(PstreamBuffers&)
     {
         if (returnReduceOr(size()))
         {
-            const vectorField& nf = faceNormals();
-            n_ = gAverage(nf);
+            // Instead of using the average unit-normal use an area weighted
+            // average instead. This avoids problem when adding zero-sized
+            // faces since these have a calculated area vector of (0 0 0)
+            const auto& areas = faceAreas();
+
+            n_ = gSum(areas).normalise(ROOTVSMALL);
 
             if (debug)
             {
@@ -60,22 +64,30 @@ void Foam::symmetryPlanePolyPatch::calcGeometry(PstreamBuffers&)
 
 
             // Check the symmetry plane is planar
-            forAll(nf, facei)
+            forAll(areas, facei)
             {
-                if (magSqr(n_ - nf[facei]) > SMALL)
+                const scalar a = mag(areas[facei]);
+
+                // Calculate only if non-zero area
+                if (a > ROOTVSMALL)
                 {
-                    FatalErrorInFunction
-                        << "Symmetry plane '" << name() << "' is not planar."
-                        << endl
-                        << "At local face at "
-                        << primitivePatch::faceCentres()[facei]
-                        << " the normal " << nf[facei]
-                        << " differs from the average normal " << n_
-                        << " by " << magSqr(n_ - nf[facei]) << endl
-                        << "Either split the patch into planar parts"
-                        << " or use the " << symmetryPolyPatch::typeName
-                        << " patch type"
-                        << exit(FatalError);
+                    const vector nf(areas[facei]/a);
+
+                    if (magSqr(n_ - nf) > SMALL)
+                    {
+                        FatalErrorInFunction
+                            << "Symmetry plane '" << name()
+                            << "' is not planar." << endl
+                            << "At local face at "
+                            << primitivePatch::faceCentres()[facei]
+                            << " the normal " << nf
+                            << " differs from the average normal " << n_
+                            << " by " << magSqr(n_ - nf) << endl
+                            << "Either split the patch into planar parts"
+                            << " or use the " << symmetryPolyPatch::typeName
+                            << " patch type"
+                            << exit(FatalError);
+                    }
                 }
             }
         }
diff --git a/src/dynamicMesh/Make/files b/src/dynamicMesh/Make/files
index 4f5379232b79b394000d0ea90544989d017da3f6..54b5f28d80b3dc9ee8583b690c0351fce9265d0c 100644
--- a/src/dynamicMesh/Make/files
+++ b/src/dynamicMesh/Make/files
@@ -101,6 +101,7 @@ motionSolvers/displacement/displacement/displacementMotionSolver.C
 motionSolvers/displacement/interpolation/displacementInterpolationMotionSolver.C
 motionSolvers/displacement/layeredSolver/displacementLayeredMotionMotionSolver.C
 motionSolvers/displacement/layeredSolver/pointEdgeStructuredWalk.C
+motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.C
 motionSolvers/componentDisplacement/componentDisplacementMotionSolver.C
 motionSolvers/velocity/velocityMotionSolver.C
 motionSolvers/velocity/velocityDisplacement/velocityDisplacementMotionSolver.C
@@ -111,6 +112,23 @@ motionSolvers/displacement/codedPoints0/codedPoints0MotionSolver.C
 
 motionSolvers/displacement/solidBody/pointPatchFields/derived/solidBodyMotionDisplacement/solidBodyMotionDisplacementPointPatchVectorField.C
 
+pointSmoothing = motionSolvers/displacement/pointSmoothing
+$(pointSmoothing)/displacementPointSmoothingMotionSolver.C
+/*
+$(pointSmoothing)/displacementPointSmoothingMotionSolver2.C
+$(pointSmoothing)/displacementPointSmoothingMotionSolver3.C
+*/
+$(pointSmoothing)/hexMeshSmootherMotionSolver.C
+$(pointSmoothing)/displacementSmartPointSmoothingMotionSolver.C
+
+pointSmoothers = $(pointSmoothing)/pointSmoothers
+$(pointSmoothers)/pointSmoother/pointSmoother.C
+$(pointSmoothers)/equipotentialPointSmoother/equipotentialPointSmoother.C
+$(pointSmoothers)/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.C
+$(pointSmoothers)/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.C
+$(pointSmoothers)/laplacianPointSmoother/laplacianPointSmoother.C
+$(pointSmoothers)/laplacianPointSmoother/laplacianConstraintPointSmoother.C
+
 createShellMesh/createShellMesh.C
 
 extrudePatchMesh/extrudePatchMesh.C
diff --git a/src/dynamicMesh/motionSolvers/displacement/displacement/displacementMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/displacement/displacementMotionSolver.C
index 00fa9ae49daee2e2d9cd94da2bd7f94f8591ddec..9f8c33aa55eadf29904355995ecc18a53ea889c5 100644
--- a/src/dynamicMesh/motionSolvers/displacement/displacement/displacementMotionSolver.C
+++ b/src/dynamicMesh/motionSolvers/displacement/displacement/displacementMotionSolver.C
@@ -57,7 +57,7 @@ Foam::displacementMotionSolver::displacementMotionSolver
             IOobject::MUST_READ,
             IOobject::AUTO_WRITE
         ),
-        pointMesh::New(mesh)
+        pointMesh::New(mesh, Foam::IOobject::READ_IF_PRESENT)
     )
 {}
 
diff --git a/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.C
new file mode 100644
index 0000000000000000000000000000000000000000..cca0664ac9bd0e4733bcfc053c3bbe1b709b7651
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.C
@@ -0,0 +1,271 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*----------------------------------------------------------------------------*/
+
+#include "multiDisplacementMotionSolver.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(multiDisplacementMotionSolver, 0);
+
+    addToRunTimeSelectionTable
+    (
+        motionSolver,
+        multiDisplacementMotionSolver,
+        dictionary
+    );
+
+    addToRunTimeSelectionTable
+    (
+        displacementMotionSolver,
+        multiDisplacementMotionSolver,
+        displacement
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::multiDisplacementMotionSolver::multiDisplacementMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict
+)
+:
+    displacementMotionSolver(mesh, dict, typeName),
+    curPoints_(mesh.points())
+{
+    // Make pointDisplacement is not registered since all lower levels
+    // have a pointDisplacement as well.
+    pointDisplacement().checkOut();
+
+    label i = 0;
+
+    const dictionary& solverDict = dict.subDict("solvers");
+
+    motionSolvers_.setSize(solverDict.size());
+
+    for (const entry& dEntry : solverDict)
+    {
+        if (dEntry.isDict())
+        {
+            IOobject io(dict);
+            io.readOpt(IOobject::NO_READ);
+            io.writeOpt(IOobject::AUTO_WRITE);
+            io.rename(dEntry.dict().dictName());
+
+            IOdictionary IOsolverDict
+            (
+                io,
+                dEntry.dict()
+            );
+
+            auto* msPtr = motionSolver::New(mesh, IOsolverDict).ptr();
+
+            motionSolvers_.set
+            (
+                i,
+                dynamic_cast<displacementMotionSolver*>(msPtr)
+            );
+
+            // Avoid conflicts with multiple registrations
+            motionSolvers_[i].pointDisplacement().checkOut();
+
+            i++;
+        }
+    }
+    motionSolvers_.setSize(i);
+
+    if (i == 0)
+    {
+        FatalErrorInFunction << "No displacementMotionSolvers in dictionary "
+            << dict << exit(FatalError);
+    }
+
+    // Re-register so only our 'pointDisplacement' is on the database.
+    pointDisplacement().checkIn();
+}
+
+
+Foam::multiDisplacementMotionSolver::
+multiDisplacementMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict,
+    const pointVectorField& pointDisplacement,
+    const pointIOField& points0
+)
+:
+    displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
+    curPoints_(mesh.points())
+{
+    // Make pointDisplacement is not registered since all lower levels
+    // have a pointDisplacement as well.
+    this->pointDisplacement().checkOut();
+
+    label i = 0;
+
+    const dictionary& solverDict = dict.subDict("solvers");
+
+    motionSolvers_.setSize(solverDict.size());
+
+    for (const entry& dEntry : solverDict)
+    {
+        if (dEntry.isDict())
+        {
+            IOobject io(dict);
+            io.readOpt(IOobject::NO_READ);
+            io.writeOpt(IOobject::AUTO_WRITE);
+            io.rename(dEntry.dict().dictName());
+
+            IOdictionary IOsolverDict
+            (
+                io,
+                dEntry.dict()
+            );
+
+            auto msPtr = displacementMotionSolver::New
+            (
+                dEntry.keyword(),
+                mesh,
+                IOsolverDict,
+                pointDisplacement,
+                points0
+            );
+
+            // Avoid conflicts with multiple registrations
+            msPtr->pointDisplacement().checkOut();
+
+            motionSolvers_.set(i++, msPtr);
+        }
+    }
+    motionSolvers_.setSize(i);
+
+    if (i == 0)
+    {
+        FatalErrorInFunction << "No displacementMotionSolvers in dictionary "
+            << dict << exit(FatalError);
+    }
+
+    // Re-register so only our 'pointDisplacement' is on the database.
+    this->pointDisplacement().checkIn();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::tmp<Foam::pointField>
+Foam::multiDisplacementMotionSolver::curPoints() const
+{
+    return curPoints_;
+}
+
+
+void Foam::multiDisplacementMotionSolver::solve()
+{
+    if (!motionSolvers_.size())
+    {
+        return;
+    }
+
+    // Bit tricky:
+    // - make sure only one copy of pointDisplacement is registered. This is
+    //   for if cellDisplacement tries to look up the pointDisplacement it
+    //   looks up its version. Or maybe we always should use our own version
+    //   only?
+    // - copy the last set of calculated points into our copy (curPoints_)
+    // - move the mesh to update the faceCentres, cellCentres etc. This assumes
+    //   that we can call movePoints() multiple times inside a time step.
+    //   (note that this is supported in pimpleFoam with the
+    //    moveMeshOuterCorrectors option)
+
+    pointDisplacement().checkOut();
+
+    // Doing first motion solver
+    motionSolvers_[0].pointDisplacement().checkIn();
+    // Take over my bc values
+    motionSolvers_[0].pointDisplacement() == pointDisplacement();
+
+    motionSolvers_[0].solve();
+    motionSolvers_[0].pointDisplacement().checkOut();
+
+    // Update my values
+    curPoints_ = motionSolvers_[0].curPoints();
+    pointDisplacement() == motionSolvers_[0].pointDisplacement();
+
+    for (label i = 1; i < motionSolvers_.size(); i++)
+    {
+        // Doing other motion solvers using new locations/face/cellCentres etc.
+        const_cast<polyMesh&>(mesh()).movePoints(curPoints_);
+        motionSolvers_[i].pointDisplacement().checkIn();
+
+        // Take over my bc values
+        motionSolvers_[i].pointDisplacement() == pointDisplacement();
+
+        motionSolvers_[i].solve();
+        motionSolvers_[i].pointDisplacement().checkOut();
+
+        // Update my values
+        curPoints_ = motionSolvers_[i].curPoints();
+        pointDisplacement() == motionSolvers_[i].pointDisplacement();
+    }
+
+    pointDisplacement().checkIn();
+
+    // Push my pointDisplacement onto all motionSolvers
+    for (auto& ms : motionSolvers_)
+    {
+        ms.pointDisplacement() == pointDisplacement();
+    }
+}
+
+
+void Foam::multiDisplacementMotionSolver::movePoints
+(
+    const pointField& newPoints
+)
+{
+    curPoints_ = newPoints;
+    for (auto& ms : motionSolvers_)
+    {
+        ms.movePoints(newPoints);
+    }
+}
+
+
+void Foam::multiDisplacementMotionSolver::updateMesh(const mapPolyMesh& mpm)
+{
+    for (auto& ms : motionSolvers_)
+    {
+        ms.updateMesh(mpm);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.H b/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.H
new file mode 100644
index 0000000000000000000000000000000000000000..291ab6265fb186b8b245b1a528b8007fd2440ae1
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/multiDisplacement/multiDisplacementMotionSolver.H
@@ -0,0 +1,170 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::multiDisplacementMotionSolver
+
+Group
+    grpMeshMotionSolvers
+
+Description
+    Mesh motion solver for a polyMesh. Applies multiple (displacement) motion
+    solvers in order.
+
+    Not very efficient : all displacementMotionSolvers store a copy
+    of the initial points (points0) and the displacement (pointDisplacement
+    or also cellDisplacement).
+    Used to combine large-scale, implicit displacement smoothing (e.g.
+    displacementLaplacian) with point smoothing.
+
+Usage
+    Example of the dynamicMeshDict specification:
+    \verbatim
+    motionSolver    multiDisplacement;
+    solvers
+    {
+        // Solve finite volume laplacian to efficiently smooth displacement
+        // (not point locations)
+        displacementLaplacian
+        {
+            motionSolver        displacementLaplacian;
+            diffusivity         uniform;
+        }
+
+        // Apply few iterations of smoothing of point locations
+        displacementPointSmoothing
+        {
+            motionSolver        displacementPointSmoothing;
+            pointSmoother       laplacian;
+            nPointSmootherIter  10;
+        }
+    }
+    \endverbatim
+
+Note
+    When using displacementLaplacian: the default behaviour for the
+    cellDisplacement is to apply fixed value boundary conditions (by averaging
+    point values) only to those pointDisplacement boundary conditions that
+    are fixed value. Quite a few point boundary conditions (e.g. surfaceSlip,
+    edgeSlip) are not so require an explicitly provided cellDisplacement
+    field with 'cellMotion' boundary conditions for those patches.
+
+SourceFiles
+    isplacementMultiMotionSolver.C
+\*----------------------------------------------------------------------------*/
+
+#ifndef Foam_multiDisplacementMotionSolver_H
+#define Foam_multiDisplacementMotionSolver_H
+
+#include "displacementMotionSolver.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                Class multiDisplacementMotionSolver Declaration
+\*---------------------------------------------------------------------------*/
+
+class multiDisplacementMotionSolver
+:
+    public displacementMotionSolver
+{
+    // Private data
+
+        //- Current points
+        pointField curPoints_;
+
+        //- List of motion solvers
+        PtrList<displacementMotionSolver> motionSolvers_;
+
+
+    // Private Member Functions
+
+        //- No copy construct
+        multiDisplacementMotionSolver
+        (
+            const multiDisplacementMotionSolver&
+        ) = delete;
+
+        //- No copy assignment
+        void operator=(const multiDisplacementMotionSolver&) = delete;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("multiDisplacement");
+
+
+    // Constructors
+
+        //- Construct from polyMesh and IOdictionary
+        multiDisplacementMotionSolver
+        (
+            const polyMesh&,
+            const IOdictionary&
+        );
+
+        //- Construct from components
+        multiDisplacementMotionSolver
+        (
+            const polyMesh& mesh,
+            const IOdictionary& dict,
+            const pointVectorField& pointDisplacement,
+            const pointIOField& points0
+        );
+
+
+    //- Destructor
+    ~multiDisplacementMotionSolver() = default;
+
+
+    // Member Functions
+
+        //- Provide current points for motion
+        virtual tmp<pointField> curPoints() const;
+
+        //- Solve for motion
+        virtual void solve();
+
+        //- Update local data for geometry changes
+        virtual void movePoints(const pointField&);
+
+        //-  Update local data for topology changes
+        virtual void updateMesh(const mapPolyMesh&);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.C
new file mode 100644
index 0000000000000000000000000000000000000000..abb52d5cfa401c0a287cf4be75372a093ce73553
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.C
@@ -0,0 +1,434 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "displacementPointSmoothingMotionSolver.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+#include "pointConstraints.H"
+#include "motionSmootherAlgo.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(displacementPointSmoothingMotionSolver, 0);
+
+    addToRunTimeSelectionTable
+    (
+        motionSolver,
+        displacementPointSmoothingMotionSolver,
+        dictionary
+    );
+
+    addToRunTimeSelectionTable
+    (
+        displacementMotionSolver,
+        displacementPointSmoothingMotionSolver,
+        displacement
+    );
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::displacementPointSmoothingMotionSolver::markAffectedFaces
+(
+    const labelHashSet& changedFaces,
+    labelHashSet& affectedFaces
+)
+{
+    PackedBoolList affectedPoints(mesh().nPoints(), false);
+
+    forAllConstIter(labelHashSet, changedFaces, iter)
+    {
+        const label faceI(iter.key());
+
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            affectedPoints[pointI] = true;
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        affectedPoints,
+        orEqOp<unsigned int>(),
+        0U
+    );
+
+    forAll(affectedPoints, pointI)
+    {
+        if (affectedPoints[pointI])
+        {
+            const labelList& pCells(mesh().pointCells()[pointI]);
+
+            forAll(pCells, pointCellI)
+            {
+                const label cellI(pCells[pointCellI]);
+
+                const labelList& cFaces(mesh().cells()[cellI]);
+
+                affectedFaces.insert(cFaces);
+            }
+        }
+    }
+}
+
+
+bool Foam::displacementPointSmoothingMotionSolver::relax()
+{
+    if
+    (
+        (relaxationFactors_.size() == 0)
+     || (relaxationFactors_.size() == 1 && relaxationFactors_[0] == 1.0)
+    )
+    {
+        relaxedPoints_ = points0() + pointDisplacement().internalField();
+        return true;
+    }
+
+
+    const pointField oldRelaxedPoints(relaxedPoints_);
+
+    labelHashSet affectedFaces(facesToMove_);
+
+    // Create a list of relaxation levels
+    // -1 indicates a point which is not to be moved
+    //  0 is the starting value for a moving point
+    labelList relaxationLevel(mesh().nPoints(), -1);
+    forAllConstIter(labelHashSet, affectedFaces, iter)
+    {
+        const label faceI(iter.key());
+
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            relaxationLevel[pointI] = 0;
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        relaxationLevel,
+        maxEqOp<label>(),
+        label(-1)
+    );
+
+    // Loop whilst relaxation levels are being incremented
+    bool complete(false);
+    while (!complete)
+    {
+        //scalar nAffectedFaces(affectedFaces.size());
+        //reduce(nAffectedFaces, sumOp<scalar>());
+        //Info << "    Moving " << nAffectedFaces << " faces" << endl;
+
+        // Move the points
+        forAll(relaxationLevel, pointI)
+        {
+            if (relaxationLevel[pointI] >= 0)
+            {
+                const scalar x
+                (
+                    relaxationFactors_[relaxationLevel[pointI]]
+                );
+
+                relaxedPoints_[pointI] =
+                    (1 - x)*oldRelaxedPoints[pointI]
+                  + x*(points0()[pointI] + pointDisplacement()[pointI]);
+            }
+        }
+
+        // Get a list of changed faces
+        labelHashSet markedFaces;
+        markAffectedFaces(affectedFaces, markedFaces);
+        labelList markedFacesList(markedFaces.toc());
+
+        // Update the geometry
+        meshGeometry_.correct(relaxedPoints_, markedFacesList);
+
+        // Check the modified face quality
+        markedFaces.clear();
+        motionSmootherAlgo::checkMesh
+        (
+            false,
+            meshQualityDict_,
+            meshGeometry_,
+            relaxedPoints_,
+            markedFacesList,
+            markedFaces
+        );
+
+        // Mark the affected faces
+        affectedFaces.clear();
+        markAffectedFaces(markedFaces, affectedFaces);
+
+        // Increase relaxation and check convergence
+        PackedBoolList pointsToRelax(mesh().nPoints(), false);
+        complete = true;
+        forAllConstIter(labelHashSet, affectedFaces, iter)
+        {
+            const label faceI(iter.key());
+
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                pointsToRelax[pointI] = true;
+            }
+        }
+
+        forAll(pointsToRelax, pointI)
+        {
+            if
+            (
+                pointsToRelax[pointI]
+             && (relaxationLevel[pointI] < relaxationFactors_.size() - 1)
+            )
+            {
+                ++ relaxationLevel[pointI];
+
+                complete = false;
+            }
+        }
+
+        // Synchronise relaxation levels
+        syncTools::syncPointList
+        (
+            mesh(),
+            relaxationLevel,
+            maxEqOp<label>(),
+            label(0)
+        );
+
+        // Synchronise completion
+        reduce(complete, andOp<bool>());
+    }
+
+    // Check for convergence
+    bool converged(true);
+    forAll(mesh().faces(), faceI)
+    {
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            if (relaxationLevel[pointI] > 0)
+            {
+                facesToMove_.insert(faceI);
+
+                converged = false;
+
+                break;
+            }
+        }
+    }
+
+    // Syncronise convergence
+    reduce(converged, andOp<bool>());
+
+    //if (converged)
+    //{
+    //    Info<< "... Converged" << endl << endl;
+    //}
+    //else
+    //{
+    //    Info<< "... Not converged" << endl << endl;
+    //}
+
+    return converged;
+}
+
+
+void Foam::displacementPointSmoothingMotionSolver::setFacesToMove
+(
+    const dictionary& dict
+)
+{
+    if (dict.getOrDefault<bool>("moveInternalFaces", true))
+    {
+        facesToMove_.resize(2*mesh().nFaces());
+        forAll(mesh().faces(), faceI)
+        {
+            facesToMove_.insert(faceI);
+        }
+    }
+    else
+    {
+        facesToMove_.resize(2*(mesh().nBoundaryFaces()));
+        for
+        (
+            label faceI = mesh().nInternalFaces();
+            faceI < mesh().nFaces();
+            ++ faceI
+        )
+        {
+            facesToMove_.insert(faceI);
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::displacementPointSmoothingMotionSolver::
+displacementPointSmoothingMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict
+)
+:
+    displacementMotionSolver(mesh, dict, typeName),
+    meshGeometry_(mesh),
+    pointSmoother_(pointSmoother::New(mesh, coeffDict())),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxedPoints_(mesh.points())
+{
+    if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
+    {
+        meshQualityDict_ = coeffDict().subDict("meshQuality");
+    }
+    setFacesToMove(coeffDict());
+}
+
+
+Foam::displacementPointSmoothingMotionSolver::
+displacementPointSmoothingMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict,
+    const pointVectorField& pointDisplacement,
+    const pointIOField& points0
+)
+:
+    displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
+    meshGeometry_(mesh),
+    pointSmoother_
+    (
+        pointSmoother::New
+        (
+            mesh,
+            coeffDict()
+        )
+    ),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxedPoints_(mesh.points())
+{
+    if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
+    {
+        meshQualityDict_ = coeffDict().subDict("meshQuality");
+    }
+    setFacesToMove(coeffDict());
+}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+Foam::tmp<Foam::pointField>
+Foam::displacementPointSmoothingMotionSolver::curPoints() const
+{
+    //Note: twoDCorrect already done by ::solve
+
+    return relaxedPoints_;
+}
+
+
+void Foam::displacementPointSmoothingMotionSolver::solve()
+{
+    //Pout<< "time:" << mesh().time().timeName()
+    //    << " mesh faceCentres:" << gAverage(mesh().faceCentres())
+    //    << " mesh cellCentres:" << gAverage(mesh().cellCentres())
+    //    << endl;
+
+    movePoints(curPoints());
+
+    // Update values on pointDisplacement
+    pointDisplacement().boundaryFieldRef().updateCoeffs();
+
+    // Extend: face-to-point-to-cell-to-faces
+    labelHashSet affectedFaces;
+    markAffectedFaces(facesToMove_, affectedFaces);
+
+    for(label i = 0; i < nPointSmootherIter_; i ++)
+    {
+        meshGeometry_.correct
+        (
+            points0() + pointDisplacement().internalField(),
+            affectedFaces.toc()
+        );
+        //Pout<< "iter:" << i
+        //    << " faceCentres:" << gAverage(meshGeometry_.faceCentres())
+        //    << " cellCentres:" << gAverage(meshGeometry_.cellCentres())
+        //    << endl;
+
+        pointSmoother_->update
+        (
+            affectedFaces.toc(),
+            points0(),
+            points0() + pointDisplacement().internalField(),
+            meshGeometry_,
+            pointDisplacement()
+        );
+    }
+
+    relax();
+
+    twoDCorrectPoints(relaxedPoints_);
+
+    // Update pointDisplacement for actual relaxedPoints. Keep fixed-value
+    // bcs.
+    pointDisplacement().primitiveFieldRef() = relaxedPoints_-points0();
+
+    // Adhere to multi-point constraints
+    const pointConstraints& pcs =
+         pointConstraints::New(pointDisplacement().mesh());
+    pcs.constrainDisplacement(pointDisplacement(), false);
+
+    // Update relaxedPoints to take constraints into account
+    relaxedPoints_ = points0() + pointDisplacement().internalField();
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.H
new file mode 100644
index 0000000000000000000000000000000000000000..8dd60c5528f3f8ce198be8c97b6d5996ffd81efa
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementPointSmoothingMotionSolver.H
@@ -0,0 +1,149 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::displacementPointSmoothingMotionSolver
+
+Description
+    Quality-based under-relaxation for run-time selectable point smoothing.
+
+SourceFiles
+    displacementPointSmoothingMotionSolver.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef displacementPointSmoothingMotionSolver_H
+#define displacementPointSmoothingMotionSolver_H
+
+#include "displacementMotionSolver.H"
+#include "pointSmoother.H"
+#include "polyMeshGeometry.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+            Class displacementPointSmoothingMotionSolver Declaration
+\*---------------------------------------------------------------------------*/
+
+class displacementPointSmoothingMotionSolver
+:
+    public displacementMotionSolver
+{
+protected:
+
+    // Protected Data
+
+        //- Part-updatable mesh geometry
+        polyMeshGeometry meshGeometry_;
+
+        //- Point smoothing method
+        autoPtr<pointSmoother> pointSmoother_;
+
+        //- Number of point smoother iterations per timestep
+        const label nPointSmootherIter_;
+
+
+        // Mesh quality based relaxation of smoothed position
+
+            //- Relaxation factors to use in each iteration
+            scalarList relaxationFactors_;
+
+            //- Relaxed point field
+            pointField relaxedPoints_;
+
+            //- Set of the faces which are to be moved
+            labelHashSet facesToMove_;
+
+            //- Mesh quality dictionary
+            dictionary meshQualityDict_;
+
+
+    // Private Member Functions
+
+        //- Mark affected faces
+        void markAffectedFaces
+        (
+            const labelHashSet& changedFaces,
+            labelHashSet& affectedFaces
+        );
+
+        //- Relax the points
+        bool relax();
+
+        //- Set all the faces to be moved
+        void virtual setFacesToMove(const dictionary&);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("displacementPointSmoothing");
+
+
+    // Constructors
+
+        //- Construct from a polyMesh and an IOdictionary
+        displacementPointSmoothingMotionSolver
+        (
+            const polyMesh&,
+            const IOdictionary&
+        );
+
+        //- Construct from components
+        displacementPointSmoothingMotionSolver
+        (
+            const polyMesh& mesh,
+            const IOdictionary& dict,
+            const pointVectorField& pointDisplacement,
+            const pointIOField& points0
+        );
+
+
+    //- Destructor
+    virtual ~displacementPointSmoothingMotionSolver() = default;
+
+
+    // Member Functions
+
+        //- Return point location obtained from the current motion field
+        virtual tmp<pointField> curPoints() const;
+
+        //- Solve for motion
+        virtual void solve();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.C
new file mode 100644
index 0000000000000000000000000000000000000000..88aa458a69f27ef4e005e7ea2a94177ee7542f8e
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.C
@@ -0,0 +1,746 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "displacementSmartPointSmoothingMotionSolver.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+#include "pointConstraints.H"
+#include "motionSmootherAlgo.H"
+
+//#include "fvMesh.H"
+//#include "fvGeometryScheme.H"
+#include "OBJstream.H"
+#include "emptyPointPatchFields.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(displacementSmartPointSmoothingMotionSolver, 0);
+
+    addToRunTimeSelectionTable
+    (
+        motionSolver,
+        displacementSmartPointSmoothingMotionSolver,
+        dictionary
+    );
+
+    addToRunTimeSelectionTable
+    (
+        displacementMotionSolver,
+        displacementSmartPointSmoothingMotionSolver,
+        displacement
+    );
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::displacementSmartPointSmoothingMotionSolver::markAffectedFaces
+(
+    const labelHashSet& changedFaces,
+    labelHashSet& affectedFaces
+)
+{
+    PackedBoolList affectedPoints(mesh().nPoints(), false);
+
+    forAllConstIter(labelHashSet, changedFaces, iter)
+    {
+        const label faceI(iter.key());
+
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            affectedPoints[pointI] = true;
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        affectedPoints,
+        orEqOp<unsigned int>(),
+        0U
+    );
+
+    forAll(affectedPoints, pointI)
+    {
+        if (affectedPoints[pointI])
+        {
+            const labelList& pCells(mesh().pointCells()[pointI]);
+
+            forAll(pCells, pointCellI)
+            {
+                const label cellI(pCells[pointCellI]);
+
+                const labelList& cFaces(mesh().cells()[cellI]);
+
+                affectedFaces.insert(cFaces);
+            }
+        }
+    }
+}
+
+
+bool Foam::displacementSmartPointSmoothingMotionSolver::relax()
+{
+    if
+    (
+        (relaxationFactors_.size() == 0)
+     || (relaxationFactors_.size() == 1 && relaxationFactors_[0] == 1.0)
+    )
+    {
+        relaxedPoints_ = points0() + pointDisplacement().internalField();
+        return true;
+    }
+
+
+    const pointField oldRelaxedPoints(relaxedPoints_);
+
+    labelHashSet affectedFaces(facesToMove_);
+
+    // Create a list of relaxation levels
+    // -1 indicates a point which is not to be moved
+    //  0 is the starting value for a moving point
+    labelList relaxationLevel(mesh().nPoints(), -1);
+    forAllConstIter(labelHashSet, affectedFaces, iter)
+    {
+        const label faceI(iter.key());
+
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            relaxationLevel[pointI] = 0;
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        relaxationLevel,
+        maxEqOp<label>(),
+        label(-1)
+    );
+
+    // Loop whilst relaxation levels are being incremented
+    bool complete(false);
+    while (!complete)
+    {
+        //scalar nAffectedFaces(affectedFaces.size());
+        //reduce(nAffectedFaces, sumOp<scalar>());
+        //Info << "    Moving " << nAffectedFaces << " faces" << endl;
+
+        // Move the points
+        forAll(relaxationLevel, pointI)
+        {
+            if (relaxationLevel[pointI] >= 0)
+            {
+                const scalar x
+                (
+                    relaxationFactors_[relaxationLevel[pointI]]
+                );
+
+                relaxedPoints_[pointI] =
+                    (1 - x)*oldRelaxedPoints[pointI]
+                  + x*(points0()[pointI] + pointDisplacement()[pointI]);
+            }
+        }
+
+        // Get a list of changed faces
+        labelHashSet markedFaces;
+        markAffectedFaces(affectedFaces, markedFaces);
+        labelList markedFacesList(markedFaces.toc());
+
+        // Update the geometry
+        meshGeometry_.correct(relaxedPoints_, markedFacesList);
+
+        // Check the modified face quality
+        if (false)
+        {
+            // Use snappyHexMesh compatible checks
+            markedFaces.clear();
+            motionSmootherAlgo::checkMesh
+            (
+                false,
+                meshQualityDict_,
+                meshGeometry_,
+                relaxedPoints_,
+                markedFacesList,
+                markedFaces
+            );
+
+            // Mark the affected faces
+            affectedFaces.clear();
+            markAffectedFaces(markedFaces, affectedFaces);
+        }
+        else
+        {
+            // Use pointSmoother specific
+            tmp<scalarField> tfaceQ
+            (
+                pointUntangler_->faceQuality
+                (
+                    relaxedPoints_,
+                    meshGeometry_.faceCentres(),
+                    meshGeometry_.faceAreas(),
+                    meshGeometry_.cellCentres(),
+                    meshGeometry_.cellVolumes()
+                )
+            );
+
+            if (debug)
+            {
+                MinMax<scalar> range(gMinMax(tfaceQ()));
+                Pout<< "    min:" << range.min() << nl
+                    << "    max:" << range.max() << endl;
+            }
+
+            labelList order;
+            Foam::sortedOrder(tfaceQ(), order);
+
+            label nUntangle = 0;
+            forAll(order, i)
+            {
+                if (tfaceQ()[order[i]] > untangleQ_)
+                {
+                    nUntangle = i;
+                    break;
+                }
+            }
+
+            affectedFaces = labelList(SubList<label>(order, nUntangle));
+        }
+
+        // Increase relaxation and check convergence
+        PackedBoolList pointsToRelax(mesh().nPoints(), false);
+        complete = true;
+        forAllConstIter(labelHashSet, affectedFaces, iter)
+        {
+            const label faceI(iter.key());
+
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                pointsToRelax[pointI] = true;
+            }
+        }
+
+        forAll(pointsToRelax, pointI)
+        {
+            if
+            (
+                pointsToRelax[pointI]
+             && (relaxationLevel[pointI] < relaxationFactors_.size() - 1)
+            )
+            {
+                ++ relaxationLevel[pointI];
+
+                complete = false;
+            }
+        }
+
+        // Synchronise relaxation levels
+        syncTools::syncPointList
+        (
+            mesh(),
+            relaxationLevel,
+            maxEqOp<label>(),
+            label(0)
+        );
+
+        // Synchronise completion
+        reduce(complete, andOp<bool>());
+    }
+
+    // Check for convergence
+    bool converged(true);
+    forAll(mesh().faces(), faceI)
+    {
+        const face& fPoints(mesh().faces()[faceI]);
+
+        forAll(fPoints, fPointI)
+        {
+            const label pointI(fPoints[fPointI]);
+
+            if (relaxationLevel[pointI] > 0)
+            {
+                facesToMove_.insert(faceI);
+
+                converged = false;
+
+                break;
+            }
+        }
+    }
+
+    // Syncronise convergence
+    reduce(converged, andOp<bool>());
+
+    //if (converged)
+    //{
+    //    Info<< "... Converged" << endl << endl;
+    //}
+    //else
+    //{
+    //    Info<< "... Not converged" << endl << endl;
+    //}
+
+    return converged;
+}
+
+
+void Foam::displacementSmartPointSmoothingMotionSolver::setFacesToMove
+(
+    const dictionary& dict
+)
+{
+    if (dict.getOrDefault<bool>("moveInternalFaces", true))
+    {
+        facesToMove_.resize(2*mesh().nFaces());
+        forAll(mesh().faces(), faceI)
+        {
+            facesToMove_.insert(faceI);
+        }
+    }
+    else
+    {
+        facesToMove_.resize(2*(mesh().nBoundaryFaces()));
+        for
+        (
+            label faceI = mesh().nInternalFaces();
+            faceI < mesh().nFaces();
+            ++ faceI
+        )
+        {
+            facesToMove_.insert(faceI);
+        }
+    }
+}
+
+
+void Foam::displacementSmartPointSmoothingMotionSolver::emptyCorrectPoints
+(
+    pointVectorField& pointDisplacement
+)
+{
+    // Assume empty point patches are already in correct location
+    // so knock out any off-plane displacement.
+    auto& fld = pointDisplacement.primitiveFieldRef();
+    for (const auto& ppf : pointDisplacement.boundaryField())
+    {
+        if (isA<emptyPointPatchVectorField>(ppf))
+        {
+            const auto& mp = ppf.patch().meshPoints();
+            forAll(mp, i)
+            {
+                pointConstraint pc;
+                ppf.patch().applyConstraint(i, pc);
+                fld[mp[i]] = pc.constrainDisplacement(fld[mp[i]]);
+            }
+        }
+    }
+
+    pointField wantedPoints(points0() + fld);
+    twoDCorrectPoints(wantedPoints);
+    fld = wantedPoints-points0();
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::displacementSmartPointSmoothingMotionSolver::
+displacementSmartPointSmoothingMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict
+)
+:
+    displacementMotionSolver(mesh, dict, typeName),
+    meshGeometry_(mesh),
+    pointUntangler_
+    (
+        pointSmoother::New
+        (
+            coeffDict().get<word>("untangler"),
+            mesh,
+            coeffDict()
+        )
+    ),
+    untangleQ_(coeffDict().get<scalar>("untangleQ")),
+    minQ_(coeffDict().get<scalar>("minQ")),
+    pointSmoother_(pointSmoother::New(mesh, coeffDict())),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxedPoints_(mesh.points())
+{
+    if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
+    {
+        meshQualityDict_ = coeffDict().subDict("meshQuality");
+    }
+    setFacesToMove(coeffDict());
+}
+
+
+Foam::displacementSmartPointSmoothingMotionSolver::
+displacementSmartPointSmoothingMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict,
+    const pointVectorField& pointDisplacement,
+    const pointIOField& points0
+)
+:
+    displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
+    meshGeometry_(mesh),
+    pointUntangler_
+    (
+        pointSmoother::New
+        (
+            coeffDict().get<word>("untangler"),
+            mesh,
+            coeffDict()
+        )
+    ),
+    untangleQ_(coeffDict().get<scalar>("untangleQ")),
+    minQ_(coeffDict().get<scalar>("minQ")),
+    pointSmoother_
+    (
+        pointSmoother::New
+        (
+            mesh,
+            coeffDict()
+        )
+    ),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxedPoints_(mesh.points())
+{
+    if (coeffDict().readIfPresent("relaxationFactors", relaxationFactors_))
+    {
+        meshQualityDict_ = coeffDict().subDict("meshQuality");
+    }
+    setFacesToMove(coeffDict());
+}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+Foam::tmp<Foam::pointField>
+Foam::displacementSmartPointSmoothingMotionSolver::curPoints() const
+{
+    //Note: twoDCorrect already done by ::solve
+
+    return relaxedPoints_;
+}
+
+
+void Foam::displacementSmartPointSmoothingMotionSolver::solve()
+{
+    movePoints(curPoints());
+
+    // Update values on pointDisplacement. Note: should also evaluate? Since
+    // e.g. cellMotionBC uses pointDisplacement value.
+    pointDisplacement().boundaryFieldRef().updateCoeffs();
+
+
+    fileName debugDir;
+    if (debug & 2)
+    {
+        debugDir = mesh().time().timePath();
+        mkDir(debugDir);
+        OBJstream os(debugDir/"bc.obj");
+
+        const pointField wantedPoints
+        (
+            points0()
+          + pointDisplacement().internalField()
+        );
+        const auto& pbm = pointDisplacement().mesh().boundary();
+        for (const auto& ppp : pbm)
+        {
+            if (!isA<emptyPointPatch>(ppp))
+            {
+                const auto& mp = ppp.meshPoints();
+                for (const label pointi : mp)
+                {
+                    os.write
+                    (
+                        linePointRef
+                        (
+                            points0()[pointi],
+                            wantedPoints[pointi]
+                        )
+                    );
+                }
+            }
+        }
+        Pout<< "Written " << os.nVertices() << " initial displacements to "
+            << os.name() << endl;
+    }
+
+
+    // Extend: face-to-point-to-cell-to-faces
+    labelHashSet affectedFaces;
+    markAffectedFaces(facesToMove_, affectedFaces);
+
+
+    for(label i = 0; i < nPointSmootherIter_; i ++)
+    {
+        const pointField wantedPoints
+        (
+            points0()
+          + pointDisplacement().internalField()
+        );
+
+        meshGeometry_.correct
+        (
+            wantedPoints,
+            affectedFaces.toc()
+        );
+
+        //{
+        //    // Debugging: check meshGeometry consistent with fvGeometryScheme
+        //    const auto& geom =
+        //        reinterpret_cast<const fvMesh&>(mesh()).geometry();
+        //    pointField faceCentres(mesh().nFaces());
+        //    vectorField faceAreas(mesh().nFaces());
+        //    pointField cellCentres(mesh().nCells());
+        //    scalarField cellVolumes(mesh().nCells());
+        //    geom.updateGeom
+        //    (
+        //        wantedPoints,
+        //        mesh().points(),    // old points
+        //        faceCentres,
+        //        faceAreas,
+        //        cellCentres,
+        //        cellVolumes
+        //    );
+        //    forAll(faceCentres, facei)
+        //    {
+        //        const point& meshFc = mesh().faceCentres()[facei];
+        //        const point& meshGeomFc = meshGeometry_.faceCentres()[facei];
+        //        const point& updatedFc = faceCentres[facei];
+        //
+        //        if (updatedFc != meshGeomFc)
+        //        {
+        //            const face& f = mesh().faces()[facei];
+        //
+        //            Pout<< "At face:" << facei << nl
+        //                << "    old         :" << meshFc << nl
+        //                << "    new         :" << updatedFc << nl
+        //                << "    polyMeshGeom:" << meshGeomFc << nl
+        //                << "    oldPoints   :"
+        //                << UIndirectList<point>(mesh().points(), f) << nl
+        //                << "    wantedPoints:"
+        //                << UIndirectList<point>(wantedPoints, f) << nl
+        //                << endl;
+        //        }
+        //    }
+        //}
+
+        // Get measure of face quality
+        tmp<scalarField> tfaceQ
+        (
+            pointUntangler_->faceQuality
+            (
+                wantedPoints,
+                meshGeometry_.faceCentres(),
+                meshGeometry_.faceAreas(),
+                meshGeometry_.cellCentres(),
+                meshGeometry_.cellVolumes()
+            )
+        );
+
+
+        if (debug)
+        {
+            MinMax<scalar> range(gMinMax(tfaceQ()));
+            Pout<< "    min:" << range.min() << nl
+                << "    max:" << range.max() << endl;
+        }
+
+        labelList order;
+        Foam::sortedOrder(tfaceQ(), order);
+
+        label nUntangle = 0;
+        forAll(order, i)
+        {
+            if (tfaceQ()[order[i]] > untangleQ_)
+            {
+                nUntangle = i;
+                break;
+            }
+        }
+        label nLow = 0;
+        forAll(order, i)
+        {
+            if (tfaceQ()[order[i]] > minQ_)
+            {
+                nLow = i;
+                break;
+            }
+        }
+
+
+        if (debug)
+        {
+            Pout<< "    nUntangle:" << returnReduce(nUntangle, sumOp<label>())
+                << nl
+                << "    nLow     :" << returnReduce(nLow, sumOp<label>())
+                << nl;
+        }
+
+
+        if (returnReduce(nUntangle, sumOp<label>()))
+        {
+            // Start untangling
+            labelList lowQFaces(SubList<label>(order, nUntangle));
+            //{
+            //    // Grow set (non parallel)
+            //    bitSet isMarkedFace(mesh().nFaces());
+            //    for (const label facei : lowQFaces)
+            //    {
+            //        for (const label pointi : mesh().faces()[facei])
+            //        {
+            //            isMarkedFace.set(mesh().pointFaces()[pointi]);
+            //        }
+            //    }
+            //    lowQFaces = isMarkedFace.sortedToc();
+            //}
+
+            //Pout<< "    untangling "
+            //    << returnReduce(lowQFaces.size(), sumOp<label>())
+            //    << " faces" << endl;
+            pointUntangler_->update
+            (
+                lowQFaces,
+                points0(),
+                wantedPoints,
+                meshGeometry_,
+                pointDisplacement()
+                //false                       // ! do NOT apply bcs, constraints
+            );
+
+            // Keep points on empty patches. Note: since pointConstraints
+            // does not implement constraints on emptyPointPatches and
+            // emptyPointPatchField does not either.
+            emptyCorrectPoints(pointDisplacement());
+
+            if (debug & 2)
+            {
+                OBJstream os(debugDir/"untangle_" + Foam::name(i) + ".obj");
+
+                const pointField wantedPoints
+                (
+                    points0()
+                  + pointDisplacement().internalField()
+                );
+                forAll(wantedPoints, pointi)
+                {
+                    os.write
+                    (
+                        linePointRef
+                        (
+                            points0()[pointi],
+                            wantedPoints[pointi]
+                        )
+                    );
+                }
+                Pout<< "Written " << os.nVertices() << " wanted untangle to "
+                    << os.name() << endl;
+            }
+        }
+        else if (returnReduce(nLow, sumOp<label>()))
+        {
+            labelList lowQFaces(SubList<label>(order, nLow));
+            //{
+            //    // Grow set (non parallel)
+            //    bitSet isMarkedFace(mesh().nFaces());
+            //    for (const label facei : lowQFaces)
+            //    {
+            //        for (const label pointi : mesh().faces()[facei])
+            //        {
+            //            isMarkedFace.set(mesh().pointFaces()[pointi]);
+            //        }
+            //    }
+            //    lowQFaces = isMarkedFace.sortedToc();
+            //}
+
+            //Pout<< "    smoothing "
+            //    << returnReduce(lowQFaces.size(), sumOp<label>())
+            //    << " faces" << endl;
+
+            pointSmoother_->update
+            (
+                lowQFaces,
+                points0(),
+                wantedPoints,
+                meshGeometry_,
+                pointDisplacement()
+            );
+            // Keep points on empty patches
+            emptyCorrectPoints(pointDisplacement());
+        }
+        else
+        {
+            //Pout<< "** converged" << endl;
+            break;
+        }
+    }
+
+
+    relax();
+    //relaxedPoints_ = points0() + pointDisplacement().internalField();
+
+    twoDCorrectPoints(relaxedPoints_);
+
+    // Update pointDisplacement for actual relaxedPoints. Keep fixed-value
+    // bcs.
+    pointDisplacement().primitiveFieldRef() = relaxedPoints_-points0();
+
+    // Adhere to multi-point constraints. Does correctBoundaryConditions +
+    // multi-patch issues.
+    const pointConstraints& pcs =
+         pointConstraints::New(pointDisplacement().mesh());
+    pcs.constrainDisplacement(pointDisplacement(), false);
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.H
new file mode 100644
index 0000000000000000000000000000000000000000..c0e3fd68d8653c8ee07cca4809b6df73a1eee948
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/displacementSmartPointSmoothingMotionSolver.H
@@ -0,0 +1,193 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::displacementSmartPointSmoothingMotionSolver
+
+Description
+    Quality-based under-relaxation for run-time selectable point smoothing. WIP.
+
+Usage
+    \table
+        Property     | Description                | Required | Default value
+        untangler    | pointSmoother for untangling | yes       | 
+        untangleQ    | quality below which untangling is applied | yes  | 
+
+        pointSmoother | pointSmoother in 'normal' mode | yes
+        minQ          | quality below which pointSmoother is applied | yes
+        nPointSmootherIter | max number of iterations
+    \endtable
+
+    Example of the motion solver specification in dynamicMeshDict:
+    \verbatim
+    motionSolver    displacementSmartPointSmoothing;
+    displacementSmartPointSmoothingCoeffs
+    {
+        //- Overall max number of smoothing iterations
+        nPointSmootherIter      10;
+
+        //- If any faces have quality below untangleQ apply untangler
+        untangleQ               0.001;
+        untangler               laplacian;
+
+        //- If any faces have quality below minQ apply 'normal' smoother
+        minQ                    0.9;
+        pointSmoother           geometricElementTransform;
+        transformationParameter 0.667;
+    }
+    \endverbatim
+
+SourceFiles
+    displacementSmartPointSmoothingMotionSolver.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef displacementSmartPointSmoothingMotionSolver_H
+#define displacementSmartPointSmoothingMotionSolver_H
+
+#include "displacementMotionSolver.H"
+#include "pointSmoother.H"
+#include "polyMeshGeometry.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+         Class displacementSmartPointSmoothingMotionSolver Declaration
+\*---------------------------------------------------------------------------*/
+
+class displacementSmartPointSmoothingMotionSolver
+:
+    public displacementMotionSolver
+{
+protected:
+
+    // Protected Data
+
+        //- Part-updatable mesh geometry
+        polyMeshGeometry meshGeometry_;
+
+        //- Point untangler method
+        autoPtr<pointSmoother> pointUntangler_;
+
+        //- Minimum allowed quality
+        const scalar untangleQ_;
+
+        //- Minimum allowed quality
+        const scalar minQ_;
+
+        //- Point smoothing method
+        autoPtr<pointSmoother> pointSmoother_;
+
+        //- Number of point smoother iterations per timestep
+        const label nPointSmootherIter_;
+
+
+        // Mesh quality based relaxation of smoothed position
+
+            //- Relaxation factors to use in each iteration
+            scalarList relaxationFactors_;
+
+            //- Relaxed point field
+            pointField relaxedPoints_;
+
+            //- Set of the faces which are to be moved
+            labelHashSet facesToMove_;
+
+            //- Mesh quality dictionary
+            dictionary meshQualityDict_;
+
+
+    // Private Member Functions
+
+        //- Mark affected faces
+        void markAffectedFaces
+        (
+            const labelHashSet& changedFaces,
+            labelHashSet& affectedFaces
+        );
+
+        //- Relax the points
+        bool relax();
+
+        //- Set all the faces to be moved
+        void virtual setFacesToMove(const dictionary&);
+
+        //- Handle 2D & empty bcs. Assume in both cases the starting mesh
+        //      - has all edges aligned with 3rd dimension
+        //      - is on planes of the empty patches
+        void emptyCorrectPoints(pointVectorField& pointDisplacement);
+
+
+public:
+
+    //- Runtime type information
+    TypeName("displacementSmartPointSmoothing");
+
+
+    // Constructors
+
+        //- Construct from a polyMesh and an IOdictionary
+        displacementSmartPointSmoothingMotionSolver
+        (
+            const polyMesh&,
+            const IOdictionary&
+        );
+
+        //- Construct from components
+        displacementSmartPointSmoothingMotionSolver
+        (
+            const polyMesh& mesh,
+            const IOdictionary& dict,
+            const pointVectorField& pointDisplacement,
+            const pointIOField& points0
+        );
+
+
+    //- Destructor
+    virtual ~displacementSmartPointSmoothingMotionSolver() = default;
+
+
+    // Member Functions
+
+        //- Return point location obtained from the current motion field
+        virtual tmp<pointField> curPoints() const;
+
+        //- Solve for motion
+        virtual void solve();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C
new file mode 100644
index 0000000000000000000000000000000000000000..78ccdaa6aaed73c30bdd16f834dc356c9ef50c16
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C
@@ -0,0 +1,1291 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021,2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "hexMeshSmootherMotionSolver.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+#include "pointConstraints.H"
+#include "unitConversion.H"
+#include "OBJstream.H"
+#include "PatchTools.H"
+//#include "geometricElementTransformPointSmoother.H"
+#include "pointList.H"
+#include "vectorList.H"
+#include "meshPointPatch.H"
+#include "pointSmoother.H"
+#include "fvMesh.H"
+#include "fvGeometryScheme.H"
+#include "emptyPointPatchFields.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(hexMeshSmootherMotionSolver, 0);
+
+    addToRunTimeSelectionTable
+    (
+        motionSolver,
+        hexMeshSmootherMotionSolver,
+        dictionary
+    );
+
+    addToRunTimeSelectionTable
+    (
+        displacementMotionSolver,
+        hexMeshSmootherMotionSolver,
+        displacement
+    );
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::labelList Foam::hexMeshSmootherMotionSolver::nonConstraintPatches
+(
+    const polyMesh& mesh
+)
+{
+    // Get list of all non-constraint patches. These are the ones where
+    // laplacian smoothing is applied.
+
+    const auto& pbm = mesh.boundaryMesh();
+
+    DynamicList<label> patchIDs(pbm.size());
+    for (const auto& pp : pbm)
+    {
+        if (!polyPatch::constraintType(pp.type()))
+        {
+            patchIDs.append(pp.index());
+        }
+    }
+    return patchIDs;
+}
+
+
+Foam::autoPtr<Foam::indirectPrimitivePatch>
+Foam::hexMeshSmootherMotionSolver::makePatch
+(
+    const polyMesh& mesh,
+    const labelList& patchIDs,
+    const labelList& zoneIDs,
+    const pointField& points0
+)
+{
+    // Mark all faces
+    bitSet isPatchFace(mesh.nFaces());
+
+    // Mark all boundary faces (or just patchIDs?)
+    for (const label patchi : patchIDs)
+    {
+        const polyPatch& pp = mesh.boundaryMesh()[patchi];
+        isPatchFace.set(pp.range());
+    }
+
+    const auto& fzs = mesh.faceZones();
+    for (const label zonei : zoneIDs)
+    {
+        isPatchFace.set(fzs[zonei]);
+    }
+
+    syncTools::syncFaceList(mesh, isPatchFace, orEqOp<unsigned int>());
+
+    const labelList patchFaces(isPatchFace.sortedToc());
+
+    return autoPtr<indirectPrimitivePatch>::New
+    (
+        IndirectList<face>(mesh.faces(), patchFaces),
+        points0
+    );
+}
+
+
+void Foam::hexMeshSmootherMotionSolver::checkMesh
+(
+    const pointField& currentPoints,
+    const vectorField& fCtrs,
+    const vectorField& fAreas,
+    const vectorField& cellCtrs,
+    const scalarField& cellVols,
+    labelHashSet& markedFaces,
+    bitSet& markedPoints
+) const
+{
+    // Replacement for motionSmootherAlgo::checkMesh. Adds to markedFaces
+    // any faces that are insufficient quality
+
+
+    markedFaces.clear();
+    markedPoints = false;
+
+
+    /*
+
+    tmp<scalarField> tminCellQ
+    (
+        pointSmoothers::geometricElementTransformPointSmoother::cellQuality
+        (
+            mesh(),
+            currentPoints
+        )
+    );
+    const scalarField& minCellQ = tminCellQ();
+
+    markedPoints.setSize(mesh().nPoints());
+
+    labelHashSet set;
+    DynamicList<label> storage;
+
+    for (label facei = 0; facei < mesh().nFaces(); facei++)
+    {
+        const label own = mesh().faceOwner()[facei];
+        if (minCellQ[own] < VSMALL)
+        {
+            markedFaces.insert(facei);
+            markedPoints.set(mesh().cellPoints(own, set, storage));
+        }
+        else if
+        (
+            mesh().isInternalFace(facei)
+         && minCellQ[mesh().faceNeighbour()[facei]] < VSMALL
+        )
+        {
+            markedFaces.insert(facei);
+            markedPoints.set
+            (
+                mesh().cellPoints(mesh().faceNeighbour()[facei], set, storage)
+            );
+        }
+    }
+    */
+
+    // Get measure of face quality
+    tmp<scalarField> tfaceQ
+    (
+        pointSmoother_->faceQuality
+        (
+            currentPoints,
+            fCtrs,
+            fAreas,
+            cellCtrs,
+            cellVols
+        )
+    );
+    const auto& faceQ = tfaceQ();
+
+    markedPoints.setSize(mesh().nPoints());
+    forAll(faceQ, facei)
+    {
+        if (faceQ[facei] < VSMALL)
+        {
+            markedFaces.insert(facei);
+            markedPoints.set(mesh().faces()[facei]);
+        }
+    }
+
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        markedPoints,
+        orEqOp<unsigned int>(),
+        0U
+    );
+
+    // Par sync. TBD.
+    {
+        bitSet isMarkedFace(mesh().nFaces());
+        isMarkedFace.set(markedFaces.toc());
+        syncTools::syncFaceList
+        (
+            mesh(),
+            isMarkedFace,
+            orEqOp<unsigned int>()
+        );
+        markedFaces.insert(isMarkedFace.toc());
+    }
+}
+
+
+//void Foam::hexMeshSmootherMotionSolver::constrainDisplacement
+//(
+//    pointField& points
+//) const
+//{
+//    // Make sure the points obey the boundary conditions
+//    // on pointDisplacement
+//
+//    // Update pointDisplacement for suppled points
+//    pointDisplacement_.primitiveFieldRef() = points-points0();
+//    const pointConstraints& pcs =
+//        pointConstraints::New(pointDisplacement_.mesh());
+//    pcs.constrainDisplacement(pointDisplacement_, false);
+////    pointDisplacement_.correctBoundaryConditions();
+//    points = points0()+pointDisplacement();
+//}
+
+
+bool Foam::hexMeshSmootherMotionSolver::relax
+(
+    const scalarList& relaxationFactors,
+    const bitSet& pointsToRelax,
+    const pointField& initialPoints,
+    const pointField& wantedPoints,
+    pointField& relaxedPoints,
+    labelList& relaxationLevel
+) const
+{
+    // Find relaxation level that makes mesh quality acceptable. Gets given
+    // initial set of mesh points
+
+    relaxedPoints = wantedPoints;
+
+    {
+        vectorField fCtrs(mesh().nFaces());
+        vectorField fAreas(mesh().nFaces());
+        vectorField cellCtrs(mesh().nCells());
+        scalarField cellVols(mesh().nCells());
+
+        // Calculate mesh quantities with new locations
+        const auto& geom =
+            reinterpret_cast<const fvMesh&>(mesh()).geometry();
+        geom.updateGeom
+        (
+            relaxedPoints,
+            mesh().points(),    // old points (for avoiding recalculation)
+            fCtrs,
+            fAreas,
+            cellCtrs,
+            cellVols
+        );
+
+        // Check the modified face quality. Marks faces with insufficient
+        // quality.
+        labelHashSet markedFaces;
+        bitSet markedPoints;
+        checkMesh
+        (
+            relaxedPoints,
+            fCtrs,
+            fAreas,
+            cellCtrs,
+            cellVols,
+            markedFaces,
+            markedPoints
+        );
+        if (debug)
+        {
+            Pout<< "** hexMeshSmootherMotionSolver::relax : errorfaces:"
+                << markedFaces.size()
+                << " errorpoints:" << markedPoints.count() << endl;
+        }
+    }
+
+
+    // Create a list of relaxation levels
+    // -1 indicates a point which is not to be moved
+    //  0 is the starting value for a moving point
+    relaxationLevel.setSize(mesh().nPoints());
+    relaxationLevel = -1;
+    for (const label pointi : pointsToRelax)
+    {
+        relaxationLevel[pointi] = 0;
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        relaxationLevel,
+        maxEqOp<label>(),
+        label(-1)
+    );
+
+    vectorField fCtrs(mesh().nFaces());
+    vectorField fAreas(mesh().nFaces());
+    vectorField cellCtrs(mesh().nCells());
+    scalarField cellVols(mesh().nCells());
+
+    // Loop whilst relaxation levels are being incremented
+    bool complete(false);
+    while (!complete)
+    {
+        //Info<< "    Moving "
+        //    << countZeroOrPos(relaxationFactors.size(), relaxationLevel)
+        //    << " points" << endl;
+
+        // Calculate current points (relaxationLevel >= 0)
+        forAll(relaxationLevel, pointi)
+        {
+            if (relaxationLevel[pointi] >= 0)
+            {
+                const scalar x
+                (
+                    relaxationFactors[relaxationLevel[pointi]]
+                );
+
+                relaxedPoints[pointi] =
+                    (1 - x)*initialPoints[pointi]
+                  + x*wantedPoints[pointi];
+            }
+        }
+
+        // Make sure the relaxed points still obey the boundary conditions
+        // on pointDisplacement. Note: could do this afterwards but better
+        // as soon as possible so we pick it up in the checkMesh
+        //constrainDisplacement(relaxedPoints);
+
+
+        // Calculate mesh quantities with new locations
+        const auto& geom =
+            reinterpret_cast<const fvMesh&>(mesh()).geometry();
+        geom.updateGeom
+        (
+            relaxedPoints,
+            mesh().points(),    // old points
+            fCtrs,
+            fAreas,
+            cellCtrs,
+            cellVols
+        );
+
+        // Check the modified face quality. Marks faces with insufficient
+        // quality.
+        labelHashSet markedFaces;
+        bitSet markedPoints;
+        checkMesh
+        (
+            relaxedPoints,
+            fCtrs,
+            fAreas,
+            cellCtrs,
+            cellVols,
+            markedFaces,
+            markedPoints
+        );
+        //Pout<< "    checkMesh : errorfaces:" << markedFaces.size()
+        //    << " errorpoints:" << markedPoints.count() << endl;
+
+        complete = true;
+        for (const label pointi : markedPoints)
+        {
+            if (relaxationLevel[pointi] < relaxationFactors.size() - 1)
+            {
+                ++relaxationLevel[pointi];
+                complete = false;
+            }
+        }
+
+        //Info<< "    After adjustment:"
+        //    << countZeroOrPos(relaxationFactors.size(), relaxationLevel)
+        //    << " points relaxed" << endl;
+
+
+        // Synchronise convergence
+        reduce(complete, andOp<bool>());
+
+        // Synchronise relaxation levels
+        syncTools::syncPointList
+        (
+            mesh(),
+            relaxationLevel,
+            maxEqOp<label>(),
+            label(0)
+        );
+    }
+
+    // Check for convergence
+    const label count(countPos(relaxationLevel));
+    const bool converged(count == 0);
+
+    //if (converged)
+    //{
+    //    Info<< "... Converged" << endl << endl;
+    //}
+    //else
+    //{
+    //    Info<< "... Not converged" << endl << endl;
+    //}
+
+    return converged;
+}
+Foam::label Foam::hexMeshSmootherMotionSolver::countPos
+(
+    const labelList& elems
+) const
+{
+    label n = 0;
+    for (const label elem : elems)
+    {
+        if (elem > 0)
+        {
+            n++;
+        }
+    }
+    return returnReduce(n, sumOp<label>());
+}
+
+
+Foam::labelList Foam::hexMeshSmootherMotionSolver::countZeroOrPos
+(
+    const label size,
+    const labelList& elems
+) const
+{
+    labelList n(size, 0);
+    for (const label elem : elems)
+    {
+        if (elem >= 0)
+        {
+            n[elem]++;
+        }
+    }
+    Pstream::listCombineGather(n, plusEqOp<label>());
+    Pstream::broadcast(n);
+    return n;
+}
+
+
+void Foam::hexMeshSmootherMotionSolver::select
+(
+    const labelUList& lst,
+    const label val,
+    bitSet& isVal
+) const
+{
+    isVal.set(lst.size());
+    isVal = false;
+    forAll(lst, i)
+    {
+        isVal[i] = (lst[i] == val);
+    }
+}
+
+
+void Foam::hexMeshSmootherMotionSolver::laplaceSmooth
+(
+    const label type,
+    const pointField& initialPoints,
+    pointField& newPoints
+) const
+{
+    if (initialPoints.size() != mesh().nPoints())
+    {
+        FatalErrorInFunction << "mesh().nPoints:" << mesh().nPoints()
+            << " initial:" << initialPoints.size() << exit(FatalError);
+    }
+
+    newPoints.setSize(initialPoints.size());
+    newPoints = Zero;
+    labelList n(initialPoints.size(), 0);
+
+    DynamicList<label> storage;
+    forAll(pointTypes_, pointi)
+    {
+        if (pointTypes_[pointi] == INTERIOR)
+        {
+            const labelList& pPoints = mesh().pointPoints(pointi, storage);
+            for (const label otherPointi : pPoints)
+            {
+                if (isMasterPoint_[otherPointi])
+                {
+                    newPoints[pointi] += initialPoints[otherPointi];
+                    n[pointi]++;
+                }
+            }
+            //Pout<< "Moving internal point " << initialPoints[pointi]
+            //    << " to average " << newPoints[pointi]/n[pointi]
+            //    << " of " << n[pointi] << " points" << endl;
+        }
+    }
+
+    // Combine
+    syncTools::syncPointList
+    (
+        mesh(),
+        n,
+        plusEqOp<label>(),
+        0
+    );
+    syncTools::syncPointList
+    (
+        mesh(),
+        newPoints,
+        plusEqOp<vector>(),
+        vector::zero
+    );
+    forAll(newPoints, pointi)
+    {
+        if (n[pointi] == 0)
+        {
+            // This can happen if not interior point
+            newPoints[pointi] = initialPoints[pointi];
+            //Pout<< "Not Moving boundary point " << newPoints[pointi] << endl;
+        }
+        else
+        {
+            newPoints[pointi] /= n[pointi];
+            //Pout<< "Moving internal point " << initialPoints[pointi]
+            //    << " to " << newPoints[pointi] << endl;
+        }
+    }
+}
+void Foam::hexMeshSmootherMotionSolver::featLaplaceSmooth
+(
+    const indirectPrimitivePatch& pp,
+    const pointField& initialPoints,
+    pointField& newPoints
+) const
+{
+    if (initialPoints.size() != pp.nPoints())
+    {
+        FatalErrorInFunction << "pp.nPoints:" << pp.nPoints()
+            << " initial:" << initialPoints.size() << exit(FatalError);
+    }
+
+    newPoints.setSize(pp.nPoints());
+    newPoints = Zero;
+    labelList n(pp.nPoints(), 0);
+
+    const edgeList& edges = pp.edges();
+    const labelListList& pointEdges = pp.pointEdges();
+    const labelList& meshPoints = pp.meshPoints();
+
+    forAll(pointEdges, pointi)
+    {
+        const label myConstraint = pointTypes_[meshPoints[pointi]];
+        if (myConstraint != INTERIOR)   // pp points should never be interior
+        {
+            const labelList& pEdges = pointEdges[pointi];
+            //Pout<< "For boundary point:" << initialPoints[pointi]
+            //    << endl;
+
+            for (const label edgei : pEdges)
+            {
+                const label otherPointi = edges[edgei].otherVertex(pointi);
+                const label otherMeshPointi = meshPoints[otherPointi];
+                const label otherConstraint = pointTypes_[otherMeshPointi];
+
+                if
+                (
+                    (otherConstraint != INTERIOR)   // Should not happen
+                 && (myConstraint <= otherConstraint)
+                 && isMasterPoint_[otherMeshPointi]
+                )
+                {
+                    //Pout<< "    summing boundary point:"
+                    //    << initialPoints[otherPointi] << endl;
+
+                    newPoints[pointi] += initialPoints[otherPointi];
+                    n[pointi]++;
+                }
+            }
+        }
+    }
+
+    // Combine
+    syncTools::syncPointList
+    (
+        mesh(),
+        meshPoints,
+        n,
+        plusEqOp<label>(),
+        0
+    );
+    syncTools::syncPointList
+    (
+        mesh(),
+        meshPoints,
+        newPoints,
+        plusEqOp<vector>(),
+        vector::zero
+    );
+
+    forAll(newPoints, pointi)
+    {
+        if (n[pointi] == 0)
+        {
+            // This can happen if surface point surrounded by feature points
+            // only.
+            newPoints[pointi] = initialPoints[pointi];
+            //Pout<< "Not Moving boundary point " << newPoints[pointi] << endl;
+        }
+        else
+        {
+            newPoints[pointi] /= n[pointi];
+            //Pout<< "Moving surface point " << initialPoints[pointi]
+            //    << " to average " << newPoints[pointi]
+            //    << " of " << n[pointi] << " points" << endl;
+        }
+    }
+}
+void Foam::hexMeshSmootherMotionSolver::snapBoundaryPoints
+(
+    const scalar scale,
+    const pointField& initialPoints,
+    pointField& newPoints
+) const
+{
+    if (initialPoints.size() != pointDisplacement_.mesh().size())
+    {
+        FatalErrorInFunction
+            << "mesh.nPoints():" << pointDisplacement_.mesh().size()
+            << " initial:" << initialPoints.size() << exit(FatalError);
+    }
+    const indirectPrimitivePatch& bnd0 = bnd0Ptr_();
+    const labelList& mp = bnd0.meshPoints();
+
+    // Save old point location
+    const vectorField bndPoints(initialPoints, mp);
+
+    // Update pointDisplacement_ to be consistent with mesh points being set to
+    // initialPoints. This makes sure that the snapping is done using the
+    // initialPoints as starting point
+    pointDisplacement_.primitiveFieldRef() = initialPoints-points0();
+    // 'snap' using boundary conditions
+    pointDisplacement_.correctBoundaryConditions();
+
+    // Calculate new position
+    newPoints = points0() + pointDisplacement().internalField();
+
+    if (scale < 1.0)
+    {
+        // Underrelax
+        vectorField d(newPoints, mp);
+        d -= bndPoints;
+        d *= scale;
+        d += bndPoints;
+        UIndirectList<point>(newPoints, mp) = d;
+    }
+}
+
+//void Foam::hexMeshSmootherMotionSolver::writeOBJ
+//(
+//    const fileName& name,
+//    const pointField& p0,
+//    const pointField& p1
+//) const
+//{
+//    OBJstream os(mesh().time().path()/name);
+//    forAll(p0, pointi)
+//    {
+//        os.write(linePointRef(p0[pointi], p1[pointi]));
+//    }
+//    Pout<< "Dumped to " << os.name() << endl;
+//}
+//void Foam::hexMeshSmootherMotionSolver::writeOBJ
+//(
+//    const fileName& name,
+//    const UIndirectList<face>& pp,
+//    const pointField& points
+//) const
+//{
+//    const faceList fcs(pp);
+//
+//    OBJstream os(mesh().time().path()/name);
+//    os.write(fcs, points, false);
+//    Pout<< "Dumped faces to " << os.name() << endl;
+//}
+
+
+void Foam::hexMeshSmootherMotionSolver::emptyCorrectPoints
+(
+    pointVectorField& pointDisplacement
+) const
+{
+    // Assume empty point patches are already in correct location
+    // so knock out any off-plane displacement.
+    auto& fld = pointDisplacement.primitiveFieldRef();
+    for (const auto& ppf : pointDisplacement.boundaryField())
+    {
+        if (isA<emptyPointPatchVectorField>(ppf))
+        {
+            const auto& mp = ppf.patch().meshPoints();
+            forAll(mp, i)
+            {
+                pointConstraint pc;
+                ppf.patch().applyConstraint(i, pc);
+                fld[mp[i]] = pc.constrainDisplacement(fld[mp[i]]);
+            }
+        }
+    }
+
+    pointField wantedPoints(points0() + fld);
+    twoDCorrectPoints(wantedPoints);
+    fld = wantedPoints-points0();
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::hexMeshSmootherMotionSolver::
+hexMeshSmootherMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict
+)
+:
+    displacementMotionSolver(mesh, dict, typeName),
+    pointSmoother_(pointSmoother::New(mesh, coeffDict())),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxationFactors_(coeffDict().lookup("relaxationFactors")),
+    relaxationLevel_(mesh.nPoints(), 0),
+    relaxedPoints_(mesh.points()),
+    //surfacesDict_(coeffDict().subDict("geometry")),
+    //featureAngle_(coeffDict().get<scalar>("featureAngle")),
+    //snapPatches_
+    //(
+    //    mesh.boundaryMesh().patchSet
+    //    (
+    //        coeffDict().get<wordRes>("patches")
+    //    ).sortedToc()
+    //),
+    //snapZones_
+    //(
+    //    mesh.faceZones().indices
+    //    (
+    //        coeffDict().get<wordRes>("faceZones")
+    //    )
+    //),
+    snapScale_(Function1<scalar>::New("snapScale", coeffDict())),
+    isMasterPoint_(syncTools::getMasterPoints(mesh)),
+    // Create big primitivePatch for all outside and any features on it
+    //bnd0Ptr_(makePatch(mesh, snapPatches_, snapZones_, points0()))
+    bnd0Ptr_
+    (
+        makePatch
+        (
+            mesh,
+            nonConstraintPatches(mesh),
+            labelList::null(),
+            points0()
+        )
+    )
+{
+//     findSurfaces();
+//
+//     // Do multi-patch constraints
+//     // ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+//     const scalar featureEdgeCos(Foam::cos(featureAngle_));
+//     const scalar featurePointCos(featureEdgeCos);
+//
+//     const indirectPrimitivePatch& bnd0 = bnd0Ptr_();
+//
+//     calcConstraints
+//     (
+//         featureEdgeCos,
+//         featurePointCos,
+//         bnd0,
+//         bnd0EdgeConstraints_,
+//         bnd0PointConstraints_
+//     );
+
+    const pointMesh& pMesh = pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
+
+    pointTypes_.setSize(pMesh.size());
+    pointTypes_ = INTERIOR;
+
+    for (const auto& pp : pMesh.boundary())
+    {
+        if (!isA<meshPointPatch>(pp))
+        {
+            const auto& mp = pp.meshPoints();
+            UIndirectList<label>(pointTypes_, mp) = pointType::SURFACE;
+        }
+    }
+
+    // Override with any explicit constraint boundaries
+    for (const auto& pp : pMesh.boundary())
+    {
+        const auto* meshPointPtr = isA<meshPointPatch>(pp);
+        if (meshPointPtr)
+        {
+            const auto& constraints = meshPointPtr->constraints();
+            const auto& mp = meshPointPtr->meshPoints();
+
+            forAll(mp, i)
+            {
+                pointTypes_[mp[i]] = pointType(constraints[i].first());
+            }
+        }
+    }
+
+    // Make sure coupled points agree. Max constraint wins.
+    syncTools::syncPointList
+    (
+        mesh,
+        pointTypes_,
+        maxEqOp<label>(),
+        0
+    );
+
+    bitSet isVal;
+    select(pointTypes_, POINT, isVal);
+    const label nFeatPoint = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, EDGE, isVal);
+    const label nFeatEdge = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, SURFACE, isVal);
+    const label nSurface = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, INTERIOR, isVal);
+    const label nInternal = returnReduce(isVal.count(), sumOp<label>());
+    Info<< "Attraction:" << nl
+        << "    feature point:" << nFeatPoint << nl
+        << "    feature edge :" << nFeatEdge << nl
+        << "    surface      :" << nSurface << nl
+        << "    none         :" << nInternal
+        << endl;
+}
+
+
+Foam::hexMeshSmootherMotionSolver::
+hexMeshSmootherMotionSolver
+(
+    const polyMesh& mesh,
+    const IOdictionary& dict,
+    const pointVectorField& pointDisplacement,
+    const pointIOField& points0
+)
+:
+    displacementMotionSolver(mesh, dict, pointDisplacement, points0, typeName),
+    pointSmoother_(pointSmoother::New(mesh, coeffDict())),
+    //pointSmoother_
+    //(
+    //    pointSmoother::New
+    //    (
+    //        coeffDict(),
+    //        displacementMotionSolver::pointDisplacement()
+    //    )
+    //),
+    nPointSmootherIter_
+    (
+        readLabel(coeffDict().lookup("nPointSmootherIter"))
+    ),
+    relaxationFactors_(coeffDict().lookup("relaxationFactors")),
+    relaxationLevel_(mesh.nPoints(), 0),
+    relaxedPoints_(mesh.points()),
+    //surfacesDict_(coeffDict().subDict("geometry")),
+    //featureAngle_(coeffDict().get<scalar>("featureAngle")),
+    //snapPatches_
+    //(
+    //    mesh.boundaryMesh().patchSet
+    //    (
+    //        coeffDict().get<wordReList>("patches")
+    //    ).sortedToc()
+    //),
+    //snapZones_
+    //(
+    //    mesh.faceZones().indices
+    //    (
+    //        coeffDict().get<wordRes>("faceZones")
+    //    )
+    //),
+    snapScale_(Function1<scalar>::New("snapScale", coeffDict())),
+    isMasterPoint_(syncTools::getMasterPoints(mesh)),
+    // Create big primitivePatch for all outside and any features on it
+    //bnd0Ptr_(makePatch(mesh, snapPatches_, snapZones_, points0))
+    bnd0Ptr_
+    (
+        makePatch
+        (
+            mesh,
+            nonConstraintPatches(mesh),
+            labelList::null(),
+            points0
+        )
+    )
+{
+//    findSurfaces();
+//
+//    const scalar featureEdgeCos(Foam::cos(featureAngle_));
+//    const scalar featurePointCos(featureEdgeCos);
+//
+//    const indirectPrimitivePatch& bnd0 = bnd0Ptr_();
+//
+//    calcConstraints
+//    (
+//        featureEdgeCos,
+//        featurePointCos,
+//        bnd0,
+//        bnd0EdgeConstraints_,
+//        bnd0PointConstraints_
+//    );
+
+    const pointMesh& pMesh = pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
+
+    pointTypes_.setSize(mesh.nPoints());
+    pointTypes_ = INTERIOR;
+
+    for (const auto& pp : pMesh.boundary())
+    {
+        if (!isA<meshPointPatch>(pp) && !pp.coupled())
+        {
+            const auto& mp = pp.meshPoints();
+            UIndirectList<label>(pointTypes_, mp) = pointType::SURFACE;
+        }
+    }
+
+    // Override with any explicit constraint boundaries
+    for (const auto& pp : pMesh.boundary())
+    {
+        const auto* meshPointPtr = isA<meshPointPatch>(pp);
+        if (meshPointPtr)
+        {
+            const auto& constraints = meshPointPtr->constraints();
+            const auto& mp = meshPointPtr->meshPoints();
+
+            forAll(mp, i)
+            {
+                pointTypes_[mp[i]] = pointType(constraints[i].first());
+            }
+        }
+    }
+
+    // Make sure coupled points agree. Max constraint wins.
+    syncTools::syncPointList
+    (
+        mesh,
+        pointTypes_,
+        maxEqOp<label>(),
+        0
+    );
+
+    bitSet isVal;
+    select(pointTypes_, POINT, isVal);
+    const label nFeatPoint = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, EDGE, isVal);
+    const label nFeatEdge = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, SURFACE, isVal);
+    const label nSurface = returnReduce(isVal.count(), sumOp<label>());
+    select(pointTypes_, INTERIOR, isVal);
+    const label nInternal = returnReduce(isVal.count(), sumOp<label>());
+    Info<< "Attraction:" << nl
+        << "    feature point:" << nFeatPoint << nl
+        << "    feature edge :" << nFeatEdge << nl
+        << "    surface      :" << nSurface << nl
+        << "    none         :" << nInternal
+        << endl;
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::hexMeshSmootherMotionSolver::
+~hexMeshSmootherMotionSolver()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+Foam::tmp<Foam::pointField>
+Foam::hexMeshSmootherMotionSolver::curPoints() const
+{
+    //Note: twoDCorrect already done by ::solve
+    return relaxedPoints_;
+}
+
+
+void Foam::hexMeshSmootherMotionSolver::solve()
+{
+    // Update any internal storage for current state
+    movePoints(mesh().points());
+
+    // No updating of bc since we don't want to do snapping yet - is done
+    // later on
+    //pointDisplacement().boundaryFieldRef().updateCoeffs();
+
+    const indirectPrimitivePatch& bnd0 = bnd0Ptr_();
+    const labelList& mp = bnd0.meshPoints();
+
+    // Points on boundary
+    bitSet isBndPoint(mesh().nPoints(), false);
+    isBndPoint.set(mp);
+
+    // Points not on boundary
+    bitSet isInternalPoint;
+    select(pointTypes_, INTERIOR, isInternalPoint);
+
+
+    const pointField& initialPoints = mesh().points();
+
+    // Wanted locations - starts off from current mesh points. Note : could
+    // use relaxedPoints_ but this should be equal to current mesh points unless
+    // we have multiple motion solvers ...
+    pointField movedPoints(initialPoints);
+
+
+    // -1 indicates a point which is not to be moved
+    //  0 is the starting value for a moving point
+    const label nRelaxed = countPos(relaxationLevel_);
+    //Pout<< "Starting relaxed:" << nRelaxed << endl;
+
+    if (nRelaxed > 0)
+    {
+        // MeshSmoother::snapSmoothing()
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // - set initialPoint from relaxedPoint
+        // - smooth internal points
+        //      - and relax point motion (= adapt relaxationLevel_)
+        // - snap boundary points
+        //      - and relax point motion (= adapt relaxationLevel_)
+        // - mark all points that are not snapped (i.e. snapped but relaxed)
+        // - smooth all boundary points (using features)
+        //      - and relax point motion (= adapt relaxationLevel_)
+
+        // Laplace smoothing of interior (=unconstrained) points
+        laplaceSmooth(INTERIOR, initialPoints, movedPoints);
+
+        // Apply constraints
+        //constrainDisplacement(movedPoints);
+
+        // Determine relaxation level to move points
+        relax
+        (
+            relaxationFactors_,
+            isInternalPoint,
+            initialPoints,      // starting location
+            movedPoints,        // wanted location
+            relaxedPoints_,     // inbetween location without errors
+            relaxationLevel_
+        );
+        //Pout<< "After laplaceSmooth:"
+        //    << countZeroOrPos(relaxationFactors_.size(), relaxationLevel_)
+        //    << endl;
+        //writeOBJ
+        //(
+        //    "laplaceSmooth_relax_" + mesh().time().timeName() + ".obj",
+        //    bnd0,
+        //    relaxedPoints_
+        //);
+
+
+        // Snap boundary points
+        const scalar scale = snapScale_->value(mesh().time().timeIndex());
+        if (scale > 0)
+        {
+            // snap to surface (=apply boundary conditions)
+            snapBoundaryPoints(scale, initialPoints, movedPoints);
+
+            // Apply constraints
+            //constrainDisplacement(movedPoints);
+
+            relax
+            (
+                relaxationFactors_,
+                isBndPoint,
+                initialPoints,
+                movedPoints,
+                relaxedPoints_,
+                relaxationLevel_
+            );
+            //Pout<< "After snapping:"
+            //    << countZeroOrPos(relaxationFactors_.size(), relaxationLevel_)
+            //    << endl;
+            //writeOBJ("snap_relax.obj", initialPoints, relaxedPoints_);
+
+            // Now relaxedPoints_ with relaxationLevel_ 0 are perfectly snapped
+            // (only applicable for bnd0 points)
+        }
+
+        // Laplace smoothing of (now snapped&relaxed) boundary points. Use
+        // average of surrounding boundary points of same type only
+        pointField bndMovedPoints;
+        featLaplaceSmooth
+        (
+            bnd0,
+            pointField(relaxedPoints_, mp),
+            bndMovedPoints
+        );
+        UIndirectList<point>(movedPoints, mp) = bndMovedPoints;
+
+        // Apply constraints
+        //constrainDisplacement(movedPoints);
+        //writeOBJ("featLaplaceSmooth.obj", initialPoints, movedPoints);
+
+        relax
+        (
+            relaxationFactors_,
+            isBndPoint,
+            initialPoints,
+            movedPoints,
+            relaxedPoints_,
+            relaxationLevel_
+        );
+    }
+    else
+    {
+        // MeshSmoother::GETMeSmoothing()
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // - set initialPoint from relaxedPoint
+        // - smooth all boundary points (using features)
+        //      - and relax point motion (= adapt relaxationLevel_)
+        // - snap boundary points
+        //      - and relax point motion (= adapt relaxationLevel_)
+        // - do all points GETMe
+        //      - and relax point motion (= adapt relaxationLevel_)
+
+
+        // Laplace smoothing of boundary points. Use average of
+        // surrounding boundary points of same type only. TBD: make consistent
+        // wrt coupled points not on boundary patch.
+        pointField bndMovedPoints;
+        featLaplaceSmooth
+        (
+            bnd0,
+            pointField(relaxedPoints_, mp),
+            bndMovedPoints
+        );
+        UIndirectList<point>(movedPoints, mp) = bndMovedPoints;
+        //writeOBJ
+        //(
+        //    "featLaplaceSmooth_unconstrain_"
+        //  + mesh().time().timeName()
+        //  + ".obj",
+        //    pointField(initialPoints, mp),
+        //    bndMovedPoints
+        //);
+
+        // Apply constraints
+        //constrainDisplacement(movedPoints);
+
+        relax
+        (
+            relaxationFactors_,
+            isBndPoint,
+            initialPoints,
+            movedPoints,
+            relaxedPoints_,
+            relaxationLevel_
+        );
+        //writeOBJ
+        //(
+        //    "featLaplaceSmooth_relax"
+        //  + mesh().time().timeName()
+        //  + ".obj",
+        //    initialPoints,
+        //    relaxedPoints_
+        //);
+
+        // Snap boundary points
+        const scalar scale = snapScale_->value(mesh().time().timeIndex());
+        if (scale > 0)
+        {
+            // snap to surface (=apply boundary conditions)
+            snapBoundaryPoints(scale, relaxedPoints_, movedPoints);
+
+            // Apply constraints
+            //constrainDisplacement(movedPoints);
+            //writeOBJ("snap.obj", initialPoints, movedPoints);
+
+            relax
+            (
+                relaxationFactors_,
+                isBndPoint,
+                initialPoints,
+                movedPoints,
+                relaxedPoints_,
+                relaxationLevel_
+            );
+            //writeOBJ("snap_relax.obj", initialPoints, relaxedPoints_);
+        }
+
+        vectorField fCtrs(mesh().nFaces());
+        vectorField fAreas(mesh().nFaces());
+        vectorField cellCtrs(mesh().nCells());
+        scalarField cellVols(mesh().nCells());
+
+        movedPoints = relaxedPoints_;
+
+        for(label i = 0; i < nPointSmootherIter_; i ++)
+        {
+            // Starting from current points do smoothing
+            // Calculate mesh quantities with new locations
+
+            const auto& geom =
+                reinterpret_cast<const fvMesh&>(mesh()).geometry();
+            geom.updateGeom
+            (
+                movedPoints,
+                mesh().points(),    // old points
+                fCtrs,
+                fAreas,
+                cellCtrs,
+                cellVols
+            );
+
+            //- Smooth point positions (returned as pointDisplacement w.r.t.
+            //  points0)
+            pointSmoother_->update
+            (
+                identity(mesh().nFaces()),
+                points0(),
+                movedPoints,
+                fCtrs,
+                fAreas,
+                cellCtrs,
+                cellVols,
+                pointDisplacement_
+            );
+            // Keep points on empty patches
+            emptyCorrectPoints(pointDisplacement());
+
+            // Update moving points
+            movedPoints = points0() + pointDisplacement().internalField();
+
+            //// snap to surface (=apply boundary conditions)
+            //snapBoundaryPoints(scale, movedPoints, movedPoints);
+        }
+
+        // snap to surface (=apply boundary conditions)
+        //snapBoundaryPoints(scale, movedPoints, movedPoints);
+
+        //writeOBJ
+        //(
+        //    "GETMeSmoothing_snapped_"
+        //  + mesh().time().timeName()
+        //  + ".obj",
+        //    pointField(initialPoints, mp),
+        //    pointField(movedPoints, mp)
+        //);
+
+        relax
+        (
+            relaxationFactors_,
+            bitSet(mesh().nPoints(), true),
+            initialPoints,
+            movedPoints,
+            relaxedPoints_,
+            relaxationLevel_
+        );
+        //writeOBJ("GETMeSmoothing_relax.obj", initialPoints, relaxedPoints_);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.H
new file mode 100644
index 0000000000000000000000000000000000000000..a71b739fa1886692b9b23bd2944ea99634873520
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.H
@@ -0,0 +1,258 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::hexMeshSmootherMotionSolver
+
+Description
+    Implementation of hexMeshSmoother (part of extBlockMesh). WIP.
+
+    See https://github.com/Etudes-NG/extBlockMesh
+    extBlockMesh Copyright (C) 2014 Etudes-NG
+
+    Quality-based under-relaxation of point smoothing.
+
+Usage
+    Example of the motion solver specification in dynamicMeshDict:
+    \verbatim
+    motionSolver    hexMeshSmoother;
+    hexMeshSmootherCoeffs
+    {
+        //- Number of smoothing iterations
+        nPointSmootherIter      10;
+
+        //- Smoother to apply
+        pointSmoother           geometricElementTransform;
+
+        //- Any smoother-specific settings
+        transformationParameter 0.667;
+
+        //- Underrelax boundary condition
+        snapScale               table ((0 0.1) (10 1.0));
+    }
+
+SourceFiles
+    hexMeshSmootherMotionSolver.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef hexMeshSmootherMotionSolver_H
+#define hexMeshSmootherMotionSolver_H
+
+#include "displacementMotionSolver.H"
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+//class searchableSurfaces;
+class pointSmoother;
+
+/*---------------------------------------------------------------------------*\
+                 Class hexMeshSmootherMotionSolver Declaration
+\*---------------------------------------------------------------------------*/
+
+class hexMeshSmootherMotionSolver
+:
+    public displacementMotionSolver
+{
+public:
+
+    // Public Data
+
+        //- Enumeration defining the type of attraction
+        enum pointType
+        {
+            INTERIOR = 0,
+            SURFACE = 1,
+            EDGE = 2,
+            POINT = 3
+        };
+
+
+protected:
+
+    // Protected Data
+
+        //- Point smoothing method
+        autoPtr<pointSmoother> pointSmoother_;
+
+        //- Number of point smoother iterations per timestep
+        const label nPointSmootherIter_;
+
+
+        // Mesh quality based relaxation of smoothed position
+
+            //- Relaxation factors to use in each iteration
+            const scalarList relaxationFactors_;
+
+            //- Per mesh point (including internal) what type
+            labelList pointTypes_;
+
+            //- Per mesh point the last used relaxation factor
+            labelList relaxationLevel_;
+
+            //- Relaxed point field
+            pointField relaxedPoints_;
+
+
+        ////- Patches that are to be snapped
+        //const labelList snapPatches_;
+        //
+        ////- FaceZones that are to be snapped
+        //const labelList snapZones_;
+
+        //- Scaling for snapping
+        const autoPtr<Function1<scalar>> snapScale_;
+
+        //- Cached per-point coupled status. For guaranteeing contributions
+        //  of coupled points only done once
+        const bitSet isMasterPoint_;
+
+        //- Create big primitivePatch for all outside and any features on it
+        const autoPtr<indirectPrimitivePatch> bnd0Ptr_;
+
+
+    // Private Member Functions
+
+        //- Collect all non-constraint (i.e. no processor, cyclic, empty etc)
+        //- patches
+        static labelList nonConstraintPatches(const polyMesh& mesh);
+
+        //- Create single patch of all supplied faces
+        static autoPtr<indirectPrimitivePatch> makePatch
+        (
+            const polyMesh& mesh,
+            const labelList& patchIDs,
+            const labelList& zoneIDs,
+            const pointField& points0
+        );
+
+        //- Check with current points
+        void checkMesh
+        (
+            const pointField& currentPoints,
+            const vectorField& fCtrs,
+            const vectorField& fAreas,
+            const vectorField& cellCtrs,
+            const scalarField& cellVols,
+            labelHashSet& markedFaces,
+            bitSet& markedPoints
+        ) const;
+
+        //- Apply current constraints (from pointDisplacement) to supplied
+        //  locations
+        void constrainDisplacement(pointField& points) const;
+
+        //- Relax the points (supplied in pointDisplacement)
+        bool relax
+        (
+            const scalarList& relaxationFactors,
+            const bitSet& pointsToRelax,
+            const pointField& initialPoints,
+            const pointField& wantedPoints,
+            pointField& relaxedPoints,
+            labelList& relaxationLevel
+        ) const;
+        label countPos(const labelList& elems) const;
+        labelList countZeroOrPos(const label size, const labelList& lst) const;
+
+        //- Helper: set in bitSet all elements with a certain value
+        void select(const labelUList&, const label val, bitSet& isVal) const;
+
+        void laplaceSmooth
+        (
+            const label type,
+            const pointField& initialPoints,
+            pointField& newPoints
+        ) const;
+        void featLaplaceSmooth
+        (
+            const indirectPrimitivePatch& pp,
+            const pointField& initialPoints,
+            pointField& newPoints
+        ) const;
+        // Snap points using boundary evaluation ...
+        void snapBoundaryPoints
+        (
+            const scalar scale,
+            const pointField& initialPoints,
+            pointField& newPoints
+        ) const;
+
+        //- Keep points on empty patches
+        void emptyCorrectPoints(pointVectorField& pointDisplacement) const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("hexMeshSmoother");
+
+
+    // Constructors
+
+        //- Construct from a polyMesh and an IOdictionary
+        hexMeshSmootherMotionSolver
+        (
+            const polyMesh&,
+            const IOdictionary&
+        );
+
+        //- Construct from components
+        hexMeshSmootherMotionSolver
+        (
+            const polyMesh& mesh,
+            const IOdictionary& dict,
+            const pointVectorField& pointDisplacement,
+            const pointIOField& points0
+        );
+
+
+    //- Destructor
+    virtual ~hexMeshSmootherMotionSolver();
+
+
+    // Member Functions
+
+        //- Return point location obtained from the current motion field
+        virtual tmp<pointField> curPoints() const;
+
+        //- Solve for motion
+        virtual void solve();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.C
new file mode 100644
index 0000000000000000000000000000000000000000..6eac2e9765af5ee66a6d9c680e803a8c73b477c4
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.C
@@ -0,0 +1,148 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+\*---------------------------------------------------------------------------*/
+
+#include "equipotentialPointSmoother.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+    defineTypeNameAndDebug(equipotentialPointSmoother, 0);
+    addToRunTimeSelectionTable
+    (
+        pointSmoother,
+        equipotentialPointSmoother,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointSmoothers::equipotentialPointSmoother::equipotentialPointSmoother
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    pointSmoother(mesh, dict)
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::pointSmoothers::equipotentialPointSmoother::calculate
+(
+    const labelList& facesToMove,
+    const pointField& oldPoints,
+    const pointField& currentPoints,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes,
+    vectorField& pointDisplacement
+) const
+{
+    // Number of points used in each average
+    scalarField weights(mesh().nPoints(), 0);
+
+    // Reset the displacements which are about to be calculated
+    reset(facesToMove, weights, pointDisplacement);
+
+    // Sum the non-internal face displacements
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (!isInternalOrProcessorFace(faceI))
+        {
+            const face& fPoints(mesh().faces()[faceI]);
+
+            const scalar area(mag(mesh().faceAreas()[faceI]));
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                pointDisplacement[pointI] +=
+                    area
+                   *(
+                        faceCentres[faceI]
+                      - oldPoints[pointI]
+                    );
+
+                weights[pointI] += area;
+            }
+        }
+    }
+
+    // Sum the internal face displacements
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (isInternalOrProcessorFace(faceI))
+        {
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                if (weights[pointI] < SMALL)
+                {
+                    const labelList& pCells(mesh().pointCells()[pointI]);
+
+                    forAll(pCells, pCellI)
+                    {
+                        const label cellI(pCells[pCellI]);
+
+                        const scalar volume(mesh().cellVolumes()[cellI]);
+
+                        pointDisplacement[pointI] +=
+                            volume
+                           *(
+                                cellCentres[cellI]
+                              - oldPoints[pointI]
+                            );
+
+                        weights[pointI] += volume;
+                    }
+                }
+            }
+        }
+    }
+
+    // Average
+    average(facesToMove, weights, pointDisplacement);
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.H
new file mode 100644
index 0000000000000000000000000000000000000000..2ec69312f49e67068f800507c322b47158ec2635
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/equipotentialPointSmoother/equipotentialPointSmoother.H
@@ -0,0 +1,105 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::equipotentialPointSmoother
+
+Description
+    Equipotential point smoothing. Points are moved towards the centroid of the
+    surrounding cell volumes. This method tends to equilise cell volumes, and
+    can generate distorted cells around refinement patterns.
+
+SourceFiles
+    equipotentialPointSmoother.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef equipotentialPointSmoother_H
+#define equipotentialPointSmoother_H
+
+#include "pointSmoother.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+
+/*---------------------------------------------------------------------------*\
+                   Class equipotentialPointSmoother Declaration
+\*---------------------------------------------------------------------------*/
+
+class equipotentialPointSmoother
+:
+    public pointSmoother
+{
+public:
+
+    //- Runtime type information
+    TypeName("equipotential");
+
+
+    // Constructors
+
+        //- Construct from a dictionary and a polyMesh
+        equipotentialPointSmoother
+        (
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~equipotentialPointSmoother() = default;
+
+
+    // Member Functions
+
+        //- Calculate the point displacements
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            vectorField& pointDisplacement
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace pointSmoothers
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.C
new file mode 100644
index 0000000000000000000000000000000000000000..558f1a5286ad09d4c430494ac6c889b699cfa16d
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.C
@@ -0,0 +1,292 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "cellPointConnectivity.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(cellPointConnectivity, 0);
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::cellPointConnectivity::generateCellPointConnectivity(label cellI)
+{
+    const cell& cFaceLabels(mesh_.cells()[cellI]);
+    const labelList cPointLabels(cFaceLabels.labels(mesh_.faces()));
+    const edgeList cEdges(cFaceLabels.edges(mesh_.faces()));
+
+    // Generate a sorted list of points and corresponding point indices
+    labelPairList pointLabelPointIndices(cPointLabels.size());
+    forAll(cPointLabels, pointI)
+    {
+        pointLabelPointIndices[pointI] =
+            labelPair(cPointLabels[pointI], pointI);
+    }
+    sort(pointLabelPointIndices);
+
+    // Generate a sorted list of edge labels and corresponding edge indices
+    // Negative values indicate an edge which runs in an opposite direction to
+    // the face node listing
+    labelListList edgeLabelsEdgeIndices
+    (
+        2*cEdges.size(),
+        labelList(3, label(-1))
+    );
+    forAll(cEdges, cEdgeI)
+    {
+        edgeLabelsEdgeIndices[2*cEdgeI][0] = cEdges[cEdgeI][0];
+        edgeLabelsEdgeIndices[2*cEdgeI][1] = cEdges[cEdgeI][1];
+        edgeLabelsEdgeIndices[2*cEdgeI][2] = cEdgeI;
+
+        edgeLabelsEdgeIndices[2*cEdgeI+1][0] = cEdges[cEdgeI][1];
+        edgeLabelsEdgeIndices[2*cEdgeI+1][1] = cEdges[cEdgeI][0];
+        edgeLabelsEdgeIndices[2*cEdgeI+1][2] = - cEdgeI - 1;
+    }
+    sort(edgeLabelsEdgeIndices);
+
+    // Generate a sorted list of edge labels and correspoinding face indices
+    labelListList edgeLabelsFaceIndices;
+    forAll(cFaceLabels, cFaceI)
+    {
+        const face& cFace(mesh_.faces()[cFaceLabels[cFaceI]]);
+
+        const bool owner(mesh_.faceOwner()[cFaceLabels[cFaceI]] == cellI);
+
+        const label cFaceNEdges(cFace.size());
+        forAll(cFace, cFaceEdgeI)
+        {
+            edgeLabelsFaceIndices.append(labelList(3, label(-1)));
+            edgeLabelsFaceIndices.last()[0] =
+                cFace[(cFaceEdgeI + owner) % cFaceNEdges];
+            edgeLabelsFaceIndices.last()[1] =
+                cFace[(cFaceEdgeI + !owner) % cFaceNEdges];
+            edgeLabelsFaceIndices.last()[2] = cFaceI;
+        }
+    }
+    sort(edgeLabelsFaceIndices);
+
+    // Assemble lists of edge-face and cell-face connectivities
+    // Negative values indicate an edge which runs in an opposite direction to
+    // the face node listing
+    labelListList edgeFaceIndices(cEdges.size());
+    labelListList faceEdgeIndices(cFaceLabels.size());
+    forAll(edgeLabelsFaceIndices, I)
+    {
+        const label edgeLabelsEdgeIndex(edgeLabelsEdgeIndices[I][2]);
+        const label absCellEdgeEdgeIndex
+        (
+            edgeLabelsEdgeIndex >= 0
+          ? edgeLabelsEdgeIndex
+          : - edgeLabelsEdgeIndex - 1
+        );
+        const label absCellEdgeFaceIndex(edgeLabelsFaceIndices[I][2]);
+        const label edgeLabelsFaceIndex
+        (
+            edgeLabelsEdgeIndex >= 0
+          ? absCellEdgeFaceIndex
+          : - absCellEdgeFaceIndex - 1
+        );
+
+        edgeFaceIndices[absCellEdgeEdgeIndex].append(edgeLabelsFaceIndex);
+        faceEdgeIndices[absCellEdgeFaceIndex].append(edgeLabelsEdgeIndex);
+    }
+
+    // Generate a list of point labels and face index pairs
+    labelListList pointLabelEdgeIndexFaceIndexPairs;
+    forAll(cEdges, edgeI)
+    {
+        const labelPair pointIndices(cEdges[edgeI]);
+
+        const labelPair faceIndices
+        (
+            edgeFaceIndices[edgeI][0],
+            edgeFaceIndices[edgeI][1]
+        );
+        const labelPair absFaceIndices
+        (
+            faceIndices[0] >= 0 ? faceIndices[0] : - faceIndices[0] - 1,
+            faceIndices[1] >= 0 ? faceIndices[1] : - faceIndices[1] - 1
+        );
+
+        const bool order(faceIndices[0] > faceIndices[1]);
+
+        pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1)));
+        pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[0];
+        pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI;
+        pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[order];
+        pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[!order];
+
+        pointLabelEdgeIndexFaceIndexPairs.append(labelList(4, label(-1)));
+        pointLabelEdgeIndexFaceIndexPairs.last()[0] = pointIndices[1];
+        pointLabelEdgeIndexFaceIndexPairs.last()[1] = edgeI;
+        pointLabelEdgeIndexFaceIndexPairs.last()[2] = absFaceIndices[!order];
+        pointLabelEdgeIndexFaceIndexPairs.last()[3] = absFaceIndices[order];
+    }
+    sort(pointLabelEdgeIndexFaceIndexPairs);
+
+    // Assemble a list of point face pairs from the sorted lists
+    labelListList pointEdgeIndices(cPointLabels.size());
+    List<List<Pair<label> > > pointFaceIndexPairs(cPointLabels.size());
+    {
+        label I(0);
+        label pointLabelOld(pointLabelEdgeIndexFaceIndexPairs[0][0]);
+        forAll
+        (
+            pointLabelEdgeIndexFaceIndexPairs,
+            pointLabelEdgeIndexFaceIndexPairI
+        )
+        {
+            const labelList& pointLabelEdgeIndexFaceIndexPair
+            (
+                pointLabelEdgeIndexFaceIndexPairs
+                [
+                    pointLabelEdgeIndexFaceIndexPairI
+                ]
+            );
+
+            if (pointLabelOld != pointLabelEdgeIndexFaceIndexPair[0])
+            {
+                I ++;
+                pointLabelOld = pointLabelEdgeIndexFaceIndexPair[0];
+            }
+
+            const label pointI(pointLabelPointIndices[I][1]);
+
+            pointEdgeIndices[pointI].append
+            (
+                pointLabelEdgeIndexFaceIndexPair[1]
+            );
+
+            pointFaceIndexPairs[pointI].append
+            (
+                labelPair
+                (
+                    pointLabelEdgeIndexFaceIndexPair[2],
+                    pointLabelEdgeIndexFaceIndexPair[3]
+                )
+            );
+        }
+    }
+
+    // Order the point face pairs and assemble a list of point face indices
+    labelListList pointFaceIndices(cPointLabels.size());
+    forAll(pointFaceIndexPairs, pointI)
+    {
+        labelPairList& faceIndexPairs(pointFaceIndexPairs[pointI]);
+
+        pointFaceIndices[pointI].append(faceIndexPairs[0][0]);
+
+        for (label pairI = 1; pairI < faceIndexPairs.size(); pairI ++)
+        {
+            for (label pairJ = pairI; pairJ < faceIndexPairs.size(); ++ pairJ)
+            {
+                if (faceIndexPairs[pairI-1][1] == faceIndexPairs[pairJ][0])
+                {
+                    Swap
+                    (
+                        pointEdgeIndices[pointI][pairI],
+                        pointEdgeIndices[pointI][pairJ]
+                    );
+
+                    Swap
+                    (
+                        faceIndexPairs[pairI],
+                        faceIndexPairs[pairJ]
+                    );
+
+                    break;
+                }
+            }
+            pointFaceIndices[pointI].append(faceIndexPairs[pairI][0]);
+        }
+    }
+
+    // convert to global indices
+    forAll(cPointLabels, pointI)
+    {
+        labelList& edgeIndices(pointEdgeIndices[pointI]);
+        labelList& faceIndices(pointFaceIndices[pointI]);
+
+        const label nPointFaces(faceIndices.size());
+
+        cellPointPoints_[cellI][pointI].resize(nPointFaces);
+
+        forAll(edgeIndices, edgeI)
+        {
+            cellPointPoints_[cellI][pointI][edgeI] =
+                cEdges[edgeIndices[edgeI]]
+                [
+                    cEdges[edgeIndices[edgeI]][0] == cPointLabels[pointI]
+                ];
+        }
+
+        cellPointFaces_[cellI][pointI].resize(nPointFaces);
+
+        forAll(faceIndices, faceI)
+        {
+            cellPointFaces_[cellI][pointI][faceI] =
+                cFaceLabels
+                [
+                    faceIndices[faceI]
+                ];
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::cellPointConnectivity::cellPointConnectivity(const polyMesh& mesh)
+:
+    MoveableMeshObject<polyMesh>(typeName, mesh),
+    mesh_(mesh),
+    cellPointPoints_(mesh.nCells()),
+    cellPointFaces_(mesh.nCells())
+{
+    forAll(mesh.cells(), cellI)
+    {
+        const label nPoints(mesh.cellPoints()[cellI].size());
+
+        cellPointPoints_[cellI].resize(nPoints);
+        cellPointFaces_[cellI].resize(nPoints);
+
+        generateCellPointConnectivity(cellI);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::cellPointConnectivity::~cellPointConnectivity()
+{}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.H
new file mode 100644
index 0000000000000000000000000000000000000000..1c850a0e9c113591fe63358160894216478636ec
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/cellPointConnectivity/cellPointConnectivity.H
@@ -0,0 +1,139 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::cellPointConnectivity
+
+Description
+    This class provides ordered connectivity for each point of each cell. Lists
+    are available of the points and faces surrounding each point of a cell. The
+    lists are ordered so that the connected points describe a polygonal cone.
+    For a convex cell, any three sequantial cone edges form a positive basis.
+
+SourceFiles
+    cellPointConnectivity.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cellPointConnectivity_H
+#define cellPointConnectivity_H
+
+#include "polyMesh.H"
+#include "MeshObject.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class cellPointConnectivity Declaration
+\*---------------------------------------------------------------------------*/
+
+class cellPointConnectivity
+:
+    public MoveableMeshObject<polyMesh>
+{
+    // Private data
+
+        //- Reference to the polyMesh
+        const polyMesh& mesh_;
+
+        //- Lists of point-point connections
+        labelListListList cellPointPoints_;
+
+        //- Lists of point-face connections
+        labelListListList cellPointFaces_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        cellPointConnectivity(const cellPointConnectivity&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const cellPointConnectivity&);
+
+        //- Generate the connectivity
+        void generateCellPointConnectivity(label cellI);
+
+
+public:
+
+    // Run-time type information
+    TypeName("cellPointConnectivity");
+
+
+    // Constructors
+
+        //- Construct an IOobject and a polymesh
+        cellPointConnectivity(const polyMesh&);
+
+
+    //- Destructor
+    ~cellPointConnectivity();
+
+
+    // Member Functions
+
+        // Access
+
+            //- Access the point-point connections
+            const labelListListList& cellPointPoints() const
+            {
+                return cellPointPoints_;
+            }
+
+            //- Access the point-face connections
+            const labelListListList& cellPointFaces() const
+            {
+                return cellPointFaces_;
+            }
+
+        // Edit
+
+            //- No action required on move points
+            virtual bool movePoints()
+            {
+                return true;
+            }
+
+            //- Dummy write for regIOobject
+            virtual bool writeData(Ostream&) const
+            {
+                return true;
+            }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.C
new file mode 100644
index 0000000000000000000000000000000000000000..42ee536d7ac1c9ed8e1502065ff2e012062c081d
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.C
@@ -0,0 +1,479 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "geometricElementTransformPointSmoother.H"
+#include "cellPointConnectivity.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+    defineTypeNameAndDebug(geometricElementTransformPointSmoother, 0);
+    addToRunTimeSelectionTable
+    (
+        pointSmoother,
+        geometricElementTransformPointSmoother,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::scalar
+Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
+(
+    const polyMesh& mesh,
+    const pointField& currentPoints,
+    const cellPointConnectivity& connectivity,
+    const label celli
+)
+{
+    const cell& cFaces = mesh.cells()[celli];
+    const labelList cPoints(cFaces.labels(mesh.faces()));
+
+    // Calculate a transformed point for each cell point
+
+    scalar cellQ = 0.0;
+    label nTets = 0;
+
+    forAll(cPoints, cPointi)
+    {
+        const label pointi(cPoints[cPointi]);
+        const point& pt = currentPoints[pointi];
+        const labelList& pPoints
+        (
+            connectivity.cellPointPoints()[celli][cPointi]
+        );
+        if (pPoints.size() != 3)
+        {
+            WarningInFunction<< "Cell:" << celli
+                << " point:" << pointi
+                << " connected points:" << pPoints << endl;
+        }
+        else
+        {
+            const Tensor<scalar> mA
+            (
+                currentPoints[pPoints[0]] - pt,
+                currentPoints[pPoints[1]] - pt,
+                currentPoints[pPoints[2]] - pt
+            );
+            const scalar sigma(det(mA));
+
+            if (sigma < ROOTVSMALL)
+            {
+                return 0;
+            }
+
+            // 3 * pow(sigma, 2.0/3.0)/magSqr(mA)
+            const scalar tetQ =
+                scalar(3) * Foam::cbrt(Foam::sqr(sigma)) / magSqr(mA);
+            cellQ += tetQ;
+            nTets++;
+        }
+    }
+
+    return cellQ/nTets;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointSmoothers::geometricElementTransformPointSmoother::
+geometricElementTransformPointSmoother
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    pointSmoother(mesh, dict),
+    transformationParameter_
+    (
+        readScalar(dict.lookup("transformationParameter"))
+    )
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::pointSmoothers::geometricElementTransformPointSmoother::calculate
+(
+    const labelList& facesToMove,
+    const pointField& oldPoints,
+    const pointField& currentPoints,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes,
+    vectorField& pointDisplacement
+) const
+{
+    // Lookup or generate the cell-point connectivity/
+    const cellPointConnectivity& connectivity =
+        MeshObject<polyMesh, MoveableMeshObject, cellPointConnectivity>::New
+        (
+            mesh()
+        );
+
+    // Number of points used in each average
+    labelField counts(mesh().nPoints(), -1);
+
+    // Reset the displacements which are about to be calculated
+    reset(facesToMove, counts, pointDisplacement);
+
+    // Identify the cells which are to be moved
+    labelHashSet cellsToMove(facesToMove.size()*2/3);
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        cellsToMove.insert(mesh().faceOwner()[faceI]);
+
+        if (mesh().isInternalFace(faceI))
+        {
+            cellsToMove.insert(mesh().faceNeighbour()[faceI]);
+        }
+    }
+
+    // Transformed point field
+    pointField transformedPoints(currentPoints);
+
+    // Calculate the internal transformations
+    forAllConstIter(labelHashSet, cellsToMove, iter)
+    {
+        const label cellI(iter.key());
+
+        const cell& cFaces
+        (
+            mesh().cells()[cellI]
+        );
+        const labelList cPoints
+        (
+            cFaces.labels(mesh().faces())
+        );
+        const edgeList cEdges
+        (
+            cFaces.edges(mesh().faces())
+        );
+
+        // Calculate a transformed point for each cell point
+        forAll(cPoints, cPointI)
+        {
+            const label pointI(cPoints[cPointI]);
+
+            if (counts[pointI] == -1) continue;
+
+            const labelList& pPoints
+            (
+                connectivity.cellPointPoints()[cellI][cPointI]
+            );
+            const labelList& pFaces
+            (
+                connectivity.cellPointFaces()[cellI][cPointI]
+            );
+            const label nPPoints(pPoints.size());
+
+            // Initial guess of the dual face centre
+            vector dualAverage(vector::zero);
+            forAll(pPoints, pPointI)
+            {
+                dualAverage +=
+                    currentPoints[pPoints[pPointI]]
+                  + faceCentres[pFaces[pPointI]];
+            }
+            dualAverage /= 2*nPPoints;
+
+            // Calculate the dual face centre and normal
+            vector dualNormal(vector::zero);
+            forAll(pPoints, pPointI)
+            {
+                const label nextPPointI((pPointI + 1) % nPPoints);
+
+                point edgeCentre
+                (
+                    0.5
+                   *(
+                        currentPoints[pPoints[pPointI]]
+                      + currentPoints[pointI]
+                    )
+                );
+                point nextFaceCentre
+                (
+                    faceCentres[pFaces[nextPPointI]]
+                );
+                point nextEdgeCentre
+                (
+                    0.5
+                   *(
+                        currentPoints[pPoints[nextPPointI]]
+                      + currentPoints[pointI]
+                    )
+                );
+
+                dualNormal +=
+                    (nextFaceCentre - edgeCentre)
+                   ^(edgeCentre - dualAverage);
+                dualNormal +=
+                    (nextEdgeCentre - nextFaceCentre)
+                   ^(nextFaceCentre - dualAverage);
+            }
+            vector dualNormalHat(dualNormal/max(mag(dualNormal), ROOTVSMALL));
+
+            scalar sumA(0);
+            vector sumAc(vector::zero);
+            forAll(pPoints, pPointI)
+            {
+                const label nextPPointI((pPointI + 1) % nPPoints);
+
+                point edgeCentre
+                (
+                    0.5
+                   *(
+                        currentPoints[pPoints[pPointI]]
+                      + currentPoints[pointI]
+                    )
+                );
+                point nextFaceCentre
+                (
+                    faceCentres[pFaces[nextPPointI]]
+                );
+                point nextEdgeCentre
+                (
+                    0.5
+                   *(
+                        currentPoints[pPoints[nextPPointI]]
+                      + currentPoints[pointI]
+                    )
+                );
+
+                vector c1 = edgeCentre + nextFaceCentre + dualAverage;
+                vector c2 = nextFaceCentre + nextEdgeCentre + dualAverage;
+
+                vector n1 =
+                    (nextFaceCentre - edgeCentre)
+                   ^(edgeCentre - dualAverage);
+                vector n2 =
+                    (nextEdgeCentre - nextFaceCentre)
+                   ^(nextFaceCentre - dualAverage);
+
+                scalar a1 = n1 & dualNormalHat;
+                scalar a2 = n2 & dualNormalHat;
+
+                sumA += a1 + a2;
+                sumAc += a1*c1 + a2*c2;
+            }
+
+            const vector dualCentre(sumAc/max(sumA, ROOTVSMALL)/3);
+
+            // Calculate the transformed point
+            transformedPoints[pointI] =
+                dualCentre
+              + transformationParameter_
+               *dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
+        }
+
+        // Length scale
+        scalar lengthScale(0), transformedLengthScale(0);
+        forAll(cEdges, cEdgeI)
+        {
+            lengthScale +=
+                cEdges[cEdgeI].mag(currentPoints);
+            transformedLengthScale +=
+                cEdges[cEdgeI].mag(transformedPoints);
+        }
+        lengthScale /= cEdges.size();
+        transformedLengthScale /= cEdges.size();
+
+        const scalar lengthScaleRatio =
+        (
+             (transformedLengthScale > SMALL)
+           ? lengthScale/transformedLengthScale
+           : scalar(0)
+        );
+
+        // Add the displacement to the average
+        forAll(cPoints, cPointI)
+        {
+            const label pointI(cPoints[cPointI]);
+
+            if (counts[pointI] == -1) continue;
+
+            const vector newPoint
+            (
+                cellCentres[cellI]
+              + lengthScaleRatio
+               *(
+                    transformedPoints[pointI]
+                  - cellCentres[cellI]
+                )
+            );
+
+            ++ counts[pointI];
+
+            pointDisplacement[pointI] += newPoint - oldPoints[pointI];
+        }
+    }
+
+    // Reset all the boundary faces
+    reset(facesToMove, counts, pointDisplacement, false);
+
+    // Calculate the boundary transformations
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (!isInternalOrProcessorFace(faceI))
+        {
+            const labelList& fPoints(mesh().faces()[faceI]);
+
+            // Face normal
+            vector faceNormalHat(faceAreas[faceI]);
+            faceNormalHat /= max(SMALL, mag(faceNormalHat));
+
+            // Calculate a transformed point for each face point
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                const label fPointIPrev
+                (
+                    (fPointI - 1 + fPoints.size()) % fPoints.size()
+                );
+                const label fPointINext
+                (
+                    (fPointI + 1) % fPoints.size()
+                );
+
+                const vector dualCentre
+                (
+                    currentPoints[pointI]/2
+                  + (
+                        currentPoints[fPoints[fPointINext]]
+                      + currentPoints[fPoints[fPointIPrev]]
+                    )/4
+                );
+                const vector dualNormal
+                (
+                    (
+                        currentPoints[fPoints[fPointINext]]
+                      - currentPoints[fPoints[fPointIPrev]]
+                    )/2
+                   ^faceNormalHat
+                );
+
+                transformedPoints[pointI] =
+                    dualCentre
+                  + transformationParameter_
+                   *dualNormal/sqrt(max(mag(dualNormal), ROOTVSMALL));
+            }
+
+            // Length scale
+            scalar lengthScale(0), transformedLengthScale(0);
+            forAll(fPoints, fPointI)
+            {
+                const label fPointINext((fPointI + 1)%fPoints.size());
+
+                const label pointI(fPoints[fPointI]);
+                const label pointINext(fPoints[fPointINext]);
+
+                lengthScale += mag
+                (
+                    currentPoints[pointINext] - currentPoints[pointI]
+                );
+                transformedLengthScale += mag
+                (
+                    transformedPoints[pointINext] - transformedPoints[pointI]
+                );
+            }
+            lengthScale /= fPoints.size();
+            transformedLengthScale /= fPoints.size();
+
+            const scalar lengthScaleRatio
+            (
+                 (transformedLengthScale > SMALL)
+               ? lengthScale/transformedLengthScale
+               : scalar(0)
+            );
+
+            // Add the displacement to the average
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                const vector newPoint
+                (
+                    faceCentres[faceI]
+                  + lengthScaleRatio
+                   *(
+                        transformedPoints[pointI]
+                      - faceCentres[faceI]
+                    )
+                );
+
+                ++ counts[pointI];
+
+                pointDisplacement[pointI] += newPoint - oldPoints[pointI];
+            }
+        }
+    }
+
+    // Average
+    average(facesToMove, counts, pointDisplacement);
+}
+
+
+Foam::tmp<Foam::scalarField>
+Foam::pointSmoothers::geometricElementTransformPointSmoother::cellQuality
+(
+    const polyMesh& mesh,
+    const pointField& currentPoints
+)
+{
+    const cellPointConnectivity& connectivity =
+        MeshObject<polyMesh, MoveableMeshObject, cellPointConnectivity>::New
+        (
+            mesh
+        );
+
+    tmp<scalarField> tfld(tmp<scalarField>::New(mesh.nCells()));
+    scalarField& fld = tfld.ref();
+
+    forAll(fld, celli)
+    {
+        fld[celli] = cellQuality(mesh, currentPoints, connectivity, celli);
+    }
+
+    return tfld;
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.H
new file mode 100644
index 0000000000000000000000000000000000000000..53b5332382fead717ebda5f1d6ffdfe66bf93ded
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/geometricElementTransformPointSmoother/geometricElementTransformPointSmoother.H
@@ -0,0 +1,149 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::pointSmoothers::geometricElementTransformPointSmoother
+
+Description
+    Geometric Element Transformation Method (GETMe) point smoother. Points are
+    moved in a direction normal to the face of the dual element. This tends to
+    orthogonalise elements. This method can "push" as well as "pull".
+
+    The original references for this method only formulate it for a limited
+    variety of specific polyhedra. This version is written for arbitrary
+    polyhedra, and most closely follows the following reference:
+
+    \verbatim
+        "Fast smoothing of mixed volume meshes based on the effective geometric
+        element transformation method"
+        Dimitris Vartziotis, Joachim Wipper,
+        Comput. Methods Appl. Mech. Engrg. 201-204 (2012) 65-81
+    \endverbatim
+
+    This implementation does not include the various specific measures employed
+    in the referred article to improve the quality of types of irregular
+    polyhedra. It also does not use the same quality criteria as these are only
+    suitable for cell vertices with exactly three connecting edges.
+
+SourceFiles
+    geometricElementTransformPointSmoother.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef geometricElementTransformPointSmoother_H
+#define geometricElementTransformPointSmoother_H
+
+#include "pointSmoother.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class cellPointConnectivity;
+
+namespace pointSmoothers
+{
+
+/*---------------------------------------------------------------------------*\
+             Class geometricElementTransformPointSmoother Declaration
+\*---------------------------------------------------------------------------*/
+
+class geometricElementTransformPointSmoother
+:
+    public pointSmoother
+{
+private:
+
+    // Private Data
+
+        //- Transformation parameter
+        const scalar transformationParameter_;
+
+
+    // Private Member Functions
+
+        static scalar cellQuality
+        (
+            const polyMesh& mesh,
+            const pointField& currentPoints,
+            const cellPointConnectivity& connectivity,
+            const label celli
+        );
+
+
+public:
+
+    //- Runtime type information
+    TypeName("geometricElementTransform");
+
+
+    // Constructors
+
+        //- Construct from a dictionary and a mesh
+        geometricElementTransformPointSmoother
+        (
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~geometricElementTransformPointSmoother() = default;
+
+
+    // Member Functions
+
+        //- Calculate the point displacements
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            vectorField& pointDisplacement
+        ) const;
+
+        static tmp<scalarField> cellQuality
+        (
+            const polyMesh& mesh,
+            const pointField& currentPoints
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace pointSmoothers
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.C
new file mode 100644
index 0000000000000000000000000000000000000000..126f3dc969daca867a8fc808edbb6c5bd7118956
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.C
@@ -0,0 +1,164 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "laplacianConstraintPointSmoother.H"
+#include "addToRunTimeSelectionTable.H"
+#include "meshPointPatch.H"
+#include "processorPointPatch.H"
+#include "pointConstraint.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+    defineTypeNameAndDebug(laplacianConstraintPointSmoother, 0);
+    addToRunTimeSelectionTable
+    (
+        pointSmoother,
+        laplacianConstraintPointSmoother,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointSmoothers::laplacianConstraintPointSmoother::
+laplacianConstraintPointSmoother
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    pointSmoother(mesh, dict)
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::pointSmoothers::laplacianConstraintPointSmoother::calculate
+(
+    const labelList& facesToMove,
+    const pointField& oldPoints,
+    const pointField& currentPoints,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes,
+    vectorField& pointDisplacement
+) const
+{
+    // Get pointMesh so we can get at the constraints
+    const auto& pMesh = pointMesh::New(mesh());
+
+    // Number of points used in each average
+    labelField counts(mesh().nPoints(), 0);
+
+    // Reset the displacements which are about to be calculated
+    reset(facesToMove, counts, pointDisplacement);
+
+    // Get affected points
+    const bitSet isMovingPoint(pointsToMove(facesToMove, true));
+
+
+    // Set constraints:
+    // - internal points : 0
+    // - normal boundary points : 1
+    // - meshPointPatch : 1 (surface)
+    //                    2 (feat-edge)
+    //                    3 (feat-point)
+    labelList nConstraints(mesh().nPoints(), Zero);
+
+    for (const auto& pp : pMesh.boundary())
+    {
+        const auto& mp = pp.meshPoints();
+        const auto* mppPtr = isA<meshPointPatch>(pp);
+        if (mppPtr)
+        {
+            const auto& pc = mppPtr->constraints();
+            forAll(mp, i)
+            {
+                nConstraints[mp[i]] = pc[i].first();
+            }
+        }
+        else //if (!isA<processorPointPatch>(pp)) // what about cyclic? AMI?
+        {
+            forAll(mp, i)
+            {
+                // Indirectly detect any constraint
+                pointConstraint pc;
+                pp.applyConstraint(i, pc);
+                nConstraints[mp[i]] = pc.first();
+            }
+        }
+    }
+
+
+    // Average from equally constrained points
+
+    const auto& edges = mesh().edges();
+    const auto& pointEdges = mesh().pointEdges();
+    forAll(pointEdges, pointi)
+    {
+        if (isMovingPoint[pointi])
+        {
+            const auto& pEdges = pointEdges[pointi];
+            for (const label edgei : pEdges)
+            {
+                const label otherPointi = edges[edgei].otherVertex(pointi);
+                if (nConstraints[otherPointi] >= nConstraints[pointi])
+                {
+                    pointDisplacement[pointi] +=
+                        currentPoints[otherPointi]
+                      - oldPoints[pointi];
+
+                    ++ counts[pointi];
+                }
+            }
+        }
+    }
+
+    // Average
+    average(facesToMove, counts, pointDisplacement);
+
+
+    // Make sure to set any unconnected points (or boundary feature points)
+    // since otherwise they never see the effect of the boundary conditions
+    forAll(counts, pointi)
+    {
+        if (isMovingPoint[pointi] && !counts[pointi])
+        {
+            pointDisplacement[pointi] = currentPoints[pointi]-oldPoints[pointi];
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.H
new file mode 100644
index 0000000000000000000000000000000000000000..ebe348e33cd99cb26b643795ff3e4af9d420d86e
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianConstraintPointSmoother.H
@@ -0,0 +1,105 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::laplacianConstraintPointSmoother
+
+Description
+    Laplacian point smoothing. Points are moved towards the average of the
+    surrounding points. In case of constraints (boundary points) only
+    use average of equal or higher constrained points.
+
+SourceFiles
+    laplacianConstraintPointSmoother.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef laplacianConstraintPointSmoother_H
+#define laplacianConstraintPointSmoother_H
+
+#include "pointSmoother.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+
+/*---------------------------------------------------------------------------*\
+              Class laplacianConstraintPointSmoother Declaration
+\*---------------------------------------------------------------------------*/
+
+class laplacianConstraintPointSmoother
+:
+    public pointSmoother
+{
+public:
+
+    //- Runtime type information
+    TypeName("laplacianConstraint");
+
+
+    // Constructors
+
+        //- Construct from a dictionary and a polyMesh
+        laplacianConstraintPointSmoother
+        (
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~laplacianConstraintPointSmoother() = default;
+
+
+    // Member Functions
+
+        //- Calculate the point displacement
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            vectorField& pointDisplacement
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace pointSmoothers
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.C
new file mode 100644
index 0000000000000000000000000000000000000000..c07cc84eda23fc3204ec7037e217bdc97481e11a
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.C
@@ -0,0 +1,139 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "laplacianPointSmoother.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+    defineTypeNameAndDebug(laplacianPointSmoother, 0);
+    addToRunTimeSelectionTable
+    (
+        pointSmoother,
+        laplacianPointSmoother,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointSmoothers::laplacianPointSmoother::laplacianPointSmoother
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    pointSmoother(mesh, dict)
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::pointSmoothers::laplacianPointSmoother::calculate
+(
+    const labelList& facesToMove,
+    const pointField& oldPoints,
+    const pointField& currentPoints,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes,
+    vectorField& pointDisplacement
+) const
+{
+    // Number of points used in each average
+    labelField counts(mesh().nPoints(), 0);
+
+    // Reset the displacements which are about to be calculated
+    reset(facesToMove, counts, pointDisplacement);
+
+    // Sum the non-internal face displacements
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (!isInternalOrProcessorFace(faceI))
+        {
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                pointDisplacement[pointI] +=
+                    faceCentres[faceI]
+                  - oldPoints[pointI];
+
+                ++ counts[pointI];
+            }
+        }
+    }
+
+    // Sum the internal face displacements
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (isInternalOrProcessorFace(faceI))
+        {
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                if (counts[pointI] == 0)
+                {
+                    const labelList& pCells(mesh().pointCells()[pointI]);
+
+                    forAll(pCells, pCellI)
+                    {
+                        const label cellI(pCells[pCellI]);
+
+                        pointDisplacement[pointI] +=
+                            cellCentres[cellI]
+                          - oldPoints[pointI];
+
+                        ++ counts[pointI];
+                    }
+                }
+            }
+        }
+    }
+
+    // Average
+    average(facesToMove, counts, pointDisplacement);
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.H
new file mode 100644
index 0000000000000000000000000000000000000000..500e6aa71a59e278a0843ded97b99666865ef676
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/laplacianPointSmoother/laplacianPointSmoother.H
@@ -0,0 +1,105 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::laplacianPointSmoother
+
+Description
+    Laplacian point smoothing (or rather Lloyds). Points are moved towards
+    the average of the surrounding cell centres (or average of boundary
+    face centres for points on boundary)
+
+SourceFiles
+    laplacianPointSmoother.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef laplacianPointSmoother_H
+#define laplacianPointSmoother_H
+
+#include "pointSmoother.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace pointSmoothers
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class laplacianPointSmoother Declaration
+\*---------------------------------------------------------------------------*/
+
+class laplacianPointSmoother
+:
+    public pointSmoother
+{
+public:
+
+    //- Runtime type information
+    TypeName("laplacian");
+
+
+    // Constructors
+
+        //- Construct from a dictionary and a polyMesh
+        laplacianPointSmoother
+        (
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~laplacianPointSmoother() = default;
+
+
+    // Member Functions
+
+        //- Calculate the point displacement
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            vectorField& pointDisplacement
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace pointSmoothers
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.C
new file mode 100644
index 0000000000000000000000000000000000000000..ed6eee487e00def8364f191a36d557fb444e1c1a
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.C
@@ -0,0 +1,300 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointSmoother.H"
+#include "pointConstraints.H"
+#include "polyMeshTools.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(pointSmoother, 0);
+    defineRunTimeSelectionTable(pointSmoother, dictionary);
+}
+
+
+// * * * * * * * * * * * *  Protected Member Functions * * * * * * * * * * * //
+
+bool Foam::pointSmoother::isInternalOrProcessorFace(const label faceI) const
+{
+    if (mesh().isInternalFace(faceI))
+    {
+        return true;
+    }
+
+    if
+    (
+        processorPatchIDs_
+        [
+            mesh().boundaryMesh().patchID()
+            [
+                faceI - mesh().nInternalFaces()
+            ]
+        ]
+    )
+    {
+        return true;
+    }
+
+    return false;
+}
+
+
+Foam::autoPtr<Foam::PackedBoolList> Foam::pointSmoother::pointsToMove
+(
+    const labelList& facesToMove,
+    const bool moveInternalFaces
+) const
+{
+    autoPtr<PackedBoolList> markerPtr
+    (
+        new PackedBoolList(mesh().nPoints(), false)
+    );
+
+    PackedBoolList& marker(markerPtr());
+
+    forAll(facesToMove, faceToMoveI)
+    {
+        const label faceI(facesToMove[faceToMoveI]);
+
+        if (moveInternalFaces || !isInternalOrProcessorFace(faceI))
+        {
+            const face& fPoints(mesh().faces()[faceI]);
+
+            forAll(fPoints, fPointI)
+            {
+                const label pointI(fPoints[fPointI]);
+
+                marker[pointI] = true;
+            }
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        marker,
+        orEqOp<unsigned int>(),
+        0U
+    );
+
+    return markerPtr;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointSmoother::pointSmoother
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    mesh_(mesh)
+{
+    for (const auto& pp : mesh.boundaryMesh())
+    {
+        if (isA<processorPolyPatch>(pp))
+        {
+            processorPatchIDs_.insert(pp.index());
+        }
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
+
+Foam::autoPtr<Foam::pointSmoother>
+Foam::pointSmoother::New
+(
+    const word& pointSmootherType,
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+{
+    Info<< "Selecting pointSmoother type " << pointSmootherType << endl;
+
+    auto cstrIter = dictionaryConstructorTablePtr_->find(pointSmootherType);
+
+    if (cstrIter == dictionaryConstructorTablePtr_->end())
+    {
+        FatalErrorIn("pointSmoother::New")
+            << "Unknown " << typeName << " type "
+            << pointSmootherType << endl << endl
+            << "Valid " << typeName << " types are : " << endl
+            << dictionaryConstructorTablePtr_->sortedToc()
+            << exit(FatalError);
+    }
+
+    return cstrIter()(mesh, dict);
+}
+
+
+Foam::autoPtr<Foam::pointSmoother>
+Foam::pointSmoother::New
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+{
+    word pointSmootherType(dict.lookup(typeName));
+
+    return New(pointSmootherType, mesh, dict);
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::pointSmoother::~pointSmoother()
+{}
+
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+void Foam::pointSmoother::update
+(
+    const labelList& facesToMove,
+    const pointField& oldPoints,
+    const pointField& currentPoints,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes,
+    pointVectorField& pointDisplacement,
+    const bool correctBCs
+) const
+{
+    // Apply point smoothing (without boundary conditions!)
+    calculate
+    (
+        facesToMove,
+        oldPoints,
+        currentPoints,
+        faceCentres,
+        faceAreas,
+        cellCentres,
+        cellVolumes,
+        pointDisplacement.ref()
+    );
+
+    // Note: do not want to apply boundary conditions whilst smoothing so
+    //       disable for now        
+    //// Take over boundary values
+    //for (auto& ppf : pointDisplacement.boundaryFieldRef())
+    //{
+    //    ppf.operator==(ppf.patchInternalField());
+    //}
+
+    if (correctBCs)
+    {
+        // Apply (multi-)patch constraints
+        pointConstraints::New
+        (
+            pointDisplacement().mesh()
+        ).constrainDisplacement(pointDisplacement);
+    }
+}
+
+
+Foam::tmp<Foam::scalarField> Foam::pointSmoother::faceQuality
+(
+    const pointField& points,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes
+) const
+{
+    // See e.g.
+    // - src/functionObjects/field/stabilityBlendingFactor/
+    //      stabilityBlendingFactor.H
+    // - maybe add function to motionSmootherCheck to return value instead
+    //   of yes/no for invalid?
+    // - for now just look at non-ortho
+
+    tmp<scalarField> tortho
+    (
+        polyMeshTools::faceOrthogonality
+        (
+            mesh(),
+            faceAreas,
+            cellCentres
+        )
+    );
+
+    //return max(tortho, scalar(0.0));
+    return tortho;
+}
+
+
+Foam::tmp<Foam::scalarField> Foam::pointSmoother::cellQuality
+(
+    const pointField& points,
+    const pointField& faceCentres,
+    const vectorField& faceAreas,
+    const pointField& cellCentres,
+    const scalarField& cellVolumes
+) const
+{
+    // Get face-based non-ortho
+    tmp<scalarField> tfaceOrtho
+    (
+        faceQuality
+        (
+            points,
+            faceCentres,
+            faceAreas,
+            cellCentres,
+            cellVolumes
+        )
+    );
+    const auto& faceOrtho = tfaceOrtho();
+
+    // Min over cells
+    tmp<scalarField> tortho(new scalarField(mesh().nCells(), GREAT));
+    auto& ortho = tortho.ref();
+
+    const auto& own = mesh().faceOwner();
+    const auto& nei = mesh().faceNeighbour();
+
+    forAll(own, facei)
+    {
+        auto& o = ortho[own[facei]];
+        o = min(o, faceOrtho[facei]);
+    }
+    for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
+    {
+        auto& o = ortho[nei[facei]];
+        o = min(o, faceOrtho[facei]);
+    }
+
+    return tortho;
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.H b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.H
new file mode 100644
index 0000000000000000000000000000000000000000..4b4b356060391cb71e9c4e668cb2047288f538f7
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmoother.H
@@ -0,0 +1,279 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::pointSmoother
+
+Description
+    Abstract base class for point smoothing methods. Handles parallel
+    communication via reset and average functions.
+
+SourceFiles
+    pointSmoother.C
+    pointSmootherTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pointSmoother_H
+#define pointSmoother_H
+
+#include "polyMeshGeometry.H"
+#include "runTimeSelectionTables.H"
+#include "PackedBoolList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class pointSmoother Declaration
+\*---------------------------------------------------------------------------*/
+
+class pointSmoother
+{
+private:
+
+    // Private data
+
+        //- Reference to the polyMesh
+        const polyMesh& mesh_;
+
+        //- Set of the processor patch indices
+        labelHashSet processorPatchIDs_;
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        pointSmoother(const pointSmoother&);
+
+        //- Disallow default bitwise assignment
+        void operator=(const pointSmoother&);
+
+
+protected:
+
+    // Protected Member Functions
+
+        //- Test if the given face is internal or on a processor boundary
+        bool isInternalOrProcessorFace(const label faceI) const;
+
+        //- Get a boolean list of the points to be moved
+        autoPtr<PackedBoolList> pointsToMove
+        (
+            const labelList& facesToMove,
+            const bool moveInternalFaces
+        ) const;
+
+        //- Reset the relevant weights and displacements to zero
+        template <class weightType>
+        void reset
+        (
+            const labelList& facesToMove,
+            Field<weightType>& weights,
+            vectorField& pointDisplacement,
+            const bool resetInternalFaces = true
+        ) const;
+
+        //- Average the displacements using the weights provided
+        template <class weightType>
+        void average
+        (
+            const labelList& facesToMove,
+            Field<weightType>& weights,
+            vectorField& pointDisplacement
+        ) const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("pointSmoother");
+
+
+    // Declare run-time constructor selection table
+    declareRunTimeSelectionTable
+    (
+        autoPtr,
+        pointSmoother,
+        dictionary,
+        (const polyMesh& mesh, const dictionary& dict),
+        (mesh, dict)
+    );
+
+
+    // Constructors
+
+        //- Construct from a dictionary and a point displacement field
+        pointSmoother(const polyMesh& mesh, const dictionary&);
+
+
+    // Selector
+
+        //- Construct given type
+        static autoPtr<pointSmoother> New
+        (
+            const word& pointSmootherType,
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+        //- Construct with type looked up from dictionary
+        static autoPtr<pointSmoother> New
+        (
+            const polyMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~pointSmoother();
+
+
+    // Member Functions
+
+        // Access the mesh
+        const polyMesh& mesh() const
+        {
+            return mesh_;
+        }
+
+        //- Update the point displacements and apply constraints
+        void update
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            pointVectorField& pointDisplacement,
+            const bool correctBCs = true
+        ) const;
+
+        //- Update the point displacements and apply constraints
+        void update
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const polyMeshGeometry& meshGeometry,
+            pointVectorField& pointDisplacement,
+            const bool correctBCs = true
+        ) const
+        {
+            update
+            (
+                facesToMove,
+                oldPoints,
+                currentPoints,
+                meshGeometry.faceCentres(),
+                meshGeometry.faceAreas(),
+                meshGeometry.cellCentres(),
+                meshGeometry.cellVolumes(),
+                pointDisplacement,
+                correctBCs
+            );
+        }
+
+        //- Calculate the point displacement
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes,
+            vectorField& pointDisplacement
+        ) const = 0;
+
+        //- Update the point displacements
+        virtual void calculate
+        (
+            const labelList& facesToMove,
+            const pointField& oldPoints,
+            const pointField& currentPoints,
+            const polyMeshGeometry& meshGeometry,
+            vectorField& pointDisplacement
+        ) const
+        {
+            calculate
+            (
+                facesToMove,
+                oldPoints,
+                currentPoints,
+                meshGeometry.faceCentres(),
+                meshGeometry.faceAreas(),
+                meshGeometry.cellCentres(),
+                meshGeometry.cellVolumes(),
+                pointDisplacement
+            );
+        }
+
+        //- Check element quality: 1 = best, 0 = invalid. (also negative?)
+        //- Topology from mesh, point locations supplied.
+        //- Move to motionSolver level?
+        virtual tmp<scalarField> faceQuality
+        (
+            const pointField& points,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes
+        ) const;
+
+        //- Check element quality: 1 = best, 0 = invalid.
+        //- Topology from mesh, point locations supplied.
+        //- Move to motionSolver level?
+        virtual tmp<scalarField> cellQuality
+        (
+            const pointField& points,
+            const pointField& faceCentres,
+            const vectorField& faceAreas,
+            const pointField& cellCentres,
+            const scalarField& cellVolumes
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "pointSmootherTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmootherTemplates.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmootherTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..1e74e6943ef1be9d27ddf34942ff0b2d998f1da0
--- /dev/null
+++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/pointSmoothers/pointSmoother/pointSmootherTemplates.C
@@ -0,0 +1,105 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointSmoother.H"
+#include "syncTools.H"
+
+// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+
+template <class weightType>
+void Foam::pointSmoother::reset
+(
+    const labelList& facesToMove,
+    Field<weightType>& weights,
+    vectorField& pointDisplacement,
+    const bool resetInternalFaces
+) const
+{
+    autoPtr<PackedBoolList> resetPointsPtr
+    (
+        pointsToMove(facesToMove, resetInternalFaces)
+    );
+
+    const PackedBoolList& resetPoints(resetPointsPtr);
+
+    forAll(resetPoints, pointI)
+    {
+        if (resetPoints[pointI])
+        {
+            weights[pointI] = pTraits<weightType>::zero;
+            pointDisplacement[pointI] = vector::zero;
+        }
+    }
+}
+
+
+template <class weightType>
+void Foam::pointSmoother::average
+(
+    const labelList& facesToMove,
+    Field<weightType>& weights,
+    vectorField& pointDisplacement
+) const
+{
+    syncTools::syncPointList
+    (
+        mesh(),
+        weights,
+        plusEqOp<weightType>(),
+        pTraits<weightType>::zero
+    );
+
+    syncTools::syncPointList
+    (
+        mesh(),
+        pointDisplacement,
+        plusEqOp<vector>(),
+        vector::zero
+    );
+
+    autoPtr<PackedBoolList> averagePointsPtr
+    (
+        pointsToMove(facesToMove, true)
+    );
+
+    const PackedBoolList& averagePoints(averagePointsPtr);
+
+    forAll(averagePoints, pointI)
+    {
+        if
+        (
+            averagePoints[pointI]
+         && weights[pointI] != pTraits<weightType>::zero
+        )
+        {
+            pointDisplacement[pointI] /= weights[pointI];
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
index c369d7246ebb6e674018d8d98ed7134bd171211b..4d3d5f5454e5955a8dad0be75b536ae31593693c 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2015-2022 OpenCFD Ltd.
+    Copyright (C) 2015-2022,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -46,8 +46,8 @@ namespace Foam
 {
     defineTypeNameAndDebug(addPatchCellLayer, 0);
 
-    // Reduction class to get minimum value over face.
-    class minEqOpFace
+    // Reduction class to get maximum value over coupled face.
+    class combineEqOpFace
     {
     public:
 
@@ -57,10 +57,18 @@ namespace Foam
             {
                 if (y.size())
                 {
+                    if (x.size() != y.size())
+                    {
+                        FatalErrorInFunction
+                            << "face x:" << flatOutput(x)
+                            << " face y:" << flatOutput(y)
+                            << exit(FatalError);
+                    }
+
                     label j = 0;
                     forAll(x, i)
                     {
-                        x[i] = min(x[i], y[j]);
+                        x[i] = max(x[i], y[j]);
 
                         j = y.rcIndex(j);
                     }
@@ -78,7 +86,6 @@ namespace Foam
             }
         }
     };
-
 }
 
 
@@ -464,6 +471,7 @@ void Foam::addPatchCellLayer::setFaceProps
 {
     patchi = mesh.boundaryMesh().whichPatch(facei);
     zonei = mesh.faceZones().whichZone(facei);
+    zoneFlip = false;
     if (zonei != -1)
     {
         label index = mesh.faceZones()[zonei].whichFace(facei);
@@ -548,61 +556,61 @@ void Foam::addPatchCellLayer::setFaceProps
 }
 
 
-void Foam::addPatchCellLayer::findZoneFace
-(
-    const bool useInternalFaces,
-    const bool useBoundaryFaces,
-
-    const polyMesh& mesh,
-    const indirectPrimitivePatch& pp,
-    const label ppEdgeI,
-    const labelUIndList& excludeFaces,
-    const labelList& meshFaces,
-
-    label& inflateFaceI,
-    label& patchI,
-    label& zoneI,
-    bool& zoneFlip
-)
-{
-    inflateFaceI = -1;
-    patchI = -1;
-    zoneI = -1;
-    zoneFlip = false;
-
-    forAll(meshFaces, k)
-    {
-        label faceI = meshFaces[k];
-
-        if
-        (
-            !excludeFaces.found(faceI)
-         && (
-                (mesh.isInternalFace(faceI) && useInternalFaces)
-             || (!mesh.isInternalFace(faceI) && useBoundaryFaces)
-            )
-        )
-        {
-            setFaceProps
-            (
-                mesh,
-                pp,
-                ppEdgeI,
-                faceI,
-
-                patchI,
-                zoneI,
-                zoneFlip,
-                inflateFaceI
-            );
-
-            if (zoneI != -1 || patchI != -1)
-            {
-                break;
-            }
-        }
-    }
-}
+//void Foam::addPatchCellLayer::findZoneFace
+//(
+//    const bool useInternalFaces,
+//    const bool useBoundaryFaces,
+//
+//    const polyMesh& mesh,
+//    const indirectPrimitivePatch& pp,
+//    const label ppEdgeI,
+//    const labelUIndList& excludeFaces,
+//    const labelList& meshFaces,
+//
+//    label& inflateFaceI,
+//    label& patchI,
+//    label& zoneI,
+//    bool& zoneFlip
+//)
+//{
+//    inflateFaceI = -1;
+//    patchI = -1;
+//    zoneI = -1;
+//    zoneFlip = false;
+//
+//    forAll(meshFaces, k)
+//    {
+//        label faceI = meshFaces[k];
+//
+//        if
+//        (
+//            !excludeFaces.found(faceI)
+//         && (
+//                (mesh.isInternalFace(faceI) && useInternalFaces)
+//             || (!mesh.isInternalFace(faceI) && useBoundaryFaces)
+//            )
+//        )
+//        {
+//            setFaceProps
+//            (
+//                mesh,
+//                pp,
+//                ppEdgeI,
+//                faceI,
+//
+//                patchI,
+//                zoneI,
+//                zoneFlip,
+//                inflateFaceI
+//            );
+//
+//            if (zoneI != -1 || patchI != -1)
+//            {
+//                break;
+//            }
+//        }
+//    }
+//}
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -611,11 +619,13 @@ void Foam::addPatchCellLayer::findZoneFace
 Foam::addPatchCellLayer::addPatchCellLayer
 (
     const polyMesh& mesh,
-    const bool addToMesh
+    const bool addToMesh,
+    const bool extrude
 )
 :
     mesh_(mesh),
     addToMesh_(addToMesh),
+    extrude_(extrude),
     addedPoints_(0),
     layerFaces_(0)
 {}
@@ -642,7 +652,7 @@ Foam::labelListList Foam::addPatchCellLayer::addedCells
 
             for (label i = 0; i < faceLabels.size()-1; i++)
             {
-                added[i] = mesh.faceNeighbour()[faceLabels[i]];
+                added[i] = mesh.faceOwner()[faceLabels[i+1]];
             }
         }
     }
@@ -660,9 +670,11 @@ Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
 (
     const polyMesh& mesh,
     const globalIndex& globalFaces,
-    const indirectPrimitivePatch& pp
+    const indirectPrimitivePatch& pp,
+    const bitSet& ppFlip
 )
 {
+
     // Precalculate mesh edges for pp.edges.
     const labelList meshEdges(pp.meshEdges(mesh.edges(), mesh.pointEdges()));
 
@@ -672,21 +684,32 @@ Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
 
     const labelListList& edgeFaces = pp.edgeFaces();
 
+    DynamicList<label> faceIDs;
+
     forAll(edgeFaces, edgeI)
     {
-        label meshEdgeI = meshEdges[edgeI];
-
-        const labelList& eFaces = edgeFaces[edgeI];
-
         // Store face and processor as unique tag.
-        labelList& globalEFaces = globalEdgeFaces[meshEdgeI];
-        globalEFaces.setSize(eFaces.size());
-        forAll(eFaces, i)
+        faceIDs.clear();
+        for (const label patchFacei : edgeFaces[edgeI])
         {
-            globalEFaces[i] = globalFaces.toGlobal(pp.addressing()[eFaces[i]]);
+            const label facei = pp.addressing()[patchFacei];
+
+            // Ignore if ppFlip is on the other side of the (coupled) boundary
+            if
+            (
+                ppFlip.empty()
+            || !ppFlip[patchFacei]
+            || mesh.isInternalFace(facei)
+            )
+            {
+                faceIDs.append(globalFaces.toGlobal(facei));
+            }
         }
+
+        globalEdgeFaces[meshEdges[edgeI]] = std::move(faceIDs);
     }
 
+
     // Synchronise across coupled edges.
     syncTools::syncEdgeList
     (
@@ -701,6 +724,17 @@ Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
 }
 
 
+Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
+(
+    const polyMesh& mesh,
+    const globalIndex& globalFaces,
+    const indirectPrimitivePatch& pp
+)
+{
+    return globalEdgeFaces(mesh, globalFaces, pp, bitSet::null());
+}
+
+
 void Foam::addPatchCellLayer::markPatchEdges
 (
     const polyMesh& mesh,
@@ -799,6 +833,11 @@ void Foam::addPatchCellLayer::globalEdgeInfo
     }
 
 
+    bitSet isPpFace(mesh.nFaces());
+    isPpFace.set(pp.addressing());
+    // Note: no need to sync isPpFace since does not include processor patches
+
+
     const faceZoneMesh& fzs = mesh.faceZones();
 
     // Extract zone info into mesh face indexing for ease of addressing
@@ -839,6 +878,11 @@ void Foam::addPatchCellLayer::globalEdgeInfo
 
         for (const label facei : isInternalOrCoupled)
         {
+            if (isPpFace[facei])
+            {
+                continue;
+            }
+
             const face& f = mesh.faces()[facei];
 
             label prevPointi = f.last();
@@ -891,9 +935,6 @@ void Foam::addPatchCellLayer::globalEdgeInfo
 
         const polyBoundaryMesh& patches = mesh.boundaryMesh();
 
-        bitSet isPpFace(mesh.nFaces());
-        isPpFace.set(pp.addressing());
-        // Note: no need to sync ppFace since does not include processor patches
 
         for (const polyPatch& pp : patches)
         {
@@ -1128,6 +1169,8 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
     edgePatchID.setSize(pp.nEdges());
     edgePatchID = -1;
     nPatches = patches.size();
+    nbrProcToPatch.clear();
+    patchToNbrProc.clear();
     edgeZoneID.setSize(pp.nEdges());
     edgeZoneID = -1;
     edgeFlip.setSize(pp.nEdges());
@@ -1487,7 +1530,7 @@ void Foam::addPatchCellLayer::setRefinement
                 << abort(FatalError);
         }
     }
-    else
+    else if (debug)
     {
         // Maybe check for adding to neighbour of boundary faces? How about
         // coupled faces where the faceZone flipMap is negated
@@ -1605,13 +1648,7 @@ void Foam::addPatchCellLayer::setRefinement
     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     bitSet isBlockedFace(mesh_.nFaces());
-    forAll(nFaceLayers, patchFacei)
-    {
-        if (nFaceLayers[patchFacei] > 0)
-        {
-            isBlockedFace.set(pp.addressing()[patchFacei]);
-        }
-    }
+    isBlockedFace.set(pp.addressing());
 
     // Some storage for edge-face-addressing.
     DynamicList<label> ef;
@@ -1839,191 +1876,50 @@ void Foam::addPatchCellLayer::setRefinement
     // Also mark any affected cells. We could transport the duplicated point
     // itself but since it is a processor-local index only we only transport
     // a boolean.
-
-    // Per face, per index in face either labelMax or a valid index. Note:
+    // Per face, per index in face either -1 or a valid index. Note:
     // most faces are not affected in which case the face will be zero size
-    // and only have a nullptr and a size.
+    // and only have a nullptr and a size. Note: we do not actually use the
+    // value of the index - it might be a remote patch point so not make any
+    // sense. All we want to know is whether it is -1 or not.
     faceList baseFaces(mesh_.nFaces());
-    bitSet isAffectedCell(mesh_.nCells());
     {
-        const faceList& localFaces = pp.localFaces();
-        forAll(localFaces, patchFacei)
+        bitSet isDupPatchPoint(pp.nPoints());
+        forAll(nPointLayers, patchPointi)
         {
-            const face& f = localFaces[patchFacei];
-            forAll(f, fp)
+            if (nPointLayers[patchPointi] > 0)
             {
-                const label patchPointi = f[fp];
-                if (nPointLayers[patchPointi] > 0)
-                {
-                    const label meshFacei = pp.addressing()[patchFacei];
-                    face& baseF = baseFaces[meshFacei];
-                    // Initialise to labelMax if not yet sized
-                    baseF.setSize(f.size(), labelMax);
-                    baseF[fp] = pp.meshPoints()[patchPointi];
-
-                    if (ppFlip[patchFacei])
-                    {
-                        // Neighbour stays. Affected points on the owner side.
-                        const label celli = mesh_.faceOwner()[meshFacei];
-                        isAffectedCell.set(celli);
-                    }
-                    else if (mesh_.isInternalFace(meshFacei))
-                    {
-                        // Owner unaffected. Unaffected points on neighbour side
-                        const label celli = mesh_.faceNeighbour()[meshFacei];
-                        isAffectedCell.set(celli);
-                    }
-                }
+                isDupPatchPoint.set(patchPointi);
             }
         }
-    }
-
-    // Transport affected side across faces. Could do across edges: say we have
-    // a loose cell edge-(but not face-)connected to face-to-be-extruded do
-    // we want it to move with the extrusion or stay connected to the original?
-    // For now just keep it connected to the original.
-    {
-        // Work space
-        Map<label> minPointValue;
-        faceList oldBoundaryFaces(mesh_.nBoundaryFaces());
-
-        while (true)
+        // Knock out point if not all local faces using it are extruded
+        // Guess not needed since done outside of routine already.
+        forAll(nFaceLayers, patchFacei)
         {
-            bitSet newIsAffectedCell(mesh_.nCells());
-
-            label nChanged = 0;
-            for (const label celli : isAffectedCell)
+            if (nFaceLayers[patchFacei] == 0)
             {
-                const cell& cFaces = mesh_.cells()[celli];
-
-                // 1. Determine marked base points. Inside a single cell all
-                //    faces use the same 'instance' of a point.
-                minPointValue.clear();
-                for (const label facei : cFaces)
-                {
-                    const face& baseF = baseFaces[facei];
-                    const face& f = mesh_.faces()[facei];
-
-                    if (baseF.size())
-                    {
-                        forAll(f, fp)
-                        {
-                            if (baseF[fp] != labelMax)
-                            {
-                                // Could check here for inconsistent patchPoint
-                                // e.g. cell using both sides of a
-                                // face-to-be-extruded. Is not possible!
-                                minPointValue.insert(f[fp], baseF[fp]);
-                            }
-                        }
-                    }
-                }
-
-                //Pout<< "For cell:" << celli
-                //    << " at:" << mesh_.cellCentres()[celli]
-                //    << " have minPointValue:" << minPointValue
-                //    << endl;
-
-                // 2. Transport marked points on all cell points
-                for (const label facei : cFaces)
+                const face& f = pp.localFaces()[patchFacei];
+                for (const label patchPointi : f)
                 {
-                    const face& f = mesh_.faces()[facei];
-                    face& baseF = baseFaces[facei];
-
-                    const label oldNChanged = nChanged;
-                    forAll(f, fp)
-                    {
-                        const auto fnd = minPointValue.find(f[fp]);
-                        if (fnd.good())
-                        {
-                            baseF.setSize(f.size(), labelMax);
-                            if (baseF[fp] == labelMax)
-                            {
-                                baseF[fp] = fnd();
-                                nChanged++;
-
-                                //Pout<< "For cell:" << celli
-                                //    << " at:" << mesh_.cellCentres()[celli]
-                                //    << " on face:" << facei
-                                //    << " points:"
-                                //    << UIndirectList<point>(mesh_.points(), f)
-                                //    << " now have baseFace:" << baseF
-                                //    << endl;
-                            }
-                        }
-                    }
-
-                    if (!isBlockedFace(facei) && nChanged > oldNChanged)
+                    if (isDupPatchPoint[patchPointi])
                     {
-                        // Mark neighbouring cells
-                        const label own = mesh_.faceOwner()[facei];
-                        if (!isAffectedCell[own])
-                        {
-                            newIsAffectedCell.set(own);
-                        }
-                        if (mesh_.isInternalFace(facei))
-                        {
-                            const label nei = mesh_.faceNeighbour()[facei];
-                            if (!isAffectedCell[nei])
-                            {
-                                newIsAffectedCell.set(nei);
-                            }
-                        }
+                        isDupPatchPoint.unset(patchPointi);
                     }
                 }
             }
+        }
 
-            if (debug)
-            {
-                Pout<< "isAffectedCell:" << isAffectedCell.count() << endl;
-                Pout<< "newIsAffectedCell:" << newIsAffectedCell.count()
-                    << endl;
-                Pout<< "nChanged:" << nChanged << endl;
-            }
-
-            if (!returnReduceOr(nChanged))
-            {
-                break;
-            }
-
-
-            // Transport minimum across coupled faces
-            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-            SubList<face> l
-            (
-                baseFaces,
-                mesh_.nBoundaryFaces(),
-                mesh_.nInternalFaces()
-            );
-            oldBoundaryFaces = l;
-            syncTools::syncBoundaryFaceList
-            (
-                mesh_,
-                l,
-                minEqOpFace(),
-                Foam::dummyTransform()  // dummy transformation
-            );
-
-            forAll(l, bFacei)
-            {
-                // Note: avoid special handling of comparing zero-sized faces
-                //       (see face::operator==). Review.
-                const labelUList& baseVts = l[bFacei];
-                const labelUList& oldVts = oldBoundaryFaces[bFacei];
-                if (baseVts != oldVts)
-                {
-                    const label facei = mesh_.nInternalFaces()+bFacei;
-                    const label own = mesh_.faceOwner()[facei];
-                    if (!isAffectedCell[own])
-                    {
-                        newIsAffectedCell.set(own);
-                    }
-                }
-            }
+        findDuplicatedPoints
+        (
+            mesh_,
+            pp,
+            ppFlip,           // optional orientation on top of pp
+            isBlockedFace,    // any mesh faces not to be traversed.
+                              // Usually pp.addressing()
+            isDupPatchPoint,
+            extrude_,
 
-            isAffectedCell = newIsAffectedCell;
-        }
+            baseFaces
+        );
     }
 
 
@@ -2120,13 +2016,13 @@ void Foam::addPatchCellLayer::setRefinement
             }
             else if (!ppFlip[patchFacei])
             {
-                // Normal: extrude from owner face
+                // Normal: extrude from owner side
                 extrudeCelli = mesh_.faceOwner()[meshFacei];
                 extrudeZonei = mesh_.cellZones().whichZone(extrudeCelli);
             }
             else if (mesh_.isInternalFace(meshFacei))
             {
-                // Extrude from neighbour face (if internal). Might be
+                // Extrude from neighbour side (if internal). Might be
                 // that it is a coupled face and the other side is
                 // extruded
                 extrudeCelli = mesh_.faceNeighbour()[meshFacei];
@@ -2164,8 +2060,9 @@ void Foam::addPatchCellLayer::setRefinement
 
 
 
-    // Create faces on top of the original patch faces.
-    // These faces are created from original patch faces outwards so in order
+    // Create faces from the original patch faces.
+    // These faces are created from original patch faces outwards (or inwards)
+    // so in order
     // of increasing cell number. So orientation should be same as original
     // patch face for them to have owner<neighbour.
 
@@ -2214,74 +2111,97 @@ void Foam::addPatchCellLayer::setRefinement
                 //    << endl;
 
                 // Get new neighbour
-                label own = addedCells[patchFacei][i];
-                label nei;
-                label patchi;
-                label zoneI = -1;
-                bool flip = false;
+                label own;
+                label nei = -1;
+                label patchi = -1;
+                label zonei = -1;
+                bool zoneFlip = false;
                 bool fluxFlip = false;
 
                 if (i == addedCells[patchFacei].size()-1)
                 {
-                    // Top layer so is either patch face or connects to
-                    // the other cell
-                    patchi = patchID[patchFacei];
-                    if (patchi == -1)
-                    {
-                        // Internal face
-                        nei =
-                        (
-                           !ppFlip[patchFacei]
-                          ? mesh_.faceNeighbour()[meshFacei]
-                          : mesh_.faceOwner()[meshFacei]
-                        );
+                    // Last layer so
+                    //  - extrude : original patch or other cell
+                    //  - intrude : original cell
 
-                        if (ppFlip[patchFacei])
+                    if (extrude_)
+                    {
+                        patchi = patchID[patchFacei];
+                        zonei = mesh_.faceZones().whichZone(meshFacei);
+                        if (zonei != -1)
                         {
-                            newFace = newFace.reverseFace();
+                            const faceZone& fz = mesh_.faceZones()[zonei];
+                            zoneFlip = fz.flipMap()[fz.whichFace(meshFacei)];
+                        }
+                        if (patchi == -1)
+                        {
+                            // Internal face between added cell and original
+                            // neighbour / owner
+                            own =
+                            (
+                               !ppFlip[patchFacei]
+                              ? mesh_.faceNeighbour()[meshFacei]
+                              : mesh_.faceOwner()[meshFacei]
+                            );
+                            nei = addedCells[patchFacei][i];
+                            if (ppFlip[patchFacei])
+                            {
+                                newFace = newFace.reverseFace();
+                                if (zonei != -1)
+                                {
+                                    zoneFlip = !zoneFlip;
+                                }
+                                fluxFlip = true;
+                            }
+                        }
+                        else
+                        {
+                            // Boundary face
+                            own = addedCells[patchFacei][i];
                         }
-                        //Pout<< "** adding top (internal) face:"
-                        //    << " at:" << mesh_.faceCentres()[meshFacei]
-                        //   <<  " own:" << own << " nei:" << nei
-                        //    << " patchi:" << patchi
-                        //    << " newFace:" << newFace
-                        //    << endl;
                     }
                     else
                     {
-                        nei = -1;
-                    }
-                    zoneI = mesh_.faceZones().whichZone(meshFacei);
-                    if (zoneI != -1)
-                    {
-                        const faceZone& fz = mesh_.faceZones()[zoneI];
-                        flip = fz.flipMap()[fz.whichFace(meshFacei)];
+                        // Intrude : face connects to original cell
+                        //if (patchID[patchFacei] == -1)
+                        {
+                            // Internal face between added cell and original
+                            // owner / neighbour. TBD: what if ppFlip set on
+                            // boundary face (so with no neighbour)
+                            own =
+                            (
+                               !ppFlip[patchFacei]
+                              ? mesh_.faceOwner()[meshFacei]
+                              : mesh_.faceNeighbour()[meshFacei]
+                            );
+                            nei = addedCells[patchFacei][i];
+                            if (ppFlip[patchFacei])
+                            {
+                                // Since neighbour now owns the face flip it
+                                newFace = newFace.reverseFace();
+                                if (zonei != -1)
+                                {
+                                    zoneFlip = !zoneFlip;
+                                }
+                                fluxFlip = true;
+                            }
+                        }
                     }
                 }
                 else
                 {
                     // Internal face between layer i and i+1
+                    own = addedCells[patchFacei][i];
                     nei = addedCells[patchFacei][i+1];
-                    patchi = -1;
-                }
 
-                if (nei != -1 && nei < own)
-                {
-                    // Wrongly oriented internal face
-                    newFace = newFace.reverseFace();
-                    std::swap(own, nei);
-                    flip = !flip;
-                    fluxFlip = true;
-
-                    //Pout<< "Flipped newFace:"
-                    //    << newFace.unitNormal(meshMod.points())
-                    //    << " own:" << own
-                    //    << " nei:" << nei
-                    //    << endl;
+                    if (ppFlip[patchFacei])
+                    {
+                        // Since neighbour now owns the face flip it
+                        newFace = newFace.reverseFace();
+                        fluxFlip = true;
+                    }
                 }
 
-
-
                 layerFaces_[patchFacei][i+1] = meshMod.setAction
                 (
                     polyAddFace
@@ -2294,8 +2214,8 @@ void Foam::addPatchCellLayer::setRefinement
                         (addToMesh_ ? meshFacei : -1), // master face
                         fluxFlip,                   // flux flip
                         patchi,                     // patch for face
-                        zoneI,                      // zone for face
-                        flip                        // face zone flip
+                        zonei,                      // zone for face
+                        zoneFlip                    // face zone flip
                     )
                 );
 
@@ -2307,13 +2227,14 @@ void Foam::addPatchCellLayer::setRefinement
                 //    << "     n:" << newFace.unitNormal(meshMod.points())
                 //    << " own:" << own << " nei:" << nei
                 //    << " patchi:" << patchi
+                //    << " zonei:" << zonei
                 //    << endl;
             }
         }
     }
 
     //
-    // Modify owner faces to have addedCells as neighbour
+    // Modify original face to have addedCells as neighbour
     //
 
     if (addToMesh_)
@@ -2322,41 +2243,110 @@ void Foam::addPatchCellLayer::setRefinement
         {
             if (addedCells[patchFacei].size())
             {
-                label meshFacei = pp.addressing()[patchFacei];
+                const label meshFacei = pp.addressing()[patchFacei];
 
                 layerFaces_[patchFacei][0] = meshFacei;
                 const face& f = pp[patchFacei];
 
-                const label own =
-                (
-                    !ppFlip[patchFacei]
-                  ? mesh_.faceOwner()[meshFacei]
-                  : mesh_.faceNeighbour()[meshFacei]
-                );
-                const label nei = addedCells[patchFacei][0];
+                if (extrude_)
+                {
+                    const label own =
+                    (
+                        !ppFlip[patchFacei]
+                      ? mesh_.faceOwner()[meshFacei]
+                      : mesh_.faceNeighbour()[meshFacei]
+                    );
+                    const label nei = addedCells[patchFacei][0];
 
-                meshMod.setAction
-                (
-                    polyModifyFace
+                    meshMod.setAction
                     (
-                        (ppFlip[patchFacei] ? f.reverseFace() : f),// verts
-                        meshFacei,                      // label of face
-                        own,                            // owner
-                        nei,                            // neighbour
-                        ppFlip[patchFacei],             // face flip
-                        -1,                             // patch for face
-                        true, //false,                  // remove from zone
-                        -1, //zoneI,                    // zone for face
-                        false                           // face flip in zone
-                    )
-                );
+                        polyModifyFace
+                        (
+                            (ppFlip[patchFacei] ? f.reverseFace() : f),// verts
+                            meshFacei,                      // label of face
+                            own,                            // owner
+                            nei,                            // neighbour
+                            ppFlip[patchFacei],             // face flip
+                            -1,                             // patch for face
+                            true, //false,                  // remove from zone
+                            -1, //zoneI,                    // zone for face
+                            false                           // face flip in zone
+                        )
+                    );
+                }
+                else
+                {
+                    label patchi;
+                    label zonei;
+                    bool zoneOrient;
+                    setFaceProps
+                    (
+                        mesh_,
+                        meshFacei,
 
-                //Pout<< "Modified bottom face " << meshFacei
-                //    << " at:" << mesh_.faceCentres()[meshFacei]
-                //    << " new own:" << own << " new nei:" << nei
-                //    << " verts:" << meshMod.faces()[meshFacei]
-                //    << " n:"
-                //    << meshMod.faces()[meshFacei].unitNormal(meshMod.points())
+                        patchi,
+                        zonei,
+                        zoneOrient
+                    );
+
+                    label own;
+                    label nei = -1;
+                    bool flip = false;
+                    if (!ppFlip[patchFacei])
+                    {
+                        if (patchi == -1)
+                        {
+                            own = mesh_.faceNeighbour()[meshFacei];
+                            nei = addedCells[patchFacei].first();
+                            flip = true;
+                        }
+                        else
+                        {
+                            own = addedCells[patchFacei].first();
+                        }
+                    }
+                    else
+                    {
+                        if (patchi == -1)
+                        {
+                            own = mesh_.faceOwner()[meshFacei];
+                            nei = addedCells[patchFacei].first();
+                        }
+                        else
+                        {
+                            own = addedCells[patchFacei].first();
+                        }
+                    }
+
+                    if (zonei != -1 && flip)
+                    {
+                        zoneOrient = !zoneOrient;
+                    }
+
+                    meshMod.setAction
+                    (
+                        polyModifyFace
+                        (
+                            (flip ? f.reverseFace() : f),   // verts
+                            meshFacei,                      // label of face
+                            own,                            // owner
+                            nei,                            // neighbour
+                            flip,                           // face flip
+                            patchi,                         // patch for face
+                            false,                          // remove from zone
+                            zonei,                          // zone for face
+                            zoneOrient                      // face flip in zone
+                        )
+                    );
+                }
+
+                //Pout<< "Modified original face " << meshFacei
+                //    << " at:" << mesh_.faceCentres()[meshFacei]
+                //    << " new own:" << meshMod.faceOwner()[meshFacei]
+                //    << " new nei:" << meshMod.faceNeighbour()[meshFacei]
+                //    << " verts:" << meshMod.faces()[meshFacei]
+                //    << " n:"
+                //    << meshMod.faces()[meshFacei].unitNormal(meshMod.points())
                 //    << endl;
             }
         }
@@ -2472,9 +2462,10 @@ void Foam::addPatchCellLayer::setRefinement
     // between the same two faces and extrude string into a single face.
     forAll(pp, patchFacei)
     {
+        // Get edges of face in vertex order
         const labelList& fEdges = faceEdges[patchFacei];
 
-        forAll(fEdges, fp)
+        forAll(fEdges, i)
         {
             // Get string of edges that needs to be extruded as a single face.
             // Returned as indices in fEdges.
@@ -2533,16 +2524,16 @@ void Foam::addPatchCellLayer::setRefinement
                 // because we loop in incrementing order as well we will
                 // always have nbrFacei > patchFacei.
 
-                label startEdgei = fEdges[startFp];
+                const label startEdgei = fEdges[startFp];
 
-                label meshEdgei = meshEdges[startEdgei];
+                const label meshEdgei = meshEdges[startEdgei];
 
-                label numEdgeSideFaces = edgeLayers[startEdgei];
+                const label numEdgeSideFaces = edgeLayers[startEdgei];
 
                 for (label i = 0; i < numEdgeSideFaces; i++)
                 {
-                    label vEnd = stringedVerts.last();
-                    label vStart = stringedVerts[0];
+                    const label vEnd = stringedVerts.last();
+                    const label vStart = stringedVerts[0];
 
                     // calculate number of points making up a face
                     label newFp = 2*stringedVerts.size();
@@ -2573,7 +2564,7 @@ void Foam::addPatchCellLayer::setRefinement
                     {
                         forAll(stringedVerts, stringedI)
                         {
-                            label v = stringedVerts[stringedI];
+                            const label v = stringedVerts[stringedI];
                             addVertex
                             (
                                 (
@@ -2590,10 +2581,10 @@ void Foam::addPatchCellLayer::setRefinement
                     {
                         forAll(stringedVerts, stringedI)
                         {
-                            label v = stringedVerts[stringedI];
+                            const label v = stringedVerts[stringedI];
                             if (addedPoints_[v].size())
                             {
-                                label offset =
+                                const label offset =
                                     addedPoints_[v].size() - numEdgeSideFaces;
                                 addVertex
                                 (
@@ -2623,7 +2614,7 @@ void Foam::addPatchCellLayer::setRefinement
                     {
                         if (i == 0 && addedPoints_[vEnd].size())
                         {
-                            label offset =
+                            const label offset =
                                 addedPoints_[vEnd].size() - numEdgeSideFaces;
                             for (label ioff = 0; ioff < offset; ioff++)
                             {
@@ -2639,10 +2630,10 @@ void Foam::addPatchCellLayer::setRefinement
 
                     forAllReverse(stringedVerts, stringedI)
                     {
-                        label v = stringedVerts[stringedI];
+                        const label v = stringedVerts[stringedI];
                         if (addedPoints_[v].size())
                         {
-                            label offset =
+                            const label offset =
                                 addedPoints_[v].size() - numEdgeSideFaces;
                             addVertex
                             (
@@ -2672,7 +2663,7 @@ void Foam::addPatchCellLayer::setRefinement
                     {
                         if (i == 0 && addedPoints_[vStart].size())
                         {
-                            label offset =
+                            const label offset =
                                 addedPoints_[vStart].size() - numEdgeSideFaces;
                             for (label ioff = offset-1; ioff >= 0; ioff--)
                             {
@@ -2695,7 +2686,7 @@ void Foam::addPatchCellLayer::setRefinement
 
                         // Walked edges as if owner face was extruded. Reverse
                         // for neighbour face extrusion.
-                        if (ppFlip[patchFacei])
+                        if (extrude_ == ppFlip[patchFacei])
                         {
                             newFace = newFace.reverseFace();
                         }
@@ -2797,7 +2788,11 @@ void Foam::addPatchCellLayer::setRefinement
     {
         face newFace;
 
-        forAll(baseFaces, facei)
+        // For intrusion correction later on: store displacement of modified
+        // points so they can be adapted on connected faces.
+        pointField displacement(mesh_.nPoints(), Zero);
+
+        forAll(mesh_.faces(), facei)
         {
             const face& f = mesh_.faces()[facei];
             const face& baseF = baseFaces[facei];
@@ -2813,20 +2808,25 @@ void Foam::addPatchCellLayer::setRefinement
             forAll(f, fp)
             {
                 const label meshPointi = f[fp];
-                if (baseF[fp] != labelMax)
+                if (baseF[fp] != -1)
                 {
-                    // Duplicated point
-                    const label patchPointi = pp.meshPointMap()[meshPointi];
-                    const label addedPointi = addedPoints_[patchPointi].last();
-
-                    //Pout<< "    For point:" << meshPointi
-                    //    << " at:" << mesh_.points()[meshPointi]
-                    //    << " at:" << pp.localPoints()[patchPointi]
-                    //    << " using addedpoint:" << addedPointi
-                    //    << " at:" << meshMod.points()[addedPointi]
-                    //    << endl;
+                    // Duplicated point. Might not be present on processor?
+                    //const label patchPointi = pp.meshPointMap()[meshPointi];
+                    const auto pointFnd = pp.meshPointMap().find(meshPointi);
+                    if (pointFnd)
+                    {
+                        const label patchPointi = pointFnd();
+                        const label addedPointi =
+                            addedPoints_[patchPointi].last();
+
+                        // Adapt vertices of face
+                        newFace[fp] = addedPointi;
 
-                    newFace[fp] = addedPointi;
+                        // Store displacement for syncing later on
+                        displacement[meshPointi] =
+                            meshMod.points()[addedPointi]
+                           -mesh_.points()[meshPointi];
+                    }
                 }
             }
 
@@ -2879,8 +2879,318 @@ void Foam::addPatchCellLayer::setRefinement
                     zoneFlip                    // face flip in zone
                 );
             }
+
+
+            //Pout<< "Adapted point on existing face:" << facei
+            //    << " at:" << mesh_.faceCentres()[facei]
+            //    << " zone:" << zoneID << nl
+            //    << "    old:" << f
+            //    << " n:" << newFace.unitNormal(meshMod.points())
+            //    << " coords:" << UIndirectList<point>(mesh_.points(), f)
+            //    << nl
+            //    << "    new:" << newFace
+            //    << " n:" << newFace.unitNormal(meshMod.points())
+            //    << " coords:"
+            //    << UIndirectList<point>(meshMod.points(), newFace)
+            //    << endl;
+        }
+
+        if (!extrude_)
+        {
+            // Bit tricky:
+            // - if intruding we're modifying the vertices on existing
+            //   coupled faces (in extrude mode we're adding additional points/
+            //   faces where we're already doing the right thing)
+            // - if the other side face is itself not on an extrudePatch
+            //   it will not be adapted so you'll get a coupled point mismatch
+            // - so send over the new point position (or use some map on
+            //   coupled faces to describe which vertex on the face is changed?)
+            // - and adapt any point that was marked but not an extrusion point
+            // - to test: take 2x2 blockMesh and remove one of the cells. Put
+            //   all 3 cells on different processors. Now one of the processors
+            //   will be coupled to extrude/intruded points but itself have
+            //   no patch.
+
+            syncTools::syncPointList
+            (
+                mesh_,
+                displacement,
+                maxMagSqrEqOp<vector>(),
+                vector::zero
+            );
+
+            forAll(baseFaces, facei)
+            {
+                const face& f = mesh_.faces()[facei];
+                const face& baseF = baseFaces[facei];
+
+                if (isBlockedFace(facei) || baseF.empty())
+                {
+                    // Either part of patch or no duplicated points on face
+                    continue;
+                }
+
+                // Start off from original face
+                forAll(f, fp)
+                {
+                    if (baseF[fp] != -1)
+                    {
+                        // Duplicated point. Might not be present on processor?
+                        const label meshPointi = f[fp];
+
+                        if
+                        (
+                           !pp.meshPointMap().found(meshPointi)
+                         && displacement[meshPointi] != vector::zero
+                        )
+                        {
+                            const point newPt
+                            (
+                                mesh_.points()[meshPointi]
+                              + displacement[meshPointi]
+                            );
+                            meshMod.modifyPoint
+                            (
+                                meshPointi,
+                                newPt,
+                                mesh_.pointZones().whichZone(meshPointi),
+                                true
+                            );
+
+                            // Unmark as being done
+                            displacement[meshPointi] = Zero;
+                        }
+                    }
+                }
+            }
         }
     }
+
+
+
+    //if (debug & 4)
+    //{
+    //    Pout<< "Checking whole mesh" << endl;
+    //    pointField fCtrs;
+    //    vectorField fAreas;
+    //    const UList<face>& faces = meshMod.faces();
+    //    const pointField p(meshMod.points());
+    //    primitiveMeshTools::makeFaceCentresAndAreas
+    //    (
+    //        faces,
+    //        p,
+    //        fCtrs,
+    //        fAreas
+    //    );
+    //
+    //    const label nCells = max(meshMod.faceOwner())+1;
+    //
+    //    pointField cellCtrs;
+    //    scalarField cellVols;
+    //    {
+    //        // See primitiveMeshTools::makeCellCentresAndVols
+    //        // Clear the fields for accumulation
+    //        cellCtrs.setSize(nCells, Zero);
+    //        cellVols.setSize(nCells, Zero);
+    //
+    //        const labelList& own = meshMod.faceOwner();
+    //        const labelList& nei = meshMod.faceNeighbour();
+    //
+    //        Field<solveVector> cEst(nCells, Zero);
+    //        labelField nCellFaces(nCells, Zero);
+    //
+    //        forAll(own, facei)
+    //        {
+    //            cEst[own[facei]] += solveVector(fCtrs[facei]);
+    //            ++nCellFaces[own[facei]];
+    //        }
+    //
+    //        forAll(nei, facei)
+    //        {
+    //            if (nei[facei] == -1)
+    //            {
+    //                continue;
+    //            }
+    //            cEst[nei[facei]] += solveVector(fCtrs[facei]);
+    //            ++nCellFaces[nei[facei]];
+    //        }
+    //
+    //        forAll(cEst, celli)
+    //        {
+    //            cEst[celli] /= nCellFaces[celli];
+    //        }
+    //
+    //        forAll(own, facei)
+    //        {
+    //            const solveVector fc(fCtrs[facei]);
+    //            const solveVector fA(fAreas[facei]);
+    //
+    //            // Calculate 3*face-pyramid volume
+    //            solveScalar pyr3Vol = fA & (fc - cEst[own[facei]]);
+    //
+    //            // Calculate face-pyramid centre
+    //            solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[own[facei]];
+    //
+    //            // Accumulate volume-weighted face-pyramid centre
+    //            cellCtrs[own[facei]] += pyr3Vol*pc;
+    //
+    //            // Accumulate face-pyramid volume
+    //            cellVols[own[facei]] += pyr3Vol;
+    //        }
+    //
+    //        forAll(nei, facei)
+    //        {
+    //            if (nei[facei] == -1)
+    //            {
+    //                continue;
+    //            }
+    //
+    //            const solveVector fc(fCtrs[facei]);
+    //            const solveVector fA(fAreas[facei]);
+    //
+    //            // Calculate 3*face-pyramid volume
+    //            solveScalar pyr3Vol = fA & (cEst[nei[facei]] - fc);
+    //
+    //            // Calculate face-pyramid centre
+    //            solveVector pc = (3.0/4.0)*fc + (1.0/4.0)*cEst[nei[facei]];
+    //
+    //            // Accumulate volume-weighted face-pyramid centre
+    //            cellCtrs[nei[facei]] += pyr3Vol*pc;
+    //
+    //            // Accumulate face-pyramid volume
+    //            cellVols[nei[facei]] += pyr3Vol;
+    //        }
+    //
+    //        forAll(cellCtrs, celli)
+    //        {
+    //            if (mag(cellVols[celli]) > VSMALL)
+    //            {
+    //                cellCtrs[celli] /= cellVols[celli];
+    //            }
+    //            else
+    //            {
+    //                cellCtrs[celli] = cEst[celli];
+    //            }
+    //        }
+    //        cellVols *= (1.0/3.0);
+    //    }
+    //    cellList cells(nCells);
+    //    {
+    //        const labelList& own = meshMod.faceOwner();
+    //        const labelList& nei = meshMod.faceNeighbour();
+    //
+    //        labelList nFaces(nCells, 0);
+    //        forAll(own, facei)
+    //        {
+    //            nFaces[own[facei]]++;
+    //        }
+    //        forAll(nei, facei)
+    //        {
+    //            if (nei[facei] == -1)
+    //            {
+    //                continue;
+    //            }
+    //            nFaces[nei[facei]]++;
+    //        }
+    //
+    //        forAll(cells, celli)
+    //        {
+    //            cells[celli].resize_nocopy(nFaces[celli]);
+    //            nFaces[celli] = 0;
+    //        }
+    //
+    //        forAll(own, facei)
+    //        {
+    //            const label celli = own[facei];
+    //            cells[celli][nFaces[celli]++] = facei;
+    //        }
+    //        forAll(nei, facei)
+    //        {
+    //            if (nei[facei] == -1)
+    //            {
+    //                continue;
+    //            }
+    //            const label celli = nei[facei];
+    //            cells[celli][nFaces[celli]++] = facei;
+    //        }
+    //    }
+    //
+    //
+    //    scalarField openness;
+    //    {
+    //        const labelList& own = meshMod.faceOwner();
+    //        const labelList& nei = meshMod.faceNeighbour();
+    //
+    //        // Loop through cell faces and sum up the face area vectors for
+    //        // each cell. This should be zero in all vector components
+    //
+    //        vectorField sumClosed(nCells, Zero);
+    //        vectorField sumMagClosed(nCells, Zero);
+    //
+    //        forAll(own, facei)
+    //        {
+    //            // Add to owner
+    //            sumClosed[own[facei]] += fAreas[facei];
+    //            sumMagClosed[own[facei]] += cmptMag(fAreas[facei]);
+    //        }
+    //
+    //        forAll(nei, facei)
+    //        {
+    //            // Subtract from neighbour
+    //            if (nei[facei] == -1)
+    //            {
+    //                continue;
+    //            }
+    //
+    //            sumClosed[nei[facei]] -= fAreas[facei];
+    //            sumMagClosed[nei[facei]] += cmptMag(fAreas[facei]);
+    //        }
+    //
+    //
+    //        // Check the sums
+    //        openness.setSize(nCells);
+    //
+    //        forAll(sumClosed, celli)
+    //        {
+    //            scalar maxOpenness = 0;
+    //
+    //            for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
+    //            {
+    //                maxOpenness = max
+    //                (
+    //                    maxOpenness,
+    //                    mag(sumClosed[celli][cmpt])
+    //                   /(sumMagClosed[celli][cmpt] + ROOTVSMALL)
+    //                );
+    //            }
+    //            openness[celli] = maxOpenness;
+    //
+    //            if (openness[celli] > 1e-9)
+    //            {
+    //                Pout<< "cell:" << celli
+    //                    << " at:" << cellCtrs[celli]
+    //                    << " openness:" << openness[celli]
+    //                    << endl;
+    //                OBJstream os
+    //                (
+    //                    mesh_.time().timePath()
+    //                   /"cell_" + Foam::name(celli) + ".obj"
+    //                );
+    //                faceList cellFaces
+    //                (
+    //                    UIndirectList<face>
+    //                    (
+    //                        meshMod.faces(),
+    //                        cells[celli]
+    //                    )
+    //                );
+    //                os.write(cellFaces, mesh_.points(), false);
+    //                Pout<< "Written " << os.nVertices() << " to "
+    //                    << os.name() << endl;
+    //            }
+    //        }
+    //    }
+    //}
 }
 
 
@@ -2947,4 +3257,261 @@ void Foam::addPatchCellLayer::updateMesh
 }
 
 
+void Foam::addPatchCellLayer::findDuplicatedPoints
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& pp,
+    const bitSet& ppFlip,           // optional orientation on top of pp
+    const bitSet& isBlockedFace,    // any mesh faces not to be traversed.
+                                    // Usually pp.addressing()
+    const bitSet& isDupPatchPoint,
+    const bool extrude,
+    faceList& isDupMeshPoint    // per face, per index either -1
+                                // or some index (value not relevant)
+)
+{
+    if (isBlockedFace.size() != mesh.nFaces())
+    {
+        FatalErrorInFunction << "Incorrect size" << exit(FatalError);
+    }
+    if (ppFlip.size() != pp.size() || isDupPatchPoint.size() != pp.nPoints())
+    {
+        FatalErrorInFunction << "Incorrect patch sizes"
+            << exit(FatalError);
+    }
+
+    const auto& owner = mesh.faceOwner();
+    const auto& neighbour = mesh.faceNeighbour();
+
+
+    // Store per face whether it uses the duplicated point or the original one
+    // Also mark any affected cells. We could transport the duplicated point
+    // itself but since it is a processor-local index only we only transport
+    // a boolean.
+
+    // Per face, per index in face either -1 or a valid index. Note:
+    // most faces are not affected in which case the face will be zero size
+    // and only have a nullptr and a size.
+    isDupMeshPoint.resize_nocopy(mesh.nFaces());
+    isDupMeshPoint = face();
+    bitSet isAffectedCell(mesh.nCells());
+    {
+        const faceList& localFaces = pp.localFaces();
+        forAll(localFaces, patchFacei)
+        {
+            const face& f = localFaces[patchFacei];
+            forAll(f, fp)
+            {
+                const label patchPointi = f[fp];
+                if (isDupPatchPoint[patchPointi])
+                {
+                    const label meshFacei = pp.addressing()[patchFacei];
+                    face& baseF = isDupMeshPoint[meshFacei];
+                    // Initialise to -1 if not yet sized
+                    baseF.setSize(f.size(), -1);
+                    baseF[fp] = pp.meshPoints()[patchPointi];
+
+                    if (extrude == ppFlip[patchFacei])
+                    {
+                        // either:
+                        // - extrude out of neighbour so new points connect
+                        //   to owner
+                        // - or intrude into owner
+                        isAffectedCell.set(owner[meshFacei]);
+                    }
+                    else if (mesh.isInternalFace(meshFacei))
+                    {
+                        // Owner unaffected. Affected points on neighbour side
+                        isAffectedCell.set(neighbour[meshFacei]);
+                    }
+                }
+            }
+        }
+    }
+
+
+    // Transport affected side across faces. Could do across edges: say we have
+    // a loose cell edge-(but not face-)connected to face-to-be-extruded do
+    // we want it to move with the extrusion or stay connected to the original?
+    // For now just keep it connected to the original.
+    {
+        // Work space
+        Map<label> minPointValue;
+
+        while (true)
+        {
+            bitSet newIsAffectedCell(mesh.nCells());
+
+            label nChanged = 0;
+            for (const label celli : isAffectedCell)
+            {
+                const cell& cFaces = mesh.cells()[celli];
+
+                // 1. Determine marked base points. Inside a single cell all
+                //    faces (e.g. 3 for hex) use the same 'instance' of a point.
+                minPointValue.clear();
+                for (const label facei : cFaces)
+                {
+                    const face& baseF = isDupMeshPoint[facei];
+                    const face& f = mesh.faces()[facei];
+
+                    forAll(baseF, fp)
+                    {
+                        if (baseF[fp] != -1)
+                        {
+                            // Could check here for inconsistent patchPoint
+                            // e.g. cell using both sides of a
+                            // face-to-be-extruded.
+
+                            const auto mpm = pp.meshPointMap().find(f[fp]);
+                            if (mpm && !isDupPatchPoint[mpm()])
+                            {
+                                // Local copy of point is explicitly not
+                                // marked for extrusion so ignore. This
+                                // occasionally happens with point-connected
+                                // faces where one face (& point) does
+                                // extrude but the other face does not
+                                // since pointing in the other direction.
+                                // Should ideally be covered by checking
+                                // across edges, not across points.
+                            }
+                            else
+                            {
+                                minPointValue.insert(f[fp], baseF[fp]);
+                            }
+                        }
+                    }
+                }
+
+
+                // 2. Transport marked points on all cell points
+                for (const label facei : cFaces)
+                {
+                    const face& f = mesh.faces()[facei];
+                    face& baseF = isDupMeshPoint[facei];
+
+                    const label oldNChanged = nChanged;
+                    forAll(f, fp)
+                    {
+                        const auto fnd = minPointValue.find(f[fp]);
+                        if (fnd.good())
+                        {
+                            const auto mpm = pp.meshPointMap().find(f[fp]);
+                            if (mpm && !isDupPatchPoint[mpm()])
+                            {
+                                // See above
+                                continue;
+                            }
+
+                            baseF.setSize(f.size(), -1);
+                            if (baseF[fp] == -1)
+                            {
+                                baseF[fp] = fnd();
+                                nChanged++;
+                            }
+                        }
+                    }
+
+                    if (!isBlockedFace(facei) && nChanged > oldNChanged)
+                    {
+                        // Mark neighbouring cells. Note that we do NOT check
+                        // for whether cell is already in isAffectedCell but
+                        // always add it. This is because different information
+                        // can come in from the neighbour in different
+                        // iterations.
+                        newIsAffectedCell.set(owner[facei]);
+                        if (mesh.isInternalFace(facei))
+                        {
+                            newIsAffectedCell.set(neighbour[facei]);
+                        }
+                    }
+                }
+            }
+
+
+            if (debug)
+            {
+                Pout<< "isAffectedCell:" << isAffectedCell.count() << endl;
+                Pout<< "newIsAffectedCell:" << newIsAffectedCell.count()
+                    << endl;
+                Pout<< "nChanged:" << nChanged << endl;
+            }
+
+
+            if (!returnReduceOr(nChanged))
+            {
+                break;
+            }
+
+
+            // Transport minimum across coupled faces
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+            // Faces can be either
+            // - null
+            // - face with some -1 or >= 0
+            // - blocked face (isBlockedFace, should be synced already)
+            faceList l(mesh.nBoundaryFaces());
+            forAll(l, bFacei)
+            {
+                const label facei = mesh.nInternalFaces()+bFacei;
+
+                if (isBlockedFace(facei))
+                {
+                    // Make sure nothing is transferred. Since isBlockedFace is
+                    // synced both sides should have null
+                    if (l[bFacei].size())
+                    {
+                        l[bFacei].clear();
+                    }
+                }
+                else
+                {
+                    l[bFacei] = isDupMeshPoint[facei];
+                }
+            }
+
+
+            syncTools::syncBoundaryFaceList
+            (
+                mesh,
+                l,
+                combineEqOpFace(),      // transport vertex >= 0
+                Foam::dummyTransform()  // dummy transformation
+            );
+
+            // Copy back
+            forAll(l, bFacei)
+            {
+                const label facei = mesh.nInternalFaces()+bFacei;
+
+                if (!isBlockedFace(facei))
+                {
+                    // 1. Check if anything changed. Update isAffectedCell.
+                    // Note: avoid special handling of comparing zero-sized
+                    //       faces (see face::operator==). Review.
+                    const labelUList& newVts = l[bFacei];
+                    const labelUList& oldVts = isDupMeshPoint[facei];
+
+                    if (newVts != oldVts)
+                    {
+                        const label own = owner[facei];
+                        if (!isAffectedCell[own])
+                        {
+                            newIsAffectedCell.set(own);
+                        }
+                    }
+
+
+                    // 2. Update isDupMeshPoint
+                    isDupMeshPoint[facei] = l[bFacei];
+                }
+            }
+
+
+            isAffectedCell = newIsAffectedCell;
+        }
+    }
+}
+
+
 // ************************************************************************* //
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H
index fe59a8f6080b4e613f750a0b203e090a98ced277..35b330e1458c3a82847b30629cd41ae8a1f9f521 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/addPatchCellLayer.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2020 OpenCFD Ltd.
+    Copyright (C) 2020,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -28,8 +28,8 @@ Class
     Foam::addPatchCellLayer
 
 Description
-    Adds layers of cells to outside of polyPatch. Can optionally create
-    stand-alone extruded mesh (addToMesh=false).
+    Adds layers of cells to outside (or inside) of polyMesh. Can optionally
+    create stand-alone extruded mesh (addToMesh=false).
 
     Call setRefinement with offset vector for every patch point and number
     of layers per patch face and number of layers per patch point.
@@ -51,24 +51,47 @@ Description
     \verbatim
         Was:
 
-           a      b         <- patch of boundary face
-        +------+------+
-        |      |      |     <- original cells
-        +------+------+
-
-        Becomes:
-
-           a      b         <- patch of boundary face
-        +------+------+
-        +      +------+
-        +------+------+
-        +------+------+
-        |      |      |     <- original cells
-        +------+------+
+               a      b         <- patch of boundary face
+            +------+------+
+            |      |      |     <- original cells
+            +------+------+
+
+        Extrusion:
+
+
+                            added   added
+                            face    cell
+                            ----    ----
+               a      b                     <- patch of boundary face
+            +------+------+  3
+            |      |      |         2
+            +      +------+  2
+            |      |      |         1
+            +------+------+  1
+            |      |      |         0
+            +------+------+  0              <- original boundary faces
+            |      |      |                 <- original cells
+            +------+------+
+
+
+
+        Intrusion:
+
+                            face    cell
+                            ----    ----
+               a      b                     <- patch of boundary face
+            +------+------+  0
+            |      |      |         0
+            +------+------+  1
+            |      |      |         1
+            +      +------+  2
+            |      |      |         2
+            +------+------+  3
+            |      |      |                 <- original cells
+            +------+------+
     \endverbatim
 
 
-    - added faces get same patchID as face they are extruded from
     - 'side' faces (i.e. on the edge of pp) get the patchID/zoneID of the
     other patch/zone they are connected to (hopefully only 1)
 
@@ -78,10 +101,15 @@ Description
     \verbatim
            a      b      b        <- patch of boundary face
         +------+------+------+
+        |      |      |      |
         |      |      |      |    <- cells
+        |      |      |      |
         +------+------+------+
 
 
+        (shown for extrusion mode only):
+
+
                ^      ^           <- wanted extrusion vector (none at far right)
            a   |  b   |  b        <- patch of boundary face
         +------+------+------+
@@ -123,7 +151,7 @@ class primitiveMesh;
 class globalIndex;
 
 /*---------------------------------------------------------------------------*\
-                           Class addPatchCellLayer Declaration
+                      Class addPatchCellLayer Declaration
 \*---------------------------------------------------------------------------*/
 
 class addPatchCellLayer
@@ -136,15 +164,23 @@ class addPatchCellLayer
         //- Add layers to existing mesh or create new mesh
         const bool addToMesh_;
 
+        //- Add layers to outside of mesh or to inside
+        const bool extrude_;
+
+
         //- For all patchpoints: list of added points (size 0 or nLayers)
         //  First point in list is one nearest to original point in patch,
-        //  last one is the new point on the surface.
+        //  last one is
+        //  - extrude : the new point on the surface
+        //  - intrude : the point connecting to the original cell.
         labelListList addedPoints_;
 
         //- For all patchfaces: list of layer faces.
         //  - empty if no face extruded
-        //  - first face is original boundary face
-        //  - last one is new boundary face.
+        //  - first element is original patch face
+        //  - last element is
+        //      - extrude : the new boundary face
+        //      - intrude : the new internal face to the original cell.
         labelListList layerFaces_;
 
 
@@ -226,25 +262,6 @@ class addPatchCellLayer
             label& inflateFaceI
         );
 
-        //- Find internal or boundary face to get extrude properties
-        //  from. zoneFlip consistent with ppEdge ordering
-        static void findZoneFace
-        (
-            const bool useInternalFaces,
-            const bool useBoundaryFaces,
-
-            const polyMesh& mesh,
-            const indirectPrimitivePatch& pp,
-            const label ppEdgeI,
-            const labelUIndList& excludeFaces,
-            const labelList& meshFaces,
-
-            label& inflateFaceI,
-            label& patchI,
-            label& zoneI,
-            bool& zoneFlip
-        );
-
         //- Mark internal and boundary edges of patch. In mesh edges
         //- since processor might not have pp but does have edge.
         static void markPatchEdges
@@ -294,7 +311,12 @@ public:
     // Constructors
 
         //- Construct from mesh.
-        explicit addPatchCellLayer(const polyMesh&, const bool addToMesh=true);
+        explicit addPatchCellLayer
+        (
+            const polyMesh&,
+            const bool addToMesh=true,
+            const bool extrude=true
+        );
 
 
     // Member Functions
@@ -314,8 +336,13 @@ public:
             }
 
             //- Helper: get added cells per patch face.
-            //  addedCells[patchFace] is list of cells added. Last element is
-            //  the top cells (i.e. the boundary cell)
+            //  addedCells[patchFace] is list of cells added.
+            //  extrude :
+            //      first element : next to original cell
+            //      last element  : is the top cell (i.e. the boundary cell)
+            //  intrude :
+            //      first element : top cell
+            //      last element  : next to original cell
             static labelListList addedCells
             (
                 const polyMesh&,
@@ -328,6 +355,18 @@ public:
 
         // Edit
 
+            //- Per patch edge the pp faces (in global indices) using it.
+            //  Uses ListOps::uniqueEqOp to remove duplicates. On coupled
+            //  faces only selects the one with the correct orientation/flip
+            //  (assumes the orientation is opposite on a coupled face pair)
+            static labelListList globalEdgeFaces
+            (
+                const polyMesh&,
+                const globalIndex& globalFaces,
+                const indirectPrimitivePatch& pp,
+                const bitSet& orientation
+            );
+
             //- Per patch edge the pp faces (in global indices) using it.
             //  Uses ListOps::uniqueEqOp to remove duplicates.
             static labelListList globalEdgeFaces
@@ -454,6 +493,28 @@ public:
                 const labelList& faceMap,   // new to old patch faces
                 const labelList& pointMap   // new to old patch points
             );
+
+
+
+            //- Helper: given patch and points on patch that are extruded
+            //  (to slave side or master side) find the affected
+            //  points. Calculates by walking across faces which vertices on
+            //  which face are affected. isDupMeshPoint:
+            //      -1  : unaffected
+            //      >=0 : should use local duplicate of point
+            //            (though it does not tell us whether it should use
+            //             slave side or master side)
+            static void findDuplicatedPoints
+            (
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& pp,
+                const bitSet& ppFlip,       // optional orientation on top of pp
+                const bitSet& isBlockedFace,// any mesh faces not to be
+                                            // traversed.Usually pp.addressing()
+                const bitSet& isDupPatchPoint,
+                const bool extrude,         // which side to extrude
+                faceList& isDupMeshPoint
+            );
 };
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
index bc8898d43d794d74b9ce7da1706816f56816c581..fb5c4a9c50831315fdd8418e7f5753cdd8a62f47 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
@@ -37,7 +37,7 @@ Usage
     \table
         Property     | Description             | Required    | Default value
         scale        | Time varying scale      | yes         |
-        patch        | patchField providing the raw patch value | yes |
+        refValue     | patchField providing the raw patch value | yes |
     \endtable
 
     Example of the boundary condition specification to scale a reference
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/averageNeighbour/averageNeighbourFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/averageNeighbour/averageNeighbourFvGeometryScheme.H
index 578179630104007992b325e068f67cdbe1a311b1..4ddf71443741c2093abc136a8d1d474800f95397 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/averageNeighbour/averageNeighbourFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/averageNeighbour/averageNeighbourFvGeometryScheme.H
@@ -164,6 +164,23 @@ public:
 
         //- Do what is necessary if the mesh has moved
         virtual void movePoints();
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const
+        {
+            NotImplemented;
+            return true;
+        }
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.C b/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.C
index 867b38a28712d2b1ba2061d168f9bd19d7865748..0a037d445ddf25e880fb9faa480b9739d3ba2b90 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.C
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.C
@@ -29,6 +29,7 @@ License
 #include "addToRunTimeSelectionTable.H"
 #include "surfaceFields.H"
 #include "volFields.H"
+#include "primitiveMeshTools.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -390,4 +391,36 @@ Foam::basicFvGeometryScheme::nonOrthCorrectionVectors() const
 }
 
 
+bool Foam::basicFvGeometryScheme::updateGeom
+(
+    const pointField& points,
+    const refPtr<pointField>& oldPoints,
+    pointField& faceCentres,
+    vectorField& faceAreas,
+    pointField& cellCentres,
+    scalarField& cellVolumes
+) const
+{
+    primitiveMeshTools::makeFaceCentresAndAreas
+    (
+        mesh_,
+        points,
+        faceCentres,
+        faceAreas
+    );
+
+    primitiveMeshTools::makeCellCentresAndVols
+    (
+        mesh_,
+        faceCentres,
+        faceAreas,
+        cellCentres,
+        cellVolumes
+    );
+
+    // Assume something has changed
+    return true;
+}
+
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.H
index b69d43e834eeae9d982262b13563cfabc82475a6..a59b9b0a177f35550079f3404338742d3b70355f 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/basic/basicFvGeometryScheme.H
@@ -93,6 +93,19 @@ public:
 
         //- Return non-orthogonality correction vectors
         virtual tmp<surfaceVectorField> nonOrthCorrectionVectors() const;
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/fvGeometryScheme/fvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/fvGeometryScheme/fvGeometryScheme.H
index 2dd14d27a282ec2685fafd4ece0db9178357b79f..20552e83ed8229d35707c32f484deb3a0b410c5b 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/fvGeometryScheme/fvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/fvGeometryScheme/fvGeometryScheme.H
@@ -160,6 +160,19 @@ public:
         //    const labelHashSet& patchIDs,
         //    const word& defaultPatchDistMethod
         //) const = 0;
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const = 0;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.C b/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.C
index 84c3eb064ae128bf4834af12018f9d51aba0931d..0f64298abc1fa40b31207b7e107f625bf160dbfc 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.C
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.C
@@ -456,4 +456,46 @@ void Foam::highAspectRatioFvGeometryScheme::movePoints()
 }
 
 
+bool Foam::highAspectRatioFvGeometryScheme::updateGeom
+(
+    const pointField& points,
+    const refPtr<pointField>& oldPoints,
+    pointField& faceCentres,
+    vectorField& faceAreas,
+    pointField& cellCentres,
+    scalarField& cellVolumes
+) const
+{
+    // Basic
+    basicFvGeometryScheme::updateGeom
+    (
+        points,
+        oldPoints,
+        faceCentres,
+        faceAreas,
+        cellCentres,
+        cellVolumes
+    );
+
+    // Average opposite faces
+    pointField avgFaceCentres;
+    pointField avgCellCentres;
+    makeAverageCentres
+    (
+        mesh_,
+        points,
+        faceAreas,
+        mag(faceAreas),
+        avgFaceCentres,
+        avgCellCentres
+    );
+
+    faceCentres = std::move(avgFaceCentres);
+    cellCentres = std::move(avgCellCentres);
+
+    // Assume something has changed.
+    return true;
+}
+
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.H
index 1ed2164b4f01cb3c5a7a9090694928847a885e8c..5965b81ca56c98af084ff7f0433ae1dcb97cab00 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/highAspectRatio/highAspectRatioFvGeometryScheme.H
@@ -123,6 +123,19 @@ public:
 
         //- Do what is necessary if the mesh has moved
         virtual void movePoints();
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.C b/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.C
index ce14fbaaf523f6afc3edeacd048db0fce4b1c292..debabcd87d73e0f9ac4c8fe07df642386aa29192 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.C
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.C
@@ -47,6 +47,92 @@ namespace Foam
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+void Foam::parallelFvGeometryScheme::adjustGeometry
+(
+    pointField& faceCentres,
+    vectorField& faceAreas
+) const
+{
+    pointField syncedBCentres;
+    syncedBCentres = SubField<vector>
+    (
+        faceCentres,
+        mesh_.nBoundaryFaces(),
+        mesh_.nInternalFaces()
+    );
+    syncTools::swapBoundaryFaceList
+    (
+        mesh_,
+        syncedBCentres
+    );
+
+    vectorField syncedBAreas;
+    syncedBAreas = SubField<vector>
+    (
+        faceAreas,
+        mesh_.nBoundaryFaces(),
+        mesh_.nInternalFaces()
+    );
+    syncTools::syncBoundaryFaceList
+    (
+        mesh_,
+        syncedBAreas,
+        eqOp<vector>(),
+        transformOriented()
+    );
+
+    const auto& pbm = mesh_.boundaryMesh();
+    for (const auto& pp : pbm)
+    {
+        const auto* ppp = isA<coupledPolyPatch>(pp);
+
+        //if (ppp)
+        //{
+        //    Pout<< "For patch:" << ppp->name()
+        //        << " size:" << ppp->size()
+        //        << endl;
+        //    forAll(*ppp, i)
+        //    {
+        //        const label facei = ppp->start()+i;
+        //        Pout<< "    Face:" << facei << nl
+        //            << "    meshFc:" << faceCentres[facei] << nl
+        //            << "    meshFa:" << faceAreas[facei] << nl
+        //            << endl;
+        //    }
+        //}
+
+        if (ppp && !ppp->owner())
+        {
+            SubField<point> patchFc
+            (
+                faceCentres,
+                ppp->size(),
+                ppp->start()
+            );
+            patchFc = SubField<vector>
+            (
+                syncedBCentres,
+                ppp->size(),
+                ppp->offset()
+            );
+
+            SubField<vector> patchArea
+            (
+                faceAreas,
+                ppp->size(),
+                ppp->start()
+            );
+            patchArea = SubField<vector>
+            (
+                syncedBAreas,
+                ppp->size(),
+                ppp->offset()
+            );
+        }
+    }
+}
+
+
 void Foam::parallelFvGeometryScheme::adjustGeometry()
 {
     // Swap face centres and areas
@@ -304,5 +390,38 @@ Foam::parallelFvGeometryScheme::nonOrthCorrectionVectors() const
 }
 
 
+bool Foam::parallelFvGeometryScheme::updateGeom
+(
+    const pointField& points,
+    const refPtr<pointField>& oldPoints,
+    pointField& faceCentres,
+    vectorField& faceAreas,
+    pointField& cellCentres,
+    scalarField& cellVolumes
+) const
+{
+    primitiveMeshTools::makeFaceCentresAndAreas
+    (
+        mesh_,
+        points,
+        faceCentres,
+        cellCentres
+    );
+
+    // Parallel consistency
+    adjustGeometry(faceCentres, faceAreas);
+
+    primitiveMeshTools::makeCellCentresAndVols
+    (
+        mesh_,
+        faceCentres,
+        faceAreas,
+        cellCentres,
+        cellVolumes
+    );
+
+    return true;
+}
+
 
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.H
index 9fa223f3c9c24a5ceb276747f98d08a7cb6a6995..f85c05d6a01b20057cb3e5b1e6510d9cf123f453 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/parallel/parallelFvGeometryScheme.H
@@ -102,6 +102,13 @@ private:
 
     // Private Member Functions
 
+        //- Swap processor-face geometry
+        void adjustGeometry
+        (
+            pointField& faceCentres,
+            vectorField& faceAreas
+        ) const;
+
         //- Swap processor-face geometry
         void adjustGeometry();
 
@@ -181,6 +188,19 @@ public:
 
         //- Return non-orthogonality correction vectors
         virtual tmp<surfaceVectorField> nonOrthCorrectionVectors() const;
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.C b/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.C
index 1898dbe506165d56db5c8b316a88c00238ce5a37..19cd197463c2a561214cd8f765488983065abe5c 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.C
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.C
@@ -45,6 +45,68 @@ namespace Foam
 }
 
 
+bool Foam::solidBodyFvGeometryScheme::markChanges
+(
+    const pointField& oldPoints,
+    const pointField& currPoints,
+    bitSet& isChangedPoint,
+    bitSet& isChangedFace,
+    bitSet& isChangedCell
+) const
+{
+    isChangedPoint.setSize(oldPoints.size());
+
+    // Check for non-identical points
+    forAll(isChangedPoint, pointi)
+    {
+        isChangedPoint.set(pointi, oldPoints[pointi] != currPoints[pointi]);
+    }
+
+    DebugInfo
+        << "SBM --- Changed points:"
+        << returnReduce(isChangedPoint.count(), sumOp<label>())
+        << endl;
+
+    // Quick return if no points have moved
+    if (returnReduceAnd(isChangedPoint.none()))
+    {
+        return false;
+    }
+
+    isChangedFace.setSize(mesh_.nFaces());
+    isChangedFace = false;
+
+    isChangedCell.setSize(mesh_.nCells());
+    isChangedCell = false;
+
+    const auto& pointFaces = mesh_.pointFaces();
+    const auto& own = mesh_.faceOwner();
+    const auto& nbr = mesh_.faceNeighbour();
+
+    // Identify faces and cells attached to moving points
+    for (const label pointi : isChangedPoint)
+    {
+        for (const auto facei : pointFaces[pointi])
+        {
+            isChangedFace.set(facei);
+
+            isChangedCell.set(own[facei]);
+            if (facei < mesh_.nInternalFaces())
+            {
+                isChangedCell.set(nbr[facei]);
+            }
+        }
+    }
+
+    DebugInfo
+        << "SBM --- Changed cells:"
+        << returnReduce(isChangedCell.count(), sumOp<label>())
+        << endl;
+
+    return true;
+}
+
+
 void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
 {
     if (!cacheInitialised_ || !cacheMotion_)
@@ -67,64 +129,86 @@ void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
                 << abort(FatalError);
         }
 
-        bitSet changedPoints(oldPoints.size());
-
-        // Check for non-identical points
-        forAll(changedPoints, pointi)
-        {
-            changedPoints.set(pointi, oldPoints[pointi] != currPoints[pointi]);
-        }
-
-        DebugInfo
-            << "SBM --- Changed points:"
-            << returnReduce(changedPoints.count(), sumOp<label>())
-            << endl;
+        //bitSet changedPoints(oldPoints.size());
+        //
+        //// Check for non-identical points
+        //forAll(changedPoints, pointi)
+        //{
+        //    changedPoints.set
+        //    (
+        //        pointi,
+        //        oldPoints[pointi] != currPoints[pointi]
+        //    );
+        //}
+        //
+        //DebugInfo
+        //    << "SBM --- Changed points:"
+        //    << returnReduce(changedPoints.count(), sumOp<label>())
+        //    << endl;
+        //
+        //// Quick return if no points have moved
+        //if (returnReduceAnd(changedPoints.none()))
+        //{
+        //    return;
+        //}
+        //
+        //bitSet cellIDs(mesh_.nCells());
+        //bitSet faceIDs(mesh_.nFaces());
+        //
+        //const auto& pointFaces = mesh_.pointFaces();
+        //const auto& own = mesh_.faceOwner();
+        //const auto& nbr = mesh_.faceNeighbour();
+        //
+        //// Identify faces and cells attached to moving points
+        //for (const label pointi : changedPoints)
+        //{
+        //    for (const auto facei : pointFaces[pointi])
+        //    {
+        //        faceIDs.set(facei);
+        //
+        //        cellIDs.set(own[facei]);
+        //        if (facei < mesh_.nInternalFaces())
+        //        {
+        //            cellIDs.set(nbr[facei]);
+        //        }
+        //    }
+        //}
+        //
+        //changedCellIDs_ = cellIDs.toc();
+        //
+        //DebugInfo
+        //    << "SBM --- Changed cells:"
+        //    << returnReduce(changedCellIDs_.size(), sumOp<label>())
+        //    << endl;
+
+        bitSet isChangedPoint;
+        bitSet isChangedFace;
+        bitSet isChangedCell;
+        const bool changed = markChanges
+        (
+            oldPoints,
+            currPoints,
+            isChangedPoint,
+            isChangedFace,
+            isChangedCell
+        );
 
         // Quick return if no points have moved
-        if (returnReduceAnd(changedPoints.none()))
+        if (!changed)
         {
             return;
         }
 
-        bitSet cellIDs(mesh_.nCells());
-        bitSet faceIDs(mesh_.nFaces());
-
-        const auto& pointFaces = mesh_.pointFaces();
-        const auto& own = mesh_.faceOwner();
-        const auto& nbr = mesh_.faceNeighbour();
-
-        // Identify faces and cells attached to moving points
-        for (const label pointi : changedPoints)
-        {
-            for (const auto facei : pointFaces[pointi])
-            {
-                faceIDs.set(facei);
-
-                cellIDs.set(own[facei]);
-                if (facei < mesh_.nInternalFaces())
-                {
-                    cellIDs.set(nbr[facei]);
-                }
-            }
-        }
-
-        changedCellIDs_ = cellIDs.toc();
-
-        DebugInfo
-            << "SBM --- Changed cells:"
-            << returnReduce(changedCellIDs_.size(), sumOp<label>())
-            << endl;
+        changedCellIDs_ = isChangedCell.toc();
 
 
         // Construct face and patch ID info
 
-        const auto changedFaceFlag = faceIDs.values();
-
-        DynamicList<label> changedFaceIDs(faceIDs.count());
-        DynamicList<label> changedPatchIDs(faceIDs.count());
+        DynamicList<label> changedFaceIDs(isChangedFace.count());
+        DynamicList<label> changedPatchIDs(changedFaceIDs.capacity());
         for (label facei = 0; facei < mesh_.nInternalFaces(); ++facei)
         {
-            if (changedFaceFlag[facei])
+            if (isChangedFace[facei])
             {
                 changedFaceIDs.append(facei);
                 changedPatchIDs.append(-1);
@@ -138,7 +222,7 @@ void Foam::solidBodyFvGeometryScheme::setMeshMotionData()
 
             for (const label meshFacei : pp.range())
             {
-                if (changedFaceFlag[meshFacei])
+                if (isChangedFace[meshFacei])
                 {
                     changedFaceIDs.append(meshFacei);
                     changedPatchIDs.append(patchi);
@@ -343,4 +427,82 @@ void Foam::solidBodyFvGeometryScheme::updateMesh(const mapPolyMesh& mpm)
 }
 
 
+bool Foam::solidBodyFvGeometryScheme::updateGeom
+(
+    const pointField& points,
+    const refPtr<pointField>& oldPoints,
+    pointField& faceCentres,
+    vectorField& faceAreas,
+    pointField& cellCentres,
+    scalarField& cellVolumes
+) const
+{
+    if
+    (
+        (faceCentres.size() != mesh_.nFaces())
+     || (faceAreas.size() != mesh_.nFaces())
+     || (cellCentres.size() != mesh_.nCells())
+     || (cellVolumes.size() != mesh_.nCells())
+     || !oldPoints
+    )
+    {
+        // Do all
+        return basicFvGeometryScheme::updateGeom
+        (
+            points,
+            oldPoints,
+            faceCentres,
+            faceAreas,
+            cellCentres,
+            cellVolumes
+        );
+    }
+    else
+    {
+        // Since oldPoints provided assume that face & cell geometry is
+        // up to date with it
+
+        bitSet isChangedPoint;
+        bitSet isChangedFace;
+        bitSet isChangedCell;
+        const bool changed = markChanges
+        (
+            oldPoints(),
+            points,
+            isChangedPoint,
+            isChangedFace,
+            isChangedCell
+        );
+
+        if (!changed)
+        {
+            return false;
+        }
+
+        // Make face centres and areas consistent with new points
+        primitiveMeshTools::updateFaceCentresAndAreas
+        (
+            mesh_,
+            isChangedFace.toc(),
+            points,
+            faceCentres,
+            faceAreas
+        );
+
+        primitiveMeshTools::updateCellCentresAndVols
+        (
+            mesh_,
+            faceCentres,
+            faceAreas,
+            isChangedCell.toc(),
+            mesh_.cells(),
+            cellCentres,
+            cellVolumes
+        );
+
+        return true;
+    }
+}
+
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.H
index 755f21080bf40c8fc3d88ac8e22307165edb7953..d52bfde28e48d5b362cddfbe2e723cebb09209cb 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/solidBody/solidBodyFvGeometryScheme.H
@@ -94,6 +94,16 @@ class solidBodyFvGeometryScheme
 
     // Private Member Functions
 
+        //- Detect what geometry has changed. Return true if anything has.
+        bool markChanges
+        (
+            const pointField& oldPoints,
+            const pointField& currPoints,
+            bitSet& isChangedPoint,
+            bitSet& isChangedFace,
+            bitSet& isChangedCell
+        ) const;
+
         //- Set the mesh motion data (point, face IDs)
         void setMeshMotionData();
 
@@ -127,6 +137,19 @@ public:
 
         //- Update mesh for topology changes
         virtual void updateMesh(const mapPolyMesh& mpm);
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.C b/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.C
index 90c3c4e00f320fefd6712645a42646cb3cfd1a39..186994a50d58c69c8db684b81b2696d81ca58424 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.C
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.C
@@ -208,4 +208,35 @@ void Foam::stabilisedFvGeometryScheme::movePoints()
 }
 
 
+bool Foam::stabilisedFvGeometryScheme::updateGeom
+(
+    const pointField& points,
+    const refPtr<pointField>& oldPoints,
+    pointField& faceCentres,
+    vectorField& faceAreas,
+    pointField& cellCentres,
+    scalarField& cellVolumes
+) const
+{
+    makeFaceCentresAndAreas
+    (
+        mesh_,
+        points,
+        faceCentres,
+        faceAreas
+    );
+
+    primitiveMeshTools::makeCellCentresAndVols
+    (
+        mesh_,
+        faceCentres,
+        faceAreas,
+        cellCentres,
+        cellVolumes
+    );
+
+    return true;
+}
+
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.H b/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.H
index c367ecf9b188cec160cece3f5cbcc5aa7ab84a7e..a137d334a9bcbe59790a65bc091869885fe38e57 100644
--- a/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.H
+++ b/src/finiteVolume/fvMesh/fvGeometryScheme/stabilised/stabilisedFvGeometryScheme.H
@@ -112,6 +112,19 @@ public:
 
         //- Do what is necessary if the mesh has moved
         virtual void movePoints();
+
+        //- Calculate geometry quantities using mesh topology and provided
+        //- points. If oldPoints provided only does local update. Returns
+        //- true if anything changed, false otherwise
+        virtual bool updateGeom
+        (
+            const pointField& points,
+            const refPtr<pointField>& oldPoints,    // optional old points
+            pointField& faceCentres,
+            vectorField& faceAreas,
+            pointField& cellCentres,
+            scalarField& cellVolumes
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C
index 2f10400289bc4aacfc5c0910c4de4b4dae6e65aa..839d102a171ffd708b3cd0dd51084d0494c50df8 100644
--- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C
+++ b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C
@@ -32,10 +32,16 @@ License
 #include "cyclicPolyPatch.H"
 #include "emptyPolyPatch.H"
 #include "processorPolyPatch.H"
+#include "meshPointPatch.H"
+#include "processorPointPatch.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-Foam::word Foam::fvMeshSubset::exposedPatchName("oldInternalFaces");
+namespace Foam
+{
+    word fvMeshSubset::exposedPatchName("oldInternalFaces");
+    defineTypeNameAndDebug(fvMeshSubset, 0);
+}
 
 
 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@@ -522,6 +528,16 @@ void Foam::fvMeshSubset::reset
 
 void Foam::fvMeshSubset::reset(const Foam::zero)
 {
+    // Was old pointMesh present?
+    const auto* basePointMeshPtr =
+            baseMesh_.thisDb().cfindObject<pointMesh>(pointMesh::typeName);
+    if (basePointMeshPtr)
+    {
+        DebugPout<< "fvMeshSubset::reset(const Foam::zero) :"
+                << " Detected pointMesh" << endl;
+    }
+
+
     clear();
 
     // Create zero-sized subMesh
@@ -574,6 +590,46 @@ void Foam::fvMeshSubset::reset(const Foam::zero)
     }
 
 
+    // Clone old additional point patches
+    if (basePointMeshPtr)
+    {
+        DebugPout<< "Subsetting pointMesh" << endl;
+        const auto& basePointMesh = *basePointMeshPtr;
+        const auto& oldPointBoundary = basePointMesh.boundary();
+
+        // 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
+        //    any additional patches
+        const auto& newSubPointMesh = pointMesh::New(newSubMesh);
+
+        auto& newBoundary =
+            const_cast<pointBoundaryMesh&>(newSubPointMesh.boundary());
+
+        // Start off from (poly)patch map
+        pointPatchMap_ = patchMap_;
+
+        // 2. Explicitly add subsetted meshPointPatches
+        for (const auto& oldPointPatch : oldPointBoundary)
+        {
+            const auto* mppPtr = isA<meshPointPatch>(oldPointPatch);
+            if (mppPtr && (newBoundary.findPatchID(mppPtr->name()) == -1))
+            {
+                newBoundary.push_back
+                (
+                    mppPtr->clone
+                    (
+                        newBoundary,
+                        newBoundary.size(),
+                        labelList::null(), // map
+                        labelList::null()  // map
+                    )
+                );
+            }
+        }
+
+        // Extend patchMap with -1
+        pointPatchMap_.setSize(newBoundary.size(), -1);
+    }
+
     // Add the zones
     subsetZones();
 }
@@ -586,6 +642,16 @@ void Foam::fvMeshSubset::reset
     const bool syncPar
 )
 {
+    // Was old pointMesh present?
+    const auto* basePointMeshPtr =
+            baseMesh_.thisDb().cfindObject<pointMesh>(pointMesh::typeName);
+    if (basePointMeshPtr)
+    {
+        DebugPout<< "fvMeshSubset::reset(const bitSet&) :"
+                << " Detected pointMesh" << endl;
+    }
+
+
     // Clear all old maps and pointers
     clear();
 
@@ -1126,6 +1192,8 @@ void Foam::fvMeshSubset::reset
 
     // Inserted patch
 
+    label newInternalPatchID = -1;
+
     if (wantedPatchID == -1)
     {
         label oldInternalSize = boundaryPatchSizes[oldInternalPatchID];
@@ -1159,6 +1227,7 @@ void Foam::fvMeshSubset::reset
             // the internal faces
             patchStart += boundaryPatchSizes[oldInternalPatchID];
             patchMap_[nNewPatches] = -1;
+            newInternalPatchID = nNewPatches;
             ++nNewPatches;
         }
     }
@@ -1233,6 +1302,98 @@ void Foam::fvMeshSubset::reset
 
     // Subset and add any zones
     subsetZones();
+
+
+    if (basePointMeshPtr)
+    {
+        DebugPout<< "Subsetting pointMesh" << endl;
+        const auto& basePointMesh = *basePointMeshPtr;
+        const auto& oldPointBoundary = basePointMesh.boundary();
+
+        // 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
+        //    any additional patches
+        const auto& newSubPointMesh = pointMesh::New(subMeshPtr_());
+
+        pointPatchMap_ = patchMap_;
+
+        auto& newBoundary =
+            const_cast<pointBoundaryMesh&>(newSubPointMesh.boundary());
+
+
+        // 2. Explicitly add subsetted meshPointPatches
+        labelList oldToNewPoints(baseMesh_.nPoints(), -1);
+        forAll(pointMap_, i)
+        {
+            oldToNewPoints[pointMap_[i]] = i;
+        }
+
+
+        // Add meshPointPatches
+        pointPatchMap_.setSize(newBoundary.size(), -1);
+
+        for (const auto& oldPointPatch : oldPointBoundary)
+        {
+            const auto* mppPtr = isA<meshPointPatch>(oldPointPatch);
+            if (mppPtr && (newBoundary.findPatchID(mppPtr->name()) == -1))
+            {
+                const auto& mp = mppPtr->meshPoints();
+                DynamicList<label> subPointMap(mp.size());
+                forAll(mp, i)
+                {
+                    const label newPointi = oldToNewPoints[mp[i]];
+                    if (newPointi != -1)
+                    {
+                        subPointMap.append(i);
+                    }
+                }
+
+                pointPatchMap_.push_back(mppPtr->index());
+
+                newBoundary.push_back
+                (
+                    mppPtr->clone
+                    (
+                        newBoundary,
+                        newBoundary.size(),
+                        subPointMap,        // map
+                        oldToNewPoints
+                    )
+                );
+            }
+        }
+
+
+        // 3. rotate into place:
+        //      - global patches (including meshPointPatches)
+        //      - optional 'internalFaces' patch
+        //      - processor patches
+        labelList oldToNew(newBoundary.size());
+        label newPatchi = 0;
+        forAll(newBoundary, patchi)
+        {
+            if
+            (
+                patchi != newInternalPatchID
+            && !isA<processorPointPatch>(newBoundary[patchi])
+            )
+            {
+                oldToNew[patchi] = newPatchi++;
+            }
+        }
+        if (newInternalPatchID != -1)
+        {
+            oldToNew[newInternalPatchID] = newPatchi++;
+        }
+        forAll(newBoundary, patchi)
+        {
+            if (isA<processorPointPatch>(newBoundary[patchi]))
+            {
+                oldToNew[patchi] = newPatchi++;
+            }
+        }
+        newBoundary.reorder(oldToNew, true);
+        inplaceReorder(oldToNew, pointPatchMap_);
+    }
 }
 
 
diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H
index bedb48e44345d5c8809e14c33459c65e21dd9eb1..d4ce7781a0a7ad2dd2aedad2926ca783996f15b0 100644
--- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H
+++ b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.H
@@ -102,6 +102,9 @@ class fvMeshSubset
         //- Patch mapping array
         labelList patchMap_;
 
+        //- PointPatch mapping array
+        labelList pointPatchMap_;
+
 
     // Private Member Functions
 
@@ -135,6 +138,10 @@ protected:
 
 public:
 
+    // Declare name of the class and its debug switch
+    ClassName("fvMeshSubset");
+
+
     // Static Data Members
 
         //- Name for exposed internal faces (default: oldInternalFaces)
@@ -225,6 +232,10 @@ public:
         //- Return patch map
         inline const labelList& patchMap() const;
 
+        //- Return point-patch map. Usually identical to patchMap except if
+        //- additional patches are added to the pointMesh.
+        inline const labelList& pointPatchMap() const;
+
 
     // Edit
 
diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetI.H b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetI.H
index c1bef91d564a504571a5cc351fa6a3e500cfdd06..b2f47f119c6a49eab63285505e0e66eef936a90c 100644
--- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetI.H
+++ b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetI.H
@@ -104,4 +104,19 @@ inline const Foam::labelList& Foam::fvMeshSubset::patchMap() const
 }
 
 
+inline const Foam::labelList& Foam::fvMeshSubset::pointPatchMap() const
+{
+    checkHasSubMesh();
+
+    if (pointPatchMap_.empty())
+    {
+        return patchMap_;
+    }
+    else
+    {
+        return pointPatchMap_;
+    }
+}
+
+
 // ************************************************************************* //
diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetTemplates.C b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetTemplates.C
index 7936eaeb1a40962874d890a1d06bc02ad0ca9bdc..5d7ce171606ca4b5e8e8bafebcfe80f69a03f4ac 100644
--- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetTemplates.C
+++ b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubsetTemplates.C
@@ -551,7 +551,7 @@ Foam::fvMeshSubset::interpolate
     (
         sf,
         pointMesh::New(subMesh()),     // subsetted point mesh
-        patchMap(),
+        pointPatchMap(),
         pointMap()
     );
 }
diff --git a/src/fvMotionSolver/Make/files b/src/fvMotionSolver/Make/files
index 426e49f6b6c3feb75eedb70739a76026fa4b4dea..83ff9c248d31c304db5e8569cef549db9d049153 100644
--- a/src/fvMotionSolver/Make/files
+++ b/src/fvMotionSolver/Make/files
@@ -38,6 +38,8 @@ $(derivedPoint)/angularOscillatingDisplacement/angularOscillatingDisplacementPoi
 $(derivedPoint)/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.C
 $(derivedPoint)/surfaceDisplacement/surfaceDisplacementPointPatchVectorField.C
 $(derivedPoint)/waveDisplacement/waveDisplacementPointPatchVectorField.C
+$(derivedPoint)/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.C
+$(derivedPoint)/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.C
 
 $(derivedPoint)/timeVaryingMappedFixedValue/timeVaryingMappedFixedValuePointPatchFields.C
 $(derivedPoint)/uniformInterpolatedDisplacement/uniformInterpolatedDisplacementPointPatchVectorField.C
diff --git a/src/fvMotionSolver/fvMotionSolvers/componentDisplacement/componentLaplacian/displacementComponentLaplacianFvMotionSolver.C b/src/fvMotionSolver/fvMotionSolvers/componentDisplacement/componentLaplacian/displacementComponentLaplacianFvMotionSolver.C
index 541cc4882baa91673d2e68db748301940330e339..826d7e4b0b937cac8e910d0a20292fe5b2410226 100644
--- a/src/fvMotionSolver/fvMotionSolvers/componentDisplacement/componentLaplacian/displacementComponentLaplacianFvMotionSolver.C
+++ b/src/fvMotionSolver/fvMotionSolvers/componentDisplacement/componentLaplacian/displacementComponentLaplacianFvMotionSolver.C
@@ -145,6 +145,18 @@ Foam::displacementComponentLaplacianFvMotionSolver::curPoints() const
         pointDisplacement_
     );
 
+    // Evaluate the bcs so they are consistent with the internal field
+    // Might fight the multi-patch behaviour inside volPointInterpolate
+    if
+    (
+        pointDisplacement_.boundaryField().size()
+     != cellDisplacement_.boundaryField().size()
+    )
+    {
+        pointDisplacement_.correctBoundaryConditions();
+    }
+
+
     if (pointLocation_)
     {
         if (debug)
diff --git a/src/fvMotionSolver/fvMotionSolvers/displacement/SBRStress/displacementSBRStressFvMotionSolver.C b/src/fvMotionSolver/fvMotionSolvers/displacement/SBRStress/displacementSBRStressFvMotionSolver.C
index c220b6635c808c85e052c7c461e0485b10d10b3d..9c0cf0d2674897405ed3351ab6113af2a41c5eab 100644
--- a/src/fvMotionSolver/fvMotionSolvers/displacement/SBRStress/displacementSBRStressFvMotionSolver.C
+++ b/src/fvMotionSolver/fvMotionSolvers/displacement/SBRStress/displacementSBRStressFvMotionSolver.C
@@ -160,6 +160,17 @@ Foam::displacementSBRStressFvMotionSolver::curPoints() const
         pointDisplacement_
     );
 
+    // Evaluate the bcs so they are consistent with the internal field
+    // Might fight the multi-patch behaviour inside volPointInterpolate
+    if
+    (
+        pointDisplacement_.boundaryField().size()
+     != cellDisplacement_.boundaryField().size()
+    )
+    {
+        pointDisplacement_.correctBoundaryConditions();
+    }
+
     tmp<pointField> tcurPoints
     (
         points0() + pointDisplacement().primitiveField()
@@ -186,6 +197,10 @@ void Foam::displacementSBRStressFvMotionSolver::solve()
        *diffusivityPtr_->operator()()
     );
 
+    // Make sure the cellMotion bcs are consistent with the pointDisplacement.
+    // This makes sure the grad below uses more up-to-date values.
+    cellDisplacement_.boundaryFieldRef().updateCoeffs();
+
     volTensorField gradCd("gradCd", fvc::grad(cellDisplacement_));
 
     fv::options& fvOptions(fv::options::New(fvMesh_));
diff --git a/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C b/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
index e29a6e486520e1a535267a8e67cd3808b641001a..765c8e2baf1dbfc2fc2660d57fc14f7e9de994bc 100644
--- a/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
+++ b/src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/displacementLaplacianFvMotionSolver.C
@@ -267,6 +267,17 @@ Foam::displacementLaplacianFvMotionSolver::curPoints() const
         pointDisplacement_
     );
 
+    // Evaluate the bcs so they are consistent with the internal field
+    // Might fight the multi-patch behaviour inside volPointInterpolate
+    if
+    (
+        pointDisplacement_.boundaryField().size()
+     != cellDisplacement_.boundaryField().size()
+    )
+    {
+        pointDisplacement_.correctBoundaryConditions();
+    }
+
     if (pointLocation_)
     {
         if (debug)
@@ -333,6 +344,10 @@ void Foam::displacementLaplacianFvMotionSolver::solve()
     diffusivity().correct();
     pointDisplacement_.boundaryFieldRef().updateCoeffs();
 
+    // Make sure the cellMotion bcs are consistent with the pointDisplacement.
+    // This makes sure the grad below uses more up-to-date values.
+    cellDisplacement_.boundaryFieldRef().updateCoeffs();
+
     fv::options& fvOptions(fv::options::New(fvMesh_));
 
     // We explicitly do NOT want to interpolate the motion inbetween
diff --git a/src/fvMotionSolver/fvMotionSolvers/displacement/solidBodyDisplacementLaplacian/solidBodyDisplacementLaplacianFvMotionSolver.C b/src/fvMotionSolver/fvMotionSolvers/displacement/solidBodyDisplacementLaplacian/solidBodyDisplacementLaplacianFvMotionSolver.C
index 79ddc0d9beddc825555178727e8b9d4713a4c75f..453931bff87114f1fead6638bbdca705587355e7 100644
--- a/src/fvMotionSolver/fvMotionSolvers/displacement/solidBodyDisplacementLaplacian/solidBodyDisplacementLaplacianFvMotionSolver.C
+++ b/src/fvMotionSolver/fvMotionSolvers/displacement/solidBodyDisplacementLaplacian/solidBodyDisplacementLaplacianFvMotionSolver.C
@@ -271,6 +271,17 @@ Foam::solidBodyDisplacementLaplacianFvMotionSolver::curPoints() const
         pointDisplacement_
     );
 
+    // Evaluate the bcs so they are consistent with the internal field
+    // Might fight the multi-patch behaviour inside volPointInterpolate
+    if
+    (
+        pointDisplacement_.boundaryField().size()
+     != cellDisplacement_.boundaryField().size()
+    )
+    {
+        pointDisplacement_.correctBoundaryConditions();
+    }
+
     tmp<pointField> tnewPoints
     (
         transformPoints(SBMFPtr_().transformation(), points0())
diff --git a/src/fvMotionSolver/fvMotionSolvers/fvMotionSolver/fvMotionSolverTemplates.C b/src/fvMotionSolver/fvMotionSolvers/fvMotionSolver/fvMotionSolverTemplates.C
index 47825b752590178940d38b06bd25430ae5fe3f71..81d6c996011af7abab71266705254dd10838d7c9 100644
--- a/src/fvMotionSolver/fvMotionSolvers/fvMotionSolver/fvMotionSolverTemplates.C
+++ b/src/fvMotionSolver/fvMotionSolvers/fvMotionSolver/fvMotionSolverTemplates.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2016 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -28,6 +29,7 @@ License
 #include "fvMotionSolver.H"
 #include "fixedValuePointPatchFields.H"
 #include "cellMotionFvPatchFields.H"
+#include "facePointPatch.H"
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
@@ -38,23 +40,33 @@ Foam::wordList Foam::fvMotionSolver::cellMotionBoundaryTypes
     Boundary& pmUbf
 ) const
 {
-    wordList cmUbf = pmUbf.types();
+    wordList cmUbf(fvMesh_.boundary().size());
 
-    // Remove global patches from the end of the list
-    cmUbf.setSize(fvMesh_.boundary().size());
-
-    forAll(cmUbf, patchi)
+    forAll(pmUbf, patchi)
     {
-        if (isA<fixedValuePointPatchField<Type>>(pmUbf[patchi]))
+        const auto& pfld = pmUbf[patchi];
+        const auto* fppPtr = isA<facePointPatch>(pfld.patch());
+        if (fppPtr)
         {
-            cmUbf[patchi] = cellMotionFvPatchField<Type>::typeName;
-        }
+            const auto& fpp = *fppPtr;
+            const label polyPatchi = fpp.patch().index();
 
-        if (debug)
-        {
-            Pout<< "Patch:" << fvMesh_.boundary()[patchi].patch().name()
-                << " pointType:" << pmUbf.types()[patchi]
-                << " cellType:" << cmUbf[patchi] << endl;
+            if (isA<fixedValuePointPatchField<Type>>(pfld))
+            {
+                cmUbf[polyPatchi] = cellMotionFvPatchField<Type>::typeName;
+            }
+            else
+            {
+                // Take over pointPatch type
+                cmUbf[polyPatchi] = pfld.type();
+            }
+
+            if (debug)
+            {
+                Pout<< "Patch:" << fvMesh_.boundary()[patchi].patch().name()
+                    << " pointType:" << pfld.type()
+                    << " cellType:" << cmUbf[patchi] << endl;
+            }
         }
     }
 
diff --git a/src/fvMotionSolver/fvPatchFields/derived/cellMotion/cellMotionFvPatchField.H b/src/fvMotionSolver/fvPatchFields/derived/cellMotion/cellMotionFvPatchField.H
index b175af60ee7452c8b9b876d994765dd976112479..26505e57d8045944c4a086baf12a2ee4c980f4ee 100644
--- a/src/fvMotionSolver/fvPatchFields/derived/cellMotion/cellMotionFvPatchField.H
+++ b/src/fvMotionSolver/fvPatchFields/derived/cellMotion/cellMotionFvPatchField.H
@@ -37,7 +37,6 @@ SourceFiles
 #ifndef cellMotionFvPatchField_H
 #define cellMotionFvPatchField_H
 
-#include "Random.H"
 #include "fixedValueFvPatchFields.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.C b/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.C
new file mode 100644
index 0000000000000000000000000000000000000000..5cc1fa769f535dfaad8205f4bd43396c3ec4b1c6
--- /dev/null
+++ b/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.C
@@ -0,0 +1,398 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "edgeSlipDisplacementPointPatchVectorField.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Time.H"
+#include "transformField.H"
+#include "displacementMotionSolver.H"
+#include "featureEdgeMesh.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::edgeSlipDisplacementPointPatchVectorField::read
+(
+    const objectRegistry& obr,
+    const dictionary& dict
+)
+{
+    const Time& tm = obr.time();
+
+    const fileName featFileName(dict.get<fileName>("file", keyType::LITERAL));
+
+    if (tm.foundObject<edgeMesh>(featFileName))
+    {
+        return;
+    }
+
+    IOobject extFeatObj
+    (
+        featFileName,                       // name
+        tm.constant(),                      // instance
+        "extendedFeatureEdgeMesh",          // local
+        obr,                                // registry
+        IOobject::MUST_READ,
+        IOobject::NO_WRITE,
+        IOobject::REGISTER
+    );
+
+    //const fileName fName(typeFilePath<extendedFeatureEdgeMesh>(extFeatObj));
+    const fileName fName(extFeatObj.typeFilePath<extendedFeatureEdgeMesh>());
+
+    if (!fName.empty() && extendedEdgeMesh::canRead(fName))
+    {
+        Info<< "Reading edgeMesh from " << extFeatObj.objectRelPath() << endl;
+        auto* eMeshPtr = new extendedFeatureEdgeMesh(extFeatObj);
+        eMeshPtr->store();
+    }
+    else
+    {
+        // Try reading as edgeMesh
+
+        IOobject featObj
+        (
+            featFileName,                       // name
+            tm.constant(),                      // instance
+            "triSurface",                       // local
+            obr,                                // registry
+            IOobject::MUST_READ,
+            IOobject::NO_WRITE,
+            IOobject::REGISTER
+        );
+
+        Info<< "Reading edgeMesh from " << featObj.objectRelPath() << endl;
+        const fileName fName(featObj.typeFilePath<featureEdgeMesh>());
+
+        if (fName.empty())
+        {
+            FatalIOErrorInFunction(dict)
+                << "Could not open " << featObj.objectPath()
+                << exit(FatalIOError);
+        }
+
+        // Read as edgeMesh
+        auto* eMeshPtr = new featureEdgeMesh(featObj);
+        eMeshPtr->store();
+    }
+}
+
+
+void Foam::edgeSlipDisplacementPointPatchVectorField::calcProjection
+(
+    vectorField& displacement
+) const
+{
+    const polyMesh& mesh = patch().boundaryMesh().mesh()();
+    const labelList& meshPoints = patch().meshPoints();
+
+    //const scalar deltaT = mesh.time().deltaTValue();
+
+    // Construct large enough vector in direction of projectDir so
+    // we're guaranteed to hit something.
+
+    //- Per point projection vector:
+    const scalar projectLen = mesh.bounds().mag();
+
+
+
+    // Get fixed points (bit of a hack)
+    const pointZone* zonePtr = nullptr;
+
+    if (frozenPointsZone_.size() > 0)
+    {
+        const pointZoneMesh& pZones = mesh.pointZones();
+
+        zonePtr = &pZones[frozenPointsZone_];
+
+        Info<< "edgeSlipDisplacementPointPatchVectorField : Fixing all "
+            << zonePtr->size() << " points in pointZone " << zonePtr->name()
+            << endl;
+    }
+
+    // Get the starting locations from the motionSolver
+    const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
+    (
+        "dynamicMeshDict"
+    ).points0();
+
+
+    pointField start(meshPoints.size());
+    forAll(start, i)
+    {
+        start[i] = points0[meshPoints[i]] + displacement[i];
+    }
+
+    const auto& tree = edgeTree();
+
+    label nNotProjected = 0;
+    forAll(meshPoints, i)
+    {
+        const label meshPointi = meshPoints[i];
+        const point& pt = mesh.points()[meshPointi];
+
+        if (zonePtr && (zonePtr->whichPoint(meshPointi) >= 0))
+        {
+            // Fixed point. Reset to point0 location.
+            displacement[i] = points0[meshPointi] - pt;
+        }
+        else
+        {
+            pointIndexHit nearest = tree.findNearest(start[i], sqr(projectLen));
+            if (nearest.hit())
+            {
+                displacement[i] = nearest.point() - points0[meshPointi];
+            }
+            else
+            {
+                nNotProjected++;
+
+                if (debug)
+                {
+                    Pout<< "    point:" << meshPointi
+                        << " coord:" << pt
+                        << "  did not find any surface within " << projectLen
+                        << endl;
+                }
+            }
+        }
+    }
+
+    reduce(nNotProjected, sumOp<label>());
+
+    if (nNotProjected > 0)
+    {
+        Info<< "edgeSlipDisplacement :"
+            << " on patch " << patch().name()
+            << " did not project " << nNotProjected
+            << " out of " << returnReduce(meshPoints.size(), sumOp<label>())
+            << " points." << endl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::edgeSlipDisplacementPointPatchVectorField::
+edgeSlipDisplacementPointPatchVectorField
+(
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF
+)
+:
+    pointPatchVectorField(p, iF),
+    velocity_(Zero)
+{}
+
+
+Foam::edgeSlipDisplacementPointPatchVectorField::
+edgeSlipDisplacementPointPatchVectorField
+(
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF,
+    const dictionary& dict
+)
+:
+    pointPatchVectorField(p, iF, dict),
+    velocity_(dict.get<vector>("velocity")),
+    featFileName_(dict.get<fileName>("file", keyType::LITERAL)),
+    frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null))
+{
+    read(this->patch().boundaryMesh().mesh().time(), dict);
+}
+
+
+Foam::edgeSlipDisplacementPointPatchVectorField::
+edgeSlipDisplacementPointPatchVectorField
+(
+    const edgeSlipDisplacementPointPatchVectorField& ppf,
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF,
+    const pointPatchFieldMapper&
+)
+:
+    pointPatchVectorField(p, iF),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+Foam::edgeSlipDisplacementPointPatchVectorField::
+edgeSlipDisplacementPointPatchVectorField
+(
+    const edgeSlipDisplacementPointPatchVectorField& ppf
+)
+:
+    pointPatchVectorField(ppf),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+Foam::edgeSlipDisplacementPointPatchVectorField::
+edgeSlipDisplacementPointPatchVectorField
+(
+    const edgeSlipDisplacementPointPatchVectorField& ppf,
+    const DimensionedField<vector, pointMesh>& iF
+)
+:
+    pointPatchVectorField(ppf, iF),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+const Foam::indexedOctree<Foam::treeDataEdge>&
+Foam::edgeSlipDisplacementPointPatchVectorField::edgeTree() const
+{
+    if (!edgeTreePtr_)
+    {
+        const Time& tm = this->patch().boundaryMesh().mesh().time();
+        const auto& eMesh = tm.lookupObject<edgeMesh>(featFileName_);
+
+        const pointField& points = eMesh.points();
+        const edgeList& edges = eMesh.edges();
+
+        // Calculate bb of all points
+        treeBoundBox bb(points);
+
+        // Random number generator. Bit dodgy since not exactly random ;-)
+        Random rndGen(65431);
+
+        // Slightly extended bb. Slightly off-centred just so on symmetric
+        // geometry there are less face/edge aligned items.
+        bb.inflate(rndGen, 1e-4, ROOTVSMALL);
+
+        edgeTreePtr_.reset
+        (
+            new indexedOctree<treeDataEdge>
+            (
+                treeDataEdge(edges, points),  // All edges
+
+                bb,     // overall search domain
+                8,      // maxLevel
+                10,     // leafsize
+                3.0     // duplicity
+            )
+        );
+    }
+
+    return edgeTreePtr_();
+}
+
+
+void Foam::edgeSlipDisplacementPointPatchVectorField::updateCoeffs()
+{
+    if (this->updated())
+    {
+        return;
+    }
+
+    const vectorField currentDisplacement(this->patchInternalField());
+
+    // Calculate displacement to project points onto surface
+    vectorField displacement(currentDisplacement);
+    calcProjection(displacement);
+
+
+    // offset wrt current displacement
+    vectorField offset(displacement-currentDisplacement);
+
+    // Clip offset to maximum displacement possible: velocity*timestep
+
+    const Time& tm = this->patch().boundaryMesh().mesh().time();
+    const scalar deltaT = tm.deltaTValue();
+    const vector clipVelocity = velocity_*deltaT;
+
+    forAll(displacement, i)
+    {
+        vector& d = offset[i];
+
+        const scalar magD(mag(d));
+        if (magD > ROOTVSMALL)
+        {
+            d /= magD;
+            d *= min(magD, mag(clipVelocity));
+        }
+    }
+
+    if (debug)
+    {
+        Pout<< type() << " :"
+            << " on patch " << patch().name()
+            << " of field " << this->internalField().name()
+            << " projection"
+            << " min:" << gMin(displacement)
+            << " max:" << gMaxMagSqr(displacement)
+            << " average:" << gAverage(displacement)
+            << endl;
+    }
+
+    // Get internal field to insert values into
+    Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
+
+    setInInternalField(iF, (currentDisplacement+offset)());
+
+    pointPatchVectorField::updateCoeffs();
+}
+
+
+void Foam::edgeSlipDisplacementPointPatchVectorField::write
+(
+    Ostream& os
+) const
+{
+    pointPatchField<vector>::write(os);
+    os.writeEntry("file", featFileName_);
+    os.writeEntryIfDifferent<word>
+    (
+        "frozenPointsZone",
+        word::null,
+        frozenPointsZone_
+    );
+    os.writeEntry("velocity", velocity_);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+makePointPatchTypeField
+(
+    pointPatchVectorField,
+    edgeSlipDisplacementPointPatchVectorField
+);
+
+} // End namespace Foam
+
+// ************************************************************************* //
diff --git a/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.H b/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.H
new file mode 100644
index 0000000000000000000000000000000000000000..d1a8257e7cf534bb6bf866e4d3a10487ecd1a3a1
--- /dev/null
+++ b/src/fvMotionSolver/pointPatchFields/derived/edgeSlipDisplacement/edgeSlipDisplacementPointPatchVectorField.H
@@ -0,0 +1,198 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::edgeSlipDisplacementPointPatchVectorField
+
+Description
+    Displacement follows an edgeMesh. Use in a displacementMotionSolver
+    as a bc on the pointDisplacement field.
+
+    Needs:
+    - file : name of edgeMesh. Either:
+        - .extendedFeatureEdgeMesh (read from  constant/extendedFeatureEdgeMesh)
+        - or .eMesh in or a known format (read from constant/triSurface)
+    - frozenPointsZone : empty or name of pointZone containing points
+                         that do not move
+    - velocity : maximum displacement velocity
+
+
+SourceFiles
+    edgeSlipDisplacementPointPatchVectorField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef edgeSlipDisplacementPointPatchVectorField_H
+#define edgeSlipDisplacementPointPatchVectorField_H
+
+#include "pointPatchFields.H"
+#include "extendedFeatureEdgeMesh.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+          Class edgeSlipDisplacementPointPatchVectorField Declaration
+\*---------------------------------------------------------------------------*/
+
+class edgeSlipDisplacementPointPatchVectorField
+:
+    public pointPatchVectorField
+{
+private:
+
+    // Private data
+
+        //- Maximum velocity
+        const vector velocity_;
+
+        //- file
+        const fileName featFileName_;
+
+        //- pointZone with frozen points
+        const word frozenPointsZone_;
+
+        //- Edge searching
+        mutable autoPtr<indexedOctree<treeDataEdge>> edgeTreePtr_;
+
+
+    // Private Member Functions
+
+        //- Calculate displacement (w.r.t. points0()) to project onto surface
+        void calcProjection(vectorField& displacement) const;
+
+        //- No copy assignment
+        void operator=
+        (
+            const edgeSlipDisplacementPointPatchVectorField&
+        ) = delete;
+
+
+protected:
+
+        const indexedOctree<treeDataEdge>& edgeTree() const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("edgeSlipDisplacement");
+
+
+    // Constructors
+
+        //- Construct from patch and internal field
+        edgeSlipDisplacementPointPatchVectorField
+        (
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        edgeSlipDisplacementPointPatchVectorField
+        (
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given patch field onto a new patch
+        edgeSlipDisplacementPointPatchVectorField
+        (
+            const edgeSlipDisplacementPointPatchVectorField&,
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&,
+            const pointPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        edgeSlipDisplacementPointPatchVectorField
+        (
+            const edgeSlipDisplacementPointPatchVectorField&
+        );
+
+        //- Construct and return a clone
+        virtual autoPtr<pointPatchVectorField> clone() const
+        {
+            return autoPtr<pointPatchVectorField>
+            (
+                new edgeSlipDisplacementPointPatchVectorField
+                (
+                    *this
+                )
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        edgeSlipDisplacementPointPatchVectorField
+        (
+            const edgeSlipDisplacementPointPatchVectorField&,
+            const DimensionedField<vector, pointMesh>&
+        );
+
+        //- Construct and return a clone setting internal field reference
+        virtual autoPtr<pointPatchVectorField> clone
+        (
+            const DimensionedField<vector, pointMesh>& iF
+        ) const
+        {
+            return autoPtr<pointPatchVectorField>
+            (
+                new edgeSlipDisplacementPointPatchVectorField
+                (
+                    *this,
+                    iF
+                )
+            );
+        }
+
+    // Member Functions
+
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
+
+        //- Read (& store) geometry. Exposed so point attraction can reuse it.
+        static void read
+        (
+            const objectRegistry& obr,
+            const dictionary& dict
+        );
+
+        //- Write
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.C b/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.C
new file mode 100644
index 0000000000000000000000000000000000000000..835b1c14859e71bf66e8c00b6d628f296399db81
--- /dev/null
+++ b/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.C
@@ -0,0 +1,324 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pointAttractionDisplacementPointPatchVectorField.H"
+#include "addToRunTimeSelectionTable.H"
+#include "Time.H"
+#include "transformField.H"
+#include "displacementMotionSolver.H"
+#include "featureEdgeMesh.H"
+#include "edgeSlipDisplacementPointPatchVectorField.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::pointAttractionDisplacementPointPatchVectorField::calcProjection
+(
+    vectorField& displacement
+) const
+{
+    const polyMesh& mesh = patch().boundaryMesh().mesh()();
+    const labelList& meshPoints = patch().meshPoints();
+
+    //const scalar deltaT = mesh.time().deltaTValue();
+
+    // Construct large enough vector in direction of projectDir so
+    // we're guaranteed to hit something.
+
+    //- Per point projection vector:
+    const scalar projectLen = mesh.bounds().mag();
+
+
+
+    // Get fixed points (bit of a hack)
+    const pointZone* zonePtr = nullptr;
+
+    if (frozenPointsZone_.size() > 0)
+    {
+        const pointZoneMesh& pZones = mesh.pointZones();
+
+        zonePtr = &pZones[frozenPointsZone_];
+
+        Pout<< "pointAttractionDisplacementPointPatchVectorField : Fixing all "
+            << zonePtr->size() << " points in pointZone " << zonePtr->name()
+            << endl;
+    }
+
+    // Get the starting locations from the motionSolver
+    const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
+    (
+        "dynamicMeshDict"
+    ).points0();
+
+
+    pointField start(meshPoints.size());
+    forAll(start, i)
+    {
+        start[i] = points0[meshPoints[i]] + displacement[i];
+    }
+
+    const auto& tree = pointTree();
+
+    label nNotProjected = 0;
+    forAll(meshPoints, i)
+    {
+        const label meshPointi = meshPoints[i];
+        const point& pt = mesh.points()[meshPointi];
+
+        if (zonePtr && (zonePtr->whichPoint(meshPointi) >= 0))
+        {
+            // Fixed point. Reset to point0 location.
+            displacement[i] = points0[meshPointi] - pt;
+        }
+        else
+        {
+            pointIndexHit nearest = tree.findNearest(start[i], sqr(projectLen));
+            if (nearest.hit())
+            {
+                displacement[i] = nearest.point() - points0[meshPointi];
+            }
+            else
+            {
+                nNotProjected++;
+
+                if (debug)
+                {
+                    Pout<< "    point:" << meshPointi
+                        << " coord:" << pt
+                        << "  did not find any surface within " << projectLen
+                        << endl;
+                }
+            }
+        }
+    }
+
+    reduce(nNotProjected, sumOp<label>());
+
+    if (nNotProjected > 0)
+    {
+        Info<< "pointAttractionDisplacement :"
+            << " on patch " << patch().name()
+            << " did not project " << nNotProjected
+            << " out of " << returnReduce(meshPoints.size(), sumOp<label>())
+            << " points." << endl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pointAttractionDisplacementPointPatchVectorField::
+pointAttractionDisplacementPointPatchVectorField
+(
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF
+)
+:
+    pointPatchVectorField(p, iF),
+    velocity_(Zero)
+{}
+
+
+Foam::pointAttractionDisplacementPointPatchVectorField::
+pointAttractionDisplacementPointPatchVectorField
+(
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF,
+    const dictionary& dict
+)
+:
+    pointPatchVectorField(p, iF, dict),
+    velocity_(dict.get<vector>("velocity")),
+    featFileName_(dict.get<fileName>("file", keyType::LITERAL)),
+    frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null))
+{
+    // Read&store edge mesh on registry
+    edgeSlipDisplacementPointPatchVectorField::read
+    (
+        this->patch().boundaryMesh().mesh().time(),
+        dict
+    );
+}
+
+
+Foam::pointAttractionDisplacementPointPatchVectorField::
+pointAttractionDisplacementPointPatchVectorField
+(
+    const pointAttractionDisplacementPointPatchVectorField& ppf,
+    const pointPatch& p,
+    const DimensionedField<vector, pointMesh>& iF,
+    const pointPatchFieldMapper&
+)
+:
+    pointPatchVectorField(p, iF),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+Foam::pointAttractionDisplacementPointPatchVectorField::
+pointAttractionDisplacementPointPatchVectorField
+(
+    const pointAttractionDisplacementPointPatchVectorField& ppf
+)
+:
+    pointPatchVectorField(ppf),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+Foam::pointAttractionDisplacementPointPatchVectorField::
+pointAttractionDisplacementPointPatchVectorField
+(
+    const pointAttractionDisplacementPointPatchVectorField& ppf,
+    const DimensionedField<vector, pointMesh>& iF
+)
+:
+    pointPatchVectorField(ppf, iF),
+    velocity_(ppf.velocity_),
+    featFileName_(ppf.featFileName_),
+    frozenPointsZone_(ppf.frozenPointsZone_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+const Foam::indexedOctree<Foam::treeDataPoint>&
+Foam::pointAttractionDisplacementPointPatchVectorField::pointTree() const
+{
+    if (!pointTreePtr_)
+    {
+        const Time& tm = this->patch().boundaryMesh().mesh().time();
+        const auto& eMesh = tm.lookupObject<edgeMesh>(featFileName_);
+
+        const pointField& points = eMesh.points();
+
+        // Calculate bb of all points
+        treeBoundBox bb(points);
+
+        // Random number generator. Bit dodgy since not exactly random ;-)
+        Random rndGen(65431);
+
+        // Slightly extended bb. Slightly off-centred just so on symmetric
+        // geometry there are less face/edge aligned items.
+        bb.inflate(rndGen, 1e-4, ROOTVSMALL);
+
+        pointTreePtr_.reset
+        (
+            new indexedOctree<treeDataPoint>
+            (
+                treeDataPoint(points),  // All edges
+
+                bb,     // overall search domain
+                8,      // maxLevel
+                10,     // leafsize
+                3.0     // duplicity
+            )
+        );
+    }
+
+    return pointTreePtr_();
+}
+
+
+void Foam::pointAttractionDisplacementPointPatchVectorField::updateCoeffs()
+{
+    if (this->updated())
+    {
+        return;
+    }
+
+    const vectorField currentDisplacement(this->patchInternalField());
+
+    // Calculate displacement to project points onto surface
+    vectorField displacement(currentDisplacement);
+    calcProjection(displacement);
+
+
+    // offset wrt current displacement
+    vectorField offset(displacement-currentDisplacement);
+
+    // Clip offset to maximum displacement possible: velocity*timestep
+
+    const Time& tm = this->patch().boundaryMesh().mesh().time();
+    const scalar deltaT = tm.deltaTValue();
+    const vector clipVelocity = velocity_*deltaT;
+
+    forAll(displacement, i)
+    {
+        vector& d = offset[i];
+
+        const scalar magD(mag(d));
+        if (magD > ROOTVSMALL)
+        {
+            d /= magD;
+            d *= min(magD, mag(clipVelocity));
+        }
+    }
+
+    // Get internal field to insert values into
+    Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
+
+    setInInternalField(iF, (currentDisplacement+offset)());
+
+    pointPatchVectorField::updateCoeffs();
+}
+
+
+void Foam::pointAttractionDisplacementPointPatchVectorField::write
+(
+    Ostream& os
+) const
+{
+    pointPatchField<vector>::write(os);
+    os.writeEntry("file", featFileName_);
+    os.writeEntryIfDifferent<word>
+    (
+        "frozenPointsZone",
+        word::null,
+        frozenPointsZone_
+    );
+    os.writeEntry("velocity", velocity_);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+makePointPatchTypeField
+(
+    pointPatchVectorField,
+    pointAttractionDisplacementPointPatchVectorField
+);
+
+} // End namespace Foam
+
+// ************************************************************************* //
diff --git a/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.H b/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.H
new file mode 100644
index 0000000000000000000000000000000000000000..cf87d9eb884f29efb450b1e63c1de0ca0b9b6360
--- /dev/null
+++ b/src/fvMotionSolver/pointPatchFields/derived/pointAttractionDisplacement/pointAttractionDisplacementPointPatchVectorField.H
@@ -0,0 +1,191 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::pointAttractionDisplacementPointPatchVectorField
+
+Description
+    Displacement by attraction to nearest point. Use in a
+    displacementMotionSolver as a bc on the pointDisplacement field.
+
+    Needs:
+    - file : name of edgeMesh. Either:
+        - .extendedFeatureEdgeMesh (read from  constant/extendedFeatureEdgeMesh)
+        - or .eMesh in or a known format (read from constant/triSurface)
+    - frozenPointsZone : empty or name of pointZone containing points
+                         that do not move
+    - velocity : maximum displacement velocity
+
+
+SourceFiles
+    pointAttractionDisplacementPointPatchVectorField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pointAttractionDisplacementPointPatchVectorField_H
+#define pointAttractionDisplacementPointPatchVectorField_H
+
+#include "pointPatchFields.H"
+#include "extendedFeatureEdgeMesh.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+      Class pointAttractionDisplacementPointPatchVectorField Declaration
+\*---------------------------------------------------------------------------*/
+
+class pointAttractionDisplacementPointPatchVectorField
+:
+    public pointPatchVectorField
+{
+private:
+
+    // Private data
+
+        //- Maximum velocity
+        const vector velocity_;
+
+        //- file
+        const fileName featFileName_;
+
+        //- pointZone with frozen points
+        const word frozenPointsZone_;
+
+        //- Point searching
+        mutable autoPtr<indexedOctree<treeDataPoint>> pointTreePtr_;
+
+
+    // Private Member Functions
+
+        //- Calculate displacement (w.r.t. points0()) to project onto surface
+        void calcProjection(vectorField& displacement) const;
+
+        //- No copy assignment
+        void operator=
+        (
+            const pointAttractionDisplacementPointPatchVectorField&
+        ) = delete;
+
+
+protected:
+
+        const indexedOctree<treeDataPoint>& pointTree() const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("pointAttraction");
+
+
+    // Constructors
+
+        //- Construct from patch and internal field
+        pointAttractionDisplacementPointPatchVectorField
+        (
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        pointAttractionDisplacementPointPatchVectorField
+        (
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given patch field onto a new patch
+        pointAttractionDisplacementPointPatchVectorField
+        (
+            const pointAttractionDisplacementPointPatchVectorField&,
+            const pointPatch&,
+            const DimensionedField<vector, pointMesh>&,
+            const pointPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        pointAttractionDisplacementPointPatchVectorField
+        (
+            const pointAttractionDisplacementPointPatchVectorField&
+        );
+
+        //- Construct and return a clone
+        virtual autoPtr<pointPatchVectorField> clone() const
+        {
+            return autoPtr<pointPatchVectorField>
+            (
+                new pointAttractionDisplacementPointPatchVectorField
+                (
+                    *this
+                )
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        pointAttractionDisplacementPointPatchVectorField
+        (
+            const pointAttractionDisplacementPointPatchVectorField&,
+            const DimensionedField<vector, pointMesh>&
+        );
+
+        //- Construct and return a clone setting internal field reference
+        virtual autoPtr<pointPatchVectorField> clone
+        (
+            const DimensionedField<vector, pointMesh>& iF
+        ) const
+        {
+            return autoPtr<pointPatchVectorField>
+            (
+                new pointAttractionDisplacementPointPatchVectorField
+                (
+                    *this,
+                    iF
+                )
+            );
+        }
+
+    // Member Functions
+
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
+
+        //- Write
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fvMotionSolver/pointPatchFields/derived/surfaceDisplacement/surfaceDisplacementPointPatchVectorField.C b/src/fvMotionSolver/pointPatchFields/derived/surfaceDisplacement/surfaceDisplacementPointPatchVectorField.C
index 92c499d62498f5b9cc176fc512a641cd452d16fa..2595f2053e5d38f900b39bd7e834c6df4e48cbfe 100644
--- a/src/fvMotionSolver/pointPatchFields/derived/surfaceDisplacement/surfaceDisplacementPointPatchVectorField.C
+++ b/src/fvMotionSolver/pointPatchFields/derived/surfaceDisplacement/surfaceDisplacementPointPatchVectorField.C
@@ -55,7 +55,6 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
 ) const
 {
     const polyMesh& mesh = patch().boundaryMesh().mesh()();
-    const pointField& localPoints = patch().localPoints();
     const labelList& meshPoints = patch().meshPoints();
 
     //const scalar deltaT = mesh.time().deltaTValue();
@@ -117,16 +116,19 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
 
         forAll(nearest, i)
         {
-            if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
+            const label meshPointi = meshPoints[i];
+            const point& pt = mesh.points()[meshPointi];
+
+            if (zonePtr && (zonePtr->whichPoint(meshPointi) >= 0))
             {
                 // Fixed point. Reset to point0 location.
-                displacement[i] = points0[meshPoints[i]] - localPoints[i];
+                displacement[i] = points0[meshPointi] - pt;
             }
             else if (nearest[i].hit())
             {
                 displacement[i] =
                     nearest[i].point()
-                  - points0[meshPoints[i]];
+                  - points0[meshPointi];
             }
             else
             {
@@ -134,8 +136,8 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
 
                 if (debug)
                 {
-                    Pout<< "    point:" << meshPoints[i]
-                        << " coord:" << localPoints[i]
+                    Pout<< "    point:" << meshPointi
+                        << " coord:" << pt
                         << "  did not find any surface within " << projectLen
                         << endl;
                 }
@@ -207,17 +209,20 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
         // 3. Choose either -fixed, nearest, right, left.
         forAll(displacement, i)
         {
-            if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
+            const label meshPointi = meshPoints[i];
+            const point& pt = mesh.points()[meshPointi];
+
+            if (zonePtr && (zonePtr->whichPoint(meshPointi) >= 0))
             {
                 // Fixed point. Reset to point0 location.
-                displacement[i] = points0[meshPoints[i]] - localPoints[i];
+                displacement[i] = points0[meshPointi] - pt;
             }
             else if (nearest[i].hit())
             {
                 // Found nearest.
                 displacement[i] =
                     nearest[i].point()
-                  - points0[meshPoints[i]];
+                  - points0[meshPointi];
             }
             else
             {
@@ -257,7 +262,7 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
                     {
                         interPt.point()[wedgePlane_] += offset[i];
                     }
-                    displacement[i] = interPt.point() - points0[meshPoints[i]];
+                    displacement[i] = interPt.point() - points0[meshPointi];
                 }
                 else
                 {
@@ -265,8 +270,8 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
 
                     if (debug)
                     {
-                        Pout<< "    point:" << meshPoints[i]
-                            << " coord:" << localPoints[i]
+                        Pout<< "    point:" << meshPointi
+                            << " coord:" << pt
                             << "  did not find any intersection between"
                             << " ray from " << start[i]-projectVecs[i]
                             << " to " << start[i]+projectVecs[i] << endl;
@@ -283,7 +288,7 @@ void Foam::surfaceDisplacementPointPatchVectorField::calcProjection
         Info<< "surfaceDisplacement :"
             << " on patch " << patch().name()
             << " did not project " << nNotProjected
-            << " out of " << returnReduce(localPoints.size(), sumOp<label>())
+            << " out of " << returnReduce(meshPoints.size(), sumOp<label>())
             << " points." << endl;
     }
 }
@@ -318,7 +323,12 @@ surfaceDisplacementPointPatchVectorField
     velocity_(dict.get<vector>("velocity")),
     surfacesDict_(dict.subDict("geometry")),
     projectMode_(projectModeNames_.get("projectMode", dict)),
-    projectDir_(dict.get<vector>("projectDirection")),
+    projectDir_
+    (
+        (projectMode_ == FIXEDNORMAL)
+      ? dict.get<vector>("projectDirection")
+      : Zero
+    ),
     wedgePlane_(dict.getOrDefault("wedgePlane", -1)),
     frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null))
 {
@@ -424,12 +434,13 @@ void Foam::surfaceDisplacementPointPatchVectorField::updateCoeffs()
 
     const polyMesh& mesh = patch().boundaryMesh().mesh()();
 
-    vectorField currentDisplacement(this->patchInternalField());
+    const vectorField currentDisplacement(this->patchInternalField());
 
     // Calculate intersections with surface w.r.t points0.
     vectorField displacement(currentDisplacement);
     calcProjection(displacement);
 
+
     // offset wrt current displacement
     vectorField offset(displacement-currentDisplacement);
 
@@ -442,21 +453,15 @@ void Foam::surfaceDisplacementPointPatchVectorField::updateCoeffs()
     {
         vector& d = offset[i];
 
-        for (direction cmpt = 0; cmpt < vector::nComponents; cmpt++)
+        const scalar magD(mag(d));
+        if (magD > ROOTVSMALL)
         {
-            if (d[cmpt] < 0)
-            {
-                d[cmpt] = max(d[cmpt], -clipVelocity[cmpt]);
-            }
-            else
-            {
-                d[cmpt] = min(d[cmpt], clipVelocity[cmpt]);
-            }
+            d /= magD;
+            d *= min(magD, mag(clipVelocity));
         }
     }
 
     this->operator==(currentDisplacement+offset);
-
     fixedValuePointPatchVectorField::updateCoeffs();
 }
 
@@ -467,9 +472,13 @@ void Foam::surfaceDisplacementPointPatchVectorField::write(Ostream& os) const
     os.writeEntry("velocity", velocity_);
     os.writeEntry("geometry", surfacesDict_);
     os.writeEntry("projectMode", projectModeNames_[projectMode_]);
-    os.writeEntry("projectDirection", projectDir_);
-    os.writeEntry("wedgePlane", wedgePlane_);
-
+    os.writeEntryIfDifferent<vector>
+    (
+        "projectDirection",
+        Zero,
+        projectDir_
+    );
+    os.writeEntryIfDifferent<label>("wedgePlane", -1, wedgePlane_);
     os.writeEntryIfDifferent<word>
     (
         "frozenPointsZone",
diff --git a/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.C b/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.C
index 8d6b096d59d016cb5ee28d84313fa64d140f039b..14f9b9f875e6b27a05aaaf9098460309beb46bf0 100644
--- a/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.C
+++ b/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2020-2022 OpenCFD Ltd.
+    Copyright (C) 2020-2022,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -32,6 +32,7 @@ License
 #include "transformField.H"
 #include "fvMesh.H"
 #include "displacementMotionSolver.H"
+#include "facePointPatch.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -272,6 +273,16 @@ void Foam::surfaceSlipDisplacementPointPatchVectorField::calcProjection
         }
     }
 
+    if (scalePtr_)
+    {
+        const scalarField s
+        (
+            scalePtr_->value(this->db().time().timeOutputValue())
+        );
+
+        displacement *= s;
+    }
+
     reduce(nNotProjected, sumOp<label>());
 
     if (nNotProjected > 0)
@@ -312,9 +323,24 @@ surfaceSlipDisplacementPointPatchVectorField
     pointPatchVectorField(p, iF, dict),
     surfacesDict_(dict.subDict("geometry")),
     projectMode_(projectModeNames_.get("projectMode", dict)),
-    projectDir_(dict.get<vector>("projectDirection")),
+    projectDir_
+    (
+        (projectMode_ == FIXEDNORMAL)
+      ? dict.get<vector>("projectDirection")
+      : Zero
+    ),
     wedgePlane_(dict.getOrDefault("wedgePlane", -1)),
-    frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null))
+    frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null)),
+    scalePtr_
+    (
+        PatchFunction1<scalar>::NewIfPresent
+        (
+            refCast<const facePointPatch>(p).patch(),
+            "scale",
+            dict,
+            false           // point values
+        )
+    )
 {}
 
 
@@ -332,7 +358,8 @@ surfaceSlipDisplacementPointPatchVectorField
     projectMode_(ppf.projectMode_),
     projectDir_(ppf.projectDir_),
     wedgePlane_(ppf.wedgePlane_),
-    frozenPointsZone_(ppf.frozenPointsZone_)
+    frozenPointsZone_(ppf.frozenPointsZone_),
+    scalePtr_(ppf.scalePtr_.clone(refCast<const facePointPatch>(p).patch()))
 {}
 
 
@@ -347,7 +374,14 @@ surfaceSlipDisplacementPointPatchVectorField
     projectMode_(ppf.projectMode_),
     projectDir_(ppf.projectDir_),
     wedgePlane_(ppf.wedgePlane_),
-    frozenPointsZone_(ppf.frozenPointsZone_)
+    frozenPointsZone_(ppf.frozenPointsZone_),
+    scalePtr_
+    (
+        ppf.scalePtr_.clone
+        (
+            refCast<const facePointPatch>(ppf.patch()).patch()
+        )
+    )
 {}
 
 
@@ -363,7 +397,14 @@ surfaceSlipDisplacementPointPatchVectorField
     projectMode_(ppf.projectMode_),
     projectDir_(ppf.projectDir_),
     wedgePlane_(ppf.wedgePlane_),
-    frozenPointsZone_(ppf.frozenPointsZone_)
+    frozenPointsZone_(ppf.frozenPointsZone_),
+    scalePtr_
+    (
+        ppf.scalePtr_.clone
+        (
+            refCast<const facePointPatch>(ppf.patch()).patch()
+        )
+    )
 {}
 
 
@@ -397,23 +438,37 @@ Foam::surfaceSlipDisplacementPointPatchVectorField::surfaces() const
 }
 
 
-void Foam::surfaceSlipDisplacementPointPatchVectorField::evaluate
-(
-    const Pstream::commsTypes commsType
-)
+void Foam::surfaceSlipDisplacementPointPatchVectorField::updateCoeffs()
 {
+    if (this->updated())
+    {
+        return;
+    }
+
     vectorField displacement(this->patchInternalField());
 
     // Calculate displacement to project points onto surface
     calcProjection(displacement);
 
+    if (debug)
+    {
+        Pout<< type() << " :"
+            << " on patch " << patch().name()
+            << " of field " << this->internalField().name()
+            << " projection"
+            << " min:" << gMin(displacement)
+            << " max:" << gMaxMagSqr(displacement)
+            << " average:" << gAverage(displacement)
+            << endl;
+    }
+
     // Get internal field to insert values into
     Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
 
     //setInInternalField(iF, motionU);
     setInInternalField(iF, displacement);
 
-    pointPatchVectorField::evaluate(commsType);
+    pointPatchVectorField::updateCoeffs();
 }
 
 
@@ -425,15 +480,24 @@ void Foam::surfaceSlipDisplacementPointPatchVectorField::write
     pointPatchField<vector>::write(os);
     os.writeEntry("geometry", surfacesDict_);
     os.writeEntry("projectMode", projectModeNames_[projectMode_]);
-    os.writeEntry("projectDirection", projectDir_);
-    os.writeEntry("wedgePlane", wedgePlane_);
-
+    os.writeEntryIfDifferent<vector>
+    (
+        "projectDirection",
+        Zero,
+        projectDir_
+    );
+    os.writeEntryIfDifferent<label>("wedgePlane", -1, wedgePlane_);
     os.writeEntryIfDifferent<word>
     (
         "frozenPointsZone",
         word::null,
         frozenPointsZone_
     );
+
+    if (scalePtr_)
+    {
+        scalePtr_->writeData(os);
+    }
 }
 
 
diff --git a/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.H b/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.H
index a65d3d791079041503ed5626a7b7dc445c69bf3e..809c6c1c389c6efb59e2d9e17cf11e9aa2099ef4 100644
--- a/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.H
+++ b/src/fvMotionSolver/pointPatchFields/derived/surfaceSlipDisplacement/surfaceSlipDisplacementPointPatchVectorField.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
+    Copyright (C) 2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -46,6 +47,8 @@ Description
     - wedgePlane : -1 or component to knock out of intersection normal
     - frozenPointsZone : empty or name of pointZone containing points
                          that do not move
+    - scale : optional scaling factor as PatchFunction1
+
 
 SourceFiles
     surfaceSlipDisplacementPointPatchVectorField.C
@@ -57,6 +60,7 @@ SourceFiles
 
 #include "pointPatchFields.H"
 #include "searchableSurfaces.H"
+#include "PatchFunction1.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -105,6 +109,9 @@ private:
         //- pointZone with frozen points
         const word frozenPointsZone_;
 
+        //- Scalar scale factor
+        autoPtr<PatchFunction1<scalar>> scalePtr_;
+
         //- Demand driven: surface to project
         mutable autoPtr<searchableSurfaces> surfacesPtr_;
 
@@ -187,11 +194,8 @@ public:
         //- Surface to follow. Demand loads surfaceNames.
         const searchableSurfaces& surfaces() const;
 
-        //- Update the patch field
-        virtual void evaluate
-        (
-            const Pstream::commsTypes commsType=Pstream::commsTypes::buffered
-        );
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
 
         //- Write
         virtual void write(Ostream&) const;
diff --git a/src/mesh/snappyHexMesh/Make/files b/src/mesh/snappyHexMesh/Make/files
index 28be73f7c19a1518a16812b2bef320e72e9bcffe..50a44505e83dcf427bc01192f08e745cc0439f79 100644
--- a/src/mesh/snappyHexMesh/Make/files
+++ b/src/mesh/snappyHexMesh/Make/files
@@ -2,6 +2,7 @@ snappyHexMeshDriver/snappyLayerDriver.C
 snappyHexMeshDriver/snappyLayerDriverSinglePass.C
 snappyHexMeshDriver/snappySnapDriver.C
 snappyHexMeshDriver/snappySnapDriverFeature.C
+snappyHexMeshDriver/snappySnapDriverBufferLayers.C
 snappyHexMeshDriver/snappyRefineDriver.C
 snappyHexMeshDriver/snappyVoxelMeshDriver.C
 
diff --git a/src/mesh/snappyHexMesh/externalDisplacementMeshMover/medialAxisMeshMover.C b/src/mesh/snappyHexMesh/externalDisplacementMeshMover/medialAxisMeshMover.C
index 7db914643c1cf8bcf945a0e223fe7f0d25bbcafb..295013ecba66b10efd07182f41cf5dbbd4961be0 100644
--- a/src/mesh/snappyHexMesh/externalDisplacementMeshMover/medialAxisMeshMover.C
+++ b/src/mesh/snappyHexMesh/externalDisplacementMeshMover/medialAxisMeshMover.C
@@ -1692,6 +1692,22 @@ void Foam::medialAxisMeshMover::calculateDisplacement
             displacement
         );
     }
+
+    if (str)
+    {
+        Info<< typeName
+            << " : Written " << returnReduce(str().nVertices(), sumOp<label>())
+            << " points with too large an extrusion distance to "
+            << str().name() << endl;
+    }
+    if (medialVecStr)
+    {
+        Info<< typeName
+            << " : Written "
+            << returnReduce(medialVecStr().nVertices(), sumOp<label>())
+            << " medial axis vectors on points with too large"
+            << " an extrusion distance to " << medialVecStr().name() << endl;
+    }
 }
 
 
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
index 6838f904db6bb303cd657cfe55929dd66ce033ab..758f69f794222ef1574af0387612f1636244650b 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C
@@ -75,6 +75,18 @@ namespace Foam
 }
 
 
+const Foam::Enum
+<
+    Foam::meshRefinement::MeshType
+>
+Foam::meshRefinement::MeshTypeNames
+({
+    { MeshType::CASTELLATED, "castellated" },
+    { MeshType::CASTELLATEDBUFFERLAYER, "castellatedBufferLayer" },
+    { MeshType::CASTELLATEDBUFFERLAYER2, "castellatedBufferLayer2" }
+});
+
+
 const Foam::Enum
 <
     Foam::meshRefinement::debugType
@@ -1178,56 +1190,90 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells
 }
 
 
+void Foam::meshRefinement::splitFace
+(
+    const face& f,
+    const labelPair& split,
+
+    face& f0,
+    face& f1
+)
+{
+    if (split.find(-1) != -1)
+    {
+        FatalErrorInFunction<< "Illegal split " << split
+            << " on face " << f << exit(FatalError);
+    }
+
+    label nVerts = split[1]-split[0];
+    if (nVerts < 0)
+    {
+        nVerts += f.size();
+    }
+    nVerts += 1;
+
+
+    // Split into f0, f1
+    f0.resize_nocopy(nVerts);
+
+    label fp = split[0];
+    forAll(f0, i)
+    {
+        f0[i] = f[fp];
+        fp = f.fcIndex(fp);
+    }
+
+    f1.resize_nocopy(f.size()-f0.size()+2);
+    fp = split[1];
+    forAll(f1, i)
+    {
+        f1[i] = f[fp];
+        fp = f.fcIndex(fp);
+    }
+}
+
+
 void Foam::meshRefinement::doSplitFaces
 (
     const labelList& splitFaces,
     const labelPairList& splits,
+    const labelPairList& splitPatches,
     //const List<Pair<point>>& splitPoints,
     polyTopoChange& meshMod
 ) const
 {
+    face f0, f1;
+
     forAll(splitFaces, i)
     {
-        label facei = splitFaces[i];
+        const label facei = splitFaces[i];
+        const auto& split = splits[i];
+        const auto& twoPatches = splitPatches[i];
+
         const face& f = mesh_.faces()[facei];
 
         // Split as start and end index in face
-        const labelPair& split = splits[i];
-
-        label nVerts = split[1]-split[0];
-        if (nVerts < 0)
-        {
-            nVerts += f.size();
-        }
-        nVerts += 1;
-
-
-        // Split into f0, f1
-        face f0(nVerts);
-
-        label fp = split[0];
-        forAll(f0, i)
-        {
-            f0[i] = f[fp];
-            fp = f.fcIndex(fp);
-        }
-
-        face f1(f.size()-f0.size()+2);
-        fp = split[1];
-        forAll(f1, i)
-        {
-            f1[i] = f[fp];
-            fp = f.fcIndex(fp);
-        }
-
+        splitFace(f, split, f0, f1);
 
         // Determine face properties
         label own = mesh_.faceOwner()[facei];
         label nei = -1;
-        label patchi = -1;
+        label patch0 = -1;
+        label patch1 = -1;
         if (facei >= mesh_.nInternalFaces())
         {
-            patchi = mesh_.boundaryMesh().whichPatch(facei);
+            patch0 =
+            (
+                twoPatches[0] != -1
+              ? twoPatches[0]
+              : mesh_.boundaryMesh().whichPatch(facei)
+            );
+            patch1 =
+            (
+                twoPatches[1] != -1
+              ? twoPatches[1]
+              : mesh_.boundaryMesh().whichPatch(facei)
+            );
         }
         else
         {
@@ -1258,7 +1304,7 @@ void Foam::meshRefinement::doSplitFaces
             own,                        // owner
             nei,                        // neighbour
             false,                      // face flip
-            patchi,                     // patch for face
+            patch0,                     // patch for face
             zonei,                      // zone for face
             zoneFlip                    // face flip in zone
         );
@@ -1272,7 +1318,7 @@ void Foam::meshRefinement::doSplitFaces
             -1,                         // master edge
             facei,                      // master face
             false,                      // face flip
-            patchi,                     // patch for face
+            patch1,                     // patch for face
             zonei,                      // zone for face
             zoneFlip                    // face flip in zone
         );
@@ -1301,6 +1347,7 @@ Foam::label Foam::meshRefinement::splitFacesUndo
 (
     const labelList& splitFaces,
     const labelPairList& splits,
+    const labelPairList& splitPatches,
     const dictionary& motionDict,
 
     labelList& duplicateFace,
@@ -1327,7 +1374,7 @@ Foam::label Foam::meshRefinement::splitFacesUndo
         );
 
         // Insert the mesh changes
-        doSplitFaces(splitFaces, splits, meshMod);
+        doSplitFaces(splitFaces, splits, splitPatches, meshMod);
 
         // Remove any unnecessary fields
         mesh_.clearOut();
@@ -1687,6 +1734,7 @@ Foam::meshRefinement::meshRefinement
     const shellSurfaces& shells,
     const shellSurfaces& limitShells,
     const labelUList& checkFaces,
+    const MeshType meshType,
     const bool dryRun
 )
 :
@@ -1698,6 +1746,7 @@ Foam::meshRefinement::meshRefinement
     features_(features),
     shells_(shells),
     limitShells_(limitShells),
+    meshType_(meshType),
     dryRun_(dryRun),
     meshCutter_
     (
@@ -1774,6 +1823,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::meshRefinement::balance
 (
     const bool keepZoneFaces,
     const bool keepBaffles,
+    const labelList& singleProcPoints,
     const scalarField& cellWeights,
     decompositionMethod& decomposer,
     fvMeshDistribute& distributor
@@ -1952,6 +2002,40 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::meshRefinement::balance
             blockedFace[baffle.second()] = false;
         }
 
+        if (returnReduceOr(singleProcPoints.size()))
+        {
+            // Modify couples to force all selected points be on the same
+            // processor
+
+            const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
+
+            label nPointFaces = 0;
+            for (const label pointi : singleProcPoints)
+            {
+                for (const label facei : mesh_.pointFaces()[pointi])
+                {
+                    if (blockedFace[facei])
+                    {
+                        if
+                        (
+                            mesh_.isInternalFace(facei)
+                         || pbm[pbm.whichPatch(facei)].coupled()
+                        )
+                        {
+                            blockedFace[facei] = false;
+                            nPointFaces++;
+                        }
+                    }
+                }
+            }
+            reduce(nPointFaces, sumOp<label>());
+            Info<< "Found " << nPointFaces
+                << " additional point-coupled faces to keep together." << endl;
+
+            nUnblocked += nPointFaces;
+        }
+
+
         distribution = decomposer.decompose
         (
             mesh_,
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
index 7e3b43f9cbb60187d953aef979a333054d991cb3..cc87edc7623c623ec0135b99255e32aa0fa8f6fe 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2015-2023 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -91,6 +91,18 @@ public:
 
     // Public Data Types
 
+        //- Enumeration for how to operate
+        enum MeshType
+        {
+            CASTELLATED,    // split-hex refinement, snapping, layer addition
+            CASTELLATEDBUFFERLAYER, // same but add buffer layers before
+                                    // snapping
+            CASTELLATEDBUFFERLAYER2 // experimental. wip.
+        };
+
+        static const Enum<MeshType> MeshTypeNames;
+
+
         //- Enumeration for what to debug. Used as a bit-pattern.
         enum debugType
         {
@@ -179,9 +191,13 @@ private:
         //- All limit-refinement interaction
         const shellSurfaces& limitShells_;
 
+        //- How to generate mesh
+        const MeshType meshType_;
+
         //- Are we operating in test mode?
         const bool dryRun_;
 
+
         //- Refinement engine
         hexRef8 meshCutter_;
 
@@ -778,10 +794,12 @@ private:
 
             //- Extract those baffles (duplicate) faces that are on the edge
             //  of a baffle region. These are candidates for merging.
+            //  samePatch : include only if both sides on the same patch.
             List<labelPair> freeStandingBaffles
             (
                 const List<labelPair>&,
-                const scalar freeStandingAngle
+                const scalar freeStandingAngle,
+                const bool samePatch
             ) const;
 
 
@@ -997,6 +1015,7 @@ public:
             const shellSurfaces&,   // omnidirectional refinement
             const shellSurfaces&,   // limit refinement
             const labelUList& checkFaces,   // initial faces to check
+            const MeshType meshType,
             const bool dryRun
         );
 
@@ -1062,6 +1081,12 @@ public:
                 return meshCutter_;
             }
 
+            //- Mode of meshing
+            MeshType meshType() const
+            {
+                return meshType_;
+            }
+
             //- Per start-end edge the index of the surface hit
             const labelList& surfaceIndex() const;
 
@@ -1098,10 +1123,12 @@ public:
             //  keepZoneFaces : find all faceZones from zoned surfaces and keep
             //                  owner and neighbour together
             //  keepBaffles   : find all baffles and keep them together
+            //  singleProcPoints : all faces using point are kept together
             autoPtr<mapDistributePolyMesh> balance
             (
                 const bool keepZoneFaces,
                 const bool keepBaffles,
+                const labelList& singleProcPoints,
                 const scalarField& cellWeights,
                 decompositionMethod& decomposer,
                 fvMeshDistribute& distributor
@@ -1366,6 +1393,7 @@ public:
             //- Merge free-standing baffles
             void mergeFreeStandingBaffles
             (
+                const bool samePatch,
                 const snapParameters& snapParams,
                 const bool useTopologicalSnapDetection,
                 const bool removeEdgeConnectedCells,
@@ -1449,6 +1477,14 @@ public:
                 const List<labelPair>& baffles
             );
 
+            //- Map baffles after layer addition. Gets new-to-old face map.
+            static void mapBaffles
+            (
+                const polyMesh& mesh,
+                const labelList& faceMap,
+                List<labelPair>& baffles
+            );
+
             //- Get per-face information (faceZone, master/slave patch)
             void getZoneFaces
             (
@@ -1625,11 +1661,24 @@ public:
                 const refPtr<coordSetWriter>& leakPathFormatter
             );
 
+            //- Helper: split face into:
+            //          - f0 : split[0] to split[1]
+            //          - f1 : split[1] to split[0]
+            static void splitFace
+            (
+                const face& f,
+                const labelPair& split,
+
+                face& f0,
+                face& f1
+            );
+
             //- Split faces into two
             void doSplitFaces
             (
                 const labelList& splitFaces,
                 const labelPairList& splits,
+                const labelPairList& splitPatches,
                 polyTopoChange& meshMod
             ) const;
 
@@ -1639,6 +1688,7 @@ public:
             (
                 const labelList& splitFaces,
                 const labelPairList& splits,
+                const labelPairList& splitPatches,
                 const dictionary& motionDict,
 
                 labelList& duplicateFace,
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
index 1286200ced72933dbda83cc36ce44a2d02fa5ef2..3afa51b1e3741b43694666cd956d65a883a4ecae 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2014 OpenFOAM Foundation
-    Copyright (C) 2015-2023 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -727,6 +727,49 @@ Foam::List<Foam::labelPair> Foam::meshRefinement::subsetBaffles
 }
 
 
+void Foam::meshRefinement::mapBaffles
+(
+    const polyMesh& mesh,
+    const labelList& faceMap,
+    List<labelPair>& baffles
+)
+{
+    // Create old-to-new map just for boundary faces. (since multiple faces
+    // get created from the same baffle face)
+    labelList reverseFaceMap(mesh.nFaces(), -1);
+    for
+    (
+        label facei = mesh.nInternalFaces();
+        facei < mesh.nFaces();
+        facei++
+    )
+    {
+        label oldFacei = faceMap[facei];
+        if (oldFacei != -1)
+        {
+            reverseFaceMap[oldFacei] = facei;
+        }
+    }
+
+
+    DynamicList<labelPair> newBaffles(baffles.size());
+    forAll(baffles, i)
+    {
+        const labelPair& p = baffles[i];
+        labelPair newBaffle
+        (
+            reverseFaceMap[p[0]],
+            reverseFaceMap[p[1]]
+        );
+        if (newBaffle[0] != -1 && newBaffle[1] != -1)
+        {
+            newBaffles.append(newBaffle);
+        }
+    }
+    baffles = std::move(newBaffles);
+}
+
+
 void Foam::meshRefinement::getZoneFaces
 (
     const labelList& zoneIDs,
@@ -927,7 +970,8 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createZoneBaffles
 Foam::List<Foam::labelPair> Foam::meshRefinement::freeStandingBaffles
 (
     const List<labelPair>& couples,
-    const scalar planarAngle
+    const scalar planarAngle,
+    const bool samePatch
 ) const
 {
     // Done by counting the number of baffles faces per mesh edge. If edge
@@ -1036,8 +1080,11 @@ Foam::List<Foam::labelPair> Foam::meshRefinement::freeStandingBaffles
 
         if
         (
-            patches.whichPatch(couple.first())
-         == patches.whichPatch(couple.second())
+           !samePatch
+         || (
+                patches.whichPatch(couple.first())
+             == patches.whichPatch(couple.second())
+            )
         )
         {
             const labelList& fEdges = mesh_.faceEdges(couple.first());
@@ -2430,15 +2477,24 @@ void Foam::meshRefinement::growCellZone
 
     // No blocked faces, limitless gap size
     const bitSet isBlockedFace(mesh_.nFaces());
-    List<scalarList> regionToBlockSize(surfaces_.surfaces().size());
+    //List<scalarList> regionToBlockSize(surfaces_.surfaces().size());
+    //{
+    //    forAll(surfaces_.surfaces(), surfi)
+    //    {
+    //        const label geomi = surfaces_.surfaces()[surfi];
+    //        const auto& s = surfaces_.geometry()[geomi];
+    //        const label nRegions = s.regions().size();
+    //        regionToBlockSize[surfi].setSize(nRegions, Foam::sqr(GREAT));
+    //    }
+    //}
+
+    //- regionToBlockSize is indexed with cellZone index (>= 0) and region
+    //- on cellZone (currently always 0)
+    const auto& czs = mesh_.cellZones();
+    List<scalarList> regionToBlockSize(czs.size());
+    for (auto& blockSizes : regionToBlockSize)
     {
-        forAll(surfaces_.surfaces(), surfi)
-        {
-            const label geomi = surfaces_.surfaces()[surfi];
-            const auto& s = surfaces_.geometry()[geomi];
-            const label nRegions = s.regions().size();
-            regionToBlockSize[surfi].setSize(nRegions, Foam::sqr(GREAT));
-        }
+        blockSizes.setSize(1, Foam::sqr(GREAT));
     }
 
 
@@ -4773,6 +4829,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
 
 void Foam::meshRefinement::mergeFreeStandingBaffles
 (
+    const bool samePatch,
     const snapParameters& snapParams,
     const bool useTopologicalSnapDetection,
     const bool removeEdgeConnectedCells,
@@ -4801,7 +4858,8 @@ void Foam::meshRefinement::mergeFreeStandingBaffles
         freeStandingBaffles    // filter out freestanding baffles
         (
             localPointRegion::findDuplicateFacePairs(mesh_),
-            planarAngle
+            planarAngle,
+            samePatch
         )
     );
 
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementProblemCells.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementProblemCells.C
index 61fa183e7d7d6c9f20fc73c8f10fefcabe6f856a..f4de036e95c714905e80adcf738dbe0966a98793 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementProblemCells.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementProblemCells.C
@@ -1112,8 +1112,9 @@ void Foam::meshRefinement::markFacesOnProblemCellsGeometric
                 *this,
                 globalToMasterPatch,
                 globalToSlavePatch,
-                snapDist,   // attraction
                 pp,
+                pp.localPoints(),
+                snapDist,   // attraction
                 nearestPoint,
                 nearestNormal
             )
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
index cec01d92c7444a28adde9532fe7229279477659b..d8c2ada5e33a22b3176a8cc3af00bcfdd9ec37db 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
@@ -2674,6 +2674,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::meshRefinement::balance
                 (
                     false,  //keepZoneFaces
                     false,  //keepBaffles
+                    labelList::null(),  //singleProcPoints
                     cellWeights,
                     decomposer,
                     distributor
diff --git a/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.C b/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.C
index 5b32ac72cfc4335e6eebfa940e49ec108c1275fc..07a648247d64b9caa9cdb7e3bcf422cb3f720a08 100644
--- a/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.C
+++ b/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2015-2022 OpenCFD Ltd.
+    Copyright (C) 2015-2022,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -208,6 +208,9 @@ Foam::refinementSurfaces::refinementSurfaces
     labelList globalBlockLevel(surfI, labelMax);
     labelList globalLeakLevel(surfI, labelMax);
 
+    // Supported in buffer-layer mode only
+    boolList globalBufferLayers(surfI, true);
+
     // Per surface, per region data
     List<Map<label>> regionMinLevel(surfI);
     List<Map<label>> regionMaxLevel(surfI);
@@ -220,6 +223,7 @@ Foam::refinementSurfaces::refinementSurfaces
     List<Map<autoPtr<dictionary>>> regionPatchInfo(surfI);
     List<Map<label>> regionBlockLevel(surfI);
     List<Map<label>> regionLeakLevel(surfI);
+    List<Map<label>> regionBufferLayers(surfI);
 
     wordHashSet unmatchedKeys(surfacesDict.toc());
 
@@ -346,7 +350,7 @@ Foam::refinementSurfaces::refinementSurfaces
             dict.readIfPresent("perpendicularAngle", globalAngle[surfI]);
             dict.readIfPresent("blockLevel", globalBlockLevel[surfI]);
             dict.readIfPresent("leakLevel", globalLeakLevel[surfI]);
-
+            dict.readIfPresent("addBufferLayers", globalBufferLayers[surfI]);
 
             if (dict.found("regions"))
             {
@@ -499,6 +503,14 @@ Foam::refinementSurfaces::refinementSurfaces
                         {
                             regionLeakLevel[surfI].insert(regionI, l);
                         }
+                        bool s;
+                        if
+                        (
+                            regionDict.readIfPresent<bool>("addBufferLayers", s)
+                        )
+                        {
+                            regionBufferLayers[surfI].insert(regionI, s);
+                        }
                     }
                 }
             }
@@ -551,6 +563,8 @@ Foam::refinementSurfaces::refinementSurfaces
     blockLevel_ = labelMax;
     leakLevel_.setSize(nRegions);
     leakLevel_ = labelMax;
+    addBufferLayers_.setSize(nRegions);
+    addBufferLayers_ = false;
 
 
     forAll(globalMinLevel, surfI)
@@ -582,6 +596,7 @@ Foam::refinementSurfaces::refinementSurfaces
             }
             blockLevel_[globalRegionI] = globalBlockLevel[surfI];
             leakLevel_[globalRegionI] = globalLeakLevel[surfI];
+            addBufferLayers_[globalRegionI] = globalBufferLayers[surfI];
         }
 
         // Overwrite with region specific information
@@ -636,6 +651,11 @@ Foam::refinementSurfaces::refinementSurfaces
             blockLevel_[globalRegionI] = iter.val();
             leakLevel_[globalRegionI] = iter.val();
         }
+        forAllConstIters(regionBufferLayers[surfI], iter)
+        {
+            const label globalRegionI = regionOffset_[surfI] + iter.key();
+            addBufferLayers_[globalRegionI] = iter.val();
+        }
     }
 }
 
diff --git a/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.H b/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.H
index 8f022033584f254f9f5ca46270280fdb1100d7de..6a035f14d0a18a9c5f018ceef5b7fe006b9ffe05 100644
--- a/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.H
+++ b/src/mesh/snappyHexMesh/refinementSurfaces/refinementSurfaces.H
@@ -119,6 +119,9 @@ class refinementSurfaces
         //- From global region number to patchType
         PtrList<dictionary> patchInfo_;
 
+        //- From global region number to whether to add buffer layers
+        boolList addBufferLayers_;
+
         //- Are we operating in test mode?
         const bool dryRun_;
 
@@ -291,6 +294,13 @@ public:
                 return patchInfo_;
             }
 
+            //- From global region number to whether to add buffer layers
+            //  when snapping
+            const boolList& addBufferLayers() const
+            {
+                return addBufferLayers_;
+            }
+
 
         // Helper
 
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.C
index 94365fc3670a0a13d312ce33efedc8447a85ebcb..42e2bd77ee3454ae634eb52bc1a13a11bef3f6f8 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.C
@@ -1000,15 +1000,16 @@ void Foam::snappyLayerDriver::handleWarpedFaces
 
 void Foam::snappyLayerDriver::setNumLayers
 (
+    meshRefinement& meshRefiner,
     const labelList& patchToNLayers,
     const labelList& patchIDs,
     const indirectPrimitivePatch& pp,
     labelList& patchNLayers,
     List<extrudeMode>& extrudeStatus,
     label& nAddedCells
-) const
+)
 {
-    const fvMesh& mesh = meshRefiner_.mesh();
+    const fvMesh& mesh = meshRefiner.mesh();
 
     Info<< nl << "Handling points with inconsistent layer specification ..."
         << endl;
@@ -1181,7 +1182,7 @@ Foam::snappyLayerDriver::makeLayerDisplacementField
             "pointDisplacement",
             mesh.time().timeName(),
             mesh,
-                IOobject::NO_READ,
+            IOobject::NO_READ,
             IOobject::AUTO_WRITE
         ),
         pMesh,
@@ -1284,6 +1285,7 @@ void Foam::snappyLayerDriver::growNoExtrusion
 
 void Foam::snappyLayerDriver::determineSidePatches
 (
+    meshRefinement& meshRefiner,
     const globalIndex& globalFaces,
     const labelListList& edgeGlobalFaces,
     const indirectPrimitivePatch& pp,
@@ -1300,7 +1302,7 @@ void Foam::snappyLayerDriver::determineSidePatches
     // mean that 2 procesors that were only edge-connected now suddenly need
     // to become face-connected i.e. have a processor patch between them.
 
-    fvMesh& mesh = meshRefiner_.mesh();
+    fvMesh& mesh = meshRefiner.mesh();
 
     // Determine edgePatchID. Any additional processor boundary gets added to
     // patchToNbrProc,nbrProcToPatch and nPatches gets set to the new number
@@ -1361,7 +1363,7 @@ void Foam::snappyLayerDriver::determineSidePatches
             //    << " between " << Pstream::myProcNo()
             //    << " and " << nbrProci << endl;
 
-            label procPatchi = meshRefiner_.appendPatch
+            label procPatchi = meshRefiner.appendPatch
             (
                 mesh,
                 mesh.boundaryMesh().size(), // new patch index
@@ -1769,14 +1771,15 @@ void Foam::snappyLayerDriver::calculateLayerThickness
 // Synchronize displacement among coupled patches.
 void Foam::snappyLayerDriver::syncPatchDisplacement
 (
+    const fvMesh& mesh,
     const indirectPrimitivePatch& pp,
     const scalarField& minThickness,
     pointField& patchDisp,
     labelList& patchNLayers,
     List<extrudeMode>& extrudeStatus
-) const
+)
 {
-    const fvMesh& mesh = meshRefiner_.mesh();
+    //const fvMesh& mesh = meshRefiner.mesh();
     const labelList& meshPoints = pp.meshPoints();
 
     //label nChangedTotal = 0;
@@ -2106,6 +2109,7 @@ void Foam::snappyLayerDriver::getPatchDisplacement
     // Make sure displacement is equal on both sides of coupled patches.
     syncPatchDisplacement
     (
+        mesh,
         pp,
         minThickness,
         patchDisp,
@@ -2300,6 +2304,7 @@ Foam::label Foam::snappyLayerDriver::truncateDisplacement
     {
         syncPatchDisplacement
         (
+            mesh,
             pp,
             minThickness,
             patchDisp,
@@ -3358,8 +3363,9 @@ bool Foam::snappyLayerDriver::writeLayerData
 }
 
 
-void Foam::snappyLayerDriver::dupFaceZonePoints
+Foam::autoPtr<Foam::mapPolyMesh> Foam::snappyLayerDriver::dupFaceZonePoints
 (
+    meshRefinement& meshRefiner,
     const labelList& patchIDs,  // patch indices
     const labelList& numLayers, // number of layers per patch
     List<labelPair> baffles,    // pairs of baffles (input & updated)
@@ -3367,7 +3373,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
                                 // point)
 )
 {
-    fvMesh& mesh = meshRefiner_.mesh();
+    fvMesh& mesh = meshRefiner.mesh();
 
     // Check outside of baffles for non-manifoldness
 
@@ -3395,6 +3401,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
         // Get number of layers per point from number of layers per patch
         setNumLayers
         (
+            meshRefiner,
             numLayers,              // per patch the num layers
             patchIDs,               // patches that are being moved
             *pp,                    // indirectpatch for all faces moving
@@ -3408,6 +3415,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
         // of the patchDisp here.
         syncPatchDisplacement
         (
+            mesh,
             *pp,
             scalarField(patchDisp.size(), Zero), //minThickness,
             patchDisp,
@@ -3474,7 +3482,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
         {
             label mpi, spi;
             surfaceZonesInfo::faceZoneType fzType;
-            bool hasInfo = meshRefiner_.getFaceZoneInfo
+            bool hasInfo = meshRefiner.getFaceZoneInfo
             (
                 mesh.faceZones()[zonei].name(),
                 mpi,
@@ -3497,7 +3505,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
 
     const localPointRegion regionSide(mesh, nonDupBaffles, candidatePoints);
 
-    autoPtr<mapPolyMesh> map = meshRefiner_.dupNonManifoldPoints
+    autoPtr<mapPolyMesh> map = meshRefiner.dupNonManifoldPoints
     (
         regionSide
     );
@@ -3539,9 +3547,9 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
         {
             const_cast<Time&>(mesh.time())++;
             Info<< "Writing point-duplicate mesh to time "
-                << meshRefiner_.timeName() << endl;
+                << meshRefiner.timeName() << endl;
 
-            meshRefiner_.write
+            meshRefiner.write
             (
                 meshRefinement::debugType(debug),
                 meshRefinement::writeType
@@ -3549,14 +3557,14 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
                     meshRefinement::writeLevel()
                   | meshRefinement::WRITEMESH
                 ),
-                mesh.time().path()/meshRefiner_.timeName()
+                mesh.time().path()/meshRefiner.timeName()
             );
 
             OBJstream str
             (
                 mesh.time().path()
               / "duplicatePoints_"
-              + meshRefiner_.timeName()
+              + meshRefiner.timeName()
               + ".obj"
             );
             Info<< "Writing point-duplicates to " << str.name() << endl;
@@ -3572,6 +3580,7 @@ void Foam::snappyLayerDriver::dupFaceZonePoints
             }
         }
     }
+    return map;
 }
 
 
@@ -3721,6 +3730,7 @@ Foam::label Foam::snappyLayerDriver::setPointNumLayers
 
     setNumLayers
     (
+        meshRefiner_,
         numLayers,                  // per patch the num layers
         patchIDs,                   // patches that are being moved
         pp,                         // indirectpatch for all faces moving
@@ -4017,6 +4027,7 @@ void Foam::snappyLayerDriver::addLayers
         // that.
         syncPatchDisplacement
         (
+            mesh,
             pp,
             minThickness,
             patchDisp,
@@ -4410,12 +4421,13 @@ void Foam::snappyLayerDriver::addLayers
 
 void Foam::snappyLayerDriver::mapFaceZonePoints
 (
+    meshRefinement& meshRefiner,
     const mapPolyMesh& map,
     labelPairList& baffles,
     labelList& pointToMaster
-) const
+)
 {
-    fvMesh& mesh = meshRefiner_.mesh();
+    fvMesh& mesh = meshRefiner.mesh();
 
     // Use geometric detection of points-to-be-merged
     //  - detect any boundary face created from a duplicated face (=baffle)
@@ -4517,7 +4529,7 @@ void Foam::snappyLayerDriver::mapFaceZonePoints
         label nNew = Foam::mergePoints
         (
             UIndirectList<point>(mesh.points(), candidates),
-            meshRefiner_.mergeDistance(),
+            meshRefiner.mergeDistance(),
             false,
             oldToNew
         );
@@ -4811,6 +4823,7 @@ void Foam::snappyLayerDriver::addLayers
     labelList pointToMaster;
     dupFaceZonePoints
     (
+        meshRefiner_,
         patchIDs,  // patch indices
         numLayers, // number of layers per patch
         baffles,
@@ -4960,7 +4973,7 @@ void Foam::snappyLayerDriver::addLayers
             << "-------------------" << endl;
         if (debug)
         {
-            Info<< " Layers to add in current iteration : " << nToAdd << endl;
+            Info<< "Layers to add in current iteration : " << nToAdd << endl;
         }
         if (nToAdd == 0)
         {
@@ -4977,6 +4990,7 @@ void Foam::snappyLayerDriver::addLayers
         labelList inflateFaceID;
         determineSidePatches
         (
+            meshRefiner_,
             globalFaces,
             edgeGlobalFaces,
             *pp,
@@ -5084,7 +5098,7 @@ void Foam::snappyLayerDriver::addLayers
         const label nTotalAdded = gSum(patchNLayers);
         if (debug)
         {
-            Info<< nl << " Added in current iteration : " << nTotalAdded
+            Info<< nl << "Added in current iteration : " << nTotalAdded
                 << " out of : " << gSum(deltaNLayers) << endl;
         }
         if (nTotalAdded == 0)
@@ -5225,7 +5239,7 @@ void Foam::snappyLayerDriver::addLayers
 
 
             // Map baffles, pointToMaster
-            mapFaceZonePoints(map, baffles, pointToMaster);
+            mapFaceZonePoints(meshRefiner_, map, baffles, pointToMaster);
 
             // Map patch and layer settings
             labelList newToOldPatchPoints;
@@ -5325,6 +5339,7 @@ void Foam::snappyLayerDriver::addLayers
         (
             false,
             false,
+            labelList::null(),
             scalarField(mesh.nCells(), 1.0),
             decomposer,
             distributor
@@ -5607,6 +5622,7 @@ void Foam::snappyLayerDriver::doLayers
                 (
                     true,           // keepZoneFaces
                     false,
+                    labelList::null(),
                     cellWeights,
                     decomposer,
                     distributor
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.H b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.H
index 5a71785bfd85e500b88665d42d112d04f84208cd..384f61ff88085c23236326114350af41c17a9e0b 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.H
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriver.H
@@ -248,8 +248,9 @@ private:
 
                 //- Determine the number of layers per point from the number of
                 //  layers per surface.
-                void setNumLayers
+                static void setNumLayers
                 (
+                    meshRefinement& meshRefiner,
                     const labelList& patchToNLayers,
                     const labelList& patchIDs,
                     const indirectPrimitivePatch& pp,
@@ -257,7 +258,7 @@ private:
                     labelList& patchNLayers,
                     List<extrudeMode>& extrudeStatus,
                     label& nIdealAddedCells
-                ) const;
+                );
 
                 //- Determine number of layers per point; include static checks
                 //- on invalid extrusion (e.g. non-manifold)
@@ -282,12 +283,6 @@ private:
                     const scalarIOField& minThickness,
                     pointVectorField& displacement
                 ) const;
-                void mapFaceZonePoints
-                (
-                    const mapPolyMesh& map,
-                    labelPairList& baffles,
-                    labelList& pointToMaster
-                ) const;
                 void updatePatch
                 (
                     const labelList& patchIDs,
@@ -319,15 +314,6 @@ private:
                     List<extrudeMode>& extrudeStatus
                 ) const;
 
-                //- Duplicate points on faceZones with layers
-                void dupFaceZonePoints
-                (
-                    const labelList& patchIDs,  // patch indices
-                    const labelList& numLayers, // number of layers per patch
-                    List<labelPair> baffles,
-                    labelList& pointToMaster
-                );
-
                 //- Re-merge points/faces on faceZones. Opposite of
                 //- dupFaceZonePoints above
                 void mergeFaceZonePoints
@@ -338,19 +324,6 @@ private:
                     scalarField& faceWantedThickness
                 );
 
-                //- See what zones and patches edges should be extruded into
-                void determineSidePatches
-                (
-                    const globalIndex& globalFaces,
-                    const labelListList& edgeGlobalFaces,
-                    const indirectPrimitivePatch& pp,
-
-                    labelList& edgePatchID,
-                    labelList& edgeZoneID,
-                    boolList& edgeFlip,
-                    labelList& inflateFaceID
-                );
-
                 //- Calculate pointwise wanted and minimum thickness.
                 //  thickness: wanted thickness
                 //  minthickness: when to give up and not extrude
@@ -374,14 +347,15 @@ private:
             // Extrusion execution
 
                 //- Synchronize displacement among coupled patches.
-                void syncPatchDisplacement
+                static void syncPatchDisplacement
                 (
+                    const fvMesh& mesh,
                     const indirectPrimitivePatch& pp,
                     const scalarField& minThickness,
                     pointField& patchDisp,
                     labelList& patchNLayers,
                     List<extrudeMode>& extrudeStatus
-                ) const;
+                );
 
                 //- Get nearest point on surface to snap to
                 void getPatchDisplacement
@@ -727,6 +701,41 @@ public:
                 decompositionMethod& decomposer,
                 fvMeshDistribute& distributor
             );
+
+            //- Helper: see what zones and patches edges should be extruded into
+            static void determineSidePatches
+            (
+                meshRefinement& meshRefiner,
+                const globalIndex& globalFaces,
+                const labelListList& edgeGlobalFaces,
+                const indirectPrimitivePatch& pp,
+
+                labelList& edgePatchID,
+                labelList& edgeZoneID,
+                boolList& edgeFlip,
+                labelList& inflateFaceID
+            );
+
+            //- Duplicate points on faceZones with layers. Re-used when adding
+            //- buffer layers. Can be made private again once multi-side
+            //- layer addition working.
+            static autoPtr<mapPolyMesh> dupFaceZonePoints
+            (
+                meshRefinement& meshRefiner,
+                const labelList& patchIDs,  // patch indices
+                const labelList& numLayers, // number of layers per patch
+                List<labelPair> baffles,
+                labelList& pointToMaster
+            );
+
+            //- Map numbering after adding cell layers
+            static void mapFaceZonePoints
+            (
+                meshRefinement& meshRefiner,
+                const mapPolyMesh& map,
+                labelPairList& baffles,
+                labelList& pointToMaster
+            );
 };
 
 
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriverSinglePass.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriverSinglePass.C
index 0b8c4f977a43402edefa4a066d80e604619a4ebb..c886d777078ed34be7df07b173b6422714e44587 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriverSinglePass.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyLayerDriverSinglePass.C
@@ -179,6 +179,7 @@ void Foam::snappyLayerDriver::addLayersSinglePass
     labelList pointToMaster;
     dupFaceZonePoints
     (
+        meshRefiner_,
         patchIDs,  // patch indices
         numLayers, // number of layers per patch
         baffles,
@@ -231,6 +232,7 @@ void Foam::snappyLayerDriver::addLayersSinglePass
     labelList inflateFaceID;
     determineSidePatches
     (
+        meshRefiner_,
         globalFaces,
         edgeGlobalFaces,
         *pp,
@@ -437,7 +439,7 @@ void Foam::snappyLayerDriver::addLayersSinglePass
 
 
         // Map baffles, pointToMaster
-        mapFaceZonePoints(map, baffles, pointToMaster);
+        mapFaceZonePoints(meshRefiner_, map, baffles, pointToMaster);
     }
 
 
@@ -471,6 +473,7 @@ void Foam::snappyLayerDriver::addLayersSinglePass
         (
             false,
             false,
+            labelList::null(),
             scalarField(mesh.nCells(), 1.0),
             decomposer,
             distributor
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
index 8837ce88015c30cd04acb0e678731206460fb6bf..bdb55c6faf16afb367b58550a65a7741606c9d9c 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2015-2023 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -49,6 +49,7 @@ License
 #include "snappyVoxelMeshDriver.H"
 #include "regionSplit.H"
 #include "removeCells.H"
+#include "addPatchCellLayer.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -2805,8 +2806,23 @@ void Foam::snappyRefineDriver::baffleAndSplitMesh
 
     if (!handleSnapProblems) // merge free standing baffles?
     {
+        // By default only merge baffles if on same patch. However the patching
+        // of the castellated mesh is not very accurate. For backwards
+        // compatibility disable check for new mode only.
+        const auto mt = meshRefiner_.meshType();
+        const bool mergeSameOnly
+        (
+            (
+                mt == meshRefinement::CASTELLATEDBUFFERLAYER
+             || mt == meshRefinement::CASTELLATEDBUFFERLAYER2
+            )
+          ? false
+          : true
+        );
+
         meshRefiner_.mergeFreeStandingBaffles
         (
+            mergeSameOnly,      // whether to merge baffles on different patches
             snapParams,
             refineParams.useTopologicalSnapDetection(),
             false,                  // perpendicular edge connected cells
@@ -2942,9 +2958,24 @@ void Foam::snappyRefineDriver::splitAndMergeBaffles
         surfFormatter_
     );
 
-    // Merge free-standing baffles always
+
+    // By default only merge baffles if on same patch. However the patching
+    // of the castellated mesh is not very accurate. For backwards
+    // compatibility disable check for new mode only.
+    const auto mt = meshRefiner_.meshType();
+    const bool mergeSameOnly
+    (
+        (
+            mt == meshRefinement::CASTELLATEDBUFFERLAYER
+         || mt == meshRefinement::CASTELLATEDBUFFERLAYER2
+        )
+      ? false
+      : true
+    );
+
     meshRefiner_.mergeFreeStandingBaffles
     (
+        mergeSameOnly,
         snapParams,
         refineParams.useTopologicalSnapDetection(),
         handleSnapProblems,
@@ -3027,6 +3058,145 @@ void Foam::snappyRefineDriver::splitAndMergeBaffles
 }
 
 
+void Foam::snappyRefineDriver::erodeNonManifoldZoneFaces
+(
+    const refinementParameters& refineParams
+)
+{
+    if (dryRun_)
+    {
+        return;
+    }
+
+    addProfiling(merge, "snappyHexMesh::refine::erode");
+    Info<< nl
+        << "Erode non-manifold zone faces" << nl
+        << "-----------------------------" << nl
+        << endl;
+
+    auto& mesh = meshRefiner_.mesh();
+    auto& fzs = mesh.faceZones();
+
+    // Detect a faceZone face that:
+    // - sits on the edge of the faceZone (i.e. has an open edge)
+    // - has a non-manifold edge
+    //
+    // Limitations:
+    // - analyses across all zones - does not support overlapping zones
+    // - requires zones to be consistent across processor patches
+
+    bitSet isZoneFace(mesh.nFaces());
+    for (const auto& fz : fzs)
+    {
+        isZoneFace.set(fz.addressing());
+    }
+    // Unmark non-owner side of processor patches so they don't get double
+    // counted.
+    const auto& pbm = mesh.boundaryMesh();
+    for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
+    {
+        if (!refCast<const processorPolyPatch>(pbm[patchi]).owner())
+        {
+            isZoneFace.unset(pbm[patchi].range());
+        }
+    }
+
+
+    // TBD: replace with mesh.globalData().globalMeshFaceAddr()
+    const globalIndex globalFaces(mesh.nFaces());
+
+    label nChanged = 0;
+
+    while (true)
+    {
+        const labelList meshFaces(isZoneFace.sortedToc());
+
+        const indirectPrimitivePatch pp
+        (
+            IndirectList<face>
+            (
+                mesh.faces(),
+                meshFaces
+            ),
+            mesh.points()
+        );
+
+        const labelListList edgeGlobalFaces
+        (
+            addPatchCellLayer::globalEdgeFaces
+            (
+                mesh,
+                globalFaces,
+                pp
+            )
+        );
+
+        const label nOldChanged = nChanged;
+        forAll(pp, patchFacei)
+        {
+            // Detect at least one open edge and one non-manifold edge
+            label nOpen = 0;
+            label nNonManif = 0;
+            for (const label edgei : pp.faceEdges()[patchFacei])
+            {
+                if (edgeGlobalFaces[edgei].size() == 1)
+                {
+                    nOpen++;
+                }
+                else if (edgeGlobalFaces[edgei].size() > 2)
+                {
+                    nNonManif++;
+                }
+            }
+            if (nNonManif > 0 && nOpen > 0)
+            {
+                isZoneFace.unset(meshFaces[patchFacei]);
+                nChanged++;
+            }
+        }
+
+        if (returnReduce((nChanged-nOldChanged), sumOp<label>()) == 0)
+        {
+            break;
+        }
+    }
+
+
+    reduce(nChanged, sumOp<label>());
+
+    if (nChanged)
+    {
+        // Filter out eroded faceZone faces
+        fzs.clearAddressing();
+
+        for (auto& fz : fzs)
+        {
+            DynamicList<label> addressing(fz.size());
+            DynamicList<bool> flipMap(fz.size());
+
+            forAll(fz.addressing(), i)
+            {
+                if (isZoneFace[fz.addressing()[i]])
+                {
+                    addressing.append(fz.addressing()[i]);
+                    flipMap.append(fz.flipMap()[i]);
+                }
+            }
+
+            //Pout<< "** on faceZone:" << fz.name()
+            //  << " from:" << fz.size()
+            //    << " to:" << addressing.size() << endl;
+
+            fz.resetAddressing(addressing, flipMap);
+        }
+    }
+
+    Info<< "Eroded " << nChanged
+        << " free-standing zone faces in = "
+        << mesh.time().cpuTimeIncrement() << " s." << endl;
+}
+
+
 void Foam::snappyRefineDriver::addFaceZones
 (
     meshRefinement& meshRefiner,
@@ -3555,9 +3725,23 @@ void Foam::snappyRefineDriver::doRefine
         motionDict
     );
 
+
     // Do something about cells with refined faces on the boundary
     if (prepareForSnapping)
     {
+        const auto mt = meshRefiner_.meshType();
+        if
+        (
+            meshRefiner_.mesh().faceZones().size()
+         && (
+                mt == meshRefinement::CASTELLATEDBUFFERLAYER
+             || mt == meshRefinement::CASTELLATEDBUFFERLAYER2
+            )
+        )
+        {
+            erodeNonManifoldZoneFaces(refineParams);
+        }
+
         mergePatchFaces(mergeType, refineParams, motionDict);
     }
 
@@ -3580,13 +3764,61 @@ void Foam::snappyRefineDriver::doRefine
             << "---------------------" << nl
             << endl;
 
+
+        /*
+        const bool hasBufferLayer
+        (
+            (meshRefiner_.meshType() == meshRefinement::CASTELLATEDBUFFERLAYER)
+         || (meshRefiner_.meshType() == meshRefinement::CASTELLATEDBUFFERLAYER2)
+        );
+        */
+        const bool hasBufferLayer = false;
+
+        labelList singleProcPoints;
+
+        /*
+        if (hasBufferLayer)
+        {
+            //- Needed since buffer layer addition did not handle
+            //- inter-processor extrusion. Fixed now. This code can be removed.
+
+            // Pick up all points on surfaces with specified buffer layers
+            const labelList& surfIndex = meshRefiner_.surfaceIndex();
+            const auto& addLayers = meshRefiner_.surfaces().addBufferLayers();
+
+            bitSet isSelected(mesh.nPoints());
+            forAll(surfIndex, facei)
+            {
+                const label surfi = surfIndex[facei];
+                if (surfIndex[facei] != -1)
+                {
+                    const label globalRegioni =
+                        meshRefiner_.surfaces().globalRegion(surfi, 0);
+                    if (addLayers[globalRegioni])
+                    {
+                        isSelected.set(mesh.faces()[facei]);
+                    }
+                }
+            }
+            syncTools::syncPointList
+            (
+                mesh,
+                isSelected,
+                orEqOp<unsigned int>(),
+                0
+            );
+            singleProcPoints = isSelected.sortedToc();
+        }
+        */
+
         // Do final balancing. Keep zoned faces on one processor since the
         // snap phase will convert them to baffles and this only works for
         // internal faces.
         meshRefiner_.balance
         (
             true,                           // keepZoneFaces
-            false,                          // keepBaffles
+            hasBufferLayer,                 // keepBaffles
+            singleProcPoints,               // keepZonePoints
             scalarField(mesh.nCells(), 1),  // cellWeights
             decomposer_,
             distributor_
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
index 17b45f4b0fff3eee0baae6bf0ee824fe66946248..ed6a105956656372123153e58e47015c36105cd1 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
@@ -243,6 +243,12 @@ class snappyRefineDriver
             const dictionary& motionDict
         );
 
+        //- Erode sticking-out zone faces. Bit heuristic.
+        void erodeNonManifoldZoneFaces
+        (
+            const refinementParameters& refineParams
+        );
+
         //- Merge refined boundary faces (from exposing coarser cell)
         void mergePatchFaces
         (
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.C
index b38620a13f0a1f24ce4097181558c9987567bc49..7d19b0aef50325bc8723a13ba445d8d5a0ec712b 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2015-2022 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -50,6 +50,10 @@ Description
 #include "refinementFeatures.H"
 #include "weightedPosition.H"
 #include "profiling.H"
+#include "addPatchCellLayer.H"
+#include "displacementMotionSolver.H"
+#include "snappyLayerDriver.H"
+#include "IOmanip.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -1116,6 +1120,7 @@ void Foam::snappySnapDriver::detectNearSurfaces
 (
     const scalar planarCos,
     const indirectPrimitivePatch& pp,
+    const pointField& localPoints,
     const pointField& nearestPoint,
     const vectorField& nearestNormal,
 
@@ -1124,7 +1129,6 @@ void Foam::snappySnapDriver::detectNearSurfaces
 {
     Info<< "Detecting near surfaces ..." << endl;
 
-    const pointField& localPoints = pp.localPoints();
     const labelList& meshPoints = pp.meshPoints();
     const refinementSurfaces& surfaces = meshRefiner_.surfaces();
     const fvMesh& mesh = meshRefiner_.mesh();
@@ -1796,8 +1800,9 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurface
     const meshRefinement& meshRefiner,
     const labelList& globalToMasterPatch,
     const labelList& globalToSlavePatch,
-    const scalarField& snapDist,
     const indirectPrimitivePatch& pp,
+    const pointField& localPoints,
+    const scalarField& snapDist,
     pointField& nearestPoint,
     vectorField& nearestNormal
 )
@@ -1822,7 +1827,6 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurface
     }
 
 
-    const pointField& localPoints = pp.localPoints();
     const refinementSurfaces& surfaces = meshRefiner.surfaces();
     const fvMesh& mesh = meshRefiner.mesh();
 
@@ -2575,6 +2579,22 @@ void Foam::snappySnapDriver::doSnap
     const snapParameters& snapParams
 )
 {
+    if (meshRefiner_.meshType() == meshRefinement::CASTELLATEDBUFFERLAYER2)
+    {
+        // Buffer-layer replacement for this routine
+
+        doSnapBufferLayers
+        (
+            snapDict,
+            motionDict,
+            mergeType,
+            featureCos,
+            planarAngle,
+            snapParams
+        );
+        return;
+    }
+
     addProfiling(snap, "snappyHexMesh::snap");
     fvMesh& mesh = meshRefiner_.mesh();
 
@@ -2616,6 +2636,48 @@ void Foam::snappySnapDriver::doSnap
 
 
 
+    // Get labels of patches where optional buffer layers are added
+    DynamicList<label> bufPatchIDs;
+    if (meshRefiner_.meshType() == meshRefinement::CASTELLATEDBUFFERLAYER)
+    {
+        bufPatchIDs.setCapacity(globalToMasterPatch_.size());
+
+        const auto& addLayers =
+            meshRefiner_.surfaces().addBufferLayers();
+
+        // Normal patches
+        forAll(globalToMasterPatch_, globalRegioni)
+        {
+            if (addLayers[globalRegioni])
+            {
+                const label masterP =
+                    globalToMasterPatch_[globalRegioni];
+                const label slaveP =
+                    globalToSlavePatch_[globalRegioni];
+
+                bufPatchIDs.append(masterP);
+                if (slaveP != masterP)
+                {
+                    bufPatchIDs.append(slaveP);
+                }
+            }
+        }
+
+        // Temporary patches from faceZones
+        for (const auto& fz : mesh.faceZones())
+        {
+            label mpI, spI;
+            surfaceZonesInfo::faceZoneType type;
+            if (meshRefiner_.getFaceZoneInfo(fz.name(), mpI, spI, type))
+            {
+                bufPatchIDs.appendUniq(mpI);
+                bufPatchIDs.appendUniq(spI);
+            }
+        }
+    }
+
+
+
     // faceZones of type internal
     const labelList internalFaceZones
     (
@@ -2629,11 +2691,10 @@ void Foam::snappySnapDriver::doSnap
         )
     );
 
-
     // Create baffles (pairs of faces that share the same points)
     // Baffles stored as owner and neighbour face that have been created.
+    List<labelPair> baffles;
     {
-        List<labelPair> baffles;
         labelList originatingFaceZone;
         meshRefiner_.createZoneBaffles
         (
@@ -2643,8 +2704,21 @@ void Foam::snappySnapDriver::doSnap
         );
     }
 
-    // Duplicate points on faceZones of type boundary
-    meshRefiner_.dupNonManifoldBoundaryPoints();
+    // Duplicate points on faceZones of type boundary. Renumber baffles
+    // (probably not necessary - faceIDs should not change)
+    {
+        autoPtr<mapPolyMesh> map = meshRefiner_.dupNonManifoldBoundaryPoints();
+        if (map)
+        {
+            const labelList& reverseFaceMap = map->reverseFaceMap();
+            forAll(baffles, i)
+            {
+                label f0 = reverseFaceMap[baffles[i].first()];
+                label f1 = reverseFaceMap[baffles[i].second()];
+                baffles[i] = labelPair(f0, f1);
+            }
+        }
+    }
 
 
     bool doFeatures = false;
@@ -2667,7 +2741,7 @@ void Foam::snappySnapDriver::doSnap
 
 
     // Get the labels of added patches.
-    labelList adaptPatchIDs(meshRefiner_.meshedPatches());
+    const labelList adaptPatchIDs(meshRefiner_.meshedPatches());
 
 
 
@@ -2681,7 +2755,6 @@ void Foam::snappySnapDriver::doSnap
             )
         );
 
-
         // Distance to attract to nearest feature on surface
         scalarField snapDist(calcSnapDistance(mesh, snapParams, ppPtr()));
 
@@ -2727,7 +2800,7 @@ void Foam::snappySnapDriver::doSnap
             << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
 
         // Extract baffles across internal faceZones (for checking mesh quality
-        // across
+        // across)
         labelPairList internalBaffles
         (
             meshRefiner_.subsetBaffles
@@ -2750,7 +2823,462 @@ void Foam::snappySnapDriver::doSnap
             meshMoverPtr()
         );
 
-        // TBD. Include re-patching?
+        // Reset moving flag in case we do any topo changes
+        mesh.moving(false);
+
+
+        // Optionally add buffer layers
+        if (meshRefiner_.meshType() == meshRefinement::CASTELLATEDBUFFERLAYER)
+        {
+            ////- merge zone baffles (since current buffer layer insertion
+            ////- does not handle non-manifold edges ... TBD
+            //autoPtr<mapPolyMesh> mapPtr = meshRefiner_.mergeZoneBaffles
+            //(
+            //    true,   // internal zones
+            //    false   // baffle zones
+            //);
+            //
+            //if (mapPtr)
+            //{
+            //    if (debug & meshRefinement::MESH)
+            //    {
+            //        const_cast<Time&>(mesh.time())++;
+            //        Info<< "Writing baffle-merged mesh to time "
+            //            << meshRefiner_.timeName() << endl;
+            //        meshRefiner_.write
+            //        (
+            //            meshRefinement::debugType(debug),
+            //            meshRefinement::writeType
+            //            (
+            //                meshRefinement::writeLevel()
+            //              | meshRefinement::WRITEMESH
+            //            ),
+            //            meshRefiner_.timeName()
+            //        );
+            //    }
+            //}
+
+            ////- use bufferLayer insertion on internalFaceZones
+            //Info<< "Adding buffer layers ..." << endl;
+            //
+            //{
+            //    // Remove references to pp
+            //    meshMoverPtr.clear();
+            //
+            //    const labelList meshFaces
+            //    (
+            //        mesh.faceZones().selection
+            //        (
+            //            internalFaceZones
+            //        ).sortedToc()
+            //    );
+            //    ppPtr.reset
+            //    (
+            //        new indirectPrimitivePatch
+            //        (
+            //            IndirectList<face>
+            //            (
+            //                mesh.faces(),
+            //                meshFaces
+            //            ),
+            //            mesh.points()
+            //        )
+            //    );
+            //    const pointField thickness
+            //    (
+            //        wantedThickness(ppPtr(), 1e-1)     //cellSizeFraction
+            //      * PatchTools::pointNormals(mesh, ppPtr())
+            //    );
+            //
+            //    // Layer mesh modifier
+            //    // - use intrusion, not extrusion
+            //    addPatchCellLayer addLayer(mesh, true, false);
+            //
+            //    // Do mesh changes : introduce point, faces, cells
+            //    autoPtr<mapPolyMesh> mapPtr = addBufferLayers
+            //    (
+            //        ppPtr(),
+            //        -thickness,  //1e-3,   //cellSizeFraction,
+            //        addLayer
+            //    );
+            //
+            //    // Update numbering on baffles, pointToMaster. Note: uses
+            //    // geometric tolerance - could be avoided since now we have
+            //    // addPatchCellLayer still intact. However would like to avoid
+            //    // use of addPatchCellLayer altogether.
+            //    if (mapPtr)
+            //    {
+            //        // Invalidate extrusion (face numbering might have changed)
+            //        ppPtr.clear();
+            //
+            //        labelList dummyPointToMaster;
+            //        snappyLayerDriver::mapFaceZonePoints
+            //        (
+            //            meshRefiner_,
+            //            mapPtr(),
+            //            internalBaffles,
+            //            dummyPointToMaster
+            //        );
+            //
+            //        if (debug & meshRefinement::MESH)
+            //        {
+            //            const_cast<Time&>(mesh.time())++;
+            //            Info<< "Writing INTERNAL ZONE buffer layer mesh"
+            //                << " to time " << meshRefiner_.timeName() << endl;
+            //            meshRefiner_.write
+            //            (
+            //                meshRefinement::debugType(debug),
+            //                meshRefinement::writeType
+            //                (
+            //                    meshRefinement::writeLevel()
+            //                  | meshRefinement::WRITEMESH
+            //                ),
+            //                meshRefiner_.timeName()
+            //            );
+            //        }
+            //    }
+            //}
+
+            ////- re-split zone baffles
+            //{
+            //    labelList originatingFaceZone;
+            //    meshRefiner_.createZoneBaffles
+            //    (
+            //        internalFaceZones,
+            //        baffles,
+            //        originatingFaceZone
+            //    );
+            //}
+
+
+            Info<< "Adding buffer layers ..." << endl;
+
+            // Remove references to pp
+            meshMoverPtr.clear();
+            // Invalidate extrusion (face numbering might have changed)
+            ppPtr.clear();
+
+            // Note: all the way up to addBufferLayers can probably be replaced
+            // once addPatchCellLayer can add to both sides of faceZone ...
+
+            // Duplicate points on faceZones that layers are added to
+            labelList pointToMaster;
+            {
+                labelList numLayers(mesh.boundaryMesh().size(), 0);
+                UIndirectList<label>(numLayers, bufPatchIDs) = 1;
+
+                autoPtr<mapPolyMesh> mapPtr =
+                    snappyLayerDriver::dupFaceZonePoints
+                    (
+                        meshRefiner_,
+                        bufPatchIDs,  // patch indices
+                        numLayers,      // num layers per patch
+                        baffles,
+                        pointToMaster
+                    );
+                if (mapPtr)
+                {
+                    // Update numbering on any baffles
+                    meshRefinement::mapBaffles
+                    (
+                        mesh,
+                        mapPtr().faceMap(),
+                        internalBaffles
+                    );
+
+
+                    //// Shrink back mesh a bit to see if there are any
+                    //// incorrect dupFaceZonePoints ...
+                    //if (debug & meshRefinement::MESH)
+                    //{
+                    //    pointField newPoints(mesh.nPoints());
+                    //    forAll(newPoints, pointi)
+                    //    {
+                    //        const auto& pCells = mesh.pointCells()[pointi];
+                    //
+                    //        point avg(Zero);
+                    //        for (const label celli : pCells)
+                    //        {
+                    //            avg += mesh.cellCentres()[celli];
+                    //        }
+                    //        avg /= pCells.size();
+                    //
+                    //        newPoints[pointi] =
+                    //            0.5*mesh.points()[pointi]
+                    //          + 0.5*avg;
+                    //    }
+                    //    mesh.movePoints(newPoints);
+                    //
+                    //    const_cast<Time&>(mesh.time())++;
+                    //    Info<< "Writing DEBUG-shrunk layer mesh to time "
+                    //        << meshRefiner_.timeName() << endl;
+                    //    meshRefiner_.write
+                    //    (
+                    //        meshRefinement::debugType(debug),
+                    //        meshRefinement::writeType
+                    //        (
+                    //            meshRefinement::writeLevel()
+                    //          | meshRefinement::WRITEMESH
+                    //        ),
+                    //        meshRefiner_.timeName()
+                    //    );
+                    //}
+                }
+            }
+
+            //- Not needed: shrinking of mesh since now using intrusion ...
+            // // Move mesh back with thickness. Two purposes:
+            // // - avoid mapFaceZonePoints below merging points extraneously
+            // //   (does not use addPatchCellLayer structure; uses geometric
+            // //    tolerance)
+            // // - see what is happening
+            // {
+            //     pointField newPoints(mesh.points());
+            //     const auto& mp = ppPtr().meshPoints();
+            //     forAll(mp, i)
+            //     {
+            //         newPoints[mp[i]] -= thickness[i];
+            //     }
+            //     mesh.movePoints(newPoints);
+            //     ppPtr().movePoints(mesh.points());
+            //
+            //     if (debug & meshRefinement::MESH)
+            //     {
+            //         const_cast<Time&>(mesh.time())++;
+            //         Info<< "Writing shrunk buffer layer mesh to time "
+            //             << meshRefiner_.timeName() << endl;
+            //         meshRefiner_.write
+            //         (
+            //             meshRefinement::debugType(debug),
+            //             meshRefinement::writeType
+            //             (
+            //                 meshRefinement::writeLevel()
+            //               | meshRefinement::WRITEMESH
+            //             ),
+            //             meshRefiner_.timeName()
+            //         );
+            //     }
+            // }
+
+
+            {
+                // Layer mesh modifier
+                // - use intrusion, not extrusion
+                addPatchCellLayer addLayer(mesh, true, false);
+
+                // Redo pp
+                autoPtr<indirectPrimitivePatch> bufPatchPtr
+                (
+                    meshRefinement::makePatch(mesh, bufPatchIDs)
+                );
+
+                pointField thickness
+                (
+                    wantedThickness(bufPatchPtr(), 1e-1)  //cellSizeFraction
+                  * PatchTools::pointNormals(mesh, bufPatchPtr())
+                );
+
+                // Make sure to adhere to constraints
+                {
+
+                    const pointMesh& pMesh = pointMesh::New(mesh);
+                    const labelList& mp = bufPatchPtr().meshPoints();
+
+                    tmp<pointVectorField> tdisp
+                    (
+                        meshRefinement::makeDisplacementField
+                        (
+                            pMesh,
+                            adaptPatchIDs
+                        )
+                    );
+                    // Set internal field
+                    UIndirectList<point>(tdisp.ref(), mp) = thickness;
+                    // Take over onto boundary field. Needed since constraint
+                    // patch might be before the fixedValue patches so its
+                    // value gets overwritten
+                    for (auto& ppf : tdisp.ref().boundaryFieldRef())
+                    {
+                        ppf == ppf.patchInternalField();
+                    }
+
+                    // Adhere to multi-point constraints
+                    const pointConstraints& pcs = pointConstraints::New(pMesh);
+                    pcs.constrainDisplacement(tdisp.ref(), false);
+
+                    thickness = UIndirectList<point>(tdisp(), mp);
+                }
+
+
+
+                // Print a bit
+                {
+                    // See snappyLayerDriver::calculateLayerThickness.
+                    const auto& pbm = mesh.boundaryMesh();
+                    label maxLen = 0;
+                    for (const label patchi : bufPatchIDs)
+                    {
+                        maxLen = max(maxLen, label(pbm[patchi].name().size()));
+                    }
+
+                    const int oldPrecision = Info.stream().precision();
+
+                    Info<< nl
+                        << setf(ios_base::left) << setw(maxLen) << "patch"
+                        << setw(0) << " faces    layers thickness[m]" << nl
+                        << setf(ios_base::left) << setw(maxLen) << "-----"
+                        << setw(0) << " -----    ------ ------------" << endl;
+
+                    for (const label patchi : bufPatchIDs)
+                    {
+                        Info<< setf(ios_base::left) << setw(maxLen)
+                            << pbm[patchi].name() << setprecision(3)
+                            << " " << setw(8)
+                            << returnReduce(pbm[patchi].size(), sumOp<scalar>())
+                            << " " << setw(6) << 1
+                            << " " << setw(8) << gAverage(mag(thickness))
+                            << endl;
+                    }
+                    Info<< setprecision(oldPrecision) << endl;
+                }
+
+
+                // Do mesh changes : introduce point, faces, cells
+                autoPtr<mapPolyMesh> mapPtr = addBufferLayers
+                (
+                    bufPatchPtr(),
+                    -thickness,  //1e-3,   //cellSizeFraction,
+                    addLayer
+                );
+
+                // Update numbering on baffles, pointToMaster. Note: uses
+                // geometric tolerance - could be avoided since now we have
+                // addPatchCellLayer still intact. However would like to avoid
+                // use of addPatchCellLayer altogether.
+                if (mapPtr)
+                {
+                    // Invalidate extrusion (face numbering might have changed)
+                    ppPtr.clear();
+
+                    snappyLayerDriver::mapFaceZonePoints
+                    (
+                        meshRefiner_,
+                        mapPtr(),
+                        internalBaffles,
+                        pointToMaster
+                    );
+                }
+            }
+
+
+
+            {
+                // Merge duplicated points (this creates illegal cells -
+                // hopefully they will be smoothed out)
+                autoPtr<mapPolyMesh> mapPtr =
+                    meshRefiner_.mergePoints(pointToMaster);
+                if (mapPtr)
+                {
+                    // Invalidate extrusion (point numbering might have changed)
+                    ppPtr.clear();
+
+                    // Update numbering on any baffles
+                    meshRefinement::mapBaffles
+                    (
+                        mesh,
+                        mapPtr().faceMap(),
+                        internalBaffles
+                    );
+                    // Extract baffles across internal faceZones
+                    internalBaffles = meshRefinement::subsetBaffles
+                    (
+                        mesh,
+                        internalFaceZones,
+                        internalBaffles
+                    );
+
+                    if (debug & meshRefinement::MESH)
+                    {
+                        const_cast<Time&>(mesh.time())++;
+                        Info<< "Writing merged points buffer layer mesh"
+                            << " to time " << meshRefiner_.timeName() << endl;
+                        meshRefiner_.write
+                        (
+                            meshRefinement::debugType(debug),
+                            meshRefinement::writeType
+                            (
+                                meshRefinement::writeLevel()
+                              | meshRefinement::WRITEMESH
+                            ),
+                            meshRefiner_.timeName()
+                        );
+                    }
+                }
+            }
+
+
+            Info<< "Inflating buffer layers ..." << endl;
+
+            const pointMesh& pMesh = pointMesh::New(mesh);
+
+            {
+                autoPtr<displacementMotionSolver> motionPtr
+                (
+                    makeMotionSolver
+                    (
+                        pMesh,
+                        snapDict,
+                        bufPatchIDs
+                        //patchConstraints
+                    )
+                );
+
+                // Solve internal displacement
+                tmp<pointField> tnewPoints(motionPtr->newPoints());
+
+                // Move points
+                mesh.movePoints(tnewPoints);
+
+                // Reset moving flag to avoid problems with topo changes
+                mesh.moving(false);
+
+                if (debug & meshRefinement::MESH)
+                {
+                    const_cast<Time&>(mesh.time())++;
+                    Info<< "Writing smoothed buffer layer mesh to time "
+                        << meshRefiner_.timeName() << endl;
+                    meshRefiner_.write
+                    (
+                        meshRefinement::debugType(debug),
+                        meshRefinement::writeType
+                        (
+                            meshRefinement::writeLevel()
+                          | meshRefinement::WRITEMESH
+                        ),
+                        meshRefiner_.timeName()
+                    );
+                }
+            }
+
+            // Update mesh mover
+            ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
+            meshMoverPtr.reset
+            (
+                new motionSmoother
+                (
+                    mesh,
+                    ppPtr(),
+                    adaptPatchIDs,
+                    meshRefinement::makeDisplacementField
+                    (
+                        pointMesh::New(mesh),
+                        adaptPatchIDs
+                    ),
+                    motionDict,
+                    dryRun_
+                )
+            );
+        }
 
 
         //- Only if in feature attraction mode:
@@ -2764,6 +3292,8 @@ void Foam::snappySnapDriver::doSnap
         DynamicList<label> splitFaces;
         //- Indices in face to split across
         DynamicList<labelPair> splits;
+        //- Patch for both sides of the face
+        DynamicList<labelPair> splitPatches;
 
 
         for (label iter = 0; iter < nFeatIter; iter++)
@@ -2811,8 +3341,9 @@ void Foam::snappySnapDriver::doSnap
                 meshRefiner_,
                 globalToMasterPatch_,           // for if strictRegionSnap
                 globalToSlavePatch_,            // for if strictRegionSnap
-                snapDist,
                 pp,
+                pp.localPoints(),
+                snapDist,
 
                 nearestPoint,
                 nearestNormal
@@ -2826,6 +3357,7 @@ void Foam::snappySnapDriver::doSnap
                 (
                     Foam::cos(degToRad(planarAngle)),// planar cos for gaps
                     pp,
+                    pp.localPoints(),
                     nearestPoint,   // surfacepoint from nearest test
                     nearestNormal,  // surfacenormal from nearest test
 
@@ -2838,10 +3370,12 @@ void Foam::snappySnapDriver::doSnap
             {
                 splitFaces.clear();
                 splits.clear();
+                splitPatches.clear();
                 disp = calcNearestSurfaceFeature
                 (
                     snapParams,
                     !doSplit,       // alignMeshEdges
+                    false,          // no special handling for >=3 patch points
                     iter,
                     featureCos,
                     scalar(iter+1)/nFeatIter,
@@ -2849,13 +3383,15 @@ void Foam::snappySnapDriver::doSnap
                     snapDist,
                     disp,
                     nearestNormal,
-                    meshMover,
+                    pp,
+                    pp.localPoints(),
 
                     patchAttraction,
                     patchConstraints,
 
                     splitFaces,
-                    splits
+                    splits,
+                    splitPatches
                 );
             }
 
@@ -2952,12 +3488,14 @@ void Foam::snappySnapDriver::doSnap
                 {
                     labelList oldSplitFaces(std::move(splitFaces));
                     List<labelPair> oldSplits(std::move(splits));
+                    List<labelPair> oldSplitPatches(std::move(splitPatches));
                     forAll(oldSplitFaces, i)
                     {
                         if (duplicateFace[oldSplitFaces[i]] == -1)
                         {
                             splitFaces.append(oldSplitFaces[i]);
                             splits.append(oldSplits[i]);
+                            splitPatches.append(oldSplitPatches[i]);
                         }
                     }
                     nTotalSplit = returnReduce
@@ -2968,10 +3506,15 @@ void Foam::snappySnapDriver::doSnap
                 }
 
                 // Update mesh
+
+                // Reset moving flag to avoid meshPhi problems with topo changes
+                mesh.moving(false);
+
                 meshRefiner_.splitFacesUndo
                 (
                     splitFaces,
                     splits,
+                    splitPatches,
                     motionDict,
 
                     duplicateFace,
@@ -3047,6 +3590,10 @@ void Foam::snappySnapDriver::doSnap
     }
 
 
+    // Reset moving flag to avoid any meshPhi mapping problems
+    mesh.moving(false);
+
+
     // Merge any introduced baffles (from faceZones of faceType 'internal')
     {
         autoPtr<mapPolyMesh> mapPtr = meshRefiner_.mergeZoneBaffles
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.H b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.H
index 5f6ed8fc1bec95b5632319d67d6ca99d5090d1f6..0ed56c89a308ce036378b473831dbad12779132c 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.H
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriver.H
@@ -41,6 +41,7 @@ SourceFiles
 
 #include "meshRefinement.H"
 #include "DynamicField.H"
+#include "pointConstraint.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -52,6 +53,9 @@ class motionSmoother;
 class refinementParameters;
 class snapParameters;
 class pointConstraint;
+class layerParameters;
+class displacementMotionSolver;
+class addPatchCellLayer;
 
 /*---------------------------------------------------------------------------*\
                            Class snappySnapDriver Declaration
@@ -79,6 +83,17 @@ class snappySnapDriver
 
         // Snapping
 
+            //- Top-level: snap onto surface & features and add buffer layer
+            void doSnapBufferLayers
+            (
+                const dictionary& snapDict,
+                const dictionary& motionDict,
+                const meshRefinement::FaceMergeType mergeType,
+                const scalar featureCos,
+                const scalar planarAngle,
+                const snapParameters& snapParams
+            );
+
             //- Calculates (geometric) shared points
             //  Requires bitSet to be sized and initialised
             static label getCollocatedPoints
@@ -106,17 +121,60 @@ class snappySnapDriver
 
             static tmp<pointField> avg
             (
+                const polyMesh& mesh,
+                const bitSet& isMasterPoint,
                 const indirectPrimitivePatch&,
                 const pointField&
             );
 
             //- Calculate displacement per patch point. Wip.
-            static pointField smoothLambdaMuPatchDisplacement
+            static tmp<pointField> smoothLambdaMuPatchDisplacement
             (
-                const motionSmoother& meshMover,
+                const polyMesh& mesh,
+                const indirectPrimitivePatch& pp,
                 const List<labelPair>& baffles
             );
 
+            tmp<scalarField> wantedThickness
+            (
+                const indirectPrimitivePatch& pp,
+                const scalar cellSizeFraction
+            ) const;
+
+            //- Create/update pointMesh
+            const pointMesh& makePointMesh
+            (
+                const indirectPrimitivePatch& pp,
+                const pointConstraintList& pointConstraints,
+                const word& allEdgePatchName,
+                const word& allPointPatchName
+            ) const;
+
+            autoPtr<displacementMotionSolver> makeMotionSolver
+            (
+                const pointMesh& pMesh,
+                const dictionary& snapDict,
+                const labelList& adaptPatchIDs
+            ) const;
+
+            void setDisplacement
+            (
+                const indirectPrimitivePatch& pp,
+                const pointField& patchDisp,
+                const labelList& adaptPatchIDs,
+                const pointField& points0,
+                pointVectorField& fld
+            );
+
+            autoPtr<mapPolyMesh> addBufferLayers
+            (
+                const indirectPrimitivePatch& pp,
+
+                //const scalar cellSizeFraction,
+                const pointField& thickness,
+                // Layer mesh modifier
+                addPatchCellLayer& addLayer
+            );
 
             //- Check that face zones are synced
             void checkCoupledFaceZones() const;
@@ -245,6 +303,7 @@ class snappySnapDriver
                 (
                     const label iter,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& faceSnapDist,
                     vectorField& faceDisp,
                     vectorField& faceSurfaceNormal,
@@ -255,6 +314,7 @@ class snappySnapDriver
                 (
                     const label iter,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
 
                     const vectorField& faceDisp,
                     const vectorField& faceSurfaceNormal,
@@ -284,6 +344,7 @@ class snappySnapDriver
                     const scalar featureCos,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
 
                     const vectorField& rawPatchAttraction,
@@ -302,6 +363,7 @@ class snappySnapDriver
                     const scalar featureCos,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
 
                     const List<List<point>>& pointFaceCentres,
@@ -376,6 +438,7 @@ class snappySnapDriver
                     const scalar concaveCos,
                     const scalar minAreaFraction,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const vectorField& patchAttraction,
                     const List<pointConstraint>& patchConstraints,
                     const vectorField& nearestAttraction,
@@ -395,13 +458,16 @@ class snappySnapDriver
                     const scalar minAreaFraction,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const vectorField& nearestAttraction,
                     const vectorField& nearestNormal,
+                    const List<labelList>& pointFacePatchID,
 
                     vectorField& patchAttraction,
                     List<pointConstraint>& patchConstraints,
                     DynamicList<label>& splitFaces,
-                    DynamicList<labelPair>& splits
+                    DynamicList<labelPair>& splits,
+                    DynamicList<labelPair>& splitPatches
                 ) const;
 
                 //- Avoid attraction across face diagonal since would
@@ -411,6 +477,7 @@ class snappySnapDriver
                     const label iter,
                     const scalar featureCos,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     vectorField& patchAttraction,
                     List<pointConstraint>& patchConstraints
                 ) const;
@@ -457,6 +524,7 @@ class snappySnapDriver
                     const scalar featureCos,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const vectorField& nearestDisp,
                     const label pointi,
@@ -481,6 +549,7 @@ class snappySnapDriver
                     const label iter,
                     const scalar featureCos,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const vectorField& nearestDisp,
 
@@ -500,8 +569,10 @@ class snappySnapDriver
                     const label iter,
                     const scalar featureCos,
                     const bool multiRegionFeatureSnap,
+                    const bool strictRegionFeatureSnap, // special feat-point
 
                     const indirectPrimitivePatch&,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const vectorField& nearestDisp,
 
@@ -528,6 +599,7 @@ class snappySnapDriver
                     const scalar featureCos,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
 
                     // Feature-point to pp point
@@ -545,6 +617,7 @@ class snappySnapDriver
                     const label iter,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
 
                     // Feature-point to pp point
@@ -570,6 +643,7 @@ class snappySnapDriver
                     const bool isRegionEdge,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const label pointi,
                     const point& estimatedPt,
@@ -591,6 +665,7 @@ class snappySnapDriver
                     const bool isRegionEdge,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const label pointi,
                     const point& estimatedPt,
@@ -610,6 +685,7 @@ class snappySnapDriver
                 (
                     const label iter,
                     const bool multiRegionFeatureSnap,
+                    const bool strictRegionFeatureSnap,
 
                     const bool detectBaffles,
                     const bool baffleFeaturePoints,
@@ -620,6 +696,7 @@ class snappySnapDriver
                     const scalar featureCos,
 
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const vectorField& nearestDisp,
                     const vectorField& nearestNormal,
@@ -638,6 +715,7 @@ class snappySnapDriver
                     const label iter,
                     const scalar featureCos,
                     const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     const scalarField& snapDist,
                     const vectorField& nearestAttraction,
 
@@ -653,18 +731,21 @@ class snappySnapDriver
                 (
                     const snapParameters& snapParams,
                     const bool alignMeshEdges,
+                    const bool strictRegionFeatureSnap, //points on >=3 patches
                     const label iter,
                     const scalar featureCos,
                     const scalar featureAttract,
                     const scalarField& snapDist,
                     const vectorField& nearestDisp,
                     const vectorField& nearestNormal,
-                    motionSmoother& meshMover,
+                    const indirectPrimitivePatch& pp,
+                    const pointField& ppLocalPoints,
                     vectorField& patchAttraction,
                     List<pointConstraint>& patchConstraints,
 
                     DynamicList<label>& splitFaces,
-                    DynamicList<labelPair>& splits
+                    DynamicList<labelPair>& splits,
+                    DynamicList<labelPair>& splitPatches
                 ) const;
 
 
@@ -730,7 +811,8 @@ public:
             void detectNearSurfaces
             (
                 const scalar planarCos,
-                const indirectPrimitivePatch&,
+                const indirectPrimitivePatch& pp,
+                const pointField& ppLocalPoints,
                 const pointField& nearestPoint,
                 const vectorField& nearestNormal,
                 vectorField& disp
@@ -745,8 +827,9 @@ public:
                 const meshRefinement& meshRefiner,
                 const labelList& globalToMasterPatch,
                 const labelList& globalToSlavePatch,
+                const indirectPrimitivePatch& pp,
+                const pointField& ppLocalPoints,
                 const scalarField& snapDist,
-                const indirectPrimitivePatch&,
                 pointField& nearestPoint,
                 vectorField& nearestNormal
             );
@@ -790,6 +873,7 @@ public:
                 const labelList& preserveFaces
             );
 
+            //- Snap onto surface & features
             void doSnap
             (
                 const dictionary& snapDict,
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverBufferLayers.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverBufferLayers.C
new file mode 100644
index 0000000000000000000000000000000000000000..e722909b518b042df9653d224d346616b52e0f99
--- /dev/null
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverBufferLayers.C
@@ -0,0 +1,2019 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Description
+    All to do with snapping to the surface with buffer layer
+
+\*----------------------------------------------------------------------------*/
+
+#include "snappySnapDriver.H"
+#include "polyTopoChange.H"
+#include "syncTools.H"
+#include "fvMesh.H"
+#include "Time.H"
+#include "OBJstream.H"
+#include "mapPolyMesh.H"
+#include "snapParameters.H"
+#include "unitConversion.H"
+#include "PatchTools.H"
+#include "profiling.H"
+#include "addPatchCellLayer.H"
+#include "snappyLayerDriver.H"
+#include "weightedPosition.H"
+
+#include "localPointRegion.H"
+#include "pointConstraints.H"
+#include "displacementMotionSolver.H"
+#include "meshPointPatch.H"
+#include "processorPointPatch.H"
+#include "dummyTransform.H"
+#include "faceSet.H"
+#include "motionSmoother.H"
+#include "tetDecomposer.H"
+#include "tetMatcher.H"
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+Foam::tmp<Foam::pointField> Foam::snappySnapDriver::avg
+(
+    const polyMesh& mesh,
+    const bitSet& isMasterPoint,
+    const indirectPrimitivePatch& pp,
+    const pointField& localPoints
+)
+{
+    const labelListList& pointEdges = pp.pointEdges();
+    const labelList& meshPoints = pp.meshPoints();
+    const edgeList& edges = pp.edges();
+
+    Field<weightedPosition> wps
+    (
+        pointEdges.size(),
+        pTraits<weightedPosition>::zero
+    );
+
+    // Calculate sum of all contributions (so not positions)
+    forAll(pointEdges, verti)
+    {
+        weightedPosition& wp = wps[verti];
+        for (const label edgei : pointEdges[verti])
+        {
+            const label otherVerti = edges[edgei].otherVertex(verti);
+
+            if (isMasterPoint[meshPoints[otherVerti]])
+            {
+                wp.first() += 1.0;
+                wp.second() += localPoints[otherVerti];
+            }
+        }
+    }
+
+    weightedPosition::syncPoints(mesh, meshPoints, wps);
+
+    tmp<pointField> tavg(new pointField(wps.size()));
+    pointField& avg = tavg.ref();
+
+    forAll(wps, verti)
+    {
+        const weightedPosition& wp = wps[verti];
+
+        if (mag(wp.first()) < VSMALL)
+        {
+            // Set to zero?
+            avg[verti] = Zero;
+        }
+        else
+        {
+            avg[verti] = wp.second()/wp.first();
+        }
+    }
+
+    return tavg;
+}
+
+
+Foam::tmp<Foam::pointField>
+Foam::snappySnapDriver::smoothLambdaMuPatchDisplacement
+(
+    const polyMesh& mesh,
+    const indirectPrimitivePatch& pp,
+    const List<labelPair>& baffles
+)
+{
+    const bitSet isMasterPoint(syncTools::getMasterPoints(mesh));
+
+    pointField newLocalPoints(pp.localPoints());
+
+    const label iters = 90;
+    const scalar lambda = 0.33;
+    const scalar mu = 0.34;
+
+    for (label iter = 0; iter < iters; iter++)
+    {
+        // Lambda
+        newLocalPoints =
+            (1 - lambda)*newLocalPoints
+          + lambda*avg(mesh, isMasterPoint, pp, newLocalPoints);
+
+        // Mu
+        newLocalPoints =
+            (1 + mu)*newLocalPoints
+          - mu*avg(mesh, isMasterPoint, pp, newLocalPoints);
+    }
+    return newLocalPoints-pp.localPoints();
+}
+
+
+Foam::tmp<Foam::scalarField>
+Foam::snappySnapDriver::wantedThickness
+(
+    const indirectPrimitivePatch& pp,
+    const scalar cellSizeFraction
+) const
+{
+    fvMesh& mesh = meshRefiner_.mesh();
+
+    const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
+    const labelList& owner = mesh.faceOwner();
+
+    // Undistorted edge length
+    const scalar edge0Len =
+        meshRefiner_.meshCutter().level0EdgeLength();
+
+
+    tmp<scalarField> tthickness(tmp<scalarField>::New(pp.nPoints()));
+    scalarField& thickness = tthickness.ref();
+
+    labelList maxPointLevel(pp.nPoints(), labelMin);
+
+    forAll(pp, i)
+    {
+        label ownLevel = cellLevel[owner[pp.addressing()[i]]];
+
+        const face& f = pp.localFaces()[i];
+
+        forAll(f, fp)
+        {
+            maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh,
+        pp.meshPoints(),
+        maxPointLevel,
+        maxEqOp<label>(),
+        labelMin            // null value
+    );
+
+    forAll(thickness, pointi)
+    {
+        const scalar edgeLen = edge0Len/(1<<maxPointLevel[pointi]);
+        thickness[pointi] = cellSizeFraction*edgeLen;
+    }
+    return tthickness;
+}
+
+
+//const Foam::pointMesh& Foam::snappySnapDriver::makePointMesh
+//(
+//    const indirectPrimitivePatch& pp,
+//    const pointConstraintList& pointConstraints,
+//    const word& allEdgePatchName,
+//    const word& allPointPatchName
+//) const
+//{
+//    fvMesh& mesh = meshRefiner_.mesh();
+//
+//    if (pointConstraints.size() != pp.nPoints())
+//    {
+//        FatalErrorInFunction<< "pointConstraints:" << pointConstraints.size()
+//            << " pp:" << pp.nPoints() << exit(FatalError);
+//    }
+//
+//
+//    // Expand pointConstraints to all meshPoints
+//    pointConstraintList meshPointConstraints(mesh.nPoints());
+//    UIndirectList<pointConstraint>(meshPointConstraints, pp.meshPoints()) =
+//        pointConstraints;
+//
+//    const auto combineConstraints = [&]
+//    (
+//        pointConstraint& x,
+//        const pointConstraint& y
+//    )
+//    {
+//        x.combine(y);
+//    };
+//
+//
+//    syncTools::syncPointList
+//    (
+//        mesh,
+//        meshPointConstraints,
+//        combineConstraints,
+//        pointConstraint(),
+//        dummyTransform()
+//    );
+//
+//
+//    // Sort point constraints:
+//    // - 0 : does not happen?
+//    // - 1 : attract to surface
+//    // - 2 : attract to feature edge
+//    // - 3 : attract to feature point
+//
+//    DynamicList<label> featEdgeMeshPoints(pointConstraints.size());
+//    DynamicList<label> featPointMeshPoints(pointConstraints.size());
+//    forAll(meshPointConstraints, pointi)
+//    {
+//        if (meshPointConstraints[pointi].first() == 2)
+//        {
+//            featEdgeMeshPoints.append(pointi);
+//        }
+//        else if (meshPointConstraints[pointi].first() == 3)
+//        {
+//            featPointMeshPoints.append(pointi);
+//        }
+//    }
+//
+//    // Lookup / construct (from polyPatches) the pointMesh
+//    auto& pMesh = pointMesh::New(meshRefiner_.mesh());
+//
+//    pointBoundaryMesh& pointBm =
+//        const_cast<pointBoundaryMesh&>(pMesh.boundary());
+//
+//    // Check if already has constraint patches
+//    label edgePatchi = pointBm.findPatchID(allEdgePatchName);
+//    if (edgePatchi != -1)
+//    {
+//        // Delete patch. TBD: clear patchGroup
+//        pointBm.set(edgePatchi, nullptr);
+//    }
+//    label pointPatchi = pointBm.findPatchID(allPointPatchName);
+//    if (pointPatchi != -1)
+//    {
+//        // Delete patch. TBD: clear patchGroup
+//        pointBm.set(pointPatchi, nullptr);
+//    }
+//
+//    // Add additional point patches in order:
+//    // - polyPatch based
+//    // - featEdge-based constraints
+//    // - featPoint-based constraints (so can override edge-based constraints)
+//    // - processor boundaries (or should this be all constraint patches, e.g.
+//    //   symmetry plane. Note: hopefully this is already handled in the
+//    //   feature extraction ...)
+//
+//    if (returnReduce(featEdgeMeshPoints.size(), sumOp<label>()))
+//    {
+//        if (edgePatchi != -1)
+//        {
+//            // Override patch
+//            const_cast<pointBoundaryMesh&>(pointBm).set
+//            (
+//                edgePatchi,
+//                new meshPointPatch
+//                (
+//                    allEdgePatchName,
+//                    featEdgeMeshPoints,
+//                    List<pointConstraint>
+//                    (
+//                        meshPointConstraints,
+//                        featEdgeMeshPoints
+//                    ),
+//                    edgePatchi,
+//                    pointBm,
+//                    meshPointPatch::typeName
+//                )
+//            );
+//        }
+//        else
+//        {
+//            // Append
+//            const_cast<pointBoundaryMesh&>(pointBm).push_back
+//            (
+//                new meshPointPatch
+//                (
+//                    allEdgePatchName,
+//                    featEdgeMeshPoints,
+//                    List<pointConstraint>
+//                    (
+//                        meshPointConstraints,
+//                        featEdgeMeshPoints
+//                    ),
+//                    pointBm.size(),
+//                    pointBm,
+//                    meshPointPatch::typeName
+//                )
+//            );
+//        }
+//    }
+//    if (returnReduce(featPointMeshPoints.size(), sumOp<label>()))
+//    {
+//        if (pointPatchi != -1)
+//        {
+//            // Override patch
+//            const_cast<pointBoundaryMesh&>(pointBm).set
+//            (
+//                pointPatchi,
+//                new meshPointPatch
+//                (
+//                    allPointPatchName,
+//                    featPointMeshPoints,
+//                    List<pointConstraint>
+//                    (
+//                        meshPointConstraints,
+//                        featPointMeshPoints
+//                    ),
+//                    pointPatchi,
+//                    pointBm,
+//                    meshPointPatch::typeName
+//                )
+//            );
+//        }
+//        else
+//        {
+//            // Append
+//            const_cast<pointBoundaryMesh&>(pointBm).push_back
+//            (
+//                new meshPointPatch
+//                (
+//                    allPointPatchName,
+//                    featPointMeshPoints,
+//                    List<pointConstraint>
+//                    (
+//                        meshPointConstraints,
+//                        featPointMeshPoints
+//                    ),
+//                    pointBm.size(),
+//                    pointBm,
+//                    meshPointPatch::typeName
+//                )
+//            );
+//        }
+//    }
+//
+//    // Shuffle into order
+//    labelList oldToNew(pointBm.size());
+//    label newPatchi = 0;
+//    forAll(pointBm, patchi)
+//    {
+//        if (!isA<processorPointPatch>(pointBm[patchi]))
+//        {
+//            oldToNew[patchi] = newPatchi++;
+//        }
+//    }
+//    forAll(pointBm, patchi)
+//    {
+//        if (isA<processorPointPatch>(pointBm[patchi]))
+//        {
+//            oldToNew[patchi] = newPatchi++;
+//        }
+//    }
+//    pointBm.reorder(oldToNew, true);
+//
+//    return pMesh;
+//}
+
+
+Foam::autoPtr<Foam::displacementMotionSolver>
+Foam::snappySnapDriver::makeMotionSolver
+(
+    const pointMesh& pMesh,
+    const dictionary& snapDict,
+    const labelList& adaptPatchIDs
+//    const pointConstraintList& pointConstraints,
+) const
+{
+    fvMesh& mesh = meshRefiner_.mesh();
+
+    tmp<pointVectorField> tallDisp
+    (
+        meshRefinement::makeDisplacementField
+        (
+            pMesh,
+            adaptPatchIDs
+        )
+    );
+
+    // Make sure the pointDisplacement is not registered (since
+    // displacementMotionSolver itself holds it)
+    tallDisp.ref().checkOut();
+
+    autoPtr<displacementMotionSolver> motionPtr
+    (
+        displacementMotionSolver::New
+        (
+            snapDict.get<word>("solver"),
+            mesh,
+            IOdictionary
+            (
+                IOobject
+                (
+                    "motionSolverDict",
+                    pMesh.thisDb().time().constant(),
+                    pMesh.thisDb(),
+                    IOobject::NO_READ,
+                    IOobject::NO_WRITE,
+                    false
+                ),
+                snapDict
+            ),
+            tallDisp(),
+            pointIOField
+            (
+                IOobject
+                (
+                    "points0",
+                    pMesh.thisDb().time().constant(),
+                    polyMesh::meshSubDir,
+                    pMesh.thisDb(),
+                    IOobject::NO_READ,
+                    IOobject::NO_WRITE,
+                    false
+                ),
+                mesh.points()
+            )
+        )
+    );
+    return motionPtr;
+}
+
+
+void Foam::snappySnapDriver::setDisplacement
+(
+    const indirectPrimitivePatch& pp,
+    const pointField& patchDisp,    // displacement w.r.t. current mesh
+    const labelList& adaptPatchIDs,
+    const pointField& points0,
+    pointVectorField& fld           // displacement w.r.t. points0
+)
+{
+    const pointMesh& pMesh = fld.mesh();
+    const pointField& points = pMesh().points();
+    const labelList& meshPoints = pp.meshPoints();
+
+    if
+    (
+        (points0.size() != points.size())
+     || (points0.size() != fld.size())
+     || (points0.size() != pMesh.size())
+     || (meshPoints.size() != patchDisp.size())
+    )
+    {
+        FatalErrorInFunction
+            << "Sizing :"
+            << " points0.size():" << points0.size()
+            << " points.size():" << points.size()
+            << " fld.size():" << fld.size()
+            << " patchDisp.size():" << patchDisp.size()
+            << " meshPoints.size():" << meshPoints.size()
+            << " mesh.nPoints():" << pMesh.size()
+            << exit(FatalError);
+    }
+
+
+    // Problem is that the patchDisp might not be consistent (parallel etc)
+    // across shared points so expand to mesh points
+
+    pointField meshDisp(pMesh.size(), Zero);
+
+    forAll(meshPoints, patchPointi)
+    {
+        const label meshPointi = meshPoints[patchPointi];
+
+        meshDisp[meshPointi] =
+            patchDisp[patchPointi]+points[meshPointi]-points0[meshPointi];
+    }
+
+    // Assign to bc
+    pointVectorField::Boundary& bfld = fld.boundaryFieldRef();
+    for (const label patchi : adaptPatchIDs)
+    {
+        bfld[patchi] == pointField(meshDisp, bfld[patchi].patch().meshPoints());
+    }
+
+    // Apply multi-patch constraints. Problem: most patches originate from
+    // meshing so are type 'wall'. The pointConstraints are only on any points
+    // remaining from the starting mesh.
+    const pointConstraints& pcs = pointConstraints::New(pMesh);
+    pcs.constrainDisplacement(fld, true);
+}
+
+
+Foam::autoPtr<Foam::mapPolyMesh> Foam::snappySnapDriver::addBufferLayers
+(
+    const indirectPrimitivePatch& pp,
+    const pointField& thickness,
+    // Layer mesh modifier
+    addPatchCellLayer& addLayer
+)
+{
+    fvMesh& mesh = meshRefiner_.mesh();
+
+    // Introduce single layer of cells. Straight from snappyLayerDriver
+
+    // Global face indices engine
+    const globalIndex globalFaces(mesh.nFaces());
+
+    // Determine extrudePatch.edgeFaces in global numbering (so across
+    // coupled patches). This is used only to string up edges
+    // between coupled
+    // faces (all edges between same (global)face indices get extruded).
+    labelListList edgeGlobalFaces
+    (
+        addPatchCellLayer::globalEdgeFaces
+        (
+            mesh,
+            globalFaces,
+            pp
+        )
+    );
+
+
+
+    // Use global edge - face connectivity to
+    // - disable any non-manifold extrusions
+    // - boundary edges can be extruded - is handled by addPatchCellLayer
+    // - what about setting numLayers to 0 to disable layers? Should that
+    //   affect buffer layer addition? Guess not since buffer layer is
+    //   to aid snapping ...
+    labelList nFaceLayers(pp.size(), 1);
+    labelList nPointLayers(pp.nPoints(), 1);
+    forAll(edgeGlobalFaces, edgei)
+    {
+        if (edgeGlobalFaces[edgei].size() > 2)
+        {
+            const edge& e = pp.edges()[edgei];
+            const edge meshE(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
+
+            nPointLayers[e[0]] = 0;
+            nPointLayers[e[1]] = 0;
+        }
+        //else if (edgeGlobalFaces[edgei].size() == 1)
+        //{
+        //    const edge& e = pp.edges()[edgei];
+        //    const edge meshE(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
+        //
+        //    nPointLayers[e[0]] = 0;
+        //    nPointLayers[e[1]] = 0;
+        //}
+        else if (edgeGlobalFaces[edgei].size() == 0)
+        {
+            const edge& e = pp.edges()[edgei];
+            const edge meshE(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]);
+            FatalErrorInFunction << "Edge:" << meshE
+                << " At:" << meshE.line(mesh.points())
+                << " has no faces!" << exit(FatalError);
+        }
+    }
+
+    syncTools::syncPointList
+    (
+        mesh,
+        pp.meshPoints(),
+        nPointLayers,
+        minEqOp<label>(),
+        labelMax            // null value
+    );
+
+    forAll(pp.localFaces(), facei)
+    {
+        const face& f = pp.localFaces()[facei];
+        const UIndirectList<label> pLayers(nPointLayers, f);
+        if (!pLayers.found(label(1)))
+        {
+            nFaceLayers[facei] = 0;
+        }
+    }
+
+
+
+    // Determine patches for extruded boundary edges. Adds any
+    // additional processor patches (since extruding coupled edge can cause
+    // additional connectivity)
+
+    labelList edgePatchID;
+    labelList edgeZoneID;
+    boolList edgeFlip;
+    labelList inflateFaceID;
+    snappyLayerDriver::determineSidePatches
+    (
+        meshRefiner_,
+        globalFaces,
+        edgeGlobalFaces,
+        pp,
+
+        edgePatchID,
+        edgeZoneID,
+        edgeFlip,
+        inflateFaceID
+    );
+
+
+    // Mesh topo change engine. Insert current mesh.
+    polyTopoChange meshMod(mesh);
+
+
+    // Add topo regardless of whether extrudeStatus is extruderemove.
+    // Not add layer if patchDisp is zero.
+
+    addLayer.setRefinement
+    (
+        globalFaces,
+        edgeGlobalFaces,
+
+        scalarField(pp.nPoints(), 1),  // expansion ratio
+        pp,
+        bitSet(pp.size()),          // no flip
+
+        edgePatchID,    // boundary patch for extruded boundary edges
+        edgeZoneID,     // zone for extruded edges
+        edgeFlip,
+        inflateFaceID,
+
+
+        labelList(0),   // exposed patchIDs, not used for adding layers
+        nFaceLayers,
+        nPointLayers,
+        thickness,  //patchAttraction,
+
+        meshMod
+    );
+
+    // Apply the stored topo changes to the current mesh.
+    autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
+    mapPolyMesh& map = *mapPtr;
+
+    // Update fields
+    mesh.updateMesh(map);
+
+    // Move mesh (since morphing does not do this)
+    if (map.hasMotionPoints())
+    {
+        mesh.movePoints(map.preMotionPoints());
+    }
+    else
+    {
+        // Hack to remove meshPhi - mapped incorrectly. TBD.
+        mesh.clearOut();
+    }
+
+    // Reset the instance for if in overwrite mode
+    mesh.setInstance(meshRefiner_.timeName());
+
+    // Update numbering on layer
+    addLayer.updateMesh
+    (
+        map,
+        identity(pp.size()),
+        identity(pp.nPoints())
+    );
+
+    // Update intersections
+    const labelListList addedCells(addLayer.addedCells());
+    bitSet isChangedFace(mesh.nFaces());
+    for (const labelList& faceToCells : addedCells)
+    {
+        for (const label celli : faceToCells)
+        {
+            isChangedFace.set(mesh.cells()[celli]);
+        }
+    }
+    meshRefiner_.updateMesh(map, isChangedFace.toc());
+
+    if (debug & meshRefinement::MESH)
+    {
+        const_cast<Time&>(mesh.time())++;
+        Info<< "Writing mesh-with-layer to time "
+            << meshRefiner_.timeName() << endl;
+        meshRefiner_.write
+        (
+            meshRefinement::debugType(debug),
+            meshRefinement::writeType
+            (
+                meshRefinement::writeLevel()
+              | meshRefinement::WRITEMESH
+            ),
+            meshRefiner_.timeName()
+        );
+    }
+    return mapPtr;
+}
+
+
+void Foam::snappySnapDriver::doSnapBufferLayers
+(
+    const dictionary& snapDict,
+    const dictionary& motionDict,
+    const meshRefinement::FaceMergeType mergeType,
+    const scalar featureCos,
+    const scalar planarAngle,
+    const snapParameters& snapParams
+)
+{
+    addProfiling(snap, "snappyHexMesh::snap");
+    fvMesh& mesh = meshRefiner_.mesh();
+
+    Info<< nl
+        << "Morphing phase" << nl
+        << "--------------" << nl
+        << endl;
+
+
+    // Name of pointPatch for any points attracted to feature edges
+    //const word allEdgePatchName("boundaryEdges");
+    // Name of pointPatch for any points attracted to feature points
+    //const word allPointPatchName("boundaryPoints");
+
+
+    // faceZone handling
+    // ~~~~~~~~~~~~~~~~~
+    //
+    // We convert all faceZones into baffles during snapping so we can use
+    // a standard mesh motion (except for the mesh checking which for baffles
+    // created from internal faces should check across the baffles). The state
+    // is stored in two variables:
+    //      baffles : pairs of boundary faces
+    //      duplicateFace : from mesh face to its baffle colleague (or -1 for
+    //                      normal faces)
+    // There are three types of faceZones according to the faceType property:
+    //
+    // internal
+    // --------
+    // - baffles: need to be checked across
+    // - duplicateFace: from face to duplicate face. Contains
+    //   all faces on faceZone to prevents merging patch faces.
+    //
+    // baffle
+    // ------
+    // - baffles: no need to be checked across
+    // - duplicateFace: contains all faces on faceZone to prevent
+    //   merging patch faces.
+    //
+    // boundary
+    // --------
+    // - baffles: no need to be checked across. Also points get duplicated
+    //            so will no longer be baffles
+    // - duplicateFace: contains no faces on faceZone since both sides can
+    //   merge faces independently.
+
+
+
+    // faceZones of type internal
+    const labelList internalFaceZones
+    (
+        meshRefiner_.getZones
+        (
+            List<surfaceZonesInfo::faceZoneType>
+            (
+                1,
+                surfaceZonesInfo::INTERNAL
+            )
+        )
+    );
+
+
+    // Create baffles (pairs of faces that share the same points)
+    // Baffles stored as owner and neighbour face that have been created.
+    {
+        List<labelPair> baffles;
+        labelList originatingFaceZone;
+        meshRefiner_.createZoneBaffles
+        (
+            identity(mesh.faceZones().size()),
+            baffles,
+            originatingFaceZone
+        );
+    }
+
+
+    // Duplicate points on faceZones of type boundary
+    meshRefiner_.dupNonManifoldBoundaryPoints();
+
+    // Extract baffles across internal faceZones (for checking mesh quality
+    // across)
+    labelPairList internalBaffles
+    (
+        meshRefiner_.subsetBaffles
+        (
+            mesh,
+            internalFaceZones,
+            localPointRegion::findDuplicateFacePairs(mesh)
+        )
+    );
+
+
+    bool doFeatures = true; //false;
+    label nFeatIter = 1;
+    if (snapParams.nFeatureSnap() > 0)
+    {
+        doFeatures = true;
+
+        if (!dryRun_)
+        {
+            nFeatIter = snapParams.nFeatureSnap();
+        }
+
+        Info<< "Snapping to features in " << nFeatIter
+            << " iterations ..." << endl;
+    }
+
+    // Get the labels of added patches.
+    const labelList adaptPatchIDs(meshRefiner_.meshedPatches());
+
+    autoPtr<indirectPrimitivePatch> ppPtr
+    (
+        meshRefinement::makePatch
+        (
+            mesh,
+            adaptPatchIDs
+        )
+    );
+
+
+    if (debug)
+    {
+        const fileName dir(mesh.time().path());
+        mkDir(dir);
+        OBJstream str
+        (
+            dir
+          / "pp_initial_" + meshRefiner_.timeName() + ".obj"
+        );
+        str.write
+        (
+            ppPtr().localFaces(),
+            ppPtr().localPoints(),
+            false
+        );
+    }
+
+
+    // Maximum distance to attract to nearest feature on surface
+    scalarField snapDist(calcSnapDistance(mesh, snapParams, ppPtr()));
+
+
+    // Smooth patch points. Equivalent of preSmoothPatch but using mesh
+    // motion solver.
+    vectorField patchDisp
+    (
+        smoothLambdaMuPatchDisplacement
+        (
+            mesh,
+            ppPtr(),
+            internalBaffles
+        )
+    );
+    pointField ppLocalPoints(ppPtr().localPoints()+patchDisp);
+
+    const bool smoothInternal = true;
+    if (smoothInternal)
+    {
+        // Create pointMesh with the correct patches
+        //const pointMesh& pMesh = makePointMesh
+        //(
+        //    ppPtr(),
+        //    patchConstraints,
+        //    allEdgePatchName,
+        //    allPointPatchName
+        //);
+        const pointMesh& pMesh = pointMesh::New(mesh);
+
+        autoPtr<displacementMotionSolver> motionPtr
+        (
+            makeMotionSolver
+            (
+                pMesh,
+                snapDict,
+                adaptPatchIDs
+                //patchConstraints
+            )
+        );
+
+        // Insert as bc to motionSmoother. Note that this takes displacement
+        // relative to points0
+        setDisplacement
+        (
+            ppPtr(),
+            patchDisp,
+            adaptPatchIDs,
+            motionPtr().points0(),
+            motionPtr().pointDisplacement()
+        );
+        // Solve internal displacement
+        tmp<pointField> tnewPoints(motionPtr->newPoints());
+
+        // Move points
+        mesh.movePoints(tnewPoints);
+
+        // Update pp for new mesh points. Ok as long as we also update geometry
+        // and wanted displacement (usually zero if mesh motion has succeeded)
+        ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+        patchDisp -= (ppLocalPoints-ppPtr().localPoints());
+
+        if (debug & meshRefinement::MESH)
+        {
+            const_cast<Time&>(mesh.time())++;
+            Info<< "Writing smoothed mesh to time "
+                << meshRefiner_.timeName() << endl;
+            meshRefiner_.write
+            (
+                meshRefinement::debugType(debug),
+                meshRefinement::writeType
+                (
+                    meshRefinement::writeLevel()
+                  | meshRefinement::WRITEMESH
+                ),
+                meshRefiner_.timeName()
+            );
+        }
+    }
+
+
+    // Construct iterative mesh mover.
+    Info<< "Constructing mesh displacer ..." << endl;
+    Info<< "Using mesh parameters " << motionDict << nl << endl;
+
+    autoPtr<displacementMotionSolver> motionPtr
+    (
+        makeMotionSolver
+        (
+            pointMesh::New(mesh),
+            snapDict,
+            adaptPatchIDs
+            //patchConstraints
+        )
+    );
+    autoPtr<motionSmoother> meshMoverPtr
+    (
+        new motionSmoother
+        (
+            mesh,
+            ppPtr(),
+            adaptPatchIDs,
+            motionPtr().pointDisplacement(),
+            motionDict,
+            dryRun_
+        )
+    );
+
+
+    // Check initial mesh
+    Info<< "Checking initial mesh ..." << endl;
+    labelHashSet wrongFaces(mesh.nFaces()/100);
+    motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces, dryRun_);
+    const label nInitErrors = returnReduce
+    (
+        wrongFaces.size(),
+        sumOp<label>()
+    );
+
+    Info<< "Detected " << nInitErrors << " illegal faces"
+        << " (concave, zero area or negative cell pyramid volume)"
+        << endl;
+
+
+    Info<< "Checked initial mesh in = "
+        << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
+
+
+
+    //- Only if in feature attraction mode:
+    // Point on nearest feature
+    vectorField patchFeaturePoint(ppPtr().nPoints(), Zero);
+    // Constraints at feature
+    List<pointConstraint> patchConstraints(ppPtr().nPoints());
+
+    for (label iter = 0; iter < nFeatIter; iter++)
+    {
+        Info<< nl
+            << "Morph iteration " << iter << nl
+            << "-----------------" << endl;
+
+
+        // Calculate displacement at every patch point if we need it:
+        // - if automatic near-surface detection
+        // - if face splitting active
+        pointField nearestPoint(ppPtr().nPoints(), vector::max);
+        vectorField nearestNormal(ppPtr().nPoints(), Zero);
+
+
+        const bool strictRegionSnap
+        (
+            iter < nFeatIter/2
+          ? snapParams.strictRegionSnap()
+          : Switch(true)
+        );
+
+        vectorField disp = calcNearestSurface
+        (
+            strictRegionSnap,               // attract points to region only
+            meshRefiner_,
+            globalToMasterPatch_,           // for if strictRegionSnap
+            globalToSlavePatch_,            // for if strictRegionSnap
+            ppPtr(),
+            ppLocalPoints,
+            snapDist,                       // max snap distance
+
+            nearestPoint,
+            nearestNormal
+        );
+
+        // Override displacement at thin gaps
+        if (snapParams.detectNearSurfacesSnap())
+        {
+            detectNearSurfaces
+            (
+                Foam::cos(degToRad(planarAngle)),// planar cos for gaps
+                ppPtr(),
+                ppLocalPoints,
+                nearestPoint,   // surfacepoint from nearest test
+                nearestNormal,  // surfacenormal from nearest test
+
+                disp
+            );
+        }
+
+        // Override displacement with feature edge attempt
+        if (doFeatures)
+        {
+            //- Any faces to split
+            DynamicList<label> splitFaces;
+            //- Indices in face to split across
+            DynamicList<labelPair> splits;
+            //- Patches for split face
+            DynamicList<labelPair> splitPatches;
+
+            // Offset to project to nearest feature. Use in combination with
+            // patchConstraints.
+            vectorField patchAttraction;
+
+            disp = calcNearestSurfaceFeature
+            (
+                snapParams,
+                false,              // no alignMeshEdges
+                true,               // check >=3 patch points
+
+                iter,
+                featureCos,
+                scalar(iter+1)/nFeatIter,
+
+                snapDist,
+                disp,               // nearest surface
+                nearestNormal,
+                ppPtr(),
+                ppLocalPoints,
+
+                patchAttraction,    // offset wrt ppLocalPoints to nearest
+                                    // feature edge/point
+                patchConstraints,   // feature type + constraint
+
+                splitFaces,
+                splits,
+                splitPatches
+            );
+
+
+            // Freeze points on exposed points/faces
+            freezeExposedPoints
+            (
+                meshRefiner_,
+                "frozenFaces",      // faceZone name
+                "frozenPoints",     // pointZone name
+                ppPtr(),
+                disp
+            );
+
+            patchFeaturePoint = ppLocalPoints+patchAttraction;
+
+            if (debug)
+            {
+                OBJstream str
+                (
+                    mesh.time().path()
+                  / "calcNearestSurfaceFeature"
+                  + meshRefiner_.timeName()
+                  + ".obj"
+                );
+                forAll(ppLocalPoints, pointi)
+                {
+                    const point& pt = ppLocalPoints[pointi];
+                    str.write(linePointRef(pt, pt+disp[pointi]));
+                }
+            }
+
+
+
+            // Split any faces:
+            // - does not move/add any points
+            // - tries to move new faces to correct patch
+
+            if (returnReduce(splitFaces.size(), sumOp<label>()))
+            {
+                polyTopoChange meshMod(mesh);
+
+                // Insert the mesh changes
+                meshRefiner_.doSplitFaces
+                (
+                    splitFaces,
+                    splits,
+                    splitPatches,
+                    meshMod
+                );
+
+                // Save old meshPoints before changing mesh
+                const Map<label> oldMeshPointMap(ppPtr->meshPointMap());
+                Pout<< "old pp points:" << ppPtr->nPoints()
+                    << " oldMeshPointMap:" << oldMeshPointMap.size()
+                    << endl;
+
+                // Remove any unnecessary fields
+                meshMoverPtr.clear();
+                motionPtr.clear();
+                ppPtr.clear();
+                mesh.clearOut();
+                mesh.moving(false);
+
+                // Change the mesh (no inflation)
+                autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
+                mapPolyMesh& map = *mapPtr;
+
+                // Update fields
+                mesh.updateMesh(map);
+
+                // Move mesh (since morphing might not do this)
+                if (map.hasMotionPoints())
+                {
+                    mesh.movePoints(map.preMotionPoints());
+                }
+                else
+                {
+                    mesh.clearOut();
+                }
+
+                // Reset the instance for if in overwrite mode
+                mesh.setInstance(meshRefiner_.timeName());
+                meshRefiner_.setInstance(mesh.facesInstance());
+
+                // Update intersections on split faces
+                {
+                    DynamicList<label> changedFaces(splitFaces.size());
+                    Map<label> splitFacesMap(splitFaces.size());
+                    forAll(splitFaces, i)
+                    {
+                        splitFacesMap.insert(splitFaces[i], i);
+                    }
+                    forAll(map.faceMap(), facei)
+                    {
+                        if (splitFacesMap.find(map.faceMap()[facei]))
+                        {
+                            changedFaces.append(facei);
+                        }
+                    }
+                    // Update intersections on changed faces
+                    meshRefiner_.updateMesh
+                    (
+                        map,
+                        meshRefiner_.growFaceCellFace(changedFaces)
+                    );
+                }
+
+                if (debug&meshRefinement::MESH)
+                {
+                    const_cast<Time&>(mesh.time())++;
+                    Info<< "Writing split-faces mesh to time "
+                        << meshRefiner_.timeName() << endl;
+                    meshRefiner_.write
+                    (
+                        meshRefinement::debugType(debug),
+                        meshRefinement::writeType
+                        (
+                            meshRefinement::writeLevel()
+                          | meshRefinement::WRITEMESH
+                        ),
+                        mesh.time().path()/meshRefiner_.timeName()
+                    );
+                }
+
+
+
+                // Update local mesh data
+                // ~~~~~~~~~~~~~~~~~~~~~~
+
+                Info<< "Updating for face-splitting" << endl;
+
+                // baffles
+                forAll(internalBaffles, i)
+                {
+                    labelPair& baffle = internalBaffles[i];
+                    baffle.first() = map.reverseFaceMap()[baffle.first()];
+                    baffle.second() = map.reverseFaceMap()[baffle.second()];
+                }
+
+                // re-do patch (since faces might have been split)
+                ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
+                motionPtr = makeMotionSolver
+                (
+                    pointMesh::New(mesh),
+                    snapDict,
+                    adaptPatchIDs
+                    //patchConstraints
+                );
+                meshMoverPtr.reset
+                (
+                    new motionSmoother
+                    (
+                        mesh,
+                        ppPtr(),
+                        adaptPatchIDs,
+                        motionPtr().pointDisplacement(),
+                        motionDict,
+                        dryRun_
+                    )
+                );
+
+                const auto& mp = ppPtr->meshPoints();
+                // pointMap (new-to-old) for pp points. Note: no points changed
+                // but local point ordering might have changed since faces
+                // split.
+                labelList ppMap(mp.size());
+                forAll(mp, i)
+                {
+                    ppMap[i] = oldMeshPointMap[mp[i]];
+                }
+                // patchDisp
+                meshRefinement::updateList(ppMap, vector::zero, patchDisp);
+                // snapDist
+                meshRefinement::updateList(ppMap, scalar(0), snapDist);
+                // patchFeaturePoint
+                meshRefinement::updateList
+                (
+                    ppMap,
+                    vector::zero,
+                    patchFeaturePoint
+                );
+                // patchConstraints
+                meshRefinement::updateList
+                (
+                    ppMap,
+                    pointConstraint(),
+                    patchConstraints
+                );
+//                // nearestPoint
+//                meshRefinement::updateList(ppMap, vector::zero, nearestPoint);
+//                // nearestNormal
+//                meshRefinement::updateList(ppMap, vector::zero, nearestNormal);
+                // disp
+                meshRefinement::updateList(ppMap, vector::zero, disp);
+                // ppLocalPoints
+                meshRefinement::updateList(ppMap, vector::zero, ppLocalPoints);
+
+                Info<< "DONE Updating for face-splitting" << endl;
+            }
+        }
+
+
+        // Attract/slide the mesh a bit
+        {
+            //// Create pointMesh with the correct patches
+            //// - points on single polyPatches stay as is
+            //// - points on two polyPatches go to allEdgePatchName
+            //// - points on >two polyPatches go to allPointPatchName
+            //const pointMesh& pMesh = makePointMesh
+            //(
+            //    ppPtr(),
+            //    patchConstraints,
+            //    allEdgePatchName,
+            //    allPointPatchName
+            //);
+            //const pointMesh& pMesh = pointMesh::New(mesh);
+            //
+            //autoPtr<displacementMotionSolver> motionPtr
+            //(
+            //    makeMotionSolver
+            //    (
+            //        pMesh,
+            //        snapDict,
+            //        adaptPatchIDs
+            //        //patchConstraints
+            //    )
+            //);
+
+            // Insert as bc to motionSmoother. Note that this takes displacement
+            // relative to points0
+            setDisplacement
+            (
+                ppPtr(),
+                disp,
+                adaptPatchIDs,
+                motionPtr().points0(),
+                motionPtr().pointDisplacement()
+            );
+
+            // Solve internal displacement
+            tmp<pointField> tnewPoints(motionPtr->newPoints());
+
+            // Move points
+            if (false)
+            {
+                // 1. Directly move points
+                mesh.movePoints(tnewPoints);
+                // Optional? Only geometry used is ppLocalPoints which we keep
+                // and update 'by hand'.
+                //ppPtr().movePoints(tnewPoints);
+            }
+            else
+            {
+                // 2. Use motionSmoother
+                // Set initial distribution of displacement field (on patches)
+                // from patchDisp and make displacement consistent with b.c.
+                // on displacement pointVectorField.
+                const vectorField newDisp(tnewPoints()-meshMoverPtr().oldPoints());
+
+                meshMoverPtr().displacement().vectorField::operator=(newDisp);
+                meshMoverPtr().setDisplacement(disp);
+
+                // Apply internal displacement to mesh.
+                const bool meshOk = scaleMesh
+                (
+                    snapParams,
+                    nInitErrors,
+                    internalBaffles,
+                    meshMoverPtr()
+                );
+
+                if (!meshOk)
+                {
+                    WarningInFunction
+                        << "Did not successfully snap mesh."
+                        << " Continuing to snap to resolve easy" << nl
+                        << "    surfaces but the"
+                        << " resulting mesh will not satisfy your quality"
+                        << " constraints" << nl << endl;
+                }
+
+                // Use current mesh as base mesh
+                meshMoverPtr().correct();
+            }
+
+            // Update pp for new mesh points. Ok as long as we also update
+            // geometry and wanted displacement (usually zero if mesh motion
+            // has succeeded)
+            ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+            patchDisp -= (ppLocalPoints-ppPtr().localPoints());
+
+            if (debug & meshRefinement::MESH)
+            {
+                const_cast<Time&>(mesh.time())++;
+                Info<< "Writing partially moved mesh to time "
+                    << meshRefiner_.timeName() << endl;
+                meshRefiner_.write
+                (
+                    meshRefinement::debugType(debug),
+                    meshRefinement::writeType
+                    (
+                        meshRefinement::writeLevel()
+                      | meshRefinement::WRITEMESH
+                    ),
+                    meshRefiner_.timeName()
+                );
+            }
+        }
+
+        // Split problematic cells
+        {
+            Info<< nl << "Checking moved mesh ..." << endl;
+            faceSet wrongFaces(mesh, "wrongFaces", mesh.nFaces()/1000);
+            motionSmoother::checkMesh
+            (
+                false,
+                mesh,
+                motionDict,
+                identity(mesh.nFaces()),
+                internalBaffles,
+                wrongFaces,
+                false           // dryRun_
+            );
+            const label nWrong(returnReduce(wrongFaces.size(), sumOp<label>()));
+            Info<< "Detected " << nWrong
+                << " illegal faces"
+                << " (concave, zero area or negative cell pyramid volume)"
+                << endl;
+
+            //if (nWrong)
+            if (false)
+            {
+                bitSet decomposeCell(mesh.nCells());
+                for (const label facei : wrongFaces)
+                {
+                    const label own = mesh.faceOwner()[facei];
+                    if (!tetMatcher::test(mesh, own))
+                    {
+                        decomposeCell.set(own);
+                    }
+                    if (mesh.isInternalFace(facei))
+                    {
+                        const label nei = mesh.faceNeighbour()[facei];
+                        if (!tetMatcher::test(mesh, nei))
+                        {
+                            decomposeCell.set(nei);
+                        }
+                    }
+                }
+                Pout<< "spliyyinG :" << decomposeCell.count() << " cells"
+                    << endl;
+
+                tetDecomposer tetDecomp(mesh);
+                polyTopoChange meshMod(mesh);
+                tetDecomp.setRefinement
+                (
+                    tetDecomposer::FACE_CENTRE_TRIS,
+                    decomposeCell,
+                    meshMod
+                );
+
+                // Save old meshPoints before changing mesh
+                const Map<label> oldMeshPointMap(ppPtr->meshPointMap());
+
+                Pout<< "old pp points:" << ppPtr->nPoints()
+                    << " oldMeshPointMap:" << oldMeshPointMap.size()
+                    << endl;
+
+                // Remove any unnecessary fields
+                meshMoverPtr.clear();
+                motionPtr.clear();
+                ppPtr.clear();
+                mesh.clearOut();
+                mesh.moving(false);
+
+                // Change the mesh (no inflation)
+                autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
+                mapPolyMesh& map = *mapPtr;
+
+                // Update fields
+                mesh.updateMesh(map);
+
+                // Move mesh (since morphing does not do this)
+                if (map.hasMotionPoints())
+                {
+                    mesh.movePoints(map.preMotionPoints());
+                }
+                else
+                {
+                    mesh.clearOut();
+                }
+
+                // Reset the instance for if in overwrite mode
+                mesh.setInstance(meshRefiner_.timeName());
+                meshRefiner_.setInstance(mesh.facesInstance());
+
+                //- Update numbering on tet-decomposition engine
+                tetDecomp.updateMesh(map);
+
+                bitSet isChangedFace(mesh.nFaces());
+                forAll(map.cellMap(), celli)
+                {
+                    if (decomposeCell[map.cellMap()[celli]])
+                    {
+                        isChangedFace.set(mesh.cells()[celli]);
+                    }
+                }
+                syncTools::syncFaceList
+                (
+                    mesh,
+                    isChangedFace,
+                    orEqOp<unsigned int>()
+                );
+
+                Pout<< "isChangedFace :" << decomposeCell.count() << " faces"
+                    << endl;
+
+
+                // Update intersection info
+                meshRefiner_.updateMesh(map, isChangedFace.toc());
+
+
+                if (debug&meshRefinement::MESH)
+                {
+                    const_cast<Time&>(mesh.time())++;
+                    Info<< "Writing tet-decomp mesh to time "
+                        << meshRefiner_.timeName() << endl;
+                    meshRefiner_.write
+                    (
+                        meshRefinement::debugType(debug),
+                        meshRefinement::writeType
+                        (
+                            meshRefinement::writeLevel()
+                          | meshRefinement::WRITEMESH
+                        ),
+                        mesh.time().path()/meshRefiner_.timeName()
+                    );
+                }
+
+
+                // Update local mesh data
+                // ~~~~~~~~~~~~~~~~~~~~~~
+
+                Info<< "Updating for tet-decomp" << endl;
+
+                // baffles
+                forAll(internalBaffles, i)
+                {
+                    labelPair& baffle = internalBaffles[i];
+                    baffle.first() = map.reverseFaceMap()[baffle.first()];
+                    baffle.second() = map.reverseFaceMap()[baffle.second()];
+                }
+
+                // re-do patch (since faces might have been split)
+                ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
+    Pout<< "new pp points:" << ppPtr->nPoints()
+        << " new meshPointMap:" << ppPtr->meshPointMap().size()
+        << endl;
+                const auto& mp = ppPtr->meshPoints();
+                // pointMap (new-to-old) for pp points. Might have new
+                // face-centre points - these get mapped from any point on
+                // the originating face.
+                labelList ppMap(mp.size(), -1);
+                forAll(mp, i)
+                {
+                    const label oldMeshPointi = map.pointMap()[mp[i]];
+                    const auto mpFnd = oldMeshPointMap.find(oldMeshPointi);
+                    if (mpFnd)
+                    {
+                        ppMap[i] = mpFnd();
+                    }
+                }
+
+                // patchDisp
+                meshRefinement::updateList(ppMap, vector::zero, patchDisp);
+                // snapDist
+                meshRefinement::updateList(ppMap, scalar(0), snapDist);
+                // patchFeaturePoint
+                meshRefinement::updateList
+                (
+                    ppMap,
+                    vector::zero,
+                    patchFeaturePoint
+                );
+                // patchConstraints
+                meshRefinement::updateList
+                (
+                    ppMap,
+                    pointConstraint(),
+                    patchConstraints
+                );
+//                // nearestPoint
+//                meshRefinement::updateList(ppMap, vector::zero, nearestPoint);
+//                // nearestNormal
+//                meshRefinement::updateList(ppMap, vector::zero, nearestNormal);
+//                // disp
+//                meshRefinement::updateList(ppMap, vector::zero, disp);
+
+                // Maximum distance to attract to nearest feature on surface
+                snapDist = calcSnapDistance(mesh, snapParams, ppPtr());
+                ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+
+                Info<< "DONE Updating for tet-decomp" << endl;
+            }
+        }
+    }
+
+//XXXXXX
+/*
+    {
+        // Introduce single layer of cells. Straight from snappyLayerDriver
+
+        // Global face indices engine
+        const globalIndex globalFaces(mesh.nFaces());
+
+        // Determine extrudePatch.edgeFaces in global numbering (so across
+        // coupled patches). This is used only to string up edges
+        // between coupled
+        // faces (all edges between same (global)face indices get extruded).
+        labelListList edgeGlobalFaces
+        (
+            addPatchCellLayer::globalEdgeFaces
+            (
+                mesh,
+                globalFaces,
+                ppPtr()
+            )
+        );
+
+        // Determine patches for extruded boundary edges. Calculates if any
+        // additional processor patches need to be constructed.
+
+        labelList edgePatchID;
+        labelList edgeZoneID;
+        boolList edgeFlip;
+        labelList inflateFaceID;
+        snappyLayerDriver::determineSidePatches
+        (
+            meshRefiner_,
+            globalFaces,
+            edgeGlobalFaces,
+            ppPtr(),
+
+            edgePatchID,
+            edgeZoneID,
+            edgeFlip,
+            inflateFaceID
+        );
+
+
+        // Mesh topo change engine. Insert current mesh.
+        polyTopoChange meshMod(mesh);
+
+        // Layer mesh modifier
+        addPatchCellLayer addLayer(mesh);
+
+        // Extrude very thin layer of cells
+        pointField extrusion(PatchTools::pointNormals(mesh, ppPtr()));
+        const tmp<scalarField> thickness
+        (
+            wantedThickness
+            (
+                ppPtr(),
+                1e-3        // cellSizeFraction
+            )
+        );
+        extrusion *= thickness;
+
+        // Add topo regardless of whether extrudeStatus is extruderemove.
+        // Not add layer if patchDisp is zero.
+
+        const label ppNFaces = ppPtr().size();
+        const label ppNPoints = ppPtr().nPoints();
+
+        addLayer.setRefinement
+        (
+            globalFaces,
+            edgeGlobalFaces,
+
+            scalarField(ppNPoints, 1),  // expansion ratio
+            ppPtr(),
+            bitSet(ppPtr().size()),     // no flip
+
+            edgePatchID,    // boundary patch for extruded boundary edges
+            edgeZoneID,     // zone for extruded edges
+            edgeFlip,
+            inflateFaceID,
+
+
+            labelList(0),   // exposed patchIDs, not used for adding layers
+            labelList(ppNFaces, 1),
+            labelList(ppNPoints, 1),
+            extrusion,  //patchAttraction,
+
+            meshMod
+        );
+
+        // Save old meshPoints before changing mesh
+        const Map<label> oldMeshPointMap(ppPtr->meshPointMap());
+        Pout<< "old pp points:" << ppPtr->nPoints()
+            << " oldMeshPointMap:" << oldMeshPointMap.size()
+            << endl;
+
+        // Remove any unnecessary fields
+        meshMoverPtr.clear();
+        motionPtr.clear();
+        ppPtr.clear();
+        mesh.clearOut();
+        mesh.moving(false);
+
+        // Apply the stored topo changes to the current mesh.
+        autoPtr<mapPolyMesh> mapPtr = meshMod.changeMesh(mesh, false);
+        mapPolyMesh& map = *mapPtr;
+
+        // Update fields
+        mesh.updateMesh(map);
+
+        // Move mesh (since morphing does not do this)
+        if (map.hasMotionPoints())
+        {
+            mesh.movePoints(map.preMotionPoints());
+        }
+        else
+        {
+            // Hack to remove meshPhi - mapped incorrectly. TBD.
+            mesh.clearOut();
+        }
+
+        // Reset the instance for if in overwrite mode
+        mesh.setInstance(meshRefiner_.timeName());
+
+        // Re-do the patch
+        ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
+    Pout<< "new pp points:" << ppPtr->nPoints()
+        << " new meshPointMap:" << ppPtr->meshPointMap().size()
+        << endl;
+        // Map the old-patch-point data to the new patch points
+        // pointMap (new-to-old) for new pp points
+        labelList ppMap(ppPtr->nPoints(), -1);
+        {
+            const labelListList& oldAddedPoints = addLayer.addedPoints();
+            forAll(oldAddedPoints, oldPatchPointi)
+            {
+                const label oldPointi = oldAddedPoints[oldPatchPointi].last();
+                const label newPointi = map.reversePointMap()[oldPointi];
+                const label newPatchPointi = ppPtr().meshPointMap()[newPointi];
+
+                ppMap[newPatchPointi] = oldPatchPointi;
+            }
+        }
+
+        // Update attraction
+        meshRefinement::updateList(ppMap, vector::zero, patchDisp);
+        // snapDist
+        meshRefinement::updateList(ppMap, scalar(0), snapDist);
+        // patchFeaturePoint
+        meshRefinement::updateList
+        (
+            ppMap,
+            vector::zero,
+            patchFeaturePoint
+        );
+        // patchConstraints
+        meshRefinement::updateList
+        (
+            ppMap,
+            pointConstraint(),
+            patchConstraints
+        );
+        // ppLocalPoints
+        //meshRefinement::updateList(ppMap, vector::zero, ppLocalPoints);
+        ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+
+
+        // Update numbering on layer
+        addLayer.updateMesh
+        (
+            map,
+            identity(ppNFaces),
+            identity(ppNPoints)
+        );
+
+        // Update intersections
+        const labelListList addedCells(addLayer.addedCells());
+        bitSet isChangedFace(mesh.nFaces());
+        for (const labelList& faceToCells : addedCells)
+        {
+            for (const label celli : faceToCells)
+            {
+                isChangedFace.set(mesh.cells()[celli]);
+            }
+        }
+        meshRefiner_.updateMesh(map, isChangedFace.toc());
+
+
+        if (debug & meshRefinement::MESH)
+        {
+            const_cast<Time&>(mesh.time())++;
+            Info<< "Writing mesh-with-layer to time "
+                << meshRefiner_.timeName() << endl;
+            meshRefiner_.write
+            (
+                meshRefinement::debugType(debug),
+                meshRefinement::writeType
+                (
+                    meshRefinement::writeLevel()
+                  | meshRefinement::WRITEMESH
+                ),
+                meshRefiner_.timeName()
+            );
+        }
+        if (debug)
+        {
+            OBJstream str
+            (
+                mesh.time().path()
+              / "new_projection"
+              + meshRefiner_.timeName()
+              + ".obj"
+            );
+            forAll(ppLocalPoints, pointi)
+            {
+                const point& pt = ppLocalPoints[pointi];
+                str.write(linePointRef(pt, patchFeaturePoint[pointi]));
+            }
+            Pout<< "** writing mapped attraction to " << str.name() << endl;
+        }
+    }
+*/
+//XXXX
+    {
+        // Layer mesh modifier
+        addPatchCellLayer addLayer(mesh);
+
+        // Save old mesh points (to construct the new-to-old local patch points)
+        const Map<label> oldMeshPointMap(ppPtr->meshPointMap());
+
+        meshMoverPtr.clear();
+        motionPtr.clear();
+
+        const pointField thickness
+        (
+            wantedThickness(ppPtr(), 1e-3)             //cellSizeFraction
+          * PatchTools::pointNormals(mesh, ppPtr())
+        );
+        autoPtr<mapPolyMesh> mapPtr = addBufferLayers
+        (
+            ppPtr(),
+            thickness,
+            addLayer
+        );
+
+        // Re-do the patch
+        ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
+        
+        // Map the old-patch-point data to the new patch points
+        // pointMap (new-to-old) for new pp points
+        labelList ppMap(ppPtr->nPoints(), -1);
+        {
+            const labelListList& addedPoints = addLayer.addedPoints();
+            forAll(addedPoints, oldPatchPointi)
+            {
+                const label newPointi = addedPoints[oldPatchPointi].last();
+                const label newPatchPointi = ppPtr().meshPointMap()[newPointi];
+                ppMap[newPatchPointi] = oldPatchPointi;
+            }
+        }
+
+        // Update attraction
+        meshRefinement::updateList(ppMap, vector::zero, patchDisp);
+        // snapDist
+        meshRefinement::updateList(ppMap, scalar(0), snapDist);
+        // patchFeaturePoint
+        meshRefinement::updateList
+        (
+            ppMap,
+            vector::zero,
+            patchFeaturePoint
+        );
+        // patchConstraints
+        meshRefinement::updateList
+        (
+            ppMap,
+            pointConstraint(),
+            patchConstraints
+        );
+        // ppLocalPoints
+        ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+    }
+//XXXXXX
+    const bool snapToGeometry = true;
+    if (snapToGeometry)
+    {
+        // Create pointMesh with the correct patches
+        // - points on single polyPatches stay as is
+        // - points on two polyPatches go to allEdgePatchName
+        // - points on >two polyPatches go to allPointPatchName
+        //const pointMesh& pMesh = makePointMesh
+        //(
+        //    ppPtr(),
+        //    patchConstraints,
+        //    allEdgePatchName,
+        //    allPointPatchName
+        //);
+        const pointMesh& pMesh = pointMesh::New(mesh);
+
+        autoPtr<displacementMotionSolver> motionPtr
+        (
+            makeMotionSolver
+            (
+                pMesh,
+                snapDict,
+                adaptPatchIDs
+                //patchConstraints
+            )
+        );
+
+        // Insert as bc to motionSmoother. Note that this takes displacement
+        // relative to points0
+        setDisplacement
+        (
+            ppPtr(),
+            patchFeaturePoint-ppLocalPoints,
+            adaptPatchIDs,
+            motionPtr().points0(),
+            motionPtr().pointDisplacement()
+        );
+
+
+        if (debug)
+        {
+            OBJstream str
+            (
+                mesh.time().path()
+              / "buffer_layer_new_projection"
+              + meshRefiner_.timeName()
+              + ".obj"
+            );
+            forAll(ppLocalPoints, pointi)
+            {
+                const point& pt = ppLocalPoints[pointi];
+                str.write(linePointRef(pt, patchFeaturePoint[pointi]));
+            }
+            Pout<< "** writing mapped attraction to " << str.name() << endl;
+        }
+
+
+        // Solve internal displacement
+        tmp<pointField> tnewPoints(motionPtr->newPoints());
+
+        // Move points
+        mesh.movePoints(tnewPoints);
+
+        // Update pp for new mesh points. Ok as long as we also update geometry
+        // and wanted displacement (usually zero if mesh motion has succeeded)
+        ppLocalPoints = pointField(mesh.points(), ppPtr().meshPoints());
+        patchDisp -= (ppLocalPoints-ppPtr().localPoints());
+
+        if (debug & meshRefinement::MESH)
+        {
+            const_cast<Time&>(mesh.time())++;
+            Info<< "Writing smoothed LAYER mesh to time "
+                << meshRefiner_.timeName() << endl;
+            meshRefiner_.write
+            (
+                meshRefinement::debugType(debug),
+                meshRefinement::writeType
+                (
+                    meshRefinement::writeLevel()
+                  | meshRefinement::WRITEMESH
+                ),
+                meshRefiner_.timeName()
+            );
+        }
+    }
+
+
+    // Merge any introduced baffles (from faceZones of faceType 'internal')
+    {
+        autoPtr<mapPolyMesh> mapPtr = meshRefiner_.mergeZoneBaffles
+        (
+            true,   // internal zones
+            false   // baffle zones
+        );
+
+        if (mapPtr.valid())
+        {
+            if (debug & meshRefinement::MESH)
+            {
+                const_cast<Time&>(mesh.time())++;
+                Info<< "Writing baffle-merged mesh to time "
+                    << meshRefiner_.timeName() << endl;
+                meshRefiner_.write
+                (
+                    meshRefinement::debugType(debug),
+                    meshRefinement::writeType
+                    (
+                        meshRefinement::writeLevel()
+                      | meshRefinement::WRITEMESH
+                    ),
+                    meshRefiner_.timeName()
+                );
+            }
+        }
+    }
+
+    // Repatch faces according to nearest. Do not repatch baffle faces.
+    {
+        labelList duplicateFace(getInternalOrBaffleDuplicateFace());
+
+        repatchToSurface(snapParams, adaptPatchIDs, duplicateFace);
+    }
+
+    if (debug & meshRefinement::MESH)
+    {
+        const_cast<Time&>(mesh.time())++;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverFeature.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverFeature.C
index e5e951c30dfcd99b6c033dfe02a69c1293197c1d..b4aaa38fa32860c24ab139052aec1c27ef7f54aa 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverFeature.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappySnapDriverFeature.C
@@ -68,65 +68,65 @@ namespace Foam
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-bool Foam::snappySnapDriver::isFeaturePoint
-(
-    const scalar featureCos,
-    const indirectPrimitivePatch& pp,
-    const bitSet& isFeatureEdge,
-    const label pointi
-) const
-{
-    const pointField& points = pp.localPoints();
-    const edgeList& edges = pp.edges();
-    const labelList& pEdges = pp.pointEdges()[pointi];
-
-    label nFeatEdges = 0;
-
-    forAll(pEdges, i)
-    {
-        if (isFeatureEdge[pEdges[i]])
-        {
-            nFeatEdges++;
-
-            for (label j = i+1; j < pEdges.size(); j++)
-            {
-                if (isFeatureEdge[pEdges[j]])
-                {
-                    const edge& ei = edges[pEdges[i]];
-                    const edge& ej = edges[pEdges[j]];
-
-                    const point& p = points[pointi];
-                    const point& pi = points[ei.otherVertex(pointi)];
-                    const point& pj = points[ej.otherVertex(pointi)];
-
-                    vector vi = p-pi;
-                    scalar viMag = mag(vi);
-
-                    vector vj = pj-p;
-                    scalar vjMag = mag(vj);
-
-                    if
-                    (
-                        viMag > SMALL
-                     && vjMag > SMALL
-                     && ((vi/viMag & vj/vjMag) < featureCos)
-                    )
-                    {
-                        return true;
-                    }
-                }
-            }
-        }
-    }
-
-    if (nFeatEdges == 1)
-    {
-        // End of feature-edge string
-        return true;
-    }
-
-    return false;
-}
+//bool Foam::snappySnapDriver::isFeaturePoint
+//(
+//    const scalar featureCos,
+//    const indirectPrimitivePatch& pp,
+//    const bitSet& isFeatureEdge,
+//    const label pointi
+//) const
+//{
+//    const pointField& points = ppLocalPoints;
+//    const edgeList& edges = pp.edges();
+//    const labelList& pEdges = pp.pointEdges()[pointi];
+//
+//    label nFeatEdges = 0;
+//
+//    forAll(pEdges, i)
+//    {
+//        if (isFeatureEdge[pEdges[i]])
+//        {
+//            nFeatEdges++;
+//
+//            for (label j = i+1; j < pEdges.size(); j++)
+//            {
+//                if (isFeatureEdge[pEdges[j]])
+//                {
+//                    const edge& ei = edges[pEdges[i]];
+//                    const edge& ej = edges[pEdges[j]];
+//
+//                    const point& p = points[pointi];
+//                    const point& pi = points[ei.otherVertex(pointi)];
+//                    const point& pj = points[ej.otherVertex(pointi)];
+//
+//                    vector vi = p-pi;
+//                    scalar viMag = mag(vi);
+//
+//                    vector vj = pj-p;
+//                    scalar vjMag = mag(vj);
+//
+//                    if
+//                    (
+//                        viMag > SMALL
+//                     && vjMag > SMALL
+//                     && ((vi/viMag & vj/vjMag) < featureCos)
+//                    )
+//                    {
+//                        return true;
+//                    }
+//                }
+//            }
+//        }
+//    }
+//
+//    if (nFeatEdges == 1)
+//    {
+//        // End of feature-edge string
+//        return true;
+//    }
+//
+//    return false;
+//}
 
 
 void Foam::snappySnapDriver::smoothAndConstrain
@@ -224,6 +224,8 @@ void Foam::snappySnapDriver::calcNearestFace
 (
     const label iter,
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
+
     const scalarField& faceSnapDist,
     vectorField& faceDisp,
     vectorField& faceSurfaceNormal,
@@ -234,6 +236,16 @@ void Foam::snappySnapDriver::calcNearestFace
     const fvMesh& mesh = meshRefiner_.mesh();
     const refinementSurfaces& surfaces = meshRefiner_.surfaces();
 
+    const pointField ppFaceCentres
+    (
+        primitivePatch
+        (
+            SubList<face>(pp.localFaces()),
+            ppLocalPoints
+        ).faceCentres()
+    );
+
+
     // Displacement and orientation per pp face.
     faceDisp.setSize(pp.size());
     faceDisp = Zero;
@@ -268,6 +280,7 @@ void Foam::snappySnapDriver::calcNearestFace
         // Get indices of faces on pp that are also in zone
         DynamicList<label> ppFaces;
         DynamicList<label> meshFaces;
+        DynamicField<point> fc;
         forAll(faceZoneNames, fzi)
         {
             const word& faceZoneName = faceZoneNames[fzi];
@@ -283,6 +296,7 @@ void Foam::snappySnapDriver::calcNearestFace
 
             ppFaces.reserve(ppFaces.capacity()+fZone.size());
             meshFaces.reserve(meshFaces.capacity()+fZone.size());
+            fc.reserve(meshFaces.capacity()+fZone.size());
 
             forAll(pp.addressing(), i)
             {
@@ -291,6 +305,7 @@ void Foam::snappySnapDriver::calcNearestFace
                     snapSurf[i] = zoneSurfi;
                     ppFaces.append(i);
                     meshFaces.append(pp.addressing()[i]);
+                    fc.append(ppFaceCentres[i]);
                 }
             }
 
@@ -299,15 +314,6 @@ void Foam::snappySnapDriver::calcNearestFace
             //    << endl;
         }
 
-        pointField fc
-        (
-            indirectPrimitivePatch
-            (
-                IndirectList<face>(mesh.faces(), meshFaces),
-                mesh.points()
-            ).faceCentres()
-        );
-
         List<pointIndexHit> hitInfo;
         labelList hitSurface;
         labelList hitRegion;
@@ -364,26 +370,19 @@ void Foam::snappySnapDriver::calcNearestFace
 
     DynamicList<label> ppFaces(pp.size());
     DynamicList<label> meshFaces(pp.size());
+    DynamicField<point> fc(pp.size());
     forAll(pp.addressing(), i)
     {
         if (snapSurf[i] == -1)
         {
             ppFaces.append(i);
             meshFaces.append(pp.addressing()[i]);
+            fc.append(ppFaceCentres[i]);
         }
     }
     //Pout<< "Found " << ppFaces.size() << " unzoned faces out of "
     //   << pp.size() << endl;
 
-    pointField fc
-    (
-        indirectPrimitivePatch
-        (
-            IndirectList<face>(mesh.faces(), meshFaces),
-            mesh.points()
-        ).faceCentres()
-    );
-
     List<pointIndexHit> hitInfo;
     labelList hitSurface;
     labelList hitRegion;
@@ -478,6 +477,7 @@ void Foam::snappySnapDriver::calcNearestFacePointProperties
 (
     const label iter,
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
 
     const vectorField& faceDisp,
     const vectorField& faceSurfaceNormal,
@@ -541,7 +541,7 @@ void Foam::snappySnapDriver::calcNearestFacePointProperties
             {
                 pNormals[nFaces] = faceSurfaceNormal[facei];
                 pDisp[nFaces] = faceDisp[facei];
-                pFc[nFaces] = pp.faceCentres()[facei];
+                pFc[nFaces] = pp.localFaces()[facei].centre(ppLocalPoints);
                 pFid[nFaces] = globalToMasterPatch_[globalRegioni];
                 nFaces++;
             }
@@ -647,7 +647,13 @@ void Foam::snappySnapDriver::calcNearestFacePointProperties
                         List<point>& pFc = pointFaceCentres[pointi];
                         labelList& pFid = pointFacePatchID[pointi];
 
-                        const point& pt = mesh.points()[f[fp]];
+
+                        // Note: these are points which are on the patch but
+                        //       the face itself is not. Could recalculate the
+                        //       facearea with the modified point but hopefully
+                        //       not necessary.
+                        //const point& pt = mesh.points()[f[fp]];
+                        const point& pt = ppLocalPoints[pointi];
                         vector fn = mesh.faceAreas()[facei];
 
                         pNormals.append(fn/mag(fn));
@@ -682,10 +688,11 @@ void Foam::snappySnapDriver::calcNearestFacePointProperties
     {
         // Make into displacement before synchronising to avoid any problems
         // with parallel cyclics
-        pointField localPoints(pp.points(), pp.meshPoints());
+        //pointField localPoints(pp.points(), pp.meshPoints());
         forAll(pointFaceCentres, pointi)
         {
-            const point& pt = pp.points()[pp.meshPoints()[pointi]];
+            //const point& pt = pp.points()[pp.meshPoints()[pointi]];
+            const point& pt = ppLocalPoints[pointi];
 
             List<point>& pFc = pointFaceCentres[pointi];
             for (point& p : pFc)
@@ -704,7 +711,8 @@ void Foam::snappySnapDriver::calcNearestFacePointProperties
         );
         forAll(pointFaceCentres, pointi)
         {
-            const point& pt = pp.points()[pp.meshPoints()[pointi]];
+            //const point& pt = pp.points()[pp.meshPoints()[pointi]];
+            const point& pt = ppLocalPoints[pointi];
 
             List<point>& pFc = pointFaceCentres[pointi];
             for (point& p : pFc)
@@ -975,6 +983,7 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const vectorField& nearestDisp,
     const label pointi,
@@ -1092,7 +1101,8 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
     }
 
 
-    const point& pt = pp.localPoints()[pointi];
+    //const point& pt = pp.localPoints()[pointi];
+    const point& pt = ppLocalPoints[pointi];
 
     // Check the number of directions
     if (surfaceNormals.size() == 1)
@@ -1168,6 +1178,7 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const vectorField& nearestDisp,
 
@@ -1212,7 +1223,7 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
     DynamicList<vector> surfaceNormals(4);
     labelList faceToNormalBin;
 
-    forAll(pp.localPoints(), pointi)
+    forAll(ppLocalPoints, pointi)
     {
         vector attraction = Zero;
         pointConstraint constraint;
@@ -1223,6 +1234,7 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
             nearestDisp,
 
@@ -1253,7 +1265,8 @@ void Foam::snappySnapDriver::featureAttractionUsingReconstruction
             patchAttraction[pointi] = attraction;
             patchConstraints[pointi] = constraint;
 
-            const point& pt = pp.localPoints()[pointi];
+            //const point& pt = pp.localPoints()[pointi];
+            const point& pt = ppLocalPoints[pointi];
 
             if (feStr && patchConstraints[pointi].first() == 2)
             {
@@ -1274,6 +1287,7 @@ void Foam::snappySnapDriver::stringFeatureEdges
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
 
     const vectorField& rawPatchAttraction,
@@ -1314,7 +1328,8 @@ void Foam::snappySnapDriver::stringFeatureEdges
         {
             if (patchConstraints[pointi].first() == 2)
             {
-                const point& pt = pp.localPoints()[pointi];
+                //const point& pt = pp.localPoints()[pointi];
+                const point& pt = ppLocalPoints[pointi];
                 const labelList& pEdges = pointEdges[pointi];
                 const vector& featVec = patchConstraints[pointi].second();
 
@@ -1330,7 +1345,8 @@ void Foam::snappySnapDriver::stringFeatureEdges
 
                     if (patchConstraints[nbrPointi].first() > 1)
                     {
-                        const point& nbrPt = pp.localPoints()[nbrPointi];
+                        //const point& nbrPt = pp.localPoints()[nbrPointi];
+                        const point& nbrPt = ppLocalPoints[nbrPointi];
                         const point featPt =
                             nbrPt + patchAttraction[nbrPointi];
                         const scalar cosAngle = (featVec & (featPt-pt));
@@ -1349,7 +1365,7 @@ void Foam::snappySnapDriver::stringFeatureEdges
                 if (!hasPos || !hasNeg)
                 {
                     //Pout<< "**Detected feature string end at  "
-                    //    << pp.localPoints()[pointi] << endl;
+                    //    << ppLocalPoints[pointi] << endl;
 
                     // No string. Assign best choice on either side
                     label bestPosPointi = -1;
@@ -1382,7 +1398,8 @@ void Foam::snappySnapDriver::stringFeatureEdges
                                 );
 
                                 const point featPt =
-                                    pp.localPoints()[nbrPointi]
+                                    //pp.localPoints()[nbrPointi]
+                                    ppLocalPoints[nbrPointi]
                                   + rawPatchAttraction[nbrPointi];
                                 const scalar cosAngle =
                                     (featVec & (featPt-pt));
@@ -1412,7 +1429,7 @@ void Foam::snappySnapDriver::stringFeatureEdges
                         // Use reconstructed-feature attraction. Use only
                         // part of it since not sure...
                         //const point& bestPt =
-                        //    pp.localPoints()[bestPosPointi];
+                        //    ppLocalPoints[bestPosPointi];
                         //Pout<< "**Overriding point " << bestPt
                         //    << " on reconstructed feature edge at "
                         //    << rawPatchAttraction[bestPosPointi]+bestPt
@@ -1429,7 +1446,7 @@ void Foam::snappySnapDriver::stringFeatureEdges
                         // Use reconstructed-feature attraction. Use only
                         // part of it since not sure...
                         //const point& bestPt =
-                        //    pp.localPoints()[bestNegPointi];
+                        //    ppLocalPoints[bestNegPointi];
                         //Pout<< "**Overriding point " << bestPt
                         //    << " on reconstructed feature edge at "
                         //    << rawPatchAttraction[bestNegPointi]+bestPt
@@ -1463,6 +1480,7 @@ void Foam::snappySnapDriver::releasePointsNextToMultiPatch
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
 
     const List<List<point>>& pointFaceCentres,
@@ -1499,7 +1517,7 @@ void Foam::snappySnapDriver::releasePointsNextToMultiPatch
     {
         pointIndexHit multiPatchPt = findMultiPatchPoint
         (
-            pp.localPoints()[pointi],
+            ppLocalPoints[pointi],
             pointFacePatchID[pointi],
             pointFaceCentres[pointi]
         );
@@ -1523,7 +1541,7 @@ void Foam::snappySnapDriver::releasePointsNextToMultiPatch
                 //if (multiPatchStr)
                 //{
                 //    Pout<< "Adding constraint on multiPatchPoint:"
-                //        << pp.localPoints()[pointi]
+                //        << ppLocalPoints[pointi]
                 //        << " constraint:" << patchConstraints[pointi]
                 //        << " attraction:" << patchAttraction[pointi]
                 //        << endl;
@@ -1568,14 +1586,14 @@ void Foam::snappySnapDriver::releasePointsNextToMultiPatch
                 {
                     //Pout<< "Knocking out constraint"
                     //    << " on non-multiPatchPoint:"
-                    //    << pp.localPoints()[pointi] << endl;
+                    //    << ppLocalPoints[pointi] << endl;
                     patchAttraction[pointi] = Zero;
                     patchConstraints[pointi] = pointConstraint();
                     nChanged++;
 
                     if (multiPatchStr)
                     {
-                        multiPatchStr().write(pp.localPoints()[pointi]);
+                        multiPatchStr().write(ppLocalPoints[pointi]);
                     }
                 }
             }
@@ -1727,6 +1745,7 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
     const scalar concaveCos,
     const scalar minAreaRatio,
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const vectorField& patchAttr,
     const List<pointConstraint>& patchConstraints,
     const vectorField& nearestAttr,
@@ -1743,8 +1762,6 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
 
     if (localF.size() >= 4)
     {
-        const pointField& localPts = pp.localPoints();
-
         //// Estimate cell centre taking patchAttraction into account
         //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         //// (is this necessary?)
@@ -1805,8 +1822,10 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
                         // Check if
                         // - sameish feature edge normal
                         // - diagonal aligned with feature edge normal
-                        point start = localPts[startPti]+patchAttr[startPti];
-                        point end = localPts[endPti]+patchAttr[endPti];
+                        point start =
+                            ppLocalPoints[startPti]+patchAttr[startPti];
+                        point end =
+                            ppLocalPoints[endPti]+patchAttr[endPti];
 
                         if
                         (
@@ -1846,15 +1865,15 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
                     // Get compact face and points
                     const face compact0(identity(f0.size()));
                     points0.clear();
-                    points0.append(localPts[f0[0]] + patchAttr[f0[0]]);
+                    points0.append(ppLocalPoints[f0[0]] + patchAttr[f0[0]]);
                     for (label fp=1; fp < f0.size()-1; fp++)
                     {
                         label pi = f0[fp];
-                        points0.append(localPts[pi] + nearestAttr[pi]);
+                        points0.append(ppLocalPoints[pi] + nearestAttr[pi]);
                     }
                     points0.append
                     (
-                        localPts[f0.last()] + patchAttr[f0.last()]
+                        ppLocalPoints[f0.last()] + patchAttr[f0.last()]
                     );
 
 
@@ -1877,15 +1896,15 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
                     // Get compact face and points
                     const face compact1(identity(f1.size()));
                     points1.clear();
-                    points1.append(localPts[f1[0]] + patchAttr[f1[0]]);
+                    points1.append(ppLocalPoints[f1[0]] + patchAttr[f1[0]]);
                     for (label fp=1; fp < f1.size()-1; fp++)
                     {
                         label pi = f1[fp];
-                        points1.append(localPts[pi] + nearestAttr[pi]);
+                        points1.append(ppLocalPoints[pi] + nearestAttr[pi]);
                     }
                     points1.append
                     (
-                        localPts[f1.last()] + patchAttr[f1.last()]
+                        ppLocalPoints[f1.last()] + patchAttr[f1.last()]
                     );
 
 
@@ -1920,8 +1939,8 @@ Foam::labelPair Foam::snappySnapDriver::findDiagonalAttraction
                     else
                     {
                         // Existing areas
-                        const scalar area0 = f0.mag(localPts);
-                        const scalar area1 = f1.mag(localPts);
+                        const scalar area0 = f0.mag(ppLocalPoints);
+                        const scalar area1 = f1.mag(ppLocalPoints);
 
                         if
                         (
@@ -1947,13 +1966,17 @@ void Foam::snappySnapDriver::splitDiagonals
     const scalar minAreaRatio,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const vectorField& nearestAttraction,
     const vectorField& nearestNormal,
+    const List<labelList>& pointFacePatchID,
 
     vectorField& patchAttraction,
     List<pointConstraint>& patchConstraints,
+
     DynamicList<label>& splitFaces,
-    DynamicList<labelPair>& splits
+    DynamicList<labelPair>& splits,
+    DynamicList<labelPair>& splitPatches
 ) const
 {
     const labelList& bFaces = pp.addressing();
@@ -1962,11 +1985,13 @@ void Foam::snappySnapDriver::splitDiagonals
     splitFaces.setCapacity(bFaces.size());
     splits.clear();
     splits.setCapacity(bFaces.size());
-
+    splitPatches.clear();
+    splitPatches.setCapacity(bFaces.size());
 
     // Work arrays for storing points of face
     DynamicField<point> facePoints0;
     DynamicField<point> facePoints1;
+    face f0, f1;
 
     forAll(bFaces, facei)
     {
@@ -1979,6 +2004,7 @@ void Foam::snappySnapDriver::splitDiagonals
                 minAreaRatio,
 
                 pp,
+                ppLocalPoints,
                 patchAttraction,
                 patchConstraints,
 
@@ -1995,13 +2021,13 @@ void Foam::snappySnapDriver::splitDiagonals
         {
             splitFaces.append(bFaces[facei]);
             splits.append(split);
+            splitPatches.append(labelPair(-1, -1));
 
             const face& f = pp.localFaces()[facei];
 
             // Knock out other attractions on face
             forAll(f, fp)
             {
-                // Knock out any other constraints
                 if
                 (
                     fp != split[0]
@@ -2020,6 +2046,105 @@ void Foam::snappySnapDriver::splitDiagonals
                     patchAttraction[f[fp]] = nearestAttraction[f[fp]];
                 }
             }
+
+
+            // Detect any patches to give to the two faces
+            labelPair& twoPatches = splitPatches.last();
+
+            // Split into two faces:
+            //  - face0 is from split[0] up to split[1]
+            //  - face1 is from split[1] up to split[0]
+            meshRefinement::splitFace(f, split, f0, f1);
+
+            // Bit heuristic:
+            // - find any inbetween vertex (i.e. not on diagonal) that
+            //   has single patch only
+            // - if we find such a point on both sides we use these patches
+            // - if only found a point on one side check the other side
+            //   for any other patch
+
+            // Find single patch
+            for (label fp = 1; fp < f0.size()-1; fp++)
+            {
+                const auto& patches = pointFacePatchID[f0[fp]];
+                if (patches.uniform())
+                {
+                    twoPatches[0] = patches[0];
+                }
+            }
+            for (label fp = 1; fp < f1.size()-1; fp++)
+            {
+                const auto& patches = pointFacePatchID[f1[fp]];
+                if (patches.uniform())
+                {
+                    twoPatches[1] = patches[0];
+                }
+            }
+
+            if (twoPatches[0] == -1)
+            {
+                // Find any patch on any point that differs from twoPatches[1]
+                // (can be -1 or a unform patch)
+
+                for (label fp = 1; fp < f0.size()-1; fp++)
+                {
+                    const auto& patches = pointFacePatchID[f0[fp]];
+
+                    // Pick any patch which is not the unique patch of the
+                    // other face. TBD: count occurences and choose most used?
+                    for (const label patchi : patches)
+                    {
+                        if (patchi != twoPatches[1])
+                        {
+                            twoPatches[0] = patchi;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (twoPatches[1] == -1)
+            {
+                // Find any patch on any point that differs from twoPatches[0]
+                // (can be -1 or a unform patch)
+
+                for (label fp = 1; fp < f1.size()-1; fp++)
+                {
+                    const auto& patches = pointFacePatchID[f1[fp]];
+
+                    // Pick any patch which is not the unique patch of the
+                    // other face. TBD: count occurences and choose most used?
+                    for (const label patchi : patches)
+                    {
+                        if (patchi != twoPatches[0])
+                        {
+                            twoPatches[1] = patchi;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // Fall-back : choose any connected patch
+            if (twoPatches[0] == -1)
+            {
+                twoPatches[0] = pointFacePatchID[f0[1]][0];
+            }
+            if (twoPatches[1] == -1)
+            {
+                twoPatches[1] = pointFacePatchID[f1[1]][0];
+            }
+
+            //if (twoPatches != labelPair(-1, -1))
+            //{
+            //    Pout<< "Face:" << bFaces[facei]
+            //        << " at:" << pp.faceCentres()[facei]
+            //        << " split into f0:" << flatOutput(f0)
+            //        << " patch:" << twoPatches[0]
+            //        << " and f1:" << flatOutput(f1)
+            //        << " patch:" << twoPatches[1]
+            //        << endl;
+            //}
         }
     }
 }
@@ -2031,6 +2156,7 @@ void Foam::snappySnapDriver::avoidDiagonalAttraction
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
 
     vectorField& patchAttraction,
     List<pointConstraint>& patchConstraints
@@ -2054,10 +2180,10 @@ void Foam::snappySnapDriver::avoidDiagonalAttraction
             // For now just attract my one to the average of those.
             const label i0 = f[diag[0]];
             const point pt0 =
-                pp.localPoints()[i0]+patchAttraction[i0];
+                ppLocalPoints[i0]+patchAttraction[i0];
             const label i1 = f[diag[1]];
             const point pt1 =
-                pp.localPoints()[i1]+patchAttraction[i1];
+                ppLocalPoints[i1]+patchAttraction[i1];
             const point mid = 0.5*(pt0+pt1);
 
             const scalar cosAngle = mag
@@ -2084,7 +2210,7 @@ void Foam::snappySnapDriver::avoidDiagonalAttraction
                     label pointi = f[fp];
                     if (patchConstraints[pointi].first() <= 1)
                     {
-                        scalar distSqr = mid.distSqr(pp.localPoints()[pointi]);
+                        scalar distSqr = mid.distSqr(ppLocalPoints[pointi]);
                         if (distSqr < minDistSqr)
                         {
                             minFp = fp;
@@ -2095,7 +2221,7 @@ void Foam::snappySnapDriver::avoidDiagonalAttraction
                 {
                     label minPointi = f[minFp];
                     patchAttraction[minPointi] =
-                        mid-pp.localPoints()[minPointi];
+                        mid-ppLocalPoints[minPointi];
                     patchConstraints[minPointi] = patchConstraints[f[diag[0]]];
                 }
             }
@@ -2127,6 +2253,7 @@ Foam::snappySnapDriver::findNearFeatureEdge
     const bool isRegionEdge,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const label pointi,
     const point& estimatedPt,
@@ -2178,7 +2305,7 @@ Foam::snappySnapDriver::findNearFeatureEdge
         edgeConstraints[feati][nearInfo.index()].append(c);
 
         // Store for later use
-        patchAttraction[pointi] = nearInfo.point()-pp.localPoints()[pointi];
+        patchAttraction[pointi] = nearInfo.point()-ppLocalPoints[pointi];
         patchConstraints[pointi] = c;
     }
     return Tuple2<label, pointIndexHit>(feati, nearInfo);
@@ -2191,6 +2318,7 @@ Foam::snappySnapDriver::findNearFeaturePoint
     const bool isRegionPoint,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const label pointi,
     const point& estimatedPt,
@@ -2224,7 +2352,7 @@ Foam::snappySnapDriver::findNearFeaturePoint
 
     if (feati != -1)
     {
-        const point& pt = pp.localPoints()[pointi];
+        const point& pt = ppLocalPoints[pointi];
 
         label featPointi = nearInfo[0].index();
         const point& featPt = nearInfo[0].hitPoint();
@@ -2236,7 +2364,7 @@ Foam::snappySnapDriver::findNearFeaturePoint
         if (oldPointi != -1)
         {
             // Check distance
-            if (distSqr >= featPt.distSqr(pp.localPoints()[oldPointi]))
+            if (distSqr >= featPt.distSqr(ppLocalPoints[oldPointi]))
             {
                 // oldPointi nearest. Keep.
                 feati = -1;
@@ -2262,9 +2390,10 @@ Foam::snappySnapDriver::findNearFeaturePoint
                     isRegionPoint,      // search region edges only
 
                     pp,
+                    ppLocalPoints,
                     snapDist,
                     oldPointi,
-                    pp.localPoints()[oldPointi],
+                    ppLocalPoints[oldPointi],
 
                     edgeAttractors,
                     edgeConstraints,
@@ -2297,8 +2426,10 @@ void Foam::snappySnapDriver::determineFeatures
     const label iter,
     const scalar featureCos,
     const bool multiRegionFeatureSnap,
+    const bool strictRegionFeatureSnap, // special >=3 patch points handling
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const vectorField& nearestDisp,
 
@@ -2387,9 +2518,9 @@ void Foam::snappySnapDriver::determineFeatures
     DynamicList<vector> surfaceNormals(4);
     labelList faceToNormalBin;
 
-    forAll(pp.localPoints(), pointi)
+    forAll(ppLocalPoints, pointi)
     {
-        const point& pt = pp.localPoints()[pointi];
+        const point& pt = ppLocalPoints[pointi];
 
 
         // Determine the geometric planes the point is (approximately) on.
@@ -2409,6 +2540,7 @@ void Foam::snappySnapDriver::determineFeatures
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
             nearestDisp,
 
@@ -2417,7 +2549,7 @@ void Foam::snappySnapDriver::determineFeatures
             pointFaceSurfNormals,
             pointFaceDisp,
             pointFaceCentres,
-            pointFacePatchID,
+            pointFacePatchID,   // currently not used
 
             surfacePoints,
             surfaceNormals,
@@ -2427,6 +2559,43 @@ void Foam::snappySnapDriver::determineFeatures
             constraint
         );
 
+
+        if (strictRegionFeatureSnap)
+        {
+            // Bit tricky: if a point is on more than 2 points and only
+            // attracted-to-surface upgrade it to attract-to-edge so it follows
+            // more complex logic below. This is easier than complicating
+            // the nearestFeatureEdge/Point below.
+
+            if (constraint.first() == 1)
+            {
+                const auto& patches = pointFacePatchID[pointi];
+                label patch1 = -1;
+                for (label i = 1; i < patches.size(); i++)
+                {
+                    if (patches[i] != patches[0])
+                    {
+                        if (patch1 == -1)
+                        {
+                            patch1 = patches[i];
+                        }
+                        else if (patches[i] != patch1)
+                        {
+                            // >= on 2 patches. Upgrade to edge-attract
+                            constraint.first() = 2;
+                            //Pout<< "** 3 patch point:" << pointi
+                            //    << " at:" << pt
+                            //    << " patches:" << flatOutput(patches)
+                            //    << " upgraded to feature-edge"
+                            //    << " attracted to " << attraction << endl;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+
         // Now combine the reconstruction with the current state of the
         // point. The logic is quite complicated:
         // - the new constraint (from reconstruction) will only win if
@@ -2497,6 +2666,7 @@ void Foam::snappySnapDriver::determineFeatures
                         (
                             true,                       // isRegionEdge
                             pp,
+                            ppLocalPoints,
                             snapDist,
                             pointi,
                             multiPatchPt.point(),       // estimatedPt
@@ -2567,6 +2737,7 @@ void Foam::snappySnapDriver::determineFeatures
                             (
                                 true,               // isRegionEdge
                                 pp,
+                                ppLocalPoints,
                                 snapDist,
                                 pointi,
                                 estimatedPt,
@@ -2597,6 +2768,7 @@ void Foam::snappySnapDriver::determineFeatures
                             (
                                 true,           // isRegionPoint
                                 pp,
+                                ppLocalPoints,
                                 snapDist,
                                 pointi,
                                 estimatedPt,
@@ -2628,6 +2800,7 @@ void Foam::snappySnapDriver::determineFeatures
                                 (
                                     true,           // isRegionEdge
                                     pp,
+                                    ppLocalPoints,
                                     snapDist,
                                     pointi,
                                     estimatedPt,
@@ -2660,6 +2833,7 @@ void Foam::snappySnapDriver::determineFeatures
                     (
                         false,      // isRegionPoint
                         pp,
+                        ppLocalPoints,
                         snapDist,
                         pointi,
                         estimatedPt,
@@ -2728,6 +2902,7 @@ void Foam::snappySnapDriver::determineFeatures
                         (
                             true,           // isRegionPoint
                             pp,
+                            ppLocalPoints,
                             snapDist,
                             pointi,
                             estimatedPt,
@@ -2749,6 +2924,7 @@ void Foam::snappySnapDriver::determineFeatures
                         (
                             false,              // isRegionPoint
                             pp,
+                            ppLocalPoints,
                             snapDist,
                             pointi,
                             estimatedPt,
@@ -2772,6 +2948,7 @@ void Foam::snappySnapDriver::determineFeatures
                     (
                         false,              // isRegionPoint
                         pp,
+                        ppLocalPoints,
                         snapDist,
                         pointi,
                         estimatedPt,
@@ -2817,6 +2994,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
 
     // Feature-point to pp point
@@ -2836,6 +3014,13 @@ void Foam::snappySnapDriver::determineBaffleFeatures
     // Calculate edge-faces
     List<List<point>> edgeFaceNormals(pp.nEdges());
 
+    vectorField ppFaceNormals(pp.size());
+    forAll(ppFaceNormals, facei)
+    {
+        ppFaceNormals[facei] = pp.localFaces()[facei].unitNormal(ppLocalPoints);
+    }
+
+
     // Fill local data
     forAll(pp.edgeFaces(), edgei)
     {
@@ -2845,7 +3030,8 @@ void Foam::snappySnapDriver::determineBaffleFeatures
         forAll(eFaces, i)
         {
             label facei = eFaces[i];
-            eFc[i] = pp.faceNormals()[facei];
+            //eFc[i] = pp.faceNormals()[facei];
+            eFc[i] = ppFaceNormals[facei];
         }
     }
 
@@ -2913,7 +3099,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
 
             if (baffleEdgeStr)
             {
-                baffleEdgeStr().write(e, pp.localPoints());
+                baffleEdgeStr().write(e, ppLocalPoints);
             }
         }
     }
@@ -2940,7 +3126,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
     //        )
     //    )
     //    {
-    //        //Pout<< "Detected feature point:" << pp.localPoints()[pointi]
+    //        //Pout<< "Detected feature point:" << ppLocalPoints[pointi]
     //        //    << endl;
     //        //-TEMPORARILY DISABLED:
     //        //pointStatus[pointi] = 1;
@@ -2964,7 +3150,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
 
     forAll(pointStatus, pointi)
     {
-        const point& pt = pp.localPoints()[pointi];
+        const point& pt = ppLocalPoints[pointi];
 
         if (pointStatus[pointi] == 0)   // baffle edge
         {
@@ -2974,6 +3160,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
             (
                 false,          // isRegionPoint?
                 pp,
+                ppLocalPoints,
                 snapDist,
                 pointi,
                 pt,
@@ -3000,6 +3187,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
                         false,          // isRegionPoint,
 
                         pp,
+                        ppLocalPoints,
                         snapDist,
                         pointi,
                         pt,             // estimatedPt,
@@ -3053,7 +3241,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
                     oldPointi == -1
                  || (
                         distSqr
-                      < featPt.distSqr(pp.localPoints()[oldPointi])
+                      < featPt.distSqr(ppLocalPoints[oldPointi])
                     )
                 )
                 {
@@ -3075,9 +3263,10 @@ void Foam::snappySnapDriver::determineBaffleFeatures
                         (
                             false,              // isRegionPoint
                             pp,
+                            ppLocalPoints,
                             snapDist,
                             oldPointi,
-                            pp.localPoints()[oldPointi],
+                            ppLocalPoints[oldPointi],
 
                             edgeAttractors,
                             edgeConstraints,
@@ -3106,6 +3295,7 @@ void Foam::snappySnapDriver::determineBaffleFeatures
                 (
                     false,                  // isRegionPoint
                     pp,
+                    ppLocalPoints,
                     snapDist,
                     pointi,
                     pt,                     // starting point
@@ -3142,6 +3332,7 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
     const label iter,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
 
     // Feature-point to pp point
@@ -3167,7 +3358,7 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
     // nearest point on pp
 
     // Get search domain and extend it a bit
-    treeBoundBox bb(pp.localPoints());
+    treeBoundBox bb(ppLocalPoints);
     {
         // Random number generator. Bit dodgy since not exactly random ;-)
         Random rndGen(65431);
@@ -3263,7 +3454,7 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
 
     indexedOctree<treeDataPoint> ppTree
     (
-        treeDataPoint(pp.localPoints(), attractPoints),
+        treeDataPoint(ppLocalPoints, attractPoints),
         bb,                             // overall search domain
         8,                              // maxLevel
         10,                             // leafsize
@@ -3360,10 +3551,7 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
         {
             if (pointAttr[featPointi] != -1)
             {
-                const point& featPt = features[feati].points()
-                [
-                    featPointi
-                ];
+                const point& featPt = features[feati].points()[featPointi];
 
                 // Find nearest pp point
                 pointIndexHit nearInfo = ppTree.findNearest
@@ -3421,6 +3609,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
 (
     const label iter,
     const bool multiRegionFeatureSnap,
+    const bool strictRegionFeatureSnap, // special >=3 patch points handling
 
     const bool detectBaffles,
     const bool baffleFeaturePoints,
@@ -3432,6 +3621,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const vectorField& nearestDisp,
     const vectorField& nearestNormal,
@@ -3496,8 +3686,10 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
         iter,
         featureCos,
         multiRegionFeatureSnap,
+        strictRegionFeatureSnap, // extra logic for points on >=3 patches 
 
         pp,
+        ppLocalPoints,
         snapDist,               // per point max distance and nearest surface
         nearestDisp,
 
@@ -3544,6 +3736,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
 
             // Feature-point to pp point
@@ -3575,6 +3768,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
         iter,
 
         pp,
+        ppLocalPoints,
         snapDist,
 
         // Feature-point to pp point
@@ -3621,7 +3815,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
 
         forAll(patchConstraints, pointi)
         {
-            const point& pt = pp.localPoints()[pointi];
+            const point& pt = ppLocalPoints[pointi];
             const vector& attr = patchAttraction[pointi];
 
             if (patchConstraints[pointi].first() == 2)
@@ -3648,6 +3842,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
 
             pointFaceCentres,
@@ -3674,6 +3869,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
 
             rawPatchAttraction,
@@ -3695,6 +3891,7 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
             iter,
             featureCos,
             pp,
+            ppLocalPoints,
             patchAttraction,
             patchConstraints
         );
@@ -3707,8 +3904,8 @@ void Foam::snappySnapDriver::featureAttractionUsingFeatureEdges
         (
             meshRefiner_.mesh().time().path()
           / "patchAttraction_" + name(iter) + ".obj",
-            pp.localPoints(),
-            pp.localPoints() + patchAttraction
+            ppLocalPoints,
+            ppLocalPoints + patchAttraction
         );
     }
 }
@@ -3721,6 +3918,7 @@ void Foam::snappySnapDriver::preventFaceSqueeze
     const scalar featureCos,
 
     const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     const scalarField& snapDist,
     const vectorField& nearestAttraction,
 
@@ -3762,7 +3960,7 @@ void Foam::snappySnapDriver::preventFaceSqueeze
         forAll(f, fp)
         {
             label pointi = f[fp];
-            const point& pt = pp.localPoints()[pointi];
+            const point& pt = ppLocalPoints[pointi];
 
             if (patchConstraints[pointi].first() > 1)
             {
@@ -3786,8 +3984,8 @@ void Foam::snappySnapDriver::preventFaceSqueeze
                 scalar maxS = -1;
                 forAll(f, fp)
                 {
-                    const point& pt = pp.localPoints()[f[fp]];
-                    const point& nextPt = pp.localPoints()[f.nextLabel(fp)];
+                    const point& pt = ppLocalPoints[f[fp]];
+                    const point& nextPt = ppLocalPoints[f.nextLabel(fp)];
 
                     scalar s = pt.distSqr(nextPt);
                     if (s > maxS)
@@ -3802,7 +4000,7 @@ void Foam::snappySnapDriver::preventFaceSqueeze
 
                     // Reset attraction on pointi to nearest
 
-                    const point& pt = pp.localPoints()[pointi];
+                    const point& pt = ppLocalPoints[pointi];
 
                     //Pout<< "** on triangle " << pp.faceCentres()[facei]
                     //    << " knocking out attraction to " << pointi
@@ -3819,7 +4017,7 @@ void Foam::snappySnapDriver::preventFaceSqueeze
             }
             else
             {
-                scalar oldArea = f.mag(pp.localPoints());
+                scalar oldArea = f.mag(ppLocalPoints);
                 scalar newArea = singleF.mag(points);
                 if (newArea < 0.1*oldArea)
                 {
@@ -3852,19 +4050,21 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
 (
     const snapParameters& snapParams,
     const bool alignMeshEdges,
+    const bool strictRegionFeatureSnap, // use patches
     const label iter,
     const scalar featureCos,
     const scalar featureAttract,
     const scalarField& snapDist,
     const vectorField& nearestDisp,
     const vectorField& nearestNormal,
-    motionSmoother& meshMover,
+    const indirectPrimitivePatch& pp,
+    const pointField& ppLocalPoints,
     vectorField& patchAttraction,
     List<pointConstraint>& patchConstraints,
 
     DynamicList<label>& splitFaces,
-    DynamicList<labelPair>& splits
-
+    DynamicList<labelPair>& splits,
+    DynamicList<labelPair>& splitPatches
 ) const
 {
     if (dryRun_)
@@ -3883,8 +4083,6 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         << "   multi-patch features : " << multiRegionFeatureSnap << nl
         << endl;
 
-    const indirectPrimitivePatch& pp = meshMover.patch();
-    const pointField& localPoints = pp.localPoints();
     const fvMesh& mesh = meshRefiner_.mesh();
 
 
@@ -3935,6 +4133,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         (
             iter,
             pp,
+            ppLocalPoints,
             faceSnapDist,
             faceDisp,
             faceSurfaceNormal,
@@ -3952,7 +4151,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         (
             iter,
             pp,
-
+            ppLocalPoints,
             faceDisp,
             faceSurfaceNormal,
             faceSurfaceGlobalRegion,
@@ -3976,10 +4175,10 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
     // here.
 
     // Nearest feature
-    patchAttraction.setSize(localPoints.size());
+    patchAttraction.setSize(ppLocalPoints.size());
     patchAttraction = Zero;
     // Constraints at feature
-    patchConstraints.setSize(localPoints.size());
+    patchConstraints.setSize(ppLocalPoints.size());
     patchConstraints = pointConstraint();
 
     if (implicitFeatureAttraction)
@@ -3993,6 +4192,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
             nearestDisp,
 
@@ -4030,6 +4230,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         (
             iter,
             multiRegionFeatureSnap,
+            strictRegionFeatureSnap,    // special logic for >=3 patches points?
 
             snapParams.detectBaffles(),
             snapParams.baffleFeaturePoints(),   // all points on baffle edges
@@ -4042,6 +4243,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
             featureCos,
 
             pp,
+            ppLocalPoints,
             snapDist,
             nearestDisp,
             nearestNormal,
@@ -4064,7 +4266,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         );
         const scalar minAreaRatio = snapParams.minAreaRatio();
 
-        Info<< "Experimental: introducing face splits to avoid rotating"
+        Info<< "Introducing face splits to avoid rotating"
             << " mesh edges. Splitting faces when" << nl
             << indent << "- angle not concave by more than "
             << snapParams.concaveAngle() << " degrees" << nl
@@ -4078,14 +4280,18 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
             concaveCos,
             minAreaRatio,
             pp,
+            ppLocalPoints,
 
             nearestDisp,
             nearestNormal,
-
+            pointFacePatchID,   // per point the connected patches. Is used
+                                // to re-patch newly split faces
             patchAttraction,
             patchConstraints,
+
             splitFaces,
-            splits
+            splits,
+            splitPatches
         );
 
         if (debug)
@@ -4102,6 +4308,7 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
         featureCos,
 
         pp,
+        ppLocalPoints,
         snapDist,
         nearestDisp,
 
@@ -4227,8 +4434,8 @@ Foam::vectorField Foam::snappySnapDriver::calcNearestSurfaceFeature
             (
                 mesh.time().path()
               / "tangPatchDispConstrained_" + name(iter) + ".obj",
-                pp.localPoints(),
-                pp.localPoints() + tangPatchDisp
+                ppLocalPoints,
+                ppLocalPoints + tangPatchDisp
             );
         }
 
diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index acbb97b1f1450d9d049b405db23fa669546b5b29..f207200fabca45b1836e841a6a99cf70c771e626 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -217,6 +217,7 @@ $(pointSources)/searchableSurfaceToPoint/searchableSurfaceToPoint.C
 $(pointSources)/sphereToPoint/sphereToPoint.C
 $(pointSources)/surfaceToPoint/surfaceToPoint.C
 $(pointSources)/zoneToPoint/zoneToPoint.C
+$(pointSources)/patchToPoint/patchToPoint.C
 
 faceZoneSources = topoSet/faceZoneSources
 $(faceZoneSources)/topoSetFaceZoneSource/topoSetFaceZoneSource.C
diff --git a/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.C b/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.C
index 8ff95a4c48ad93a1fb538572e1ba26e28baef00e..0e35e0275d63abe759897e924a98bbe01b69c41d 100644
--- a/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.C
+++ b/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2019-2023 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -36,7 +36,7 @@ License
 // refCast<const facePointPatch>(p).patch()
 
 template<class Type>
-const Foam::polyPatch&
+const Foam::polyPatch*
 Foam::uniformFixedValuePointPatchField<Type>::getPatch(const pointPatch& p)
 {
     const polyMesh& mesh = p.boundaryMesh().mesh()();
@@ -44,11 +44,12 @@ Foam::uniformFixedValuePointPatchField<Type>::getPatch(const pointPatch& p)
 
     if (patchi == -1)
     {
-        FatalErrorInFunction
-            << "Cannot use uniformFixedValue on patch " << p.name()
-            << " since there is no underlying mesh patch" << exit(FatalError);
+        return nullptr;
+    }
+    else
+    {
+        return &mesh.boundaryMesh()[patchi];
     }
-    return mesh.boundaryMesh()[patchi];
 }
 
 
@@ -63,7 +64,8 @@ uniformFixedValuePointPatchField
 )
 :
     fixedValuePointPatchField<Type>(p, iF),
-    refValueFunc_(nullptr)
+    refValueFunc_(nullptr),
+    refPointValueFunc_(nullptr)
 {}
 
 
@@ -79,13 +81,26 @@ uniformFixedValuePointPatchField
     fixedValuePointPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
     refValueFunc_
     (
-        PatchFunction1<Type>::New
+        this->getPatch(p)
+      ? PatchFunction1<Type>::New
         (
-            this->getPatch(p),
+            *(this->getPatch(p)),
             "uniformValue",
             dict,
             false           // generate point values
         )
+      : nullptr
+    ),
+    refPointValueFunc_
+    (
+        this->getPatch(p)
+      ? nullptr
+      : Function1<Type>::New
+        (
+            "uniformValue",
+            dict,
+            &this->internalField().db()
+        )
     )
 {
     if (!this->readValueEntry(dict))
@@ -110,7 +125,8 @@ uniformFixedValuePointPatchField
 )
 :
     fixedValuePointPatchField<Type>(ptf, p, iF, mapper),
-    refValueFunc_(ptf.refValueFunc_.clone(this->getPatch(p)))
+    refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(p)))),
+    refPointValueFunc_(ptf.refPointValueFunc_.clone())
 {
     if (mapper.direct() && !mapper.hasUnmapped())
     {
@@ -133,7 +149,8 @@ uniformFixedValuePointPatchField
 )
 :
     fixedValuePointPatchField<Type>(ptf),
-    refValueFunc_(ptf.refValueFunc_.clone(this->getPatch(this->patch())))
+    refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(this->patch())))),
+    refPointValueFunc_(ptf.refPointValueFunc_.clone())
 {}
 
 
@@ -146,7 +163,8 @@ uniformFixedValuePointPatchField
 )
 :
     fixedValuePointPatchField<Type>(ptf, iF),
-    refValueFunc_(ptf.refValueFunc_.clone(this->getPatch(this->patch())))
+    refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(this->patch())))),
+    refPointValueFunc_(ptf.refPointValueFunc_.clone())
 {}
 
 
@@ -170,6 +188,14 @@ void Foam::uniformFixedValuePointPatchField<Type>::autoMap
             this->evaluate();
         }
     }
+    if (refPointValueFunc_)
+    {
+        if (refPointValueFunc_().constant())
+        {
+            // If mapper is not dependent on time we're ok to evaluate
+            this->evaluate();
+        }
+    }
 }
 
 
@@ -201,7 +227,14 @@ void Foam::uniformFixedValuePointPatchField<Type>::updateCoeffs()
     }
     const scalar t = this->db().time().timeOutputValue();
 
-    valuePointPatchField<Type>::operator=(refValueFunc_->value(t));
+    if (refValueFunc_)
+    {
+        valuePointPatchField<Type>::operator=(refValueFunc_->value(t));
+    }
+    else
+    {
+        valuePointPatchField<Type>::operator=(refPointValueFunc_->value(t));
+    }
     fixedValuePointPatchField<Type>::updateCoeffs();
 }
 
@@ -216,6 +249,10 @@ write(Ostream& os) const
     {
         refValueFunc_->writeData(os);
     }
+    if (refPointValueFunc_)
+    {
+        refPointValueFunc_->writeData(os);
+    }
 }
 
 
diff --git a/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.H b/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.H
index 9cf2a5c27efc5136ceb572db716db072ce76cf78..3312fb063c86dfcb71fa7a5cb8da8c67ec524e42 100644
--- a/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.H
+++ b/src/meshTools/fields/pointPatchFields/uniformFixedValue/uniformFixedValuePointPatchField.H
@@ -86,10 +86,13 @@ class uniformFixedValuePointPatchField
         //- Function providing the value
         autoPtr<PatchFunction1<Type>> refValueFunc_;
 
+        //- Function providing the value (if not on polyPatch)
+        autoPtr<Function1<Type>> refPointValueFunc_;
+
 
     // Private Member Functions
 
-        static const polyPatch& getPatch(const pointPatch&);
+        static const polyPatch* getPatch(const pointPatch&);
 
 
 public:
diff --git a/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.C b/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.C
new file mode 100644
index 0000000000000000000000000000000000000000..ed7198f14940c6fd4e7c7c4b6237d341bf9041fc
--- /dev/null
+++ b/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.C
@@ -0,0 +1,185 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "patchToPoint.H"
+#include "pointMesh.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(patchToPoint, 0);
+    addToRunTimeSelectionTable(topoSetSource, patchToPoint, word);
+    addToRunTimeSelectionTable(topoSetSource, patchToPoint, istream);
+    addToRunTimeSelectionTable(topoSetPointSource, patchToPoint, word);
+    addToRunTimeSelectionTable(topoSetPointSource, patchToPoint, istream);
+    addNamedToRunTimeSelectionTable
+    (
+        topoSetPointSource,
+        patchToPoint,
+        word,
+        patch
+    );
+    addNamedToRunTimeSelectionTable
+    (
+        topoSetPointSource,
+        patchToPoint,
+        istream,
+        patch
+    );
+}
+
+
+Foam::topoSetSource::addToUsageTable Foam::patchToPoint::usage_
+(
+    patchToPoint::typeName,
+    "\n    Usage: patchToPoint patch\n\n"
+    "    Select all points in the pointPatch."
+    " Note:accepts wildcards for patch.\n\n"
+);
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::patchToPoint::combine(topoSet& set, const bool add) const
+{
+    const pointMesh& pMesh = pointMesh::New(mesh_, IOobject::READ_IF_PRESENT);
+    const pointBoundaryMesh& pbm = pMesh.boundary();
+
+    labelList patchIDs
+    (
+        pbm.indices
+        (
+            selectedPatches_,
+            true        // useGroups
+        )
+    );
+
+
+    for (const label patchi : patchIDs)
+    {
+        const pointPatch& pp = pbm[patchi];
+
+        if (verbose_)
+        {
+            Info<< "    Found matching patch " << pp.name() << " with "
+                << returnReduce(pp.size(), sumOp<label>()) << " points" << endl;
+        }
+
+        for (const label pointi : pp.meshPoints())
+        {
+            addOrDelete(set, pointi, add);
+        }
+    }
+
+    if (patchIDs.empty())
+    {
+        WarningInFunction
+            << "Cannot find any patches matching "
+            << flatOutput(selectedPatches_) << nl
+            //<< "Valid names: " << flatOutput(mesh_.boundaryMesh().names())
+            << endl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::patchToPoint::patchToPoint
+(
+    const polyMesh& mesh,
+    const wordRe& patchName
+)
+:
+    topoSetPointSource(mesh),
+    selectedPatches_(one{}, patchName)
+{}
+
+
+Foam::patchToPoint::patchToPoint
+(
+    const polyMesh& mesh,
+    const dictionary& dict
+)
+:
+    topoSetPointSource(mesh),
+    selectedPatches_()
+{
+    // Look for 'patches' and 'patch', but accept 'name' as well
+    if (!dict.readIfPresent("patches", selectedPatches_))
+    {
+        selectedPatches_.resize(1);
+        selectedPatches_.front() =
+            dict.getCompat<wordRe>("patch", {{"name", 1806}});
+    }
+}
+
+
+Foam::patchToPoint::patchToPoint
+(
+    const polyMesh& mesh,
+    Istream& is
+)
+:
+    topoSetPointSource(mesh),
+    selectedPatches_(one{}, wordRe(checkIs(is)))
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::patchToPoint::applyToSet
+(
+    const topoSetSource::setAction action,
+    topoSet& set
+) const
+{
+    if (action == topoSetSource::ADD || action == topoSetSource::NEW)
+    {
+        if (verbose_)
+        {
+            Info<< "    Adding all points of patches: "
+                << flatOutput(selectedPatches_) << " ..." << endl;
+        }
+
+        combine(set, true);
+    }
+    else if (action == topoSetSource::SUBTRACT)
+    {
+        if (verbose_)
+        {
+            Info<< "    Removing all points of patches: "
+                << flatOutput(selectedPatches_) << " ..." << endl;
+        }
+
+        combine(set, false);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.H b/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.H
new file mode 100644
index 0000000000000000000000000000000000000000..b1ed3913775fdc6b1e238a3b038b60d0c95e62e0
--- /dev/null
+++ b/src/meshTools/topoSet/pointSources/patchToPoint/patchToPoint.H
@@ -0,0 +1,174 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2024 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::patchToPoint
+
+Description
+    A \c topoSetPointSource to select points associated with given patch(es).
+
+    Operands:
+    \table
+      Operand   | Type     | Location
+      output    | pointSet | $FOAM_CASE/constant/polyMesh/sets/\<set\>
+    \endtable
+
+Usage
+    Minimal example by using \c system/topoSetDict.actions:
+    \verbatim
+    {
+        // Mandatory (inherited) entries
+        name        <name>;
+        type        pointSet;
+        action      <action>;
+
+        // Mandatory entries
+        source      patchToPoint;
+
+        // Conditional mandatory entries
+        // Select either of the below
+
+        // Option-1
+        patches
+        (
+            <patchName1>
+            <patchName2>
+            ...
+        );
+
+        // Option-2
+        patch    <patchName>;
+    }
+    \endverbatim
+
+    where the entries mean:
+    \table
+      Property   | Description                         | Type | Req'd | Dflt
+      name       | Name of pointSet                    | word |  yes  | -
+      type       | Type name: pointSet                 | word |  yes  | -
+      action     | Action applied on points - see below | word |  yes  | -
+      source     | Source name: patchToPoint            | word |  yes  | -
+    \endtable
+
+    Options for the \c action entry:
+    \verbatim
+      new      | Create a new pointSet from selected points
+      add      | Add selected points into this pointSet
+      subtract | Remove selected points from this pointSet
+    \endverbatim
+
+    Options for the conditional mandatory entries:
+    \verbatim
+      Entry    | Description           | Type     | Req'd  | Dflt
+      patches  | Names of patches      | wordList | cond'l | -
+      patch    | Name of patch         | word     | cond'l | -
+    \endverbatim
+
+Note
+    The order of precedence among the conditional mandatory entries from the
+    highest to the lowest is \c patches, and \c patch.
+
+See also
+    - Foam::patchToFace
+
+SourceFiles
+    patchToPoint.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef patchToPoint_H
+#define patchToPoint_H
+
+#include "topoSetPointSource.H"
+#include "wordRes.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class patchToPoint Declaration
+\*---------------------------------------------------------------------------*/
+
+class patchToPoint
+:
+    public topoSetPointSource
+{
+    // Private Data
+
+        //- Add usage string
+        static addToUsageTable usage_;
+
+        //- Matcher for patches
+        wordRes selectedPatches_;
+
+
+    // Private Member Functions
+
+        void combine(topoSet& set, const bool add) const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("patchToPoint");
+
+
+    // Constructors
+
+        //- Construct from components
+        patchToPoint(const polyMesh& mesh, const wordRe& patchName);
+
+        //- Construct from dictionary
+        patchToPoint(const polyMesh& mesh, const dictionary& dict);
+
+        //- Construct from Istream
+        patchToPoint(const polyMesh& mesh, Istream& is);
+
+
+    //- Destructor
+    virtual ~patchToPoint() = default;
+
+
+    // Member Functions
+
+        virtual void applyToSet
+        (
+            const topoSetSource::setAction action,
+            topoSet& set
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/parallel/reconstruct/reconstruct/processorMeshes.C b/src/parallel/reconstruct/reconstruct/processorMeshes.C
index beaa2ea85888f3cb82e634f93328bf12881275e5..22c07913b261d0ca55db20b4ef6890de7ed27eee 100644
--- a/src/parallel/reconstruct/reconstruct/processorMeshes.C
+++ b/src/parallel/reconstruct/reconstruct/processorMeshes.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -31,6 +31,7 @@ License
 #include "IndirectList.H"
 #include "primitiveMesh.H"
 #include "OSspecific.H"
+#include "pointMesh.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -46,6 +47,9 @@ void Foam::processorMeshes::read()
 {
     // Make sure to clear (and hence unregister) any previously loaded meshes
     // and fields
+    pBoundaryProcAddressing_.free();
+    pMeshes_.free();
+
     boundaryProcAddressing_.free();
     cellProcAddressing_.free();
     faceProcAddressing_.free();
@@ -92,6 +96,39 @@ void Foam::processorMeshes::read()
         // boundaryProcAddressing (polyMesh)
         ioAddr.rename("boundaryProcAddressing");
         boundaryProcAddressing_.emplace_set(proci, ioAddr);
+
+
+        // pointMesh
+        // ~~~~~~~~~
+
+        pMeshes_.set
+        (
+            proci,
+            new pointMesh
+            (
+                meshes_[proci],
+                IOobject::READ_IF_PRESENT
+            )
+        );
+
+        pBoundaryProcAddressing_.set
+        (
+            proci,
+            autoPtr<labelIOList>::New
+            (
+                IOobject
+                (
+                    "boundaryProcAddressing",
+                    meshes_[proci].facesInstance(),
+                    polyMesh::meshSubDir/pointMesh::meshSubDir,
+                    pMeshes_[proci].thisDb(),
+                    IOobject::READ_IF_PRESENT,
+                    IOobject::NO_WRITE,
+                    IOobject::NO_REGISTER
+                ),
+                boundaryProcAddressing_[proci]
+            )
+        );
     }
 }
 
@@ -110,7 +147,9 @@ Foam::processorMeshes::processorMeshes
     pointProcAddressing_(databases.size()),
     faceProcAddressing_(databases.size()),
     cellProcAddressing_(databases.size()),
-    boundaryProcAddressing_(databases.size())
+    boundaryProcAddressing_(databases.size()),
+    pMeshes_(databases.size()),
+    pBoundaryProcAddressing_(databases.size())
 {
     read();
 }
@@ -250,6 +289,26 @@ void Foam::processorMeshes::removeFiles(const polyMesh& mesh)
     // boundaryProcAddressing
     io.rename("boundaryProcAddressing");
     fileHandler().rm(fileHandler().filePath(io.objectPath()));
+
+
+
+    // pointMesh
+    // ~~~~~~~~~
+
+    IOobject pointIO
+    (
+        "boundary",
+        mesh.facesInstance(),
+        polyMesh::meshSubDir/pointMesh::meshSubDir,
+        mesh.thisDb()
+    );
+
+    // pointMesh/boundary
+    fileHandler().rm(fileHandler().filePath(pointIO.objectPath()));
+
+    // boundaryProcAddressing
+    io.rename("boundaryProcAddressing");
+    fileHandler().rm(fileHandler().filePath(pointIO.objectPath()));
 }
 
 
diff --git a/src/parallel/reconstruct/reconstruct/processorMeshes.H b/src/parallel/reconstruct/reconstruct/processorMeshes.H
index 9272681ba1ba625ea1110f29205f2352cc700b4c..d8da977c737976b9a105d5e5aeb33e67c66a5e1e 100644
--- a/src/parallel/reconstruct/reconstruct/processorMeshes.H
+++ b/src/parallel/reconstruct/reconstruct/processorMeshes.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2014 OpenFOAM Foundation
-    Copyright (C) 2016 OpenCFD Ltd.
+    Copyright (C) 2016,2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -77,6 +77,15 @@ class processorMeshes
         PtrList<labelIOList> boundaryProcAddressing_;
 
 
+        // pointMesh
+
+            //- List of processor meshes
+            PtrList<pointMesh> pMeshes_;
+
+            //- List of processor boundary addressing lists for pointMeshes
+            PtrList<labelIOList> pBoundaryProcAddressing_;
+
+
     // Private Member Functions
 
         //- Read all meshes
@@ -140,6 +149,20 @@ public:
         }
 
 
+        // pointMesh
+
+            const PtrList<pointMesh>& pointMeshes() const noexcept
+            {
+                return pMeshes_;
+            }
+
+            const PtrList<labelIOList>& pointMeshBoundaryProcAddressing()
+            const noexcept
+            {
+                return pBoundaryProcAddressing_;
+            }
+
+
         //- Helper: remove all procAddressing files from mesh instance
         static void removeFiles(const polyMesh& mesh);
 };
diff --git a/tutorials/mesh/blockMesh/pipe/0.orig/pointDisplacement b/tutorials/mesh/blockMesh/pipe/0.orig/pointDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..1fc81f71beb2ece674cebba9c302827eefed0699
--- /dev/null
+++ b/tutorials/mesh/blockMesh/pipe/0.orig/pointDisplacement
@@ -0,0 +1,78 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  2309                                  |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    arch        "LSB;label=32;scalar=64";
+    class       pointVectorField;
+    location    "0";
+    object      pointDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+
+// Some macros
+__surfaceSlipDisplacement
+{
+    type            surfaceSlipDisplacement;
+    value           uniform (0 0 0);
+    geometry
+    {
+        box
+        {
+            type            triSurfaceMesh;
+            file            blockMesh.obj;
+        }
+    }
+    projectMode     nearest;
+}
+
+__edgeSlipDisplacement
+{
+    type            edgeSlipDisplacement;
+    file            "blockMesh.eMesh";
+    // Underrelax the displacement on edges since conflicts with
+    // smoothing. TBD.
+    velocity        (1 1 1);
+}
+
+
+boundaryField
+{
+    // Attract to feature lines
+    wallsEdges
+    {
+        ${__edgeSlipDisplacement};
+    }
+
+    // Attract to feature lines
+    boundaryEdges
+    {
+        ${__edgeSlipDisplacement};
+    }
+
+    // Attract to feature lines
+    sideEdges
+    {
+        ${__edgeSlipDisplacement};
+    }
+
+    // Default is to attract to surface
+    ".*"
+    {
+        ${__surfaceSlipDisplacement};
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/pipe/Allclean b/tutorials/mesh/blockMesh/pipe/Allclean
index 64435d02b1407ff6f433978ca54fecadc70675c1..09746eab8109993bfc6e213e321387ad6ed349fc 100755
--- a/tutorials/mesh/blockMesh/pipe/Allclean
+++ b/tutorials/mesh/blockMesh/pipe/Allclean
@@ -6,5 +6,11 @@ cd "${0%/*}" || exit                                # Run from this directory
 cleanCase0
 
 rm -rf constant/geometry
+rm -rf constant/extendedFeatureEdgeMesh
+rm -rf constant/geometry
+
+#- From pointMesh generation
+rm -rf constant/pointMesh
+rm -rf constant/triSurface
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/mesh/blockMesh/pipe/Allrun b/tutorials/mesh/blockMesh/pipe/Allrun
index 9c48a0769cecbc408f32f23493ffbd00aafe3373..bc3ee363bbed60a8b485136ece9ea41ea9ed15f2 100755
--- a/tutorials/mesh/blockMesh/pipe/Allrun
+++ b/tutorials/mesh/blockMesh/pipe/Allrun
@@ -11,8 +11,29 @@ cp -f \
 
 runApplication blockMesh
 
+# See if we can improve the mesh with a bit of smoothing (whilst freezing
+# the features)
+# - feature-edge attraction conflicts with mesh smoothing so faces with
+#   three vertices on feature edge get distorted.
+
+#- Analyse mesh and
+#   - generate pointMesh with additional feature patches
+#     (in constant/pointMesh/boundary).
+#   - write .obj file with outside of mesh
+mkdir -p constant/triSurface
+runApplication surfaceMeshExtract -featureAngle 50 \
+    constant/triSurface/blockMesh.obj
+
+#- Extract features from surface (original of blockMesh). Writes .eMesh.
+runApplication surfaceFeatureExtract
+
+#- Set the initial field
 restore0Dir
 
-runApplication $(getApplication)
+#- Run mesh smoother
+runApplication moveDynamicMesh
+
+#- Check mesh, generate postprocessing fields
+runApplication checkMesh -writeFields '(nonOrthoAngle)'
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/mesh/blockMesh/pipe/README.txt b/tutorials/mesh/blockMesh/pipe/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d4e7d6df7abedfc8d9c6a9cc1f31c3ae6f775b34
--- /dev/null
+++ b/tutorials/mesh/blockMesh/pipe/README.txt
@@ -0,0 +1,12 @@
+Demos:
+
+- blockMesh:
+    - snapping to surface
+    - surface defined by extrusion of line
+
+- surfaceMeshExtract
+    - generation of additional pointPatches to handle features
+
+- moveDynamicMesh
+    - point-based smoothers
+    - feature-attraction through boundary conditions
diff --git a/tutorials/mesh/blockMesh/pipe/constant/dynamicMeshDict b/tutorials/mesh/blockMesh/pipe/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..65c6223a7f783b7f6aadf5c4299ad312454263a4
--- /dev/null
+++ b/tutorials/mesh/blockMesh/pipe/constant/dynamicMeshDict
@@ -0,0 +1,29 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+motionSolverLibs (fvMotionSolvers);
+
+motionSolver    displacementPointSmoothing;
+displacementPointSmoothingCoeffs
+{
+    pointSmoother           geometricElementTransform;
+    transformationParameter 0.667;
+    nPointSmootherIter      1;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/pipe/system/controlDict b/tutorials/mesh/blockMesh/pipe/system/controlDict
index b98630e1a02dc49fa726353aea72d02fdbde16ff..a210ebbd6fb7fbcf42ac72f22d0e577b8f1234ff 100644
--- a/tutorials/mesh/blockMesh/pipe/system/controlDict
+++ b/tutorials/mesh/blockMesh/pipe/system/controlDict
@@ -14,17 +14,7 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-libs            (blockMesh);
-
-DebugSwitches
-{
-    //project 1;
-    //searchableExtrudedCircle 1;
-    //projectCurve 1;
-    solution    1;
-}
-
-application     simpleFoam;
+application     moveDynamicMesh;
 
 startFrom       startTime;
 
@@ -32,7 +22,7 @@ startTime       0;
 
 stopAt          endTime;
 
-endTime         100;
+endTime         10;
 
 deltaT          1;
 
diff --git a/tutorials/mesh/blockMesh/pipe/system/surfaceFeatureExtractDict b/tutorials/mesh/blockMesh/pipe/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..192e95601eafcd7802c3089e9dca24f19e76bf75
--- /dev/null
+++ b/tutorials/mesh/blockMesh/pipe/system/surfaceFeatureExtractDict
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+blockMesh.obj
+{
+    // How to obtain raw features (extractFromFile || extractFromSurface)
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       130;
+
+    // Write features to obj format for postprocessing
+    writeObj            yes;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/0.orig/cellDisplacement b/tutorials/mesh/blockMesh/sphere7/0.orig/cellDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..1322070750e8de199d163e12a93d04826ea4e375
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/0.orig/cellDisplacement
@@ -0,0 +1,58 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  2312                                  |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    arch        "LSB;label=32;scalar=64";
+    class       volVectorField;
+    location    "1";
+    object      cellDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    minX
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+    maxX
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+    minY
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+    maxY
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+    minZ
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+    maxZ
+    {
+        type            cellMotion;
+        value           uniform (0 0 0);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/0.orig/pointDisplacement b/tutorials/mesh/blockMesh/sphere7/0.orig/pointDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..43cfe34877938e5555012a2d5f80f1fc3d980edb
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/0.orig/pointDisplacement
@@ -0,0 +1,81 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  2309                                  |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    arch        "LSB;label=32;scalar=64";
+    class       pointVectorField;
+    location    "0";
+    object      pointDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    minX
+    {
+        type            surfaceSlipDisplacement;
+        value           uniform (0 0 0);
+        velocity        (0.1 0.1 0.1);
+        //velocity        (100 100 100);
+        geometry
+        {
+            box
+            {
+                type            triSurfaceMesh;
+                file            box222.obj;
+            }
+        }
+        projectMode     nearest;
+    }
+    maxX
+    {
+        $minX
+    }
+    minY
+    {
+        $minX
+    }
+    maxY
+    {
+        $minX
+    }
+    minZ
+    {
+        $minX
+    }
+    maxZ
+    {
+        $minX
+    }
+    boundaryEdges
+    {
+        type            edgeSlipDisplacement;
+        file            "box222.eMesh";
+        //file            "box222.extendedFeatureEdgeMesh";
+        //- Underrelax motion by limiting displacement velocity
+        velocity        (0.1 0.1 0.1);
+        //velocity        (100 100 100);
+    }
+    boundaryPoints
+    {
+        type            pointAttraction;
+        file            "box222.eMesh";
+        //- Underrelax motion by limiting displacement velocity
+        velocity        (0.1 0.1 0.1);
+        //velocity        (100 100 100);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/Allclean b/tutorials/mesh/blockMesh/sphere7/Allclean
index d4f5975bc81100693691ef5bc2e8e027d5231e53..0d325ec274bd399cd9863381be036289c564420d 100755
--- a/tutorials/mesh/blockMesh/sphere7/Allclean
+++ b/tutorials/mesh/blockMesh/sphere7/Allclean
@@ -5,6 +5,14 @@ cd "${0%/*}" || exit                                # Run from this directory
 
 cleanCase0
 
-rm -rf constant
+rm -rf constant/extendedFeatureEdgeMesh
+
+#- From pointMesh generation
+rm -rf constant/pointMesh
+rm -f constant/triSurface/blockMesh.obj
+rm -f constant/triSurface/outside.obj
+
+#- From surfaceFeatureExtract
+rm -f constant/triSurface/box222.eMesh
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/mesh/blockMesh/sphere7/Allrun b/tutorials/mesh/blockMesh/sphere7/Allrun
index c0ee92beedf30f397cf3c31f146983b44bf406d5..2da43c1d7fe8478a71dd401c154c724cbf813c0e 100755
--- a/tutorials/mesh/blockMesh/sphere7/Allrun
+++ b/tutorials/mesh/blockMesh/sphere7/Allrun
@@ -3,6 +3,44 @@ cd "${0%/*}" || exit                                # Run from this directory
 . ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
 #------------------------------------------------------------------------------
 
+#- Run blockMesh with projection
 runApplication blockMesh
 
+# Optional
+
+    ##- Extrude very thin cells to make it harder. Note: requires a
+    ##- pointSmoother first before doing the displacementLaplacian
+    #runApplication extrudeMesh
+
+    #- Refine some cells
+    runApplication topoSet
+    runApplication refineHexMesh c0 -overwrite
+
+
+#- Generate pointMesh with additional feature patches
+#  (in constant/pointMesh/boundary). Extracted outside of mesh is not used.
+runApplication surfaceMeshExtract -featureAngle 45 \
+    constant/triSurface/blockMesh.obj
+
+#- Set the initial field
+restore0Dir
+
+#- TBD. move triSurfaces to resources
+#mkdir -p constant/triSurface
+#cp -f \
+#    "$FOAM_TUTORIALS"/resources/geometry/box222.obj \
+#    constant/triSurface/
+
+#- Extract features from surface. Writes .eMesh
+runApplication surfaceFeatureExtract
+
+##- Morph mesh to the surface (.obj file) and feature-edges (.eMesh file)
+#runApplication moveDynamicMesh
+
+runApplication decomposePar
+
+runParallel moveDynamicMesh
+
+runApplication reconstructPar
+
 #------------------------------------------------------------------------------
diff --git a/tutorials/mesh/blockMesh/sphere7/constant/dynamicMeshDict b/tutorials/mesh/blockMesh/sphere7/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..6e89b3d992a9e3df6af0ee032a12ec6855634041
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/constant/dynamicMeshDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+motionSolverLibs (fvMotionSolvers);
+
+//motionSolver    displacementPointSmoothing;
+//displacementPointSmoothingCoeffs
+//{
+//    //pointSmoother           geometricElementTransform;
+//    //transformationParameter 0.667;
+//    pointSmoother           laplacian;
+//
+//    nPointSmootherIter      10;
+//
+//    //relaxationFactors       (1);
+//    //meshQuality             {}
+//    //moveInternalFaces       true;
+//}
+
+motionSolver    multiDisplacement;
+solvers
+{
+    displacementLaplacian
+    {
+        motionSolver        displacementLaplacian;
+        diffusivity         uniform;
+    }
+
+    displacementPointSmoothing
+    {
+        motionSolver        displacementPointSmoothing;
+        pointSmoother       laplacian;
+        nPointSmootherIter  10;
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box222.obj b/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box222.obj
new file mode 100644
index 0000000000000000000000000000000000000000..f1aceeca48a77cbe62aea577f651b129de3fa96d
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box222.obj
@@ -0,0 +1,79 @@
+# Generated by Visualization Toolkit
+v -1 -1 -1
+v -1 -1 1
+v -1 1 -1
+v -1 1 1
+v 1 -1 -1
+v 1 -1 1
+v 1 1 -1
+v 1 1 1
+v -1 -1 -1
+v -1 -1 1
+v 1 -1 -1
+v 1 -1 1
+v -1 1 -1
+v -1 1 1
+v 1 1 -1
+v 1 1 1
+v -1 -1 -1
+v 1 -1 -1
+v -1 1 -1
+v 1 1 -1
+v -1 -1 1
+v 1 -1 1
+v -1 1 1
+v 1 1 1
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vt -0.5 -0.5
+vt 1.5 -0.5
+vt -0.5 1.5
+vt 1.5 1.5
+vt 0.5 -0.5
+vt -1.5 -0.5
+vt 0.5 1.5
+vt -1.5 1.5
+vt 0.5 0.5
+vt 0.5 -1.5
+vt -1.5 0.5
+vt -1.5 -1.5
+vt -0.5 0.5
+vt -0.5 -1.5
+vt 1.5 0.5
+vt 1.5 -1.5
+vt 0.5 -0.5
+vt -1.5 -0.5
+vt 0.5 1.5
+vt -1.5 1.5
+vt -0.5 -0.5
+vt 1.5 -0.5
+vt -0.5 1.5
+vt 1.5 1.5
+f 1/1/1 2/2/2 4/4/4 3/3/3
+f 5/5/5 7/7/7 8/8/8 6/6/6
+f 9/9/9 11/11/11 12/12/12 10/10/10
+f 13/13/13 14/14/14 16/16/16 15/15/15
+f 17/17/17 19/19/19 20/20/20 18/18/18
+f 21/21/21 22/22/22 24/24/24 23/23/23
diff --git a/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box422.obj b/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box422.obj
new file mode 100644
index 0000000000000000000000000000000000000000..f77a6fc86c684089966ad6b8b3b4de9ad0c8448a
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/constant/triSurface/box422.obj
@@ -0,0 +1,79 @@
+# Generated by Visualization Toolkit
+v -2 -1 -1
+v -2 -1 1
+v -2 1 -1
+v -2 1 1
+v 2 -1 -1
+v 2 -1 1
+v 2 1 -1
+v 2 1 1
+v -2 -1 -1
+v -2 -1 1
+v 2 -1 -1
+v 2 -1 1
+v -2 1 -1
+v -2 1 1
+v 2 1 -1
+v 2 1 1
+v -2 -1 -1
+v 2 -1 -1
+v -2 1 -1
+v 2 1 -1
+v -2 -1 1
+v 2 -1 1
+v -2 1 1
+v 2 1 1
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vt -0.5 -0.5
+vt 1.5 -0.5
+vt -0.5 1.5
+vt 1.5 1.5
+vt 0.5 -0.5
+vt -1.5 -0.5
+vt 0.5 1.5
+vt -1.5 1.5
+vt 1.5 0.5
+vt 1.5 -1.5
+vt -2.5 0.5
+vt -2.5 -1.5
+vt -1.5 0.5
+vt -1.5 -1.5
+vt 2.5 0.5
+vt 2.5 -1.5
+vt 1.5 -0.5
+vt -2.5 -0.5
+vt 1.5 1.5
+vt -2.5 1.5
+vt -1.5 -0.5
+vt 2.5 -0.5
+vt -1.5 1.5
+vt 2.5 1.5
+f 1/1/1 2/2/2 4/4/4 3/3/3
+f 5/5/5 7/7/7 8/8/8 6/6/6
+f 9/9/9 11/11/11 12/12/12 10/10/10
+f 13/13/13 14/14/14 16/16/16 15/15/15
+f 17/17/17 19/19/19 20/20/20 18/18/18
+f 21/21/21 22/22/22 24/24/24 23/23/23
diff --git a/tutorials/mesh/blockMesh/sphere7/system/blockMeshDict b/tutorials/mesh/blockMesh/sphere7/system/blockMeshDict
index 66b82df1e9169c31b61ce88597642932dfc87f36..a58c78cadeb0357965154cfebbc02b44ad023f55 100644
--- a/tutorials/mesh/blockMesh/sphere7/system/blockMeshDict
+++ b/tutorials/mesh/blockMesh/sphere7/system/blockMeshDict
@@ -127,16 +127,56 @@ faces
 
 boundary
 (
-    walls
+    minX
     {
-        type wall;
+        type patch;
         faces
         (
             (1 0)  // block 1: x-min
+        );
+    }
+
+    maxX
+    {
+        type patch;
+        faces
+        (
             (2 1)  // block 2: x-max
+        );
+    }
+
+    minY
+    {
+        type patch;
+        faces
+        (
             (3 2)  // block 3: y-min
+        );
+    }
+
+    maxY
+    {
+        type patch;
+        faces
+        (
             (4 3)  // block 4: y-max
+        );
+    }
+
+    minZ
+    {
+        type patch;
+        faces
+        (
             (5 4)  // block 5: z-min
+        );
+    }
+
+    maxZ
+    {
+        type patch;
+        faces
+        (
             (6 5)  // block 6: z-max
         );
     }
diff --git a/tutorials/mesh/blockMesh/sphere7/system/controlDict b/tutorials/mesh/blockMesh/sphere7/system/controlDict
index 468b34946173297764ef3b800f2a6af7bd0e757f..ab5a65c8533048f74e6aa587126223244389fd17 100644
--- a/tutorials/mesh/blockMesh/sphere7/system/controlDict
+++ b/tutorials/mesh/blockMesh/sphere7/system/controlDict
@@ -14,6 +14,11 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+DebugSwitches
+{
+    pointBoundaryMesh   1;
+}
+
 application     blockMesh;
 
 startFrom       startTime;
@@ -22,9 +27,9 @@ startTime       0;
 
 stopAt          endTime;
 
-endTime         0;
+endTime         20;
 
-deltaT          0;
+deltaT          1;
 
 writeControl    timeStep;
 
diff --git a/tutorials/mesh/blockMesh/sphere7/system/decomposeParDict b/tutorials/mesh/blockMesh/sphere7/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..a3282112ad11ad20a8a9873519a3900c94de32d6
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/system/decomposeParDict
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  2;
+
+//- The decomposition method (mandatory)
+method          scotch;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/system/extrudeMeshDict b/tutorials/mesh/blockMesh/sphere7/system/extrudeMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..78d7de718a525a5843e81c2065a10b49bc5056f5
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/system/extrudeMeshDict
@@ -0,0 +1,55 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      extrudeMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// What to extrude:
+//      patch   : from patch of another case ('sourceCase')
+//      mesh    : as above but with original case included
+//      surface : from externally read surface
+
+constructFrom mesh;
+
+// If construct from patch/mesh:
+sourceCase      "<case>";
+
+// and one of sourcePatches or sourceFaceZones (but not both):
+//sourceFaceZones (someFacesZone);
+sourcePatches   (".*");
+
+// Flip surface normals before usage. Valid only for extrude from surface or
+// patch.
+flipNormals false;
+
+//- Linear extrusion in point-normal direction
+extrudeModel        linearNormal;
+
+nLayers             1;
+
+expansionRatio      1.0;
+
+linearNormalCoeffs
+{
+    thickness       1e-6;
+}
+
+// Do front and back need to be merged? Usually only makes sense for 360
+// degree wedges.
+mergeFaces false;
+
+// Merge small edges. Fraction of bounding box.
+mergeTol 0;
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/tutorials/mesh/blockMesh/sphere7/system/fvSchemes b/tutorials/mesh/blockMesh/sphere7/system/fvSchemes
index a04c1fb001bdd5169eaba84849ee90a2f668ea04..5b5385b05209a42c09e8018e35a78b5ad4d8bd1b 100644
--- a/tutorials/mesh/blockMesh/sphere7/system/fvSchemes
+++ b/tutorials/mesh/blockMesh/sphere7/system/fvSchemes
@@ -18,19 +18,27 @@ ddtSchemes
 {}
 
 gradSchemes
-{}
+{
+    default         Gauss linear;
+}
 
 divSchemes
 {}
 
 laplacianSchemes
-{}
+{
+    default         Gauss linear corrected;
+}
 
 interpolationSchemes
-{}
+{
+    default         linear;
+}
 
 snGradSchemes
-{}
+{
+    default         corrected;
+}
 
 
 // ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/system/fvSolution b/tutorials/mesh/blockMesh/sphere7/system/fvSolution
index 2999073b91ebce15d75792e9bd64bd252e102e77..9283a875542a0e15ffbb62133e774f9c624654d5 100644
--- a/tutorials/mesh/blockMesh/sphere7/system/fvSolution
+++ b/tutorials/mesh/blockMesh/sphere7/system/fvSolution
@@ -14,5 +14,20 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+solvers
+{
+    "cellDisplacement.*"
+    {
+        solver          GAMG;
+        tolerance       1e-08;
+        relTol          0;
+        smoother        GaussSeidel;
+    }
+}
+
+
+PIMPLE
+{}
+
 
 // ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/system/surfaceFeatureExtractDict b/tutorials/mesh/blockMesh/sphere7/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..9039408675c88bdcb9ca01631b684db47c22448a
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/system/surfaceFeatureExtractDict
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+box222.obj
+{
+    // How to obtain raw features (extractFromFile || extractFromSurface)
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       135;
+
+    // Write features to obj format for postprocessing
+    writeObj            yes;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/blockMesh/sphere7/system/topoSetDict b/tutorials/mesh/blockMesh/sphere7/system/topoSetDict
new file mode 100644
index 0000000000000000000000000000000000000000..fa7fef4902005a115811ac8a6f23affe917adfae
--- /dev/null
+++ b/tutorials/mesh/blockMesh/sphere7/system/topoSetDict
@@ -0,0 +1,47 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    {
+        name    c0;
+        type    cellSet;
+        action  new;
+        source  boundaryToCell;
+    }
+    {
+        name    c0;
+        type    cellSet;
+        action  subset;
+        source  boxToCell;
+        sourceInfo
+        {
+            box (-100 -100 -100) (0 100 100);
+        }
+    }
+    {
+        name    c0;
+        type    cellSet;
+        action  add;
+        source  boxToCell;
+        sourceInfo
+        {
+            box (-0.3 -0.3 -0.3) (0 0 0);
+        }
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/0/pointDisplacement b/tutorials/mesh/moveDynamicMesh/badMove/0/pointDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..2dd44c19be6e956ffe12f69e2da0a1edafc392e1
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/0/pointDisplacement
@@ -0,0 +1,62 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  2309                                  |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    arch        "LSB;label=32;scalar=64";
+    class       pointVectorField;
+    location    "0";
+    object      pointDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    minX
+    {
+        type    slip;
+    }
+    maxX
+    {
+        $minX
+    }
+    minY
+    {
+        $minX
+    }
+    maxY
+    {
+        $minX
+    }
+    minZ
+    {
+        $minX
+    }
+    maxZ
+    {
+        $minX
+    }
+    boundaryEdges
+    {
+        type            uniformFixedValue;
+        uniformValue    table
+        (
+            ( 0.0        (0 0 0))
+            ( 1.0        (1.0 -1.0 0))
+            //(10.0        (0 0 0))
+        );
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/Allclean b/tutorials/mesh/moveDynamicMesh/badMove/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..5ef46f9d35db1f707b94b73f1b5c3903b6e47332
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/Allclean
@@ -0,0 +1,17 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+cleanCase
+
+rm -rf constant/extendedFeatureEdgeMesh
+
+#- From pointMesh generation
+rm -rf constant/pointMesh
+rm -f constant/triSurface/blockMesh.obj
+
+#- From surfaceFeatureExtract
+rm -f constant/triSurface/box222.eMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/Allrun b/tutorials/mesh/moveDynamicMesh/badMove/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..e48b35c7fa6a6a3744905afc6286da061dd9b5cd
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/Allrun
@@ -0,0 +1,23 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+#- Generate mesh
+runApplication blockMesh
+
+runApplication surfaceMeshExtract \
+    -featureAngle 45 \
+    -patches '(minX maxY)' \
+    constant/triSurface/blockMesh.obj
+
+#- For postprocessing: extract new pointPatches as vtk files
+setSet <<EOF
+pointSet p0 new patchToPoint boundaryEdges
+EOF
+
+#- Morph mesh to the surface (.obj file) and feature-edges (.eMesh file)
+#- Note: needs point-based motion solver
+runApplication moveDynamicMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/README.txt b/tutorials/mesh/moveDynamicMesh/badMove/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c357006107b3d8eeae1b2feadc5df8e9bee5e0f5
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/README.txt
@@ -0,0 +1 @@
+Testing relaxation of mesh motion
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/constant/dynamicMeshDict b/tutorials/mesh/moveDynamicMesh/badMove/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..d4d20613a9d7d57840c106ed64272b335bd162a3
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/constant/dynamicMeshDict
@@ -0,0 +1,39 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+// For point-bcs
+motionSolverLibs (fvMotionSolvers);
+
+motionSolver    displacementPointSmoothing;
+displacementPointSmoothingCoeffs
+{
+    // Use geometricElementTransform to maintain relative sizes
+    //pointSmoother           geometricElementTransform;
+    //transformationParameter 0.667;
+    //nPointSmootherIter      10;
+
+    pointSmoother           laplacian;
+    nPointSmootherIter      10;
+    relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+    meshQuality
+    {
+        #includeEtc "caseDicts/meshQualityDict"
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/system/blockMeshDict b/tutorials/mesh/moveDynamicMesh/badMove/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..239ef4d94e125c4c392cf17bd155511ce1df11c6
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/system/blockMeshDict
@@ -0,0 +1,95 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    // Inner block
+    (-2 -2 -2)
+    ( 2 -2 -2)
+    ( 2  2 -2)
+    (-2  2 -2)
+    (-2 -2  2)
+    ( 2 -2  2)
+    ( 2  2  2)
+    (-2  2  2)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (5 5 4) grading (1 1 1)  // Inner block
+);
+
+boundary
+(
+    minX
+    {
+        type patch;
+        faces
+        (
+            (0 0)  // block 0: x-min
+        );
+    }
+
+    maxX
+    {
+        type patch;
+        faces
+        (
+            (0 1)  // block 0: x-max
+        );
+    }
+
+    minY
+    {
+        type patch;
+        faces
+        (
+            (0 2)  // block 0: y-min
+        );
+    }
+
+    maxY
+    {
+        type patch;
+        faces
+        (
+            (0 3)  // block 0: y-max
+        );
+    }
+
+    minZ
+    {
+        type patch;
+        faces
+        (
+            (0 4)  // block 0: z-min
+        );
+    }
+
+    maxZ
+    {
+        type patch;
+        faces
+        (
+            (0 5)  // block 0: z-max
+        );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/system/controlDict b/tutorials/mesh/moveDynamicMesh/badMove/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..f7bf44fca761a8dfcc42bf1e0743c56cd3362daa
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/system/controlDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+DebugSwitches
+{
+    pointBoundaryMesh   1;
+}
+
+application     moveDynamicMesh;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         10;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/system/fvSchemes b/tutorials/mesh/moveDynamicMesh/badMove/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..dce45d04ae700d8dc803ec1a4749fef42b01ad9a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/system/fvSchemes
@@ -0,0 +1,44 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/badMove/system/fvSolution b/tutorials/mesh/moveDynamicMesh/badMove/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..eaff818230d35f16dff830ce18b781ad43ace4d3
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/badMove/system/fvSolution
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    "cellDisplacement.*"
+    {
+        solver          GAMG;
+        tolerance       1e-08;
+        relTol          0;
+        smoother        GaussSeidel;
+    }
+}
+
+
+PIMPLE
+{}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/0/pointDisplacement b/tutorials/mesh/moveDynamicMesh/bendJunction/0/pointDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..70f2c0752818ff34d38ffd94d13f013b8c5f4185
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/0/pointDisplacement
@@ -0,0 +1,130 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       pointVectorField;
+    location    "0";
+    object      pointDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+_surfaceDisplacement
+{
+    type                surfaceSlipDisplacement;
+    value               $internalField;
+    projectMode         nearest;
+//    // if fixedNormal : normal
+//    projectDirection    (0 0 1);
+//    //- -1 or component to knock out before doing projection
+//    wedgePlane          -1;
+//    relax               0.5;
+    //- Underrelax motion by limiting displacement velocity
+    velocity        (100 100 100);
+}
+
+
+boundaryField
+{
+    //#includeEtc "caseDicts/setConstraintTypes"
+
+    InletSmall
+    {
+        ${^_surfaceDisplacement}
+        geometry
+        {
+            InletSmall
+            {
+                type    triSurfaceMesh;
+                file    "InletSmall.obj";
+            }
+        }
+    }
+    Outlet
+    {
+        ${^_surfaceDisplacement}
+        geometry
+        {
+            Outlet
+            {
+                type    triSurfaceMesh;
+                file    "Outlet.obj";
+            }
+        }
+    }
+    SmallPipe
+    {
+        ${^_surfaceDisplacement}
+        geometry
+        {
+            SmallPipe
+            {
+                type    triSurfaceMesh;
+                file    "SmallPipe.obj";
+            }
+        }
+    }
+    Inlet
+    {
+        ${^_surfaceDisplacement}
+        geometry
+        {
+            Inlet
+            {
+                type    triSurfaceMesh;
+                file    "Inlet.obj";
+            }
+        }
+    }
+    BigPipe
+    {
+        ${^_surfaceDisplacement}
+        geometry
+        {
+            BigPipe
+            {
+                type    triSurfaceMesh;
+                file    "BigPipe.obj";
+            }
+        }
+    }
+
+    // Per-patch feature-edges
+    SmallPipeEdges
+    {
+        type            edgeSlipDisplacement;
+        file            "SmallPipe.eMesh";
+        //file            "box222.extendedFeatureEdgeMesh";
+        //- Underrelax motion by limiting displacement velocity
+        velocity        (100 100 100);
+    }
+    BigPipeEdges
+    {
+        type            edgeSlipDisplacement;
+        file            "BigPipe.eMesh";
+        //file            "box222.extendedFeatureEdgeMesh";
+        //- Underrelax motion by limiting displacement velocity
+        velocity        (100 100 100);
+    }
+    // Inter-patch feature-edges
+    boundaryEdges
+    {
+        type            edgeSlipDisplacement;
+        file            "geometry.eMesh";
+        //file            "box222.extendedFeatureEdgeMesh";
+        //- Underrelax motion by limiting displacement velocity
+        velocity        (100 100 100);
+    }
+}
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/Allclean b/tutorials/mesh/moveDynamicMesh/bendJunction/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..c0ceba7bef8401e0d57357211a744b094d989d20
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/Allclean
@@ -0,0 +1,16 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+#cleanCase0
+cleanCase
+
+rm -f constant/triSurface/boundary.obj
+rm -f constant/triSurface/geometry.eMesh
+rm -f constant/triSurface/geometry.obj
+rm -f constant/triSurface/blockMesh.obj
+rm -f constant/triSurface/outside*.obj
+rm -rf constant/extendedFeatureEdgeMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/Allrun b/tutorials/mesh/moveDynamicMesh/bendJunction/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..c3efbea1188bc802f55bed4f11194707fff708a6
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/Allrun
@@ -0,0 +1,54 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+
+# Add bit of preprocessing of the surface
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# Add all surfaces
+runApplication -s BigPipeInlet  surfaceAdd \
+    constant/triSurface/BigPipe.obj constant/triSurface/Inlet.obj \
+    constant/triSurface/geometry.obj
+runApplication -s InletSmall    surfaceAdd \
+    constant/triSurface/geometry.obj constant/triSurface/InletSmall.obj \
+    constant/triSurface/geometry.obj
+runApplication -s Outlet        surfaceAdd \
+    constant/triSurface/geometry.obj constant/triSurface/Outlet.obj \
+    constant/triSurface/geometry.obj
+runApplication -s SmallPipe     surfaceAdd \
+    constant/triSurface/geometry.obj constant/triSurface/SmallPipe.obj \
+    constant/triSurface/geometry.obj
+
+# Extract features from surface
+runApplication surfaceFeatureExtract
+
+
+
+# Generate mesh and features
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+runApplication blockMesh
+runApplication -s presmooth checkMesh
+
+# Detect feature edges on mesh and generate new point patches from these.
+# Note we only are interested in inter-patch features for this particular
+# geometry.
+runApplication surfaceMeshExtract \
+    -featureAngle 180 constant/triSurface/blockMesh.obj
+
+# Generate some VTK files for the added point patches
+setSet <<POINTPATCH
+#pointSet SmallPipeEdges new patchToPoint SmallPipeEdges
+#pointSet BigPipeEdges new patchToPoint BigPipeEdges
+pointSet boundaryEdges new patchToPoint boundaryEdges
+POINTPATCH
+
+# Do mesh motion to conform to surface
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+runApplication moveDynamicMesh
+runApplication -s postsmooth checkMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/README.txt b/tutorials/mesh/moveDynamicMesh/bendJunction/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4f60bea01e52021c5721bb7240630653eb1c1ebc
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/README.txt
@@ -0,0 +1,4 @@
+Copy of extBlockMesh/tutorial/bendJunction from
+https://github.com/Etudes-NG/extBlockMesh
+
+Adapted to use simple OpenFOAM mesh motion solver
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/dynamicMeshDict b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..7469174a2819a769e0485134b4b08e465c5e81f4
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/dynamicMeshDict
@@ -0,0 +1,38 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2406                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+motionSolverLibs (fvMotionSolvers);
+
+//motionSolver displacementSBRStress;
+//diffusivity  uniform;
+
+motionSolver    displacementPointSmoothing;
+displacementPointSmoothingCoeffs
+{
+    // Use geometricElementTransform to maintain relative sizes
+    //pointSmoother           geometricElementTransform;
+    //transformationParameter 0.667;
+    //nPointSmootherIter      10;
+
+    pointSmoother           laplacian;
+    nPointSmootherIter      10;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/BigPipe.obj b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/BigPipe.obj
new file mode 100644
index 0000000000000000000000000000000000000000..907ec0eae5fedee38d3bf9090c565278d6fd945a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/BigPipe.obj
@@ -0,0 +1,23708 @@
+# Wavefront OBJ file
+# Regions:
+#     0    CATIASTL
+#
+# points    : 8010
+# triangles : 15690
+#
+v 69.8947 -9.79717e-15 3.8378
+v 69.0543 -9.79717e-15 11.4672
+v 21.2989 -9.79717e-15 66.681
+v 55.375 -9.79717e-15 42.8207
+v -23.9414 -9.79717e-15 65.7785
+v 64.9029 -9.79717e-15 26.2225
+v 68.3218 -9.79717e-15 15.236
+v 67.3837 -9.79717e-15 18.9588
+v 47.6121 -9.79717e-15 51.3136
+v 35.3019 -9.79717e-15 60.4465
+v 59.7304 -9.79717e-15 36.5005
+v 44.7272 -9.79717e-15 53.8468
+v 41.7077 -9.79717e-15 56.218
+v 69.5792 -9.79717e-15 7.66405
+v 24.9227 -9.79717e-15 65.413
+v 6.27475 -9.79717e-15 69.7182
+v 70 -9.79717e-15 0
+v -1.39617 -9.79717e-15 69.9861
+v 28.4716 -9.79717e-15 63.9482
+v -5.23111 -9.79717e-15 69.8043
+v 57.6394 -9.79717e-15 39.7203
+v 2.44297 -9.79717e-15 69.9574
+v -12.8423 -9.79717e-15 68.8119
+v -16.5956 -9.79717e-15 68.0043
+v 61.6417 -9.79717e-15 33.1708
+v 52.944 -9.79717e-15 45.7923
+v -20.299 -9.79717e-15 66.9922
+v 38.5628 -9.79717e-15 58.4201
+v 66.2429 -9.79717e-15 22.6247
+v 63.3676 -9.79717e-15 29.7414
+v -9.05031 -9.79717e-15 69.4125
+v 31.9347 -9.79717e-15 62.291
+v 50.3538 -9.79717e-15 48.6261
+v 10.0877 -9.79717e-15 69.2693
+v 17.6111 -9.79717e-15 67.7484
+v 13.8702 -9.79717e-15 68.6121
+v -19.9205 4.1183 67.2163
+v -19.9205 -4.1183 67.2163
+v 70.0735 4.1183 2.13608
+v 70.0735 -4.1183 2.13608
+v -13.7008 4.1183 68.7543
+v -13.7008 -4.1183 68.7543
+v 42.7933 4.1183 55.5301
+v 26.1541 4.1183 65.0448
+v 66.204 4.1183 23.0629
+v 59.8209 4.1183 36.5558
+v 41.0815 4.1183 56.8082
+v 66.204 -4.1183 23.0629
+v 59.8209 -4.1183 36.5558
+v 42.7933 -4.1183 55.5301
+v 41.0815 -4.1183 56.8082
+v 26.1541 -4.1183 65.0448
+v 61.9364 4.1183 32.8442
+v 24.1601 4.1183 65.8115
+v 61.9364 -4.1183 32.8442
+v 24.1601 -4.1183 65.8115
+v 18.051 4.1183 67.7423
+v 18.051 -4.1183 67.7423
+v 69.2938 4.1183 10.6408
+v 69.2938 -4.1183 10.6408
+v 69.8133 4.1183 6.40031
+v 69.8133 -4.1183 6.40031
+v 65.4705 4.1183 25.0694
+v 28.1238 4.1183 64.2177
+v 65.4705 -4.1183 25.0694
+v 28.1238 -4.1183 64.2177
+v -11.5996 4.1183 69.1398
+v -11.5996 -4.1183 69.1398
+v 49.228 4.1183 49.9146
+v 64.6763 4.1183 27.0526
+v 64.6763 -4.1183 27.0526
+v 49.228 -4.1183 49.9146
+v 15.9785 4.1183 68.2609
+v -23.9777 4.1183 65.8782
+v 15.9785 -4.1183 68.2609
+v -23.9777 -4.1183 65.8782
+v 63.822 4.1183 29.0106
+v 53.5793 4.1183 45.2119
+v 50.726 4.1183 48.3915
+v 46.0962 4.1183 52.8204
+v 70.1061 4.1183 0
+v 37.545 4.1183 59.205
+v 20.1066 4.1183 67.1609
+v 63.822 -4.1183 29.0106
+v 53.5793 -4.1183 45.2119
+v 50.726 -4.1183 48.3915
+v 46.0962 -4.1183 52.8204
+v 20.1066 -4.1183 67.1609
+v 70.1061 -4.1183 0
+v 37.545 -4.1183 59.205
+v 13.8912 4.1183 68.716
+v 13.8912 -4.1183 68.716
+v 68.517 4.1183 14.8417
+v 68.517 -4.1183 14.8417
+v 58.6793 4.1183 38.3615
+v 58.6793 -4.1183 38.3615
+v 69.5859 4.1183 8.5245
+v 69.5859 -4.1183 8.5245
+v -5.23903 4.1183 69.91
+v -5.23903 -4.1183 69.91
+v 60.9069 4.1183 34.7161
+v 39.3315 4.1183 58.0335
+v 35.7237 4.1183 60.3215
+v -17.8632 4.1183 67.7921
+v 60.9069 -4.1183 34.7161
+v 39.3315 -4.1183 58.0335
+v 35.7237 -4.1183 60.3215
+v -17.8632 -4.1183 67.7921
+v -9.48755 4.1183 69.4611
+v -9.48755 -4.1183 69.4611
+v -7.36671 4.1183 69.718
+v -7.36671 -4.1183 69.718
+v 56.2337 4.1183 41.8644
+v 22.1437 4.1183 66.5171
+v 54.932 4.1183 43.5584
+v 56.2337 -4.1183 41.8644
+v 54.932 -4.1183 43.5584
+v 22.1437 -4.1183 66.5171
+v -3.10649 4.1183 70.0372
+v -3.10649 -4.1183 70.0372
+v 1.16526 4.1183 70.0964
+v 1.16526 -4.1183 70.0964
+v 68.033 4.1183 16.9225
+v 68.033 -4.1183 16.9225
+v 5.43269 4.1183 69.8953
+v 5.43269 -4.1183 69.8953
+v 33.8691 4.1183 61.382
+v 30.0674 4.1183 63.331
+v 52.1769 4.1183 46.8235
+v 47.6842 4.1183 51.3914
+v 52.1769 -4.1183 46.8235
+v 47.6842 -4.1183 51.3914
+v 33.8691 -4.1183 61.382
+v 30.0674 -4.1183 63.331
+v 11.7911 4.1183 69.1074
+v 11.7911 -4.1183 69.1074
+v 69.9759 4.1183 4.27018
+v 69.9759 -4.1183 4.27018
+v 7.55982 4.1183 69.6973
+v 7.55982 -4.1183 69.6973
+v 67.4858 4.1183 18.9876
+v 67.4858 -4.1183 18.9876
+v -0.971066 4.1183 70.0993
+v -0.971066 -4.1183 70.0993
+v 9.67994 4.1183 69.4346
+v 9.67994 -4.1183 69.4346
+v 66.8759 4.1183 21.035
+v 68.9374 4.1183 12.7472
+v 68.9374 -4.1183 12.7472
+v 66.8759 -4.1183 21.035
+v 44.4654 4.1183 54.2004
+v 44.4654 -4.1183 54.2004
+v 3.30051 4.1183 70.0283
+v 3.30051 -4.1183 70.0283
+v 31.9831 4.1183 62.3854
+v 31.9831 -4.1183 62.3854
+v 57.4832 4.1183 40.1316
+v 57.4832 -4.1183 40.1316
+v 62.9084 4.1183 30.9418
+v 62.9084 -4.1183 30.9418
+v -15.7894 4.1183 68.3049
+v -15.7894 -4.1183 68.3049
+v -21.9593 4.1183 66.5782
+v -21.9593 -4.1183 66.5782
+v -15.861 8.22568 68.6146
+v -15.861 -8.22568 68.6146
+v 3.31548 8.22568 70.3459
+v 3.31548 -8.22568 70.3459
+v 58.9454 8.22568 38.5355
+v 58.9454 -8.22568 38.5355
+v -11.6522 8.22568 69.4533
+v -11.6522 -8.22568 69.4533
+v 61.1831 8.22568 34.8735
+v 41.2678 8.22568 57.0658
+v 61.1831 -8.22568 34.8735
+v 41.2678 -8.22568 57.0658
+v 64.9696 8.22568 27.1752
+v 52.4135 8.22568 47.0358
+v 64.9696 -8.22568 27.1752
+v 52.4135 -8.22568 47.0358
+v -7.40012 8.22568 70.0341
+v -7.40012 -8.22568 70.0341
+v -20.0109 8.22568 67.5212
+v -20.0109 -8.22568 67.5212
+v 68.8278 8.22568 14.909
+v 20.1978 8.22568 67.4655
+v 68.8278 -8.22568 14.909
+v 20.1978 -8.22568 67.4655
+v 69.2501 8.22568 12.805
+v 69.2501 -8.22568 12.805
+v 56.4887 8.22568 42.0543
+v 56.4887 -8.22568 42.0543
+v 24.2697 8.22568 66.1099
+v 24.2697 -8.22568 66.1099
+v 70.3913 8.22568 2.14577
+v 70.3913 -8.22568 2.14577
+v 35.8857 8.22568 60.595
+v 28.2514 8.22568 64.5089
+v 35.8857 -8.22568 60.595
+v 28.2514 -8.22568 64.5089
+v -0.97547 8.22568 70.4173
+v -0.97547 -8.22568 70.4173
+v 16.051 8.22568 68.5704
+v 16.051 -8.22568 68.5704
+v 70.1299 8.22568 6.42934
+v 70.1299 -8.22568 6.42934
+v 49.4512 8.22568 50.141
+v 47.9005 8.22568 51.6245
+v 49.4512 -8.22568 50.141
+v 47.9005 -8.22568 51.6245
+v 7.59411 8.22568 70.0134
+v 7.59411 -8.22568 70.0134
+v 63.1937 8.22568 31.0821
+v 44.6671 8.22568 54.4462
+v 37.7153 8.22568 59.4735
+v 63.1937 -8.22568 31.0821
+v 44.6671 -8.22568 54.4462
+v 37.7153 -8.22568 59.4735
+v -13.763 8.22568 69.0661
+v -13.763 -8.22568 69.0661
+v 18.1328 8.22568 68.0496
+v 18.1328 -8.22568 68.0496
+v 5.45733 8.22568 70.2122
+v 5.45733 -8.22568 70.2122
+v 67.1792 8.22568 21.1304
+v -5.26279 8.22568 70.2271
+v 67.1792 -8.22568 21.1304
+v -5.26279 -8.22568 70.2271
+v 66.5042 8.22568 23.1675
+v 62.2173 8.22568 32.9931
+v 50.956 8.22568 48.611
+v 46.3053 8.22568 53.06
+v 66.5042 -8.22568 23.1675
+v 62.2173 -8.22568 32.9931
+v 50.956 -8.22568 48.611
+v 46.3053 -8.22568 53.06
+v -9.53057 8.22568 69.7761
+v -9.53057 -8.22568 69.7761
+v 70.2933 8.22568 4.28955
+v 70.2933 -8.22568 4.28955
+v 34.0227 8.22568 61.6603
+v 32.1282 8.22568 62.6683
+v 64.1114 8.22568 29.1422
+v 32.1282 -8.22568 62.6683
+v 34.0227 -8.22568 61.6603
+v 64.1114 -8.22568 29.1422
+v 13.9543 8.22568 69.0277
+v 13.9543 -8.22568 69.0277
+v -22.0589 8.22568 66.8801
+v -22.0589 -8.22568 66.8801
+v 70.424 8.22568 0
+v 55.1811 8.22568 43.756
+v 26.2727 8.22568 65.3398
+v 70.424 -8.22568 0
+v 55.1811 -8.22568 43.756
+v 26.2727 -8.22568 65.3398
+v 1.17055 8.22568 70.4143
+v 1.17055 -8.22568 70.4143
+v 69.9015 8.22568 8.56316
+v 57.7439 8.22568 40.3136
+v 69.9015 -8.22568 8.56316
+v 57.7439 -8.22568 40.3136
+v 11.8445 8.22568 69.4208
+v 11.8445 -8.22568 69.4208
+v 67.7919 8.22568 19.0737
+v 67.7919 -8.22568 19.0737
+v -3.12058 8.22568 70.3548
+v -3.12058 -8.22568 70.3548
+v 53.8223 8.22568 45.417
+v 42.9874 8.22568 55.7819
+v 53.8223 -8.22568 45.417
+v 42.9874 -8.22568 55.7819
+v 39.5099 8.22568 58.2967
+v 30.2038 8.22568 63.6182
+v 39.5099 -8.22568 58.2967
+v 30.2038 -8.22568 63.6182
+v 69.6081 8.22568 10.689
+v 69.6081 -8.22568 10.689
+v 65.7674 8.22568 25.1831
+v 65.7674 -8.22568 25.1831
+v 60.0922 8.22568 36.7216
+v 60.0922 -8.22568 36.7216
+v -17.9442 8.22568 68.0995
+v -17.9442 -8.22568 68.0995
+v 22.2441 8.22568 66.8187
+v 22.2441 -8.22568 66.8187
+v 9.72384 8.22568 69.7495
+v 9.72384 -8.22568 69.7495
+v 68.3416 8.22568 16.9993
+v 68.3416 -8.22568 16.9993
+v -24.0864 8.22568 66.1769
+v -24.0864 -8.22568 66.1769
+v 70.953 12.3112 0
+v 70.953 -12.3112 0
+v 61.6427 12.3112 35.1355
+v 61.6427 -12.3112 35.1355
+v 70.1309 12.3112 10.7693
+v 70.1309 -12.3112 10.7693
+v -15.9801 12.3112 69.13
+v -15.9801 -12.3112 69.13
+v 3.34038 12.3112 70.8743
+v 3.34038 -12.3112 70.8743
+v 69.7702 12.3112 12.9012
+v 69.7702 -12.3112 12.9012
+v 28.4636 12.3112 64.9934
+v 28.4636 -12.3112 64.9934
+v -0.982796 12.3112 70.9462
+v -0.982796 -12.3112 70.9462
+v -7.4557 12.3112 70.5602
+v -7.4557 -12.3112 70.5602
+v 56.913 12.3112 42.3702
+v 56.913 -12.3112 42.3702
+v 68.8549 12.3112 17.1269
+v 68.8549 -12.3112 17.1269
+v 67.6838 12.3112 21.2891
+v 67.6838 -12.3112 21.2891
+v 70.6567 12.3112 6.47763
+v 70.6567 -12.3112 6.47763
+v 52.8072 12.3112 47.3891
+v 49.8226 12.3112 50.5176
+v 48.2603 12.3112 52.0122
+v 52.8072 -12.3112 47.3891
+v 49.8226 -12.3112 50.5176
+v 48.2603 -12.3112 52.0122
+v 22.4112 12.3112 67.3206
+v 20.3495 12.3112 67.9722
+v 22.4112 -12.3112 67.3206
+v 20.3495 -12.3112 67.9722
+v -22.2246 12.3112 67.3824
+v -22.2246 -12.3112 67.3824
+v -5.30232 12.3112 70.7546
+v -5.30232 -12.3112 70.7546
+v 68.301 12.3112 19.2169
+v -18.079 12.3112 68.611
+v 68.301 -12.3112 19.2169
+v -18.079 -12.3112 68.611
+v -24.2673 12.3112 66.674
+v -24.2673 -12.3112 66.674
+v 66.2614 12.3112 25.3722
+v 65.4576 12.3112 27.3794
+v 45.0026 12.3112 54.8552
+v 16.1716 12.3112 69.0855
+v 66.2614 -12.3112 25.3722
+v 65.4576 -12.3112 27.3794
+v 45.0026 -12.3112 54.8552
+v 16.1716 -12.3112 69.0855
+v 5.49832 12.3112 70.7396
+v 5.49832 -12.3112 70.7396
+v -3.14402 12.3112 70.8833
+v -3.14402 -12.3112 70.8833
+v 55.5956 12.3112 44.0846
+v 18.269 12.3112 68.5607
+v 55.5956 -12.3112 44.0846
+v 18.269 -12.3112 68.5607
+v 63.6684 12.3112 31.3156
+v -20.1612 12.3112 68.0283
+v 63.6684 -12.3112 31.3156
+v -20.1612 -12.3112 68.0283
+v -13.8663 12.3112 69.5848
+v -13.8663 -12.3112 69.5848
+v 1.17934 12.3112 70.9432
+v 1.17934 -12.3112 70.9432
+v 32.3695 12.3112 63.139
+v 58.1776 12.3112 40.6164
+v 54.2266 12.3112 45.7581
+v 30.4307 12.3112 64.096
+v -11.7397 12.3112 69.975
+v 32.3695 -12.3112 63.139
+v 58.1776 -12.3112 40.6164
+v 54.2266 -12.3112 45.7581
+v 30.4307 -12.3112 64.096
+v -11.7397 -12.3112 69.975
+v -9.60216 12.3112 70.3002
+v -9.60216 -12.3112 70.3002
+v 9.79688 12.3112 70.2734
+v 9.79688 -12.3112 70.2734
+v 70.4265 12.3112 8.62748
+v 70.4265 -12.3112 8.62748
+v 34.2783 12.3112 62.1235
+v 60.5435 12.3112 36.9974
+v 37.9986 12.3112 59.9202
+v 24.452 12.3112 66.6065
+v 34.2783 -12.3112 62.1235
+v 60.5435 -12.3112 36.9974
+v 37.9986 -12.3112 59.9202
+v 24.452 -12.3112 66.6065
+v 70.8212 12.3112 4.32176
+v 70.8212 -12.3112 4.32176
+v 70.92 12.3112 2.16189
+v 70.92 -12.3112 2.16189
+v 67.0037 12.3112 23.3415
+v 64.593 12.3112 29.3611
+v 14.0591 12.3112 69.5462
+v 67.0037 -12.3112 23.3415
+v 64.593 -12.3112 29.3611
+v 14.0591 -12.3112 69.5462
+v 11.9335 12.3112 69.9422
+v 11.9335 -12.3112 69.9422
+v 36.1552 12.3112 61.0502
+v 46.6531 12.3112 53.4585
+v 43.3103 12.3112 56.2009
+v 39.8067 12.3112 58.7346
+v 46.6531 -12.3112 53.4585
+v 43.3103 -12.3112 56.2009
+v 39.8067 -12.3112 58.7346
+v 36.1552 -12.3112 61.0502
+v 7.65115 12.3112 70.5392
+v 7.65115 -12.3112 70.5392
+v 41.5778 12.3112 57.4944
+v 41.5778 -12.3112 57.4944
+v 69.3447 12.3112 15.021
+v 69.3447 -12.3112 15.021
+v 62.6846 12.3112 33.241
+v 59.3881 12.3112 38.8249
+v 51.3387 12.3112 48.9761
+v 62.6846 -12.3112 33.241
+v 59.3881 -12.3112 38.8249
+v 51.3387 -12.3112 48.9761
+v 26.4701 12.3112 65.8305
+v 26.4701 -12.3112 65.8305
+v -3.17675 16.3642 71.6211
+v -3.17675 -16.3642 71.6211
+v -11.8619 16.3642 70.7034
+v -11.8619 -16.3642 70.7034
+v 70.0666 16.3642 15.1774
+v 70.0666 -16.3642 15.1774
+v 71.1596 16.3642 8.71729
+v 71.1596 -16.3642 8.71729
+v -16.1464 16.3642 69.8496
+v -16.1464 -16.3642 69.8496
+v 69.012 16.3642 19.417
+v 69.012 -16.3642 19.417
+v 53.3569 16.3642 47.8824
+v 48.7626 16.3642 52.5536
+v 53.3569 -16.3642 47.8824
+v 48.7626 -16.3642 52.5536
+v -22.4559 16.3642 68.0838
+v -22.4559 -16.3642 68.0838
+v 71.6915 16.3642 0
+v 32.7065 16.3642 63.7963
+v 47.1387 16.3642 54.015
+v 43.7611 16.3642 56.7859
+v 24.7065 16.3642 67.2998
+v 71.6915 -16.3642 0
+v 32.7065 -16.3642 63.7963
+v 47.1387 -16.3642 54.015
+v 43.7611 -16.3642 56.7859
+v 24.7065 -16.3642 67.2998
+v 9.89886 16.3642 71.0049
+v 9.89886 -16.3642 71.0049
+v 71.6583 16.3642 2.18439
+v 71.6583 -16.3642 2.18439
+v 34.6351 16.3642 62.7701
+v 57.5055 16.3642 42.8112
+v 22.6444 16.3642 68.0214
+v 34.6351 -16.3642 62.7701
+v 57.5055 -16.3642 42.8112
+v 22.6444 -16.3642 68.0214
+v 12.0577 16.3642 70.6703
+v 12.0577 -16.3642 70.6703
+v 67.7012 16.3642 23.5845
+v 30.7474 16.3642 64.7632
+v 67.7012 -16.3642 23.5845
+v 30.7474 -16.3642 64.7632
+v 36.5316 16.3642 61.6857
+v 56.1743 16.3642 44.5435
+v 56.1743 -16.3642 44.5435
+v 36.5316 -16.3642 61.6857
+v -7.53331 16.3642 71.2946
+v -7.53331 -16.3642 71.2946
+v -5.35752 16.3642 71.4911
+v -5.35752 -16.3642 71.4911
+v 66.1389 16.3642 27.6644
+v 26.7456 16.3642 66.5158
+v 20.5614 16.3642 68.6797
+v 14.2054 16.3642 70.2701
+v 66.1389 -16.3642 27.6644
+v 26.7456 -16.3642 66.5158
+v 20.5614 -16.3642 68.6797
+v 14.2054 -16.3642 70.2701
+v 60.0063 16.3642 39.2291
+v 54.791 16.3642 46.2344
+v 60.0063 -16.3642 39.2291
+v 54.791 -16.3642 46.2344
+v 1.19161 16.3642 71.6816
+v 1.19161 -16.3642 71.6816
+v 70.8609 16.3642 10.8814
+v 70.8609 -16.3642 10.8814
+v 3.37515 16.3642 71.6121
+v 3.37515 -16.3642 71.6121
+v 64.3311 16.3642 31.6415
+v 64.3311 -16.3642 31.6415
+v -9.70211 16.3642 71.032
+v -9.70211 -16.3642 71.032
+v 61.1737 16.3642 37.3825
+v 40.221 16.3642 59.346
+v 61.1737 -16.3642 37.3825
+v 40.221 -16.3642 59.346
+v 71.5584 16.3642 4.36675
+v 71.5584 -16.3642 4.36675
+v 65.2653 16.3642 29.6667
+v 65.2653 -16.3642 29.6667
+v 62.2844 16.3642 35.5012
+v 45.471 16.3642 55.4262
+v 28.7599 16.3642 65.67
+v 62.2844 -16.3642 35.5012
+v 45.471 -16.3642 55.4262
+v 28.7599 -16.3642 65.67
+v -0.993027 16.3642 71.6847
+v -0.993027 -16.3642 71.6847
+v 68.3884 16.3642 21.5107
+v 68.3884 -16.3642 21.5107
+v 16.3399 16.3642 69.8046
+v 16.3399 -16.3642 69.8046
+v 58.7832 16.3642 41.0392
+v 38.3941 16.3642 60.5439
+v 18.4592 16.3642 69.2744
+v 58.7832 -16.3642 41.0392
+v 38.3941 -16.3642 60.5439
+v 18.4592 -16.3642 69.2744
+v 5.55555 16.3642 71.476
+v 5.55555 -16.3642 71.476
+v 71.3922 16.3642 6.54506
+v -20.371 16.3642 68.7365
+v 71.3922 -16.3642 6.54506
+v -20.371 -16.3642 68.7365
+v -24.52 16.3642 67.368
+v -24.52 -16.3642 67.368
+v 51.8731 16.3642 49.4859
+v 50.3413 16.3642 51.0435
+v 42.0106 16.3642 58.0929
+v 51.8731 -16.3642 49.4859
+v 50.3413 -16.3642 51.0435
+v 42.0106 -16.3642 58.0929
+v 69.5716 16.3642 17.3052
+v 69.5716 -16.3642 17.3052
+v 70.4965 16.3642 13.0354
+v 70.4965 -16.3642 13.0354
+v 66.9512 16.3642 25.6363
+v 66.9512 -16.3642 25.6363
+v 63.3371 16.3642 33.587
+v 63.3371 -16.3642 33.587
+v 7.73079 16.3642 71.2735
+v 7.73079 -16.3642 71.2735
+v -18.2672 16.3642 69.3252
+v -18.2672 -16.3642 69.3252
+v -14.0107 16.3642 70.3092
+v -14.0107 -16.3642 70.3092
+v 67.0119 20.3737 28.0295
+v 67.0119 -20.3737 28.0295
+v 27.0986 20.3737 67.3937
+v 27.0986 -20.3737 67.3937
+v 56.9157 20.3737 45.1314
+v 56.9157 -20.3737 45.1314
+v 72.5029 20.3737 4.42439
+v 72.5029 -20.3737 4.42439
+v -22.7523 20.3737 68.9825
+v 31.1533 20.3737 65.618
+v -22.7523 -20.3737 68.9825
+v 31.1533 -20.3737 65.618
+v -20.6399 20.3737 69.6437
+v -20.6399 -20.3737 69.6437
+v 47.7609 20.3737 54.7279
+v 38.9009 20.3737 61.343
+v 10.0295 20.3737 71.942
+v 47.7609 -20.3737 54.7279
+v 38.9009 -20.3737 61.343
+v 10.0295 -20.3737 71.942
+v -5.42823 20.3737 72.4347
+v -5.42823 -20.3737 72.4347
+v -24.8436 20.3737 68.2572
+v 37.0137 20.3737 62.4998
+v 33.1381 20.3737 64.6383
+v 58.2645 20.3737 43.3763
+v 33.1381 -20.3737 64.6383
+v -24.8436 -20.3737 68.2572
+v 58.2645 -20.3737 43.3763
+v 37.0137 -20.3737 62.4998
+v -14.1956 20.3737 71.2372
+v -14.1956 -20.3737 71.2372
+v 72.6378 20.3737 0
+v 64.1731 20.3737 34.0303
+v 49.4062 20.3737 53.2473
+v 72.6378 -20.3737 0
+v 64.1731 -20.3737 34.0303
+v 49.4062 -20.3737 53.2473
+v 72.0988 20.3737 8.83235
+v 68.5948 20.3737 23.8957
+v 72.0988 -20.3737 8.83235
+v 68.5948 -20.3737 23.8957
+v 71.4269 20.3737 13.2075
+v 71.4269 -20.3737 13.2075
+v -1.00613 20.3737 72.6308
+v -1.00613 -20.3737 72.6308
+v 70.4899 20.3737 17.5336
+v 69.291 20.3737 21.7946
+v 59.559 20.3737 41.5809
+v 42.5651 20.3737 58.8597
+v 70.4899 -20.3737 17.5336
+v 69.291 -20.3737 21.7946
+v 59.559 -20.3737 41.5809
+v 42.5651 -20.3737 58.8597
+v 69.9229 20.3737 19.6733
+v 69.9229 -20.3737 19.6733
+v 1.20734 20.3737 72.6277
+v 1.20734 -20.3737 72.6277
+v 29.1395 20.3737 66.5368
+v 29.1395 -20.3737 66.5368
+v 71.7962 20.3737 11.025
+v 71.7962 -20.3737 11.025
+v 60.7983 20.3737 39.7468
+v 60.7983 -20.3737 39.7468
+v -18.5083 20.3737 70.2402
+v -18.5083 -20.3737 70.2402
+v -9.83017 20.3737 71.9695
+v -9.83017 -20.3737 71.9695
+v 66.1267 20.3737 30.0583
+v 22.9433 20.3737 68.9192
+v 18.7028 20.3737 70.1887
+v 66.1267 -20.3737 30.0583
+v 22.9433 -20.3737 68.9192
+v 18.7028 -20.3737 70.1887
+v 72.6041 20.3737 2.21322
+v 72.6041 -20.3737 2.21322
+v -7.63274 20.3737 72.2356
+v -7.63274 -20.3737 72.2356
+v 67.8348 20.3737 25.9747
+v 67.8348 -20.3737 25.9747
+v 72.3344 20.3737 6.63144
+v 72.3344 -20.3737 6.63144
+v 63.1064 20.3737 35.9698
+v 55.5142 20.3737 46.8446
+v 46.0712 20.3737 56.1577
+v 40.7519 20.3737 60.1293
+v 63.1064 -20.3737 35.9698
+v 55.5142 -20.3737 46.8446
+v 46.0712 -20.3737 56.1577
+v 40.7519 -20.3737 60.1293
+v -3.21867 20.3737 72.5664
+v -3.21867 -20.3737 72.5664
+v 70.9914 20.3737 15.3777
+v 70.9914 -20.3737 15.3777
+v -12.0185 20.3737 71.6366
+v -12.0185 -20.3737 71.6366
+v -16.3596 20.3737 70.7716
+v -16.3596 -20.3737 70.7716
+v 5.62888 20.3737 72.4194
+v 5.62888 -20.3737 72.4194
+v 12.2169 20.3737 71.603
+v 12.2169 -20.3737 71.603
+v 54.0611 20.3737 48.5144
+v 52.5578 20.3737 50.139
+v 25.0326 20.3737 68.1881
+v 54.0611 -20.3737 48.5144
+v 52.5578 -20.3737 50.139
+v 25.0326 -20.3737 68.1881
+v 16.5555 20.3737 70.726
+v 16.5555 -20.3737 70.726
+v 35.0922 20.3737 63.5986
+v 65.1802 20.3737 32.0592
+v 61.9812 20.3737 37.8759
+v 44.3387 20.3737 57.5354
+v 35.0922 -20.3737 63.5986
+v 65.1802 -20.3737 32.0592
+v 61.9812 -20.3737 37.8759
+v 44.3387 -20.3737 57.5354
+v 3.4197 20.3737 72.5572
+v 3.4197 -20.3737 72.5572
+v 51.0057 20.3737 51.7172
+v 51.0057 -20.3737 51.7172
+v 14.3929 20.3737 71.1976
+v 14.3929 -20.3737 71.1976
+v 20.8328 20.3737 69.5862
+v 20.8328 -20.3737 69.5862
+v 7.83283 20.3737 72.2142
+v 7.83283 -20.3737 72.2142
+v 7.95699 24.3292 73.3589
+v 7.95699 -24.3292 73.3589
+v 54.918 24.3292 49.2834
+v 54.918 -24.3292 49.2834
+v 31.6471 24.3292 66.6581
+v 31.6471 -24.3292 66.6581
+v -18.8017 24.3292 71.3536
+v -18.8017 -24.3292 71.3536
+v -9.98598 24.3292 73.1103
+v -9.98598 -24.3292 73.1103
+v 10.1885 24.3292 73.0824
+v 10.1885 -24.3292 73.0824
+v 21.163 24.3292 70.6892
+v 21.163 -24.3292 70.6892
+v 57.8179 24.3292 45.8468
+v 18.9993 24.3292 71.3012
+v 57.8179 -24.3292 45.8468
+v 18.9993 -24.3292 71.3012
+v 66.2134 24.3292 32.5673
+v 59.188 24.3292 44.0638
+v 43.2398 24.3292 59.7927
+v 66.2134 -24.3292 32.5673
+v 59.188 -24.3292 44.0638
+v 43.2398 -24.3292 59.7927
+v 73.481 24.3292 6.73656
+v 73.481 -24.3292 6.73656
+v 72.5591 24.3292 13.4169
+v -14.4206 24.3292 72.3663
+v 72.5591 -24.3292 13.4169
+v -14.4206 -24.3292 72.3663
+v 72.1167 24.3292 15.6215
+v 14.621 24.3292 72.3261
+v 72.1167 -24.3292 15.6215
+v 14.621 -24.3292 72.3261
+v 72.9343 24.3292 11.1998
+v 72.9343 -24.3292 11.1998
+v -3.2697 24.3292 73.7167
+v -3.2697 -24.3292 73.7167
+v 73.7892 24.3292 0
+v 71.6072 24.3292 17.8115
+v 53.3909 24.3292 50.9338
+v 41.3979 24.3292 61.0824
+v 73.7892 -24.3292 0
+v 71.6072 -24.3292 17.8115
+v 53.3909 -24.3292 50.9338
+v 41.3979 -24.3292 61.0824
+v 73.6522 24.3292 4.49452
+v 73.6522 -24.3292 4.49452
+v 71.0312 24.3292 19.9851
+v 71.0312 -24.3292 19.9851
+v 35.6485 24.3292 64.6067
+v 35.6485 -24.3292 64.6067
+v -7.75373 24.3292 73.3807
+v -7.75373 -24.3292 73.3807
+v 16.818 24.3292 71.847
+v 16.818 -24.3292 71.847
+v -1.02208 24.3292 73.7821
+v -1.02208 -24.3292 73.7821
+v 51.8142 24.3292 52.5369
+v 50.1894 24.3292 54.0913
+v 46.8015 24.3292 57.0479
+v 29.6014 24.3292 67.5914
+v 51.8142 -24.3292 52.5369
+v 50.1894 -24.3292 54.0913
+v 46.8015 -24.3292 57.0479
+v 29.6014 -24.3292 67.5914
+v -16.6189 24.3292 71.8934
+v -16.6189 -24.3292 71.8934
+v 1.22648 24.3292 73.779
+v 1.22648 -24.3292 73.779
+v 67.1749 24.3292 30.5347
+v 61.7621 24.3292 40.3769
+v 67.1749 -24.3292 30.5347
+v 61.7621 -24.3292 40.3769
+v 5.7181 24.3292 73.5673
+v 5.7181 -24.3292 73.5673
+v -23.1129 24.3292 70.0759
+v 69.6821 24.3292 24.2745
+v 68.9101 24.3292 26.3864
+v -23.1129 -24.3292 70.0759
+v 69.6821 -24.3292 24.2745
+v 68.9101 -24.3292 26.3864
+v -5.51427 24.3292 73.5828
+v -5.51427 -24.3292 73.5828
+v -25.2374 24.3292 69.3391
+v 37.6004 24.3292 63.4905
+v 68.0741 24.3292 28.4738
+v -25.2374 -24.3292 69.3391
+v 68.0741 -24.3292 28.4738
+v 37.6004 -24.3292 63.4905
+v 25.4294 24.3292 69.269
+v 25.4294 -24.3292 69.269
+v 33.6634 24.3292 65.6629
+v 62.9636 24.3292 38.4763
+v 60.5031 24.3292 42.24
+v 39.5175 24.3292 62.3154
+v 33.6634 -24.3292 65.6629
+v 62.9636 -24.3292 38.4763
+v 60.5031 -24.3292 42.24
+v 39.5175 -24.3292 62.3154
+v 3.4739 24.3292 73.7074
+v 3.4739 -24.3292 73.7074
+v 73.7549 24.3292 2.2483
+v 73.7549 -24.3292 2.2483
+v 56.3942 24.3292 47.5872
+v 48.518 24.3292 55.5954
+v 27.5282 24.3292 68.462
+v 56.3942 -24.3292 47.5872
+v 48.518 -24.3292 55.5954
+v 27.5282 -24.3292 68.462
+v 12.4105 24.3292 72.738
+v 12.4105 -24.3292 72.738
+v -12.209 24.3292 72.7721
+v -12.209 -24.3292 72.7721
+v 45.0415 24.3292 58.4474
+v 23.307 24.3292 70.0116
+v 45.0415 -24.3292 58.4474
+v 23.307 -24.3292 70.0116
+v -20.9671 24.3292 70.7476
+v -20.9671 -24.3292 70.7476
+v 65.1903 24.3292 34.5697
+v 64.1067 24.3292 36.54
+v 65.1903 -24.3292 34.5697
+v 64.1067 -24.3292 36.54
+v 73.2417 24.3292 8.97235
+v 73.2417 -24.3292 8.97235
+v 70.3893 24.3292 22.1401
+v 70.3893 -24.3292 22.1401
+v 5.82299 28.2202 74.9167
+v 5.82299 -28.2202 74.9167
+v 72.9206 28.2202 18.1383
+v 72.9206 -28.2202 18.1383
+v -1.04083 28.2202 75.1354
+v -1.04083 -28.2202 75.1354
+v 70.1741 28.2202 26.8704
+v 70.1741 -28.2202 26.8704
+v 75.1426 28.2202 0
+v 75.1426 -28.2202 0
+v -7.89595 28.2202 74.7266
+v -7.89595 -28.2202 74.7266
+v 38.2901 28.2202 64.6551
+v 38.2901 -28.2202 64.6551
+v 1.24898 28.2202 75.1323
+v 1.24898 -28.2202 75.1323
+v 74.2721 28.2202 11.4052
+v 74.2721 -28.2202 11.4052
+v 74.5851 28.2202 9.13692
+v 74.5851 -28.2202 9.13692
+v 72.3341 28.2202 20.3517
+v 55.9254 28.2202 50.1874
+v 52.7646 28.2202 53.5006
+v 42.1572 28.2202 62.2028
+v -10.1692 28.2202 74.4514
+v 72.3341 -28.2202 20.3517
+v 55.9254 -28.2202 50.1874
+v 52.7646 -28.2202 53.5006
+v 42.1572 -28.2202 62.2028
+v -10.1692 -28.2202 74.4514
+v -12.4329 28.2202 74.107
+v -12.4329 -28.2202 74.107
+v 67.4279 28.2202 33.1647
+v 67.4279 -28.2202 33.1647
+v 12.6382 28.2202 74.0722
+v 12.6382 -28.2202 74.0722
+v 69.3228 28.2202 28.9961
+v 62.8949 28.2202 41.1175
+v 61.6129 28.2202 43.0148
+v 58.8785 28.2202 46.6877
+v 57.4286 28.2202 48.46
+v 49.4079 28.2202 56.6152
+v 32.2276 28.2202 67.8808
+v 69.3228 -28.2202 28.9961
+v 62.8949 -28.2202 41.1175
+v 61.6129 -28.2202 43.0148
+v 58.8785 -28.2202 46.6877
+v 57.4286 -28.2202 48.46
+v 49.4079 -28.2202 56.6152
+v 32.2276 -28.2202 67.8808
+v -23.5369 28.2202 71.3613
+v 74.8288 28.2202 6.86013
+v 30.1443 28.2202 68.8312
+v -23.5369 -28.2202 71.3613
+v 74.8288 -28.2202 6.86013
+v 30.1443 -28.2202 68.8312
+v 10.3754 28.2202 74.4229
+v 10.3754 -28.2202 74.4229
+v 8.10294 28.2202 74.7045
+v 8.10294 -28.2202 74.7045
+v -19.1466 28.2202 72.6624
+v -19.1466 -28.2202 72.6624
+v 36.3024 28.2202 65.7918
+v 54.3702 28.2202 51.8681
+v 40.2424 28.2202 63.4584
+v -16.9237 28.2202 73.2121
+v 36.3024 -28.2202 65.7918
+v 54.3702 -28.2202 51.8681
+v 40.2424 -28.2202 63.4584
+v -16.9237 -28.2202 73.2121
+v -25.7003 28.2202 70.611
+v 19.3478 28.2202 72.6091
+v -25.7003 -28.2202 70.611
+v 19.3478 -28.2202 72.6091
+v 71.6805 28.2202 22.5462
+v 44.0329 28.2202 60.8894
+v 71.6805 -28.2202 22.5462
+v 44.0329 -28.2202 60.8894
+v 3.53762 28.2202 75.0593
+v 3.53762 -28.2202 75.0593
+v 17.1265 28.2202 73.1649
+v 17.1265 -28.2202 73.1649
+v -5.61542 28.2202 74.9325
+v -5.61542 -28.2202 74.9325
+v 73.4395 28.2202 15.908
+v 14.8892 28.2202 73.6528
+v 73.4395 -28.2202 15.908
+v 14.8892 -28.2202 73.6528
+v 73.8901 28.2202 13.663
+v 73.8901 -28.2202 13.663
+v 51.11 28.2202 55.0835
+v 47.6599 28.2202 58.0943
+v 25.8958 28.2202 70.5395
+v 51.11 -28.2202 55.0835
+v 47.6599 -28.2202 58.0943
+v 25.8958 -28.2202 70.5395
+v -3.32967 28.2202 75.0688
+v -3.32967 -28.2202 75.0688
+v 68.4071 28.2202 31.0948
+v 66.3861 28.2202 35.2038
+v 68.4071 -28.2202 31.0948
+v 66.3861 -28.2202 35.2038
+v -21.3517 28.2202 72.0453
+v -21.3517 -28.2202 72.0453
+v 34.2809 28.2202 66.8673
+v 60.2737 28.2202 44.8721
+v 45.8677 28.2202 59.5195
+v 34.2809 -28.2202 66.8673
+v 60.2737 -28.2202 44.8721
+v 45.8677 -28.2202 59.5195
+v 70.9602 28.2202 24.7198
+v 65.2826 28.2202 37.2102
+v 70.9602 -28.2202 24.7198
+v 65.2826 -28.2202 37.2102
+v 28.0331 28.2202 69.7178
+v 28.0331 -28.2202 69.7178
+v -14.6851 28.2202 73.6937
+v -14.6851 -28.2202 73.6937
+v 23.7345 28.2202 71.2958
+v 23.7345 -28.2202 71.2958
+v 21.5512 28.2202 71.9859
+v 21.5512 -28.2202 71.9859
+v 75.1078 28.2202 2.28954
+v 75.1078 -28.2202 2.28954
+v 75.0031 28.2202 4.57696
+v 75.0031 -28.2202 4.57696
+v 64.1186 28.2202 39.182
+v 64.1186 -28.2202 39.182
+v 26.4307 32.0363 71.9964
+v 26.4307 -32.0363 71.9964
+v 3.61069 32.0363 76.6096
+v 3.61069 -32.0363 76.6096
+v -24.023 32.0363 72.8352
+v -24.023 -32.0363 72.8352
+v 55.4932 32.0363 52.9393
+v 55.4932 -32.0363 52.9393
+v -5.7314 32.0363 76.4802
+v -5.7314 -32.0363 76.4802
+v 19.7474 32.0363 74.1088
+v 19.7474 -32.0363 74.1088
+v 76.1256 32.0363 9.32564
+v 76.1256 -32.0363 9.32564
+v 10.5897 32.0363 75.96
+v 10.5897 -32.0363 75.96
+v 37.0522 32.0363 67.1506
+v 70.7545 32.0363 29.595
+v 67.7572 32.0363 35.9309
+v 37.0522 -32.0363 67.1506
+v 70.7545 -32.0363 29.595
+v 67.7572 -32.0363 35.9309
+v 5.94325 32.0363 76.464
+v 5.94325 -32.0363 76.464
+v -1.06233 32.0363 76.6873
+v -1.06233 -32.0363 76.6873
+v 64.1939 32.0363 41.9667
+v 24.2247 32.0363 72.7683
+v 64.1939 -32.0363 41.9667
+v 24.2247 -32.0363 72.7683
+v -12.6897 32.0363 75.6376
+v -12.6897 -32.0363 75.6376
+v 12.8992 32.0363 75.6021
+v 12.8992 -32.0363 75.6021
+v 61.5186 32.0363 45.7989
+v 52.1656 32.0363 56.2211
+v 48.6443 32.0363 59.2942
+v 61.5186 -32.0363 45.7989
+v 52.1656 -32.0363 56.2211
+v 48.6443 -32.0363 59.2942
+v -8.05903 32.0363 76.2701
+v -8.05903 -32.0363 76.2701
+v 15.1967 32.0363 75.174
+v 15.1967 -32.0363 75.174
+v 62.8854 32.0363 43.9032
+v 41.0735 32.0363 64.7691
+v 30.7669 32.0363 70.2529
+v 62.8854 -32.0363 43.9032
+v 41.0735 -32.0363 64.7691
+v 30.7669 -32.0363 70.2529
+v 69.82 32.0363 31.7371
+v 69.82 -32.0363 31.7371
+v 53.8544 32.0363 54.6056
+v 46.8151 32.0363 60.7488
+v 53.8544 -32.0363 54.6056
+v 46.8151 -32.0363 60.7488
+v 1.27477 32.0363 76.6841
+v 1.27477 -32.0363 76.6841
+v 39.081 32.0363 65.9905
+v 65.4428 32.0363 39.9913
+v 65.4428 -32.0363 39.9913
+v 39.081 -32.0363 65.9905
+v 74.4268 32.0363 18.5129
+v 74.4268 -32.0363 18.5129
+v -14.9884 32.0363 75.2158
+v -14.9884 -32.0363 75.2158
+v 58.6147 32.0363 49.4609
+v 50.4284 32.0363 57.7845
+v 44.9424 32.0363 62.147
+v 28.6121 32.0363 71.1577
+v 58.6147 -32.0363 49.4609
+v 50.4284 -32.0363 57.7845
+v 44.9424 -32.0363 62.147
+v 28.6121 -32.0363 71.1577
+v -26.2311 32.0363 72.0694
+v 73.1609 32.0363 23.0119
+v -26.2311 -32.0363 72.0694
+v 73.1609 -32.0363 23.0119
+v 32.8932 32.0363 69.2828
+v 32.8932 -32.0363 69.2828
+v 8.2703 32.0363 76.2474
+v 8.2703 -32.0363 76.2474
+v 21.9963 32.0363 73.4727
+v 17.4802 32.0363 74.676
+v 21.9963 -32.0363 73.4727
+v 17.4802 -32.0363 74.676
+v 75.4162 32.0363 13.9452
+v 75.4162 -32.0363 13.9452
+v 76.6946 32.0363 0
+v 68.8205 32.0363 33.8497
+v 76.6946 -32.0363 0
+v 68.8205 -32.0363 33.8497
+v -17.2732 32.0363 74.7242
+v -17.2732 -32.0363 74.7242
+v 76.3744 32.0363 7.00182
+v 76.3744 -32.0363 7.00182
+v -10.3792 32.0363 75.9891
+v -10.3792 -32.0363 75.9891
+v 66.631 32.0363 37.9787
+v 66.631 -32.0363 37.9787
+v 72.4258 32.0363 25.2303
+v 71.6234 32.0363 27.4254
+v 72.4258 -32.0363 25.2303
+v 71.6234 -32.0363 27.4254
+v 34.9889 32.0363 68.2484
+v 34.9889 -32.0363 68.2484
+v 76.659 32.0363 2.33683
+v 76.659 -32.0363 2.33683
+v 73.8281 32.0363 20.772
+v 73.8281 -32.0363 20.772
+v -19.542 32.0363 74.1632
+v -19.542 -32.0363 74.1632
+v 60.0945 32.0363 47.652
+v 43.0279 32.0363 63.4875
+v 60.0945 -32.0363 47.652
+v 43.0279 -32.0363 63.4875
+v 74.9563 32.0363 16.2365
+v 74.9563 -32.0363 16.2365
+v 57.0805 32.0363 51.2239
+v -21.7926 32.0363 73.5333
+v 57.0805 -32.0363 51.2239
+v -21.7926 -32.0363 73.5333
+v -3.39844 32.0363 76.6193
+v -3.39844 -32.0363 76.6193
+v 76.5523 32.0363 4.67149
+v 76.5523 -32.0363 4.67149
+v 75.8061 32.0363 11.6408
+v 75.8061 -32.0363 11.6408
+v 6.07859 35.7675 78.2051
+v 6.07859 -35.7675 78.2051
+v -5.86191 35.7675 78.2217
+v -5.86191 -35.7675 78.2217
+v -15.3297 35.7675 76.9285
+v -15.3297 -35.7675 76.9285
+v 17.8782 35.7675 76.3765
+v 17.8782 -35.7675 76.3765
+v 8.45862 35.7675 77.9836
+v 8.45862 -35.7675 77.9836
+v 74.8269 35.7675 23.5359
+v 72.3657 35.7675 30.2689
+v 74.8269 -35.7675 23.5359
+v 72.3657 -35.7675 30.2689
+v -17.6666 35.7675 76.4257
+v -17.6666 -35.7675 76.4257
+v -26.8284 35.7675 73.7105
+v -26.8284 -35.7675 73.7105
+v 77.1335 35.7675 14.2627
+v 77.1335 -35.7675 14.2627
+v -8.24254 35.7675 78.0068
+v -8.24254 -35.7675 78.0068
+v 10.8308 35.7675 77.6897
+v 10.8308 -35.7675 77.6897
+v 74.075 35.7675 25.8048
+v 74.075 -35.7675 25.8048
+v -19.987 35.7675 75.8519
+v -19.987 -35.7675 75.8519
+v 68.1482 35.7675 38.8435
+v 64.3174 35.7675 44.9029
+v 61.4629 35.7675 48.7371
+v 68.1482 -35.7675 38.8435
+v 64.3174 -35.7675 44.9029
+v 61.4629 -35.7675 48.7371
+v 73.2543 35.7675 28.0499
+v -3.47583 35.7675 78.364
+v 73.2543 -35.7675 28.0499
+v -3.47583 -35.7675 78.364
+v 78.1135 35.7675 7.16125
+v 78.1135 -35.7675 7.16125
+v 78.2954 35.7675 4.77786
+v 78.2954 -35.7675 4.77786
+v 75.5092 35.7675 21.245
+v 69.3001 35.7675 36.7491
+v 29.2636 35.7675 72.778
+v 24.7763 35.7675 74.4253
+v 75.5092 -35.7675 21.245
+v 69.3001 -35.7675 36.7491
+v 29.2636 -35.7675 72.778
+v 24.7763 -35.7675 74.4253
+v 78.441 35.7675 0
+v 70.3876 35.7675 34.6205
+v 62.9194 35.7675 46.8417
+v 59.9494 35.7675 50.5872
+v 55.0807 35.7675 55.849
+v 47.8811 35.7675 62.1321
+v 45.9657 35.7675 63.5622
+v 44.0077 35.7675 64.9332
+v 31.4675 35.7675 71.8526
+v 78.441 -35.7675 0
+v 70.3876 -35.7675 34.6205
+v 62.9194 -35.7675 46.8417
+v 59.9494 -35.7675 50.5872
+v 55.0807 -35.7675 55.849
+v 47.8811 -35.7675 62.1321
+v 45.9657 -35.7675 63.5622
+v 44.0077 -35.7675 64.9332
+v 31.4675 -35.7675 71.8526
+v 76.6631 35.7675 16.6063
+v 76.6631 -35.7675 16.6063
+v 1.3038 35.7675 78.4302
+v 1.3038 -35.7675 78.4302
+v 15.5428 35.7675 76.8857
+v 15.5428 -35.7675 76.8857
+v 77.5322 35.7675 11.9059
+v 58.3802 35.7675 52.3903
+v 56.7568 35.7675 54.1448
+v 51.5767 35.7675 59.1003
+v 49.752 35.7675 60.6444
+v 77.5322 -35.7675 11.9059
+v 58.3802 -35.7675 52.3903
+v 56.7568 -35.7675 54.1448
+v 51.5767 -35.7675 59.1003
+v 49.752 -35.7675 60.6444
+v -24.57 35.7675 74.4937
+v 27.0325 35.7675 73.6359
+v 20.1971 35.7675 75.7963
+v -24.57 -35.7675 74.4937
+v 27.0325 -35.7675 73.6359
+v 20.1971 -35.7675 75.7963
+v -1.08652 35.7675 78.4335
+v -1.08652 -35.7675 78.4335
+v 3.69291 35.7675 78.3541
+v 3.69291 -35.7675 78.3541
+v 71.4098 35.7675 32.4597
+v 71.4098 -35.7675 32.4597
+v 13.1929 35.7675 77.3236
+v 13.1929 -35.7675 77.3236
+v 53.3535 35.7675 57.5014
+v 33.6422 35.7675 70.8604
+v 53.3535 -35.7675 57.5014
+v 33.6422 -35.7675 70.8604
+v -12.9787 35.7675 77.3599
+v -12.9787 -35.7675 77.3599
+v 77.859 35.7675 9.53799
+v 77.859 -35.7675 9.53799
+v 65.6557 35.7675 42.9223
+v 42.0088 35.7675 66.2439
+v 65.6557 -35.7675 42.9223
+v 42.0088 -35.7675 66.2439
+v 39.9709 35.7675 67.4931
+v 35.7856 35.7675 69.8025
+v 66.933 35.7675 40.9019
+v 22.4971 35.7675 75.1457
+v 35.7856 -35.7675 69.8025
+v 66.933 -35.7675 40.9019
+v 39.9709 -35.7675 67.4931
+v 22.4971 -35.7675 75.1457
+v 78.4046 35.7675 2.39004
+v 78.4046 -35.7675 2.39004
+v -10.6155 35.7675 77.7194
+v -10.6155 -35.7675 77.7194
+v 37.8959 35.7675 68.6797
+v 37.8959 -35.7675 68.6797
+v -22.2889 35.7675 75.2077
+v -22.2889 -35.7675 75.2077
+v 76.1215 35.7675 18.9344
+v 76.1215 -35.7675 18.9344
+v 77.373 39.4039 21.7694
+v 77.373 -39.4039 21.7694
+v -22.839 39.4039 77.0641
+v -22.839 -39.4039 77.0641
+v 69.8303 39.4039 39.8023
+v 61.4291 39.4039 51.8358
+v 69.8303 -39.4039 39.8023
+v 61.4291 -39.4039 51.8358
+v -20.4803 39.4039 77.7242
+v -20.4803 -39.4039 77.7242
+v -15.7081 39.4039 78.8273
+v -15.7081 -39.4039 78.8273
+v -13.299 39.4039 79.2693
+v -13.299 -39.4039 79.2693
+v 34.4726 39.4039 72.6095
+v 34.4726 -39.4039 72.6095
+v 1.33598 39.4039 80.3661
+v 1.33598 -39.4039 80.3661
+v 64.4724 39.4039 47.9979
+v 52.8497 39.4039 60.5591
+v 64.4724 -39.4039 47.9979
+v 52.8497 -39.4039 60.5591
+v 27.6998 39.4039 75.4534
+v 27.6998 -39.4039 75.4534
+v 76.6738 39.4039 24.1168
+v 76.6738 -39.4039 24.1168
+v 58.1577 39.4039 55.4813
+v 54.6704 39.4039 58.9206
+v 58.1577 -39.4039 55.4813
+v 54.6704 -39.4039 58.9206
+v 11.0981 39.4039 79.6073
+v 11.0981 -39.4039 79.6073
+v 79.7808 39.4039 9.77341
+v 25.3879 39.4039 76.2624
+v 79.7808 -39.4039 9.77341
+v 25.3879 -39.4039 76.2624
+v -6.00659 39.4039 80.1524
+v -6.00659 -39.4039 80.1524
+v 38.8312 39.4039 70.3749
+v 38.8312 -39.4039 70.3749
+v -18.1026 39.4039 78.3121
+v -18.1026 -39.4039 78.3121
+v 79.4459 39.4039 12.1997
+v 79.4459 -39.4039 12.1997
+v 80.3399 39.4039 2.44903
+v 80.3399 -39.4039 2.44903
+v 72.125 39.4039 35.475
+v 62.98 39.4039 49.9401
+v 56.4403 39.4039 57.2275
+v 47.1003 39.4039 65.1311
+v 72.125 -39.4039 35.475
+v 62.98 -39.4039 49.9401
+v 56.4403 -39.4039 57.2275
+v 47.1003 -39.4039 65.1311
+v -1.11334 39.4039 80.3695
+v -1.11334 -39.4039 80.3695
+v 15.9264 39.4039 78.7835
+v 15.9264 -39.4039 78.7835
+v -10.8776 39.4039 79.6377
+v -10.8776 -39.4039 79.6377
+v 8.6674 39.4039 79.9085
+v -8.44599 39.4039 79.9322
+v 8.6674 -39.4039 79.9085
+v -8.44599 -39.4039 79.9322
+v 78.0004 39.4039 19.4018
+v 78.0004 -39.4039 19.4018
+v 68.5851 39.4039 41.9115
+v 20.6956 39.4039 77.6671
+v 68.5851 -39.4039 41.9115
+v 20.6956 -39.4039 77.6671
+v 29.9859 39.4039 74.5744
+v 29.9859 -39.4039 74.5744
+v 80.3772 39.4039 0
+v 79.0373 39.4039 14.6147
+v 67.2763 39.4039 43.9818
+v 59.8212 39.4039 53.6835
+v 50.98 39.4039 62.1412
+v 43.0457 39.4039 67.879
+v 80.3772 -39.4039 0
+v 79.0373 -39.4039 14.6147
+v 67.2763 -39.4039 43.9818
+v 59.8212 -39.4039 53.6835
+v 50.98 -39.4039 62.1412
+v 43.0457 -39.4039 67.879
+v 75.0625 39.4039 28.7422
+v 75.0625 -39.4039 28.7422
+v -3.56162 39.4039 80.2982
+v -3.56162 -39.4039 80.2982
+v 32.2442 39.4039 73.6261
+v 32.2442 -39.4039 73.6261
+v -25.1765 39.4039 76.3324
+v -25.1765 -39.4039 76.3324
+v 80.0415 39.4039 7.33801
+v 80.0415 -39.4039 7.33801
+v -27.4906 39.4039 75.5298
+v 75.9034 39.4039 26.4418
+v 65.9049 39.4039 46.0112
+v 49.0629 39.4039 63.6657
+v -27.4906 -39.4039 75.5298
+v 75.9034 -39.4039 26.4418
+v 65.9049 -39.4039 46.0112
+v 49.0629 -39.4039 63.6657
+v 6.22862 39.4039 80.1355
+v 6.22862 -39.4039 80.1355
+v 78.5553 39.4039 17.0162
+v 74.1519 39.4039 31.016
+v 45.0939 39.4039 66.5359
+v 78.5553 -39.4039 17.0162
+v 74.1519 -39.4039 31.016
+v 45.0939 -39.4039 66.5359
+v 18.3195 39.4039 78.2617
+v 18.3195 -39.4039 78.2617
+v 13.5186 39.4039 79.2322
+v 13.5186 -39.4039 79.2322
+v 80.2279 39.4039 4.8958
+v 80.2279 -39.4039 4.8958
+v 36.6689 39.4039 71.5254
+v 73.1724 39.4039 33.2609
+v 36.6689 -39.4039 71.5254
+v 73.1724 -39.4039 33.2609
+v 40.9575 39.4039 69.1591
+v 40.9575 -39.4039 69.1591
+v 3.78406 39.4039 80.2881
+v 3.78406 -39.4039 80.2881
+v 23.0524 39.4039 77.0005
+v 23.0524 -39.4039 77.0005
+v 71.0106 39.4039 37.6561
+v 71.0106 -39.4039 37.6561
+v 82.1534 42.9357 7.53163
+v 82.1534 -42.9357 7.53163
+v 81.5421 42.9357 12.5216
+v 81.5421 -42.9357 12.5216
+v 80.628 42.9357 17.4651
+v 80.628 -42.9357 17.4651
+v 13.8752 42.9357 81.3227
+v 13.8752 -42.9357 81.3227
+v 61.3996 42.9357 55.0999
+v 61.3996 -42.9357 55.0999
+v -25.8408 42.9357 78.3464
+v -25.8408 -42.9357 78.3464
+v 69.0514 42.9357 45.1422
+v 69.0514 -42.9357 45.1422
+v -8.66884 42.9357 82.0412
+v -8.66884 -42.9357 82.0412
+v 18.8029 42.9357 80.3266
+v 18.8029 -42.9357 80.3266
+v -13.6499 42.9357 81.3609
+v -13.6499 -42.9357 81.3609
+v 66.1735 42.9357 49.2644
+v 66.1735 -42.9357 49.2644
+v 82.4596 42.9357 2.51365
+v 82.4596 -42.9357 2.51365
+v 80.0585 42.9357 19.9137
+v 80.0585 -42.9357 19.9137
+v 78.6969 42.9357 24.7531
+v 23.6607 42.9357 79.0322
+v 78.6969 -42.9357 24.7531
+v 23.6607 -42.9357 79.0322
+v 3.8839 42.9357 82.4065
+v 3.8839 -42.9357 82.4065
+v -28.216 42.9357 77.5227
+v 81.1228 42.9357 15.0003
+v 64.6417 42.9357 51.2578
+v 33.095 42.9357 75.5687
+v -23.4416 42.9357 79.0974
+v -28.216 -42.9357 77.5227
+v 81.1228 -42.9357 15.0003
+v 64.6417 -42.9357 51.2578
+v 33.095 -42.9357 75.5687
+v -23.4416 -42.9357 79.0974
+v 8.89609 42.9357 82.0169
+v 8.89609 -42.9357 82.0169
+v 75.1031 42.9357 34.1385
+v 74.028 42.9357 36.411
+v 28.4306 42.9357 77.4443
+v 75.1031 -42.9357 34.1385
+v 74.028 -42.9357 36.411
+v 28.4306 -42.9357 77.4443
+v 6.39297 42.9357 82.2499
+v 6.39297 -42.9357 82.2499
+v 1.37123 42.9357 82.4866
+v 1.37123 -42.9357 82.4866
+v -6.16508 42.9357 82.2673
+v -6.16508 -42.9357 82.2673
+v 77.9061 42.9357 27.1395
+v 72.8842 42.9357 38.6497
+v 77.9061 -42.9357 27.1395
+v 72.8842 -42.9357 38.6497
+v 11.391 42.9357 81.7078
+v 11.391 -42.9357 81.7078
+v -3.65559 42.9357 82.4169
+v -3.65559 -42.9357 82.4169
+v 42.0382 42.9357 70.9838
+v 42.0382 -42.9357 70.9838
+v 63.0499 42.9357 53.2035
+v 59.6922 42.9357 56.9451
+v 57.9295 42.9357 58.7375
+v 56.1129 42.9357 60.4753
+v 30.7771 42.9357 76.542
+v 21.2416 42.9357 79.7164
+v -16.1226 42.9357 80.9072
+v 63.0499 -42.9357 53.2035
+v 59.6922 -42.9357 56.9451
+v 57.9295 -42.9357 58.7375
+v 56.1129 -42.9357 60.4753
+v 30.7771 -42.9357 76.542
+v 21.2416 -42.9357 79.7164
+v -16.1226 -42.9357 80.9072
+v 77.043 42.9357 29.5006
+v 77.043 -42.9357 29.5006
+v 81.8858 42.9357 10.0313
+v 81.8858 -42.9357 10.0313
+v 82.3448 42.9357 5.02497
+v 82.3448 -42.9357 5.02497
+v 70.3948 42.9357 43.0173
+v 54.2442 42.9357 62.1569
+v 52.3251 42.9357 63.7808
+v 46.2837 42.9357 68.2915
+v 44.1815 42.9357 69.67
+v 26.0578 42.9357 78.2746
+v 70.3948 -42.9357 43.0173
+v 54.2442 -42.9357 62.1569
+v 52.3251 -42.9357 63.7808
+v 46.2837 -42.9357 68.2915
+v 44.1815 -42.9357 69.67
+v 26.0578 -42.9357 78.2746
+v -21.0207 42.9357 79.7749
+v -21.0207 -42.9357 79.7749
+v 16.3466 42.9357 80.8622
+v 16.3466 -42.9357 80.8622
+v 76.1084 42.9357 31.8344
+v -1.14271 42.9357 82.49
+v 76.1084 -42.9357 31.8344
+v -1.14271 -42.9357 82.49
+v 67.6439 42.9357 47.2252
+v 67.6439 -42.9357 47.2252
+v -11.1646 42.9357 81.739
+v -11.1646 -42.9357 81.739
+v 71.6728 42.9357 40.8525
+v 71.6728 -42.9357 40.8525
+v 50.3575 42.9357 65.3455
+v 48.343 42.9357 66.8496
+v 50.3575 -42.9357 65.3455
+v 48.343 -42.9357 66.8496
+v 35.3821 42.9357 74.5253
+v 35.3821 -42.9357 74.5253
+v 79.4145 42.9357 22.3438
+v -18.5803 42.9357 80.3784
+v 79.4145 -42.9357 22.3438
+v -18.5803 -42.9357 80.3784
+v 82.498 42.9357 0
+v 39.8558 42.9357 72.2318
+v 37.6365 42.9357 73.4126
+v 82.498 -42.9357 0
+v 37.6365 -42.9357 73.4126
+v 39.8558 -42.9357 72.2318
+v 3.99217 46.3537 84.7037
+v 3.99217 -46.3537 84.7037
+v 34.0176 46.3537 77.6753
+v 34.0176 -46.3537 77.6753
+v 82.8757 46.3537 17.952
+v 82.8757 -46.3537 17.952
+v 49.6907 46.3537 68.7131
+v 26.7841 46.3537 80.4566
+v 49.6907 -46.3537 68.7131
+v 26.7841 -46.3537 80.4566
+v -26.5612 46.3537 80.5305
+v -26.5612 -46.3537 80.5305
+v 73.6708 46.3537 41.9913
+v 73.6708 -46.3537 41.9913
+v 79.1907 46.3537 30.323
+v 47.574 46.3537 70.1952
+v 79.1907 -46.3537 30.323
+v 47.574 -46.3537 70.1952
+v 38.6856 46.3537 75.4591
+v 24.3203 46.3537 81.2353
+v 38.6856 -46.3537 75.4591
+v 24.3203 -46.3537 81.2353
+v 84.7977 46.3537 0
+v 80.0779 46.3537 27.896
+v 84.7977 -46.3537 0
+v 80.0779 -46.3537 27.896
+v 21.8338 46.3537 81.9386
+v 14.262 46.3537 83.5898
+v 21.8338 -46.3537 81.9386
+v 14.262 -46.3537 83.5898
+v 84.6403 46.3537 5.16505
+v 84.6403 -46.3537 5.16505
+v -3.7575 46.3537 84.7144
+v -3.7575 -46.3537 84.7144
+v 78.23 46.3537 32.7218
+v 16.8023 46.3537 83.1164
+v 78.23 -46.3537 32.7218
+v 16.8023 -46.3537 83.1164
+v 19.327 46.3537 82.5659
+v 19.327 -46.3537 82.5659
+v 83.8153 46.3537 12.8707
+v 72.3571 46.3537 44.2165
+v 36.3685 46.3537 76.6028
+v 83.8153 -46.3537 12.8707
+v 72.3571 -46.3537 44.2165
+v 36.3685 -46.3537 76.6028
+v 83.3842 46.3537 15.4185
+v 70.9763 46.3537 46.4007
+v 57.6771 46.3537 62.1611
+v 51.7613 46.3537 67.1672
+v 45.4131 46.3537 71.6122
+v 83.3842 -46.3537 15.4185
+v 70.9763 -46.3537 46.4007
+v 57.6771 -46.3537 62.1611
+v 51.7613 -46.3537 67.1672
+v 45.4131 -46.3537 71.6122
+v 9.14409 46.3537 84.3033
+v -8.9105 46.3537 84.3283
+v 9.14409 -46.3537 84.3033
+v -8.9105 -46.3537 84.3283
+v 11.7085 46.3537 83.9855
+v 11.7085 -46.3537 83.9855
+v 40.9669 46.3537 74.2454
+v 76.0917 46.3537 37.426
+v 31.6351 46.3537 78.6758
+v 40.9669 -46.3537 74.2454
+v 76.0917 -46.3537 37.426
+v 31.6351 -46.3537 78.6758
+v -14.0304 46.3537 83.629
+v -14.0304 -46.3537 83.629
+v -1.17456 46.3537 84.7896
+v -1.17456 -46.3537 84.7896
+v 43.21 46.3537 72.9626
+v 82.2902 46.3537 20.4688
+v 74.916 46.3537 39.7271
+v 68.0182 46.3537 50.6377
+v 64.8076 46.3537 54.6867
+v 63.1112 46.3537 56.6359
+v 82.2902 -46.3537 20.4688
+v 74.916 -46.3537 39.7271
+v 68.0182 -46.3537 50.6377
+v 64.8076 -46.3537 54.6867
+v 63.1112 -46.3537 56.6359
+v 43.21 -46.3537 72.9626
+v 1.40946 46.3537 84.786
+v 1.40946 -46.3537 84.786
+v 6.57118 46.3537 84.5427
+v 6.57118 -46.3537 84.5427
+v 84.7584 46.3537 2.58373
+v 84.7584 -46.3537 2.58373
+v 80.8907 46.3537 25.4431
+v 80.8907 -46.3537 25.4431
+v 84.4436 46.3537 7.74158
+v 84.4436 -46.3537 7.74158
+v 69.5295 46.3537 48.5417
+v 61.3563 46.3537 58.5326
+v 69.5295 -46.3537 48.5417
+v 61.3563 -46.3537 58.5326
+v -24.0951 46.3537 81.3024
+v -24.0951 -46.3537 81.3024
+v -6.33694 46.3537 84.5606
+v -6.33694 -46.3537 84.5606
+v 77.1967 46.3537 35.0902
+v 77.1967 -46.3537 35.0902
+v -29.0025 46.3537 79.6838
+v 81.6284 46.3537 22.9667
+v 29.2232 46.3537 79.6031
+v -29.0025 -46.3537 79.6838
+v 81.6284 -46.3537 22.9667
+v 29.2232 -46.3537 79.6031
+v -19.0982 46.3537 82.6191
+v -19.0982 -46.3537 82.6191
+v 59.5443 46.3537 60.3749
+v 55.7563 46.3537 63.8897
+v 59.5443 -46.3537 60.3749
+v 55.7563 -46.3537 63.8897
+v -21.6067 46.3537 81.9988
+v -21.6067 -46.3537 81.9988
+v -11.4758 46.3537 84.0176
+v -11.4758 -46.3537 84.0176
+v 53.7838 46.3537 65.5589
+v 53.7838 -46.3537 65.5589
+v 66.4438 46.3537 52.6866
+v 66.4438 -46.3537 52.6866
+v 84.1685 46.3537 10.3109
+v 84.1685 -46.3537 10.3109
+v -16.572 46.3537 83.1626
+v -16.572 -46.3537 83.1626
+v 79.4477 49.6488 36.1134
+v 79.4477 -49.6488 36.1134
+v 64.9515 49.6488 58.2874
+v 64.9515 -49.6488 58.2874
+v -22.2367 49.6488 84.3899
+v -22.2367 -49.6488 84.3899
+v 39.8137 49.6488 77.6595
+v 39.8137 -49.6488 77.6595
+v -3.86707 49.6488 87.1847
+v -3.86707 -49.6488 87.1847
+v 19.8906 49.6488 84.9735
+v -24.7977 49.6488 83.6732
+v 19.8906 -49.6488 84.9735
+v -24.7977 -49.6488 83.6732
+v -11.8104 49.6488 86.4676
+v -11.8104 -49.6488 86.4676
+v 73.0459 49.6488 47.7537
+v 66.6973 49.6488 56.2813
+v 61.2806 49.6488 62.1354
+v 73.0459 -49.6488 47.7537
+v 66.6973 -49.6488 56.2813
+v 61.2806 -49.6488 62.1354
+v -14.4395 49.6488 86.0676
+v -14.4395 -49.6488 86.0676
+v 12.0499 49.6488 86.4345
+v 12.0499 -49.6488 86.4345
+v -29.8482 49.6488 82.0074
+v -19.6551 49.6488 85.0282
+v -29.8482 -49.6488 82.0074
+v -19.6551 -49.6488 85.0282
+v 71.557 49.6488 49.9572
+v 57.3822 49.6488 65.7527
+v 37.429 49.6488 78.8365
+v 32.5575 49.6488 80.9699
+v 71.557 -49.6488 49.9572
+v 57.3822 -49.6488 65.7527
+v 37.429 -49.6488 78.8365
+v 32.5575 -49.6488 80.9699
+v 83.2494 49.6488 26.1851
+v 25.0294 49.6488 83.6041
+v 83.2494 -49.6488 26.1851
+v 25.0294 -49.6488 83.6041
+v -9.17033 49.6488 86.7873
+v -9.17033 -49.6488 86.7873
+v 27.5652 49.6488 82.8027
+v 27.5652 -49.6488 82.8027
+v 87.2299 49.6488 2.65907
+v 87.2299 -49.6488 2.65907
+v 14.6779 49.6488 86.0272
+v 14.6779 -49.6488 86.0272
+v 87.2704 49.6488 0
+v 75.819 49.6488 43.2158
+v 74.467 49.6488 45.5059
+v 59.359 49.6488 63.9737
+v 87.2704 -49.6488 0
+v 75.819 -49.6488 43.2158
+v 74.467 -49.6488 45.5059
+v 59.359 -49.6488 63.9737
+v 85.8157 49.6488 15.8681
+v 85.8157 -49.6488 15.8681
+v 6.7628 49.6488 87.008
+v 6.7628 -49.6488 87.008
+v 84.6898 49.6488 21.0657
+v 84.6898 -49.6488 21.0657
+v 1.45056 49.6488 87.2584
+v 1.45056 -49.6488 87.2584
+v 78.3105 49.6488 38.5174
+v 78.3105 -49.6488 38.5174
+v 17.2923 49.6488 85.5401
+v 17.2923 -49.6488 85.5401
+v -6.52173 49.6488 87.0264
+v -6.52173 -49.6488 87.0264
+v -17.0553 49.6488 85.5876
+v -17.0553 -49.6488 85.5876
+v 42.1614 49.6488 76.4103
+v 68.3812 49.6488 54.223
+v 63.1454 49.6488 60.2394
+v 55.3521 49.6488 67.4705
+v 51.1397 49.6488 70.7168
+v 35.0095 49.6488 79.9404
+v 42.1614 -49.6488 76.4103
+v 68.3812 -49.6488 54.223
+v 63.1454 -49.6488 60.2394
+v 55.3521 -49.6488 67.4705
+v 51.1397 -49.6488 70.7168
+v 35.0095 -49.6488 79.9404
+v 86.906 49.6488 7.96733
+v 86.906 -49.6488 7.96733
+v 84.0086 49.6488 23.6364
+v 84.0086 -49.6488 23.6364
+v 30.0753 49.6488 81.9244
+v 30.0753 -49.6488 81.9244
+v 48.9612 49.6488 72.2421
+v 48.9612 -49.6488 72.2421
+v 4.10858 49.6488 87.1737
+v 4.10858 -49.6488 87.1737
+v 82.4129 49.6488 28.7095
+v 82.4129 -49.6488 28.7095
+v 22.4705 49.6488 84.328
+v 22.4705 -49.6488 84.328
+v 53.2706 49.6488 69.1257
+v 46.7373 49.6488 73.7004
+v 53.2706 -49.6488 69.1257
+v 46.7373 -49.6488 73.7004
+v -1.20881 49.6488 87.262
+v -1.20881 -49.6488 87.262
+v 86.6229 49.6488 10.6116
+v 86.6229 -49.6488 10.6116
+v 77.1006 49.6488 40.8856
+v 77.1006 -49.6488 40.8856
+v 44.47 49.6488 75.0902
+v 80.5112 49.6488 33.6759
+v 70.0016 49.6488 52.1143
+v 80.5112 -49.6488 33.6759
+v 70.0016 -49.6488 52.1143
+v 44.47 -49.6488 75.0902
+v 87.1084 49.6488 5.31566
+v 87.1084 -49.6488 5.31566
+v 85.2923 49.6488 18.4755
+v 85.2923 -49.6488 18.4755
+v -27.3357 49.6488 82.8788
+v 81.4999 49.6488 31.2072
+v -27.3357 -49.6488 82.8788
+v 81.4999 -49.6488 31.2072
+v 9.41073 49.6488 86.7615
+v 9.41073 -49.6488 86.7615
+v 86.2593 49.6488 13.246
+v 86.2593 -49.6488 13.246
+v 87.8715 52.8122 19.0342
+v 87.8715 -52.8122 19.0342
+v -20.2495 52.8122 87.5995
+v -20.2495 -52.8122 87.5995
+v -25.5476 52.8122 86.2034
+v -25.5476 -52.8122 86.2034
+v 43.4364 52.8122 78.7209
+v 59.1174 52.8122 67.741
+v 43.4364 -52.8122 78.7209
+v 59.1174 -52.8122 67.741
+v 6.9673 52.8122 89.6391
+v 6.9673 -52.8122 89.6391
+v 68.7143 52.8122 57.9833
+v 36.0682 52.8122 82.3577
+v 68.7143 -52.8122 57.9833
+v 36.0682 -52.8122 82.3577
+v 66.9156 52.8122 60.05
+v 54.8815 52.8122 71.2161
+v 66.9156 -52.8122 60.05
+v 54.8815 -52.8122 71.2161
+v 15.1218 52.8122 88.6287
+v 15.1218 -52.8122 88.6287
+v 89.8677 52.8122 2.73948
+v 89.8677 -52.8122 2.73948
+v 17.8152 52.8122 88.1268
+v -22.9092 52.8122 86.9418
+v 17.8152 -52.8122 88.1268
+v -22.9092 -52.8122 86.9418
+v 89.534 52.8122 8.20826
+v 89.534 -52.8122 8.20826
+v 73.7209 52.8122 51.4679
+v 72.1184 52.8122 53.6902
+v 61.1539 52.8122 65.9083
+v 50.4418 52.8122 74.4267
+v 73.7209 -52.8122 51.4679
+v 72.1184 -52.8122 53.6902
+v 61.1539 -52.8122 65.9083
+v 50.4418 -52.8122 74.4267
+v -9.44764 52.8122 89.4117
+v -9.44764 -52.8122 89.4117
+v 83.9644 52.8122 32.1509
+v 79.4321 52.8122 42.1219
+v 78.1117 52.8122 44.5226
+v 83.9644 -52.8122 32.1509
+v 79.4321 -52.8122 42.1219
+v 78.1117 -52.8122 44.5226
+v -1.24537 52.8122 89.9008
+v -1.24537 -52.8122 89.9008
+v -12.1676 52.8122 89.0823
+v -12.1676 -52.8122 89.0823
+v 82.9458 52.8122 34.6943
+v 76.7189 52.8122 46.882
+v 75.2548 52.8122 49.1978
+v 57.0259 52.8122 69.5108
+v 82.9458 -52.8122 34.6943
+v 76.7189 -52.8122 46.882
+v 75.2548 -52.8122 49.1978
+v 57.0259 -52.8122 69.5108
+v -17.571 52.8122 88.1758
+v -17.571 -52.8122 88.1758
+v 12.4143 52.8122 89.0483
+v 12.4143 -52.8122 89.0483
+v -30.7508 52.8122 84.4872
+v 80.6786 52.8122 39.6821
+v 20.4921 52.8122 87.543
+v -30.7508 -52.8122 84.4872
+v 80.6786 -52.8122 39.6821
+v 20.4921 -52.8122 87.543
+v -28.1623 52.8122 85.385
+v -28.1623 -52.8122 85.385
+v 89.9094 52.8122 0
+v 86.549 52.8122 24.3511
+v 81.8502 52.8122 37.2055
+v 38.5608 52.8122 81.2205
+v 89.9094 -52.8122 0
+v 86.549 -52.8122 24.3511
+v 81.8502 -52.8122 37.2055
+v 38.5608 -52.8122 81.2205
+v 88.8678 52.8122 13.6466
+v 88.8678 -52.8122 13.6466
+v -6.71894 52.8122 89.658
+v -6.71894 -52.8122 89.658
+v 85.7669 52.8122 26.9769
+v 25.7863 52.8122 86.1323
+v 85.7669 -52.8122 26.9769
+v 25.7863 -52.8122 86.1323
+v -3.984 52.8122 89.8211
+v -3.984 -52.8122 89.8211
+v 45.8148 52.8122 77.3609
+v 48.1507 52.8122 75.9291
+v 48.1507 -52.8122 75.9291
+v 45.8148 -52.8122 77.3609
+v -14.8762 52.8122 88.6702
+v -14.8762 -52.8122 88.6702
+v 4.23283 52.8122 89.8098
+v 4.23283 -52.8122 89.8098
+v 89.7425 52.8122 5.47641
+v 89.7425 -52.8122 5.47641
+v 41.0177 52.8122 80.0079
+v 41.0177 -52.8122 80.0079
+v 9.6953 52.8122 89.3852
+v 9.6953 -52.8122 89.3852
+v 65.0549 52.8122 62.061
+v 63.1337 52.8122 64.0144
+v 33.5421 52.8122 83.4185
+v 65.0549 -52.8122 62.061
+v 63.1337 -52.8122 64.0144
+v 33.5421 -52.8122 83.4185
+v 89.2423 52.8122 10.9325
+v 89.2423 -52.8122 10.9325
+v 84.9051 52.8122 29.5776
+v 84.9051 -52.8122 29.5776
+v 52.6861 52.8122 72.8552
+v 52.6861 -52.8122 72.8552
+v 87.2508 52.8122 21.7027
+v 87.2508 -52.8122 21.7027
+v 30.9848 52.8122 84.4017
+v 30.9848 -52.8122 84.4017
+v 70.4491 52.8122 55.8627
+v 23.15 52.8122 86.878
+v 70.4491 -52.8122 55.8627
+v 23.15 -52.8122 86.878
+v 1.49442 52.8122 89.897
+v 1.49442 -52.8122 89.897
+v 88.4107 52.8122 16.348
+v 88.4107 -52.8122 16.348
+v 28.3987 52.8122 85.3066
+v 28.3987 -52.8122 85.3066
+v 1.54094 55.8355 92.695
+v 1.54094 -55.8355 92.695
+v 92.7078 55.8355 0
+v 92.7078 -55.8355 0
+v 83.1897 55.8355 40.9172
+v 83.1897 -55.8355 40.9172
+v 91.6337 55.8355 14.0713
+v 91.6337 -55.8355 14.0713
+v -26.3428 55.8355 88.8864
+v -26.3428 -55.8355 88.8864
+v 81.9043 55.8355 43.4329
+v 81.9043 -55.8355 43.4329
+v 4.36457 55.8355 92.605
+v 4.36457 -55.8355 92.605
+v -29.0388 55.8355 88.0425
+v 77.5971 55.8355 50.729
+v 72.6417 55.8355 57.6014
+v 60.9574 55.8355 69.8494
+v -29.0388 -55.8355 88.0425
+v 77.5971 -55.8355 50.729
+v 72.6417 -55.8355 57.6014
+v 60.9574 -55.8355 69.8494
+v 15.5924 55.8355 91.3872
+v 15.5924 -55.8355 91.3872
+v 31.9492 55.8355 87.0287
+v 31.9492 -55.8355 87.0287
+v 89.2428 55.8355 25.109
+v 85.5275 55.8355 35.7741
+v 80.5429 55.8355 45.9084
+v 49.6493 55.8355 78.2923
+v 89.2428 -55.8355 25.109
+v 85.5275 -55.8355 35.7741
+v 80.5429 -55.8355 45.9084
+v 49.6493 -55.8355 78.2923
+v -6.92806 55.8355 92.4486
+v -6.92806 -55.8355 92.4486
+v 21.1299 55.8355 90.2678
+v 21.1299 -55.8355 90.2678
+v -15.3392 55.8355 91.43
+v -15.3392 -55.8355 91.43
+v -18.1179 55.8355 90.9202
+v -18.1179 -55.8355 90.9202
+v 12.8007 55.8355 91.8198
+v 12.8007 -55.8355 91.8198
+v 42.2943 55.8355 82.4981
+v 87.5477 55.8355 30.4982
+v 39.761 55.8355 83.7485
+v 42.2943 -55.8355 82.4981
+v 87.5477 -55.8355 30.4982
+v 39.761 -55.8355 83.7485
+v 92.5357 55.8355 5.64686
+v 92.5357 -55.8355 5.64686
+v -31.7079 55.8355 87.1169
+v 44.7883 55.8355 81.1711
+v 44.7883 -55.8355 81.1711
+v -31.7079 -55.8355 87.1169
+v 23.8705 55.8355 89.582
+v -23.6222 55.8355 89.6478
+v 23.8705 -55.8355 89.582
+v -23.6222 -55.8355 89.6478
+v 76.0154 55.8355 53.0698
+v 70.853 55.8355 59.788
+v 67.0797 55.8355 63.9926
+v 63.0573 55.8355 67.9596
+v 52.0118 55.8355 76.7432
+v 76.0154 -55.8355 53.0698
+v 70.853 -55.8355 59.788
+v 67.0797 -55.8355 63.9926
+v 63.0573 -55.8355 67.9596
+v 52.0118 -55.8355 76.7432
+v 18.3697 55.8355 90.8697
+v 18.3697 -55.8355 90.8697
+v -1.28413 55.8355 92.6989
+v -1.28413 -55.8355 92.6989
+v 91.1624 55.8355 16.8568
+v 88.4363 55.8355 27.8165
+v 91.1624 -55.8355 16.8568
+v 88.4363 -55.8355 27.8165
+v 92.6648 55.8355 2.82474
+v 92.6648 -55.8355 2.82474
+v 92.0199 55.8355 11.2727
+v 92.0199 -55.8355 11.2727
+v -12.5463 55.8355 91.8549
+v -12.5463 -55.8355 91.8549
+v -4.10801 55.8355 92.6168
+v -4.10801 -55.8355 92.6168
+v 79.1067 55.8355 48.3411
+v 74.3631 55.8355 55.3613
+v 68.9984 55.8355 61.919
+v 58.8008 55.8355 71.6743
+v 56.5896 55.8355 73.4326
+v 79.1067 -55.8355 48.3411
+v 74.3631 -55.8355 55.3613
+v 68.9984 -55.8355 61.919
+v 58.8008 -55.8355 71.6743
+v 56.5896 -55.8355 73.4326
+v 7.18415 55.8355 92.429
+v 7.18415 -55.8355 92.429
+v 29.2826 55.8355 87.9617
+v 29.2826 -55.8355 87.9617
+v 9.99707 55.8355 92.1672
+v 9.99707 -55.8355 92.1672
+v 65.0987 55.8355 66.0068
+v 37.1908 55.8355 84.9211
+v 65.0987 -55.8355 66.0068
+v 37.1908 -55.8355 84.9211
+v 92.3207 55.8355 8.46373
+v 92.3207 -55.8355 8.46373
+v -20.8797 55.8355 90.326
+v -20.8797 -55.8355 90.326
+v 89.9664 55.8355 22.3782
+v 89.9664 -55.8355 22.3782
+v -9.74169 55.8355 92.1946
+v -9.74169 -55.8355 92.1946
+v 86.5778 55.8355 33.1516
+v 86.5778 -55.8355 33.1516
+v 34.586 55.8355 86.0148
+v 34.586 -55.8355 86.0148
+v 84.3978 55.8355 38.3635
+v 84.3978 -55.8355 38.3635
+v 90.6065 55.8355 19.6266
+v 90.6065 -55.8355 19.6266
+v 26.5889 55.8355 88.8131
+v 26.5889 -55.8355 88.8131
+v 54.3259 55.8355 75.1228
+v 54.3259 -55.8355 75.1228
+v 47.2407 55.8355 79.7688
+v 47.2407 -55.8355 79.7688
+v 43.6403 58.7108 85.1235
+v 43.6403 -58.7108 85.1235
+v -21.5442 58.7108 93.2004
+v -21.5442 -58.7108 93.2004
+v -12.9455 58.7108 94.7781
+v -12.9455 -58.7108 94.7781
+v 46.2136 58.7108 83.7543
+v 46.2136 -58.7108 83.7543
+v 4.50347 58.7108 95.5521
+v 4.50347 -58.7108 95.5521
+v -32.717 58.7108 89.8892
+v 95.6581 58.7108 0
+v 95.6581 -58.7108 0
+v -32.717 -58.7108 89.8892
+v -15.8273 58.7108 94.3397
+v -15.8273 -58.7108 94.3397
+v 92.8295 58.7108 23.0904
+v 92.8295 -58.7108 23.0904
+v 81.6242 58.7108 49.8795
+v 81.6242 -58.7108 49.8795
+v -18.6945 58.7108 93.8136
+v -18.6945 -58.7108 93.8136
+v 87.0836 58.7108 39.5844
+v 78.4345 58.7108 54.7587
+v 18.9543 58.7108 93.7615
+v 87.0836 -58.7108 39.5844
+v 78.4345 -58.7108 54.7587
+v 18.9543 -58.7108 93.7615
+v -27.1811 58.7108 91.7151
+v -27.1811 -58.7108 91.7151
+v 94.5499 58.7108 14.5191
+v 94.5499 -58.7108 14.5191
+v -29.963 58.7108 90.8444
+v -29.963 -58.7108 90.8444
+v 92.0828 58.7108 25.9081
+v 92.0828 -58.7108 25.9081
+v 13.2081 58.7108 94.7419
+v 13.2081 -58.7108 94.7419
+v 93.4899 58.7108 20.2512
+v 88.2493 58.7108 36.9126
+v 58.3905 58.7108 75.7695
+v 93.4899 -58.7108 20.2512
+v 88.2493 -58.7108 36.9126
+v 58.3905 -58.7108 75.7695
+v -1.325 58.7108 95.649
+v -1.325 -58.7108 95.649
+v 21.8023 58.7108 93.1404
+v 21.8023 -58.7108 93.1404
+v 24.6301 58.7108 92.4329
+v 24.6301 -58.7108 92.4329
+v 90.3338 58.7108 31.4688
+v 27.4351 58.7108 91.6395
+v 90.3338 -58.7108 31.4688
+v 27.4351 -58.7108 91.6395
+v 91.2507 58.7108 28.7018
+v 89.333 58.7108 34.2066
+v 80.0665 58.7108 52.3434
+v 74.9535 58.7108 59.4344
+v 51.2293 58.7108 80.7839
+v 41.0263 58.7108 86.4136
+v 91.2507 -58.7108 28.7018
+v 89.333 -58.7108 34.2066
+v 80.0665 -58.7108 52.3434
+v 74.9535 -58.7108 59.4344
+v 51.2293 -58.7108 80.7839
+v 41.0263 -58.7108 86.4136
+v 7.41278 58.7108 95.3705
+v 7.41278 -58.7108 95.3705
+v -4.23874 58.7108 95.5642
+v -4.23874 -58.7108 95.5642
+v 95.2587 58.7108 8.73308
+v 95.2587 -58.7108 8.73308
+v 85.8371 58.7108 42.2194
+v 53.667 58.7108 79.1854
+v 10.3152 58.7108 95.1003
+v 85.8371 -58.7108 42.2194
+v 53.667 -58.7108 79.1854
+v 10.3152 -58.7108 95.1003
+v 84.5108 58.7108 44.8152
+v 35.6867 58.7108 88.7521
+v 84.5108 -58.7108 44.8152
+v 35.6867 -58.7108 88.7521
+v 48.7441 58.7108 82.3073
+v 83.1061 58.7108 47.3693
+v 76.7296 58.7108 57.1231
+v 69.2144 58.7108 66.0291
+v 83.1061 -58.7108 47.3693
+v 76.7296 -58.7108 57.1231
+v 69.2144 -58.7108 66.0291
+v 48.7441 -58.7108 82.3073
+v 94.9483 58.7108 11.6315
+v 94.9483 -58.7108 11.6315
+v -24.374 58.7108 92.5007
+v -24.374 -58.7108 92.5007
+v 16.0886 58.7108 94.2955
+v 16.0886 -58.7108 94.2955
+v 95.4805 58.7108 5.82656
+v 95.4805 -58.7108 5.82656
+v 30.2145 58.7108 90.761
+v 30.2145 -58.7108 90.761
+v 1.58997 58.7108 95.6449
+v 1.58997 -58.7108 95.6449
+v 94.0636 58.7108 17.3932
+v 94.0636 -58.7108 17.3932
+v 73.1078 58.7108 61.6906
+v 62.8973 58.7108 72.0723
+v 73.1078 -58.7108 61.6906
+v 62.8973 -58.7108 72.0723
+v 32.9659 58.7108 89.7983
+v 32.9659 -58.7108 89.7983
+v 95.6137 58.7108 2.91463
+v 95.6137 -58.7108 2.91463
+v 71.1942 58.7108 63.8895
+v 60.6721 58.7108 73.9553
+v 56.0548 58.7108 77.5135
+v 71.1942 -58.7108 63.8895
+v 60.6721 -58.7108 73.9553
+v 56.0548 -58.7108 77.5135
+v 67.1704 58.7108 68.1074
+v 65.0641 58.7108 70.1224
+v 67.1704 -58.7108 68.1074
+v 65.0641 -58.7108 70.1224
+v -10.0517 58.7108 95.1286
+v -10.0517 -58.7108 95.1286
+v -7.14854 58.7108 95.3907
+v -7.14854 -58.7108 95.3907
+v 38.3743 58.7108 87.6236
+v 38.3743 -58.7108 87.6236
+v 71.4534 61.4304 68.165
+v 71.4534 -61.4304 68.165
+v 87.2446 61.4304 46.2649
+v 87.2446 -61.4304 46.2649
+v 92.2228 61.4304 35.3131
+v 92.2228 -61.4304 35.3131
+v 75.4727 61.4304 63.6862
+v 75.4727 -61.4304 63.6862
+v 93.256 61.4304 32.4868
+v 93.256 -61.4304 32.4868
+v 16.6091 61.4304 97.3458
+v 16.6091 -61.4304 97.3458
+v 31.1919 61.4304 93.697
+v 31.1919 -61.4304 93.697
+v 55.403 61.4304 81.747
+v 55.403 -61.4304 81.747
+v 28.3225 61.4304 94.6039
+v 28.3225 -61.4304 94.6039
+v 34.0323 61.4304 92.7031
+v 34.0323 -61.4304 92.7031
+v 98.5692 61.4304 6.01505
+v 98.5692 -61.4304 6.01505
+v 97.1064 61.4304 17.9559
+v 97.1064 -61.4304 17.9559
+v 50.3209 61.4304 84.9698
+v 95.0616 61.4304 26.7462
+v 82.6566 61.4304 54.0366
+v 77.3781 61.4304 61.3571
+v 95.0616 -61.4304 26.7462
+v 82.6566 -61.4304 54.0366
+v 77.3781 -61.4304 61.3571
+v 50.3209 -61.4304 84.9698
+v -7.37979 61.4304 98.4764
+v -7.37979 -61.4304 98.4764
+v 4.64915 61.4304 98.643
+v 4.64915 -61.4304 98.643
+v 25.4269 61.4304 95.4229
+v 7.65257 61.4304 98.4556
+v 25.4269 -61.4304 95.4229
+v 7.65257 -61.4304 98.4556
+v -25.1624 61.4304 95.493
+v -25.1624 -61.4304 95.493
+v 84.2646 61.4304 51.493
+v 79.2117 61.4304 58.9709
+v 69.3433 61.4304 70.3105
+v 64.9319 61.4304 74.4037
+v 84.2646 -61.4304 51.493
+v 79.2117 -61.4304 58.9709
+v 69.3433 -61.4304 70.3105
+v 64.9319 -61.4304 74.4037
+v 98.0198 61.4304 12.0077
+v 98.0198 -61.4304 12.0077
+v 88.6138 61.4304 43.5851
+v 42.3535 61.4304 89.209
+v 88.6138 -61.4304 43.5851
+v 42.3535 -61.4304 89.209
+v -4.37585 61.4304 98.6555
+v -4.37585 -61.4304 98.6555
+v -10.3769 61.4304 98.2058
+v -10.3769 -61.4304 98.2058
+v 89.9007 61.4304 40.8649
+v 52.8865 61.4304 83.3971
+v 22.5076 61.4304 96.1534
+v 89.9007 -61.4304 40.8649
+v 52.8865 -61.4304 83.3971
+v 22.5076 -61.4304 96.1534
+v 36.8411 61.4304 91.6231
+v 36.8411 -61.4304 91.6231
+v -1.36786 61.4304 98.7431
+v -1.36786 -61.4304 98.7431
+v 98.7525 61.4304 0
+v 91.104 61.4304 38.1067
+v 85.7945 61.4304 48.9017
+v 67.1688 61.4304 72.3907
+v 60.2794 61.4304 78.2206
+v 98.7525 -61.4304 0
+v 91.104 -61.4304 38.1067
+v 85.7945 -61.4304 48.9017
+v 67.1688 -61.4304 72.3907
+v 60.2794 -61.4304 78.2206
+v 13.6353 61.4304 97.8067
+v 13.6353 -61.4304 97.8067
+v 97.6084 61.4304 14.9888
+v 97.6084 -61.4304 14.9888
+v 80.9717 61.4304 56.53
+v 57.8681 61.4304 80.0209
+v 80.9717 -61.4304 56.53
+v 57.8681 -61.4304 80.0209
+v -13.3643 61.4304 97.8441
+v -13.3643 -61.4304 97.8441
+v 94.2025 61.4304 29.6302
+v 94.2025 -61.4304 29.6302
+v 39.6157 61.4304 90.4581
+v 39.6157 -61.4304 90.4581
+v -16.3393 61.4304 97.3914
+v -16.3393 -61.4304 97.3914
+v 10.6489 61.4304 98.1767
+v 10.6489 -61.4304 98.1767
+v -28.0604 61.4304 94.682
+v -28.0604 -61.4304 94.682
+v -33.7754 61.4304 92.797
+v 47.7086 61.4304 86.4636
+v 47.7086 -61.4304 86.4636
+v -33.7754 -61.4304 92.797
+v 98.3401 61.4304 9.01558
+v 98.3401 -61.4304 9.01558
+v 95.8324 61.4304 23.8373
+v 95.8324 -61.4304 23.8373
+v -22.2411 61.4304 96.2154
+v -22.2411 -61.4304 96.2154
+v 45.052 61.4304 87.8771
+v 45.052 -61.4304 87.8771
+v 1.64141 61.4304 98.7389
+v 1.64141 -61.4304 98.7389
+v 19.5674 61.4304 96.7945
+v 19.5674 -61.4304 96.7945
+v 73.4972 61.4304 65.9563
+v 73.4972 -61.4304 65.9563
+v 96.5142 61.4304 20.9063
+v 96.5142 -61.4304 20.9063
+v -30.9322 61.4304 93.7831
+v -30.9322 -61.4304 93.7831
+v -19.2992 61.4304 96.8484
+v -19.2992 -61.4304 96.8484
+v 62.6347 61.4304 76.3476
+v 62.6347 -61.4304 76.3476
+v 98.7067 61.4304 3.00892
+v 98.7067 -61.4304 3.00892
+v 14.0814 63.9871 101.006
+v 14.0814 -63.9871 101.006
+v 101.226 63.9871 12.4005
+v 101.226 -63.9871 12.4005
+v -16.8738 63.9871 100.577
+v -16.8738 -63.9871 100.577
+v -31.944 63.9871 96.8508
+v -31.944 -63.9871 96.8508
+v 83.6204 63.9871 58.3792
+v 83.6204 -63.9871 58.3792
+v 101.936 63.9871 3.10735
+v 101.936 -63.9871 3.10735
+v 32.2122 63.9871 96.7619
+v 32.2122 -63.9871 96.7619
+v 57.2153 63.9871 84.421
+v 57.2153 -63.9871 84.421
+v 23.2439 63.9871 99.2987
+v 23.2439 -63.9871 99.2987
+v 87.021 63.9871 53.1774
+v -25.9855 63.9871 98.6167
+v 87.021 -63.9871 53.1774
+v -25.9855 -63.9871 98.6167
+v 96.3065 63.9871 33.5494
+v 96.3065 -63.9871 33.5494
+v 49.2692 63.9871 89.2919
+v 73.7907 63.9871 70.3948
+v 49.2692 -63.9871 89.2919
+v 73.7907 -63.9871 70.3948
+v 26.2586 63.9871 98.5443
+v 26.2586 -63.9871 98.5443
+v 38.0462 63.9871 94.6202
+v 38.0462 -63.9871 94.6202
+v 98.1712 63.9871 27.6211
+v 85.3604 63.9871 55.8042
+v 62.2512 63.9871 80.7793
+v 43.7389 63.9871 92.1271
+v 98.1712 -63.9871 27.6211
+v 85.3604 -63.9871 55.8042
+v 62.2512 -63.9871 80.7793
+v 43.7389 -63.9871 92.1271
+v 97.284 63.9871 30.5995
+v 97.284 -63.9871 30.5995
+v 94.0842 63.9871 39.3532
+v 90.0985 63.9871 47.7782
+v 77.9415 63.9871 65.7695
+v 75.9014 63.9871 68.1138
+v 69.366 63.9871 74.7587
+v 67.0559 63.9871 76.8375
+v 54.6165 63.9871 86.1251
+v 94.0842 -63.9871 39.3532
+v 90.0985 -63.9871 47.7782
+v 77.9415 -63.9871 65.7695
+v 75.9014 -63.9871 68.1138
+v 69.366 -63.9871 74.7587
+v 67.0559 -63.9871 76.8375
+v 54.6165 -63.9871 86.1251
+v 101.794 63.9871 6.2118
+v 101.794 -63.9871 6.2118
+v 95.2395 63.9871 36.4683
+v 95.2395 -63.9871 36.4683
+v 99.6713 63.9871 21.5902
+v 29.249 63.9871 97.6985
+v 99.6713 -63.9871 21.5902
+v 29.249 -63.9871 97.6985
+v 20.2075 63.9871 99.9608
+v 20.2075 -63.9871 99.9608
+v 88.6009 63.9871 50.5013
+v 35.1455 63.9871 95.7355
+v 88.6009 -63.9871 50.5013
+v 35.1455 -63.9871 95.7355
+v -34.8802 63.9871 95.8325
+v 40.9116 63.9871 93.4171
+v -34.8802 -63.9871 95.8325
+v 40.9116 -63.9871 93.4171
+v 81.8028 63.9871 60.8999
+v 71.6116 63.9871 72.6105
+v 64.6836 63.9871 78.845
+v 81.8028 -63.9871 60.8999
+v 71.6116 -63.9871 72.6105
+v 64.6836 -63.9871 78.845
+v 100.801 63.9871 15.4791
+v 100.801 -63.9871 15.4791
+v -28.9782 63.9871 97.7792
+v -28.9782 -63.9871 97.7792
+v 91.5125 63.9871 45.0108
+v 91.5125 -63.9871 45.0108
+v 46.5257 63.9871 90.7517
+v 46.5257 -63.9871 90.7517
+v 79.9093 63.9871 63.3641
+v 79.9093 -63.9871 63.3641
+v -7.62119 63.9871 101.698
+v -7.62119 -63.9871 101.698
+v 51.967 63.9871 87.7493
+v 59.761 63.9871 82.6385
+v 59.761 -63.9871 82.6385
+v 51.967 -63.9871 87.7493
+v 92.8414 63.9871 42.2016
+v 17.1524 63.9871 100.53
+v 92.8414 -63.9871 42.2016
+v 17.1524 -63.9871 100.53
+v -4.51899 63.9871 101.883
+v -4.51899 -63.9871 101.883
+v 10.9972 63.9871 101.388
+v 10.9972 -63.9871 101.388
+v 98.9672 63.9871 24.6171
+v 98.9672 -63.9871 24.6171
+v -22.9687 63.9871 99.3627
+v -22.9687 -63.9871 99.3627
+v 7.9029 63.9871 101.676
+v 7.9029 -63.9871 101.676
+v -19.9305 63.9871 100.016
+v -19.9305 -63.9871 100.016
+v 4.80123 63.9871 101.87
+v 4.80123 -63.9871 101.87
+v -1.4126 63.9871 101.973
+v -1.4126 -63.9871 101.973
+v 101.557 63.9871 9.3105
+v 101.557 -63.9871 9.3105
+v 1.6951 63.9871 101.969
+v 1.6951 -63.9871 101.969
+v -10.7163 63.9871 101.418
+v -10.7163 -63.9871 101.418
+v 100.283 63.9871 18.5432
+v 100.283 -63.9871 18.5432
+v -13.8015 63.9871 101.045
+v -13.8015 -63.9871 101.045
+v 101.983 63.9871 0
+v 101.983 -63.9871 0
+v 70 9.79717e-15 -100
+v -117.911 9.79717e-15 31.5765
+v 70.1061 -4.1183 -100
+v 70.1061 4.1183 -100
+v -117.947 -4.1183 31.6761
+v -117.947 4.1183 31.6761
+v 70.424 -8.22568 -100
+v 70.424 8.22568 -100
+v -118.056 -8.22568 31.9749
+v -118.056 8.22568 31.9749
+v 70.953 -12.3112 -100
+v 70.953 12.3112 -100
+v -118.237 -12.3112 32.472
+v -118.237 12.3112 32.472
+v -118.489 -16.3642 33.166
+v -118.489 16.3642 33.166
+v 71.6915 -16.3642 -100
+v 71.6915 16.3642 -100
+v 11.3593 66.3742 104.726
+v 11.3593 -66.3742 104.726
+v 102.953 66.3742 22.301
+v 102.953 -66.3742 22.301
+v 8.16309 66.3742 105.024
+v 8.16309 -66.3742 105.024
+v 104.12 66.3742 15.9887
+v 104.12 -66.3742 15.9887
+v 24.0091 66.3742 102.568
+v 24.0091 -66.3742 102.568
+v 102.226 66.3742 25.4275
+v 102.226 -66.3742 25.4275
+v 100.487 66.3742 31.6069
+v 100.487 -66.3742 31.6069
+v -4.66778 66.3742 105.237
+v -4.66778 -66.3742 105.237
+v 103.585 66.3742 19.1537
+v 103.585 -66.3742 19.1537
+v -26.8411 66.3742 101.864
+v -26.8411 -66.3742 101.864
+v 101.403 66.3742 28.5305
+v 101.403 -66.3742 28.5305
+v 14.545 66.3742 104.331
+v 14.545 -66.3742 104.331
+v -11.0691 66.3742 104.757
+v -11.0691 -66.3742 104.757
+v 105.145 66.3742 6.41632
+v 105.145 -66.3742 6.41632
+v -14.2559 66.3742 104.371
+v -14.2559 -66.3742 104.371
+v 71.6497 66.3742 77.22
+v 71.6497 -66.3742 77.22
+v -29.9323 66.3742 100.998
+v -29.9323 -66.3742 100.998
+v 17.7171 66.3742 103.84
+v 17.7171 -66.3742 103.84
+v 50.8913 66.3742 92.2317
+v 50.8913 -66.3742 92.2317
+v 53.6779 66.3742 90.6383
+v 93.0649 66.3742 49.3513
+v 45.179 66.3742 95.1603
+v 93.0649 -66.3742 49.3513
+v 53.6779 -66.3742 90.6383
+v 45.179 -66.3742 95.1603
+v 33.2728 66.3742 99.9477
+v 33.2728 -66.3742 99.9477
+v 105.34 66.3742 0
+v 48.0575 66.3742 93.7395
+v 80.5076 66.3742 67.9349
+v 78.4003 66.3742 70.3563
+v 73.9693 66.3742 75.0011
+v 36.3027 66.3742 98.8875
+v 105.34 -66.3742 0
+v 48.0575 -66.3742 93.7395
+v 80.5076 -66.3742 67.9349
+v 78.4003 -66.3742 70.3563
+v 73.9693 -66.3742 75.0011
+v 36.3027 -66.3742 98.8875
+v -36.0286 66.3742 98.9877
+v 95.8981 66.3742 43.591
+v 42.2585 66.3742 96.4927
+v -36.0286 -66.3742 98.9877
+v 95.8981 -66.3742 43.591
+v 42.2585 -66.3742 96.4927
+v 99.4772 66.3742 34.654
+v 88.1707 66.3742 57.6415
+v 99.4772 -66.3742 34.654
+v 88.1707 -66.3742 57.6415
+v 39.2988 66.3742 97.7355
+v 39.2988 -66.3742 97.7355
+v 91.518 66.3742 52.164
+v 86.3735 66.3742 60.3013
+v 66.8132 66.3742 81.4409
+v 91.518 -66.3742 52.164
+v 86.3735 -66.3742 60.3013
+v 66.8132 -66.3742 81.4409
+v -32.9958 66.3742 100.039
+v -32.9958 -66.3742 100.039
+v 56.4147 66.3742 88.9607
+v 56.4147 -66.3742 88.9607
+v 4.9593 66.3742 105.224
+v 4.9593 -66.3742 105.224
+v 104.901 66.3742 9.61703
+v 104.901 -66.3742 9.61703
+v 69.2636 66.3742 79.3673
+v 64.3007 66.3742 83.4388
+v 59.0991 66.3742 87.2005
+v 69.2636 -66.3742 79.3673
+v 64.3007 -66.3742 83.4388
+v 59.0991 -66.3742 87.2005
+v -1.45911 66.3742 105.33
+v -1.45911 -66.3742 105.33
+v 89.8861 66.3742 54.9282
+v 84.4961 66.3742 62.905
+v 89.8861 -66.3742 54.9282
+v 84.4961 -66.3742 62.905
+v 30.212 66.3742 100.915
+v 30.212 -66.3742 100.915
+v 82.5402 66.3742 65.4503
+v 76.2202 66.3742 72.7125
+v 82.5402 -66.3742 65.4503
+v 76.2202 -66.3742 72.7125
+v 94.5254 66.3742 46.4927
+v 94.5254 -66.3742 46.4927
+v 105.292 66.3742 3.20965
+v 105.292 -66.3742 3.20965
+v 61.7286 66.3742 85.3593
+v 61.7286 -66.3742 85.3593
+v 98.3752 66.3742 37.6689
+v 98.3752 -66.3742 37.6689
+v 97.1818 66.3742 40.6488
+v 97.1818 -66.3742 40.6488
+v -20.5867 66.3742 103.309
+v -20.5867 -66.3742 103.309
+v -17.4294 66.3742 103.889
+v -17.4294 -66.3742 103.889
+v 27.1232 66.3742 101.789
+v 27.1232 -66.3742 101.789
+v 104.559 66.3742 12.8088
+v 104.559 -66.3742 12.8088
+v -23.7249 66.3742 102.634
+v -23.7249 -66.3742 102.634
+v 20.8728 66.3742 103.252
+v 20.8728 -66.3742 103.252
+v 1.75091 66.3742 105.326
+v 1.75091 -66.3742 105.326
+v -7.87211 66.3742 105.046
+v -7.87211 -66.3742 105.046
+v -118.813 -20.3737 34.0552
+v -118.813 20.3737 34.0552
+v 72.6378 -20.3737 -100
+v 72.6378 20.3737 -100
+v -119.207 -24.3292 35.1371
+v -119.207 24.3292 35.1371
+v 73.7892 -24.3292 -100
+v 73.7892 24.3292 -100
+v 75.1426 -28.2202 -100
+v 75.1426 28.2202 -100
+v -119.67 -28.2202 36.409
+v -119.67 28.2202 36.409
+v 103.803 68.5852 32.6499
+v 103.803 -68.5852 32.6499
+v 1.80869 68.5852 108.801
+v 1.80869 -68.5852 108.801
+v -11.4344 68.5852 108.214
+v -11.4344 -68.5852 108.214
+v -34.0846 68.5852 103.341
+v -34.0846 -68.5852 103.341
+v -18.0045 68.5852 107.317
+v -18.0045 -68.5852 107.317
+v 108.009 68.5852 13.2315
+v 108.009 -68.5852 13.2315
+v 107.556 68.5852 16.5163
+v 107.556 -68.5852 16.5163
+v 37.5006 68.5852 102.151
+v 37.5006 -68.5852 102.151
+v -1.50726 68.5852 108.806
+v -1.50726 -68.5852 108.806
+v -21.266 68.5852 106.718
+v -21.266 -68.5852 106.718
+v 31.209 68.5852 104.245
+v 31.209 -68.5852 104.245
+v -37.2175 68.5852 102.254
+v -37.2175 -68.5852 102.254
+v 102.76 68.5852 35.7975
+v 102.76 -68.5852 35.7975
+v -24.5078 68.5852 106.021
+v -24.5078 -68.5852 106.021
+v 24.8014 68.5852 105.952
+v 24.8014 -68.5852 105.952
+v 105.599 68.5852 26.2666
+v 105.599 -68.5852 26.2666
+v 108.615 68.5852 6.62805
+v 108.615 -68.5852 6.62805
+v 34.3707 68.5852 103.246
+v 34.3707 -68.5852 103.246
+v 106.35 68.5852 23.0369
+v 106.35 -68.5852 23.0369
+v 21.5616 68.5852 106.659
+v 21.5616 -68.5852 106.659
+v 5.12295 68.5852 108.696
+v 5.12295 -68.5852 108.696
+v 63.7655 68.5852 88.176
+v 63.7655 -68.5852 88.176
+v -14.7263 68.5852 107.815
+v -14.7263 -68.5852 107.815
+v 99.0626 68.5852 45.0295
+v 89.2237 68.5852 62.2911
+v 71.5492 68.5852 81.9863
+v 99.0626 -68.5852 45.0295
+v 89.2237 -68.5852 62.2911
+v 71.5492 -68.5852 81.9863
+v -8.13187 68.5852 108.512
+v -8.13187 -68.5852 108.512
+v 85.2638 68.5852 67.6101
+v 78.7353 68.5852 75.1119
+v 66.4226 68.5852 86.1922
+v 85.2638 -68.5852 67.6101
+v 78.7353 -68.5852 75.1119
+v 66.4226 -68.5852 86.1922
+v 55.4492 68.5852 93.6292
+v 55.4492 -68.5852 93.6292
+v 97.6446 68.5852 48.0269
+v 69.0179 68.5852 84.1283
+v 61.0492 68.5852 90.0779
+v 97.6446 -68.5852 48.0269
+v 69.0179 -68.5852 84.1283
+v 61.0492 -68.5852 90.0779
+v 49.6433 68.5852 96.8328
+v 49.6433 -68.5852 96.8328
+v -30.92 68.5852 104.331
+v -30.92 -68.5852 104.331
+v 96.1359 68.5852 50.9798
+v 87.2843 68.5852 64.9808
+v 83.1642 68.5852 70.1766
+v 96.1359 -68.5852 50.9798
+v 87.2843 -68.5852 64.9808
+v 83.1642 -68.5852 70.1766
+v 101.621 68.5852 38.9119
+v 101.621 -68.5852 38.9119
+v 94.5379 68.5852 53.8853
+v 91.0802 68.5852 59.5436
+v 94.5379 -68.5852 53.8853
+v 91.0802 -68.5852 59.5436
+v 46.6698 68.5852 98.3004
+v 46.6698 -68.5852 98.3004
+v 100.389 68.5852 41.9902
+v 100.389 -68.5852 41.9902
+v 15.0249 68.5852 107.774
+v 15.0249 -68.5852 107.774
+v 43.653 68.5852 99.6768
+v 43.653 -68.5852 99.6768
+v 52.5707 68.5852 95.2753
+v 52.5707 -68.5852 95.2753
+v -4.82181 68.5852 108.71
+v -4.82181 -68.5852 108.71
+v 74.0141 68.5852 79.7682
+v 58.2763 68.5852 91.8963
+v 74.0141 -68.5852 79.7682
+v 58.2763 -68.5852 91.8963
+v 80.9874 68.5852 72.678
+v 76.4102 68.5852 77.476
+v 80.9874 -68.5852 72.678
+v 76.4102 -68.5852 77.476
+v 92.8522 68.5852 56.7408
+v 92.8522 -68.5852 56.7408
+v 40.5956 68.5852 100.961
+v 40.5956 -68.5852 100.961
+v 104.749 68.5852 29.4719
+v 104.749 -68.5852 29.4719
+v 108.817 68.5852 0
+v 108.817 -68.5852 0
+v -27.7268 68.5852 105.225
+v -27.7268 -68.5852 105.225
+v 107.003 68.5852 19.7858
+v 107.003 -68.5852 19.7858
+v 11.7341 68.5852 108.182
+v 11.7341 -68.5852 108.182
+v 28.0182 68.5852 105.148
+v 28.0182 -68.5852 105.148
+v 8.43246 68.5852 108.489
+v 8.43246 -68.5852 108.489
+v 18.3018 68.5852 107.267
+v 18.3018 -68.5852 107.267
+v 108.766 68.5852 3.31556
+v 108.766 -68.5852 3.31556
+v 108.362 68.5852 9.93438
+v 108.362 -68.5852 9.93438
+v 76.6946 -32.0363 -100
+v 76.6946 32.0363 -100
+v -120.2 -32.0363 37.8674
+v -120.2 32.0363 37.8674
+v 78.441 -35.7675 -100
+v 78.441 35.7675 -100
+v -120.798 -35.7675 39.5084
+v -120.798 35.7675 39.5084
+v 25.6185 70.6143 109.443
+v 25.6185 -70.6143 109.443
+v 107.223 70.6143 33.7256
+v 107.223 -70.6143 33.7256
+v 109.854 70.6143 23.7959
+v 109.854 -70.6143 23.7959
+v 51.2789 70.6143 100.023
+v 51.2789 -70.6143 100.023
+v 45.0913 70.6143 102.961
+v 45.0913 -70.6143 102.961
+v 15.52 70.6143 111.325
+v 15.52 -70.6143 111.325
+v 48.2075 70.6143 101.539
+v 48.2075 -70.6143 101.539
+v 12.1208 70.6143 111.746
+v 12.1208 -70.6143 111.746
+v 1.86828 70.6143 112.386
+v 1.86828 -70.6143 112.386
+v 5.29174 70.6143 112.277
+v 5.29174 -70.6143 112.277
+v 41.9332 70.6143 104.287
+v 41.9332 -70.6143 104.287
+v 111.568 70.6143 13.6674
+v 111.568 -70.6143 13.6674
+v 104.97 70.6143 40.194
+v 104.97 -70.6143 40.194
+v -18.5977 70.6143 110.853
+v -18.5977 -70.6143 110.853
+v -15.2115 70.6143 111.368
+v -15.2115 -70.6143 111.368
+v -35.2076 70.6143 106.745
+v -35.2076 -70.6143 106.745
+v -28.6403 70.6143 108.692
+v -28.6403 -70.6143 108.692
+v 85.9043 70.6143 72.4888
+v 85.9043 -70.6143 72.4888
+v 22.272 70.6143 110.173
+v 22.272 -70.6143 110.173
+v 90.1601 70.6143 67.1217
+v 88.0731 70.6143 69.8377
+v 73.9066 70.6143 84.6876
+v 65.8665 70.6143 91.0812
+v 90.1601 -70.6143 67.1217
+v 88.0731 -70.6143 69.8377
+v 73.9066 -70.6143 84.6876
+v 65.8665 -70.6143 91.0812
+v 103.696 70.6143 43.3737
+v 103.696 -70.6143 43.3737
+v 57.2762 70.6143 96.7141
+v 81.3295 70.6143 77.5866
+v 78.9277 70.6143 80.0287
+v 81.3295 -70.6143 77.5866
+v 78.9277 -70.6143 80.0287
+v 57.2762 -70.6143 96.7141
+v 32.2372 70.6143 107.68
+v 32.2372 -70.6143 107.68
+v 97.6528 70.6143 55.6607
+v 76.4527 70.6143 82.3964
+v 63.0607 70.6143 93.0458
+v 97.6528 -70.6143 55.6607
+v 76.4527 -70.6143 82.3964
+v 63.0607 -70.6143 93.0458
+v -31.9388 70.6143 107.769
+v -31.9388 -70.6143 107.769
+v 94.0811 70.6143 61.5054
+v 94.0811 -70.6143 61.5054
+v -38.4437 70.6143 105.623
+v 92.1634 70.6143 64.3435
+v 83.6558 70.6143 75.0726
+v 71.2919 70.6143 86.9002
+v 68.6111 70.6143 89.032
+v -38.4437 -70.6143 105.623
+v 92.1634 -70.6143 64.3435
+v 83.6558 -70.6143 75.0726
+v 71.2919 -70.6143 86.9002
+v 68.6111 -70.6143 89.032
+v -25.3153 70.6143 109.514
+v -25.3153 -70.6143 109.514
+v 99.3034 70.6143 52.6595
+v 95.9115 70.6143 58.6103
+v 99.3034 -70.6143 52.6595
+v 95.9115 -70.6143 58.6103
+v 54.3027 70.6143 98.4144
+v 54.3027 -70.6143 98.4144
+v 60.1964 70.6143 94.924
+v 38.7362 70.6143 105.516
+v 60.1964 -70.6143 94.924
+v 38.7362 -70.6143 105.516
+v 109.078 70.6143 27.132
+v 109.078 -70.6143 27.132
+v -21.9667 70.6143 110.234
+v -21.9667 -70.6143 110.234
+v 111.1 70.6143 17.0605
+v 111.1 -70.6143 17.0605
+v 110.528 70.6143 20.4377
+v 110.528 -70.6143 20.4377
+v 102.326 70.6143 46.5131
+v 102.326 -70.6143 46.5131
+v -11.8111 70.6143 111.78
+v -11.8111 -70.6143 111.78
+v -1.55692 70.6143 112.391
+v -1.55692 -70.6143 112.391
+v 112.35 70.6143 3.4248
+v 112.35 -70.6143 3.4248
+v 18.9048 70.6143 110.801
+v 18.9048 -70.6143 110.801
+v 35.5032 70.6143 106.648
+v 35.5032 -70.6143 106.648
+v 100.862 70.6143 49.6093
+v 100.862 -70.6143 49.6093
+v 106.146 70.6143 36.977
+v 106.146 -70.6143 36.977
+v -8.3998 70.6143 112.088
+v -8.3998 -70.6143 112.088
+v -4.98067 70.6143 112.291
+v -4.98067 -70.6143 112.291
+v 111.933 70.6143 10.2617
+v 111.933 -70.6143 10.2617
+v 112.193 70.6143 6.84643
+v 112.193 -70.6143 6.84643
+v 112.402 70.6143 0
+v 108.201 70.6143 30.443
+v 112.402 -70.6143 0
+v 108.201 -70.6143 30.443
+v 8.71029 70.6143 112.064
+v 8.71029 -70.6143 112.064
+v 28.9413 70.6143 108.612
+v 28.9413 -70.6143 108.612
+v 80.3772 -39.4039 -100
+v 80.3772 39.4039 -100
+v -121.46 -39.4039 41.3278
+v -121.46 39.4039 41.3278
+v -122.185 -42.9357 43.3207
+v -122.185 42.9357 43.3207
+v 82.498 -42.9357 -100
+v 82.498 42.9357 -100
+v -8.67518 72.4562 115.762
+v -8.67518 -72.4562 115.762
+v 116.087 72.4562 0
+v 109.625 72.4562 38.1892
+v 116.087 -72.4562 0
+v 109.625 -72.4562 38.1892
+v 108.411 72.4562 41.5117
+v 108.411 -72.4562 41.5117
+v 110.738 72.4562 34.8313
+v 26.4584 72.4562 113.031
+v 110.738 -72.4562 34.8313
+v 26.4584 -72.4562 113.031
+v 114.152 72.4562 21.1077
+v 114.152 -72.4562 21.1077
+v 12.5181 72.4562 115.41
+v 12.5181 -72.4562 115.41
+v 40.0061 72.4562 108.976
+v 40.0061 -72.4562 108.976
+v 16.0288 72.4562 114.975
+v 16.0288 -72.4562 114.975
+v 23.0022 72.4562 113.785
+v 23.0022 -72.4562 113.785
+v 102.559 72.4562 54.3859
+v 102.559 -72.4562 54.3859
+v 5.46523 72.4562 115.958
+v 5.46523 -72.4562 115.958
+v -22.6868 72.4562 113.848
+v -22.6868 -72.4562 113.848
+v -5.14396 72.4562 115.973
+v -5.14396 -72.4562 115.973
+v -19.2074 72.4562 114.487
+v -19.2074 -72.4562 114.487
+v -1.60796 72.4562 116.076
+v -1.60796 -72.4562 116.076
+v 112.654 72.4562 28.0215
+v 112.654 -72.4562 28.0215
+v 100.854 72.4562 57.4855
+v 100.854 -72.4562 57.4855
+v 46.5695 72.4562 106.336
+v 46.5695 -72.4562 106.336
+v 1.92953 72.4562 116.071
+v 1.92953 -72.4562 116.071
+v 52.9601 72.4562 103.302
+v 52.9601 -72.4562 103.302
+v 111.748 72.4562 31.441
+v 111.748 -72.4562 31.441
+v -26.1452 72.4562 113.104
+v -26.1452 -72.4562 113.104
+v 113.456 72.4562 24.576
+v 113.456 -72.4562 24.576
+v 104.168 72.4562 51.2357
+v 104.168 -72.4562 51.2357
+v 88.7206 72.4562 74.8653
+v 88.7206 -72.4562 74.8653
+v 99.0558 72.4562 60.5318
+v 99.0558 -72.4562 60.5318
+v 115.871 72.4562 7.07088
+v 115.871 -72.4562 7.07088
+v 36.6671 72.4562 110.144
+v 36.6671 -72.4562 110.144
+v 93.116 72.4562 69.3223
+v 90.9605 72.4562 72.1273
+v 78.9591 72.4562 85.0977
+v 76.3296 72.4562 87.464
+v 93.116 -72.4562 69.3223
+v 90.9605 -72.4562 72.1273
+v 78.9591 -72.4562 85.0977
+v 76.3296 -72.4562 87.464
+v 81.5153 72.4562 82.6523
+v 65.1281 72.4562 96.0963
+v 81.5153 -72.4562 82.6523
+v 65.1281 -72.4562 96.0963
+v -15.7102 72.4562 115.019
+v -15.7102 -72.4562 115.019
+v 49.7879 72.4562 104.868
+v 49.7879 -72.4562 104.868
+v 86.3983 72.4562 77.5338
+v 83.9958 72.4562 80.1303
+v 70.8604 72.4562 91.9509
+v 86.3983 -72.4562 77.5338
+v 83.9958 -72.4562 80.1303
+v 70.8604 -72.4562 91.9509
+v 29.8901 72.4562 112.173
+v 29.8901 -72.4562 112.173
+v 97.1655 72.4562 63.5218
+v 62.1699 72.4562 98.036
+v 97.1655 -72.4562 63.5218
+v 62.1699 -72.4562 98.036
+v 95.1849 72.4562 66.4529
+v 73.6292 72.4562 89.7491
+v 95.1849 -72.4562 66.4529
+v 73.6292 -72.4562 89.7491
+v 56.083 72.4562 101.641
+v 59.1539 72.4562 99.8848
+v 56.083 -72.4562 101.641
+v 59.1539 -72.4562 99.8848
+v 68.0258 72.4562 94.0672
+v 68.0258 -72.4562 94.0672
+v -32.9859 72.4562 111.302
+v -32.9859 -72.4562 111.302
+v 43.3079 72.4562 107.706
+v 33.2941 72.4562 111.21
+v 43.3079 -72.4562 107.706
+v 33.2941 -72.4562 111.21
+v 114.742 72.4562 17.6198
+v 114.742 -72.4562 17.6198
+v 107.096 72.4562 44.7957
+v 107.096 -72.4562 44.7957
+v -12.1983 72.4562 115.444
+v -12.1983 -72.4562 115.444
+v 105.681 72.4562 48.038
+v -29.5793 72.4562 112.255
+v 105.681 -72.4562 48.038
+v -29.5793 -72.4562 112.255
+v 8.99585 72.4562 115.738
+v 8.99585 -72.4562 115.738
+v 115.226 72.4562 14.1155
+v 115.226 -72.4562 14.1155
+v 19.5245 72.4562 114.433
+v 19.5245 -72.4562 114.433
+v 115.602 72.4562 10.5981
+v 115.602 -72.4562 10.5981
+v -39.704 72.4562 109.086
+v -36.3618 72.4562 110.245
+v -36.3618 -72.4562 110.245
+v -39.704 -72.4562 109.086
+v 116.033 72.4562 3.53708
+v 116.033 -72.4562 3.53708
+v 84.7977 -46.3537 -100
+v 84.7977 46.3537 -100
+v -122.972 -46.3537 45.4818
+v -122.972 46.3537 45.4818
+v 115.382 74.1059 32.4634
+v 115.382 -74.1059 32.4634
+v 9.28838 74.1059 119.501
+v 9.28838 -74.1059 119.501
+v -26.9954 74.1059 116.782
+v -26.9954 -74.1059 116.782
+v 12.9252 74.1059 119.163
+v 12.9252 -74.1059 119.163
+v 30.8621 74.1059 115.82
+v 30.8621 -74.1059 115.82
+v 117.864 74.1059 21.7941
+v 117.864 -74.1059 21.7941
+v -5.31123 74.1059 119.744
+v -5.31123 -74.1059 119.744
+v 114.339 74.1059 35.964
+v 114.339 -74.1059 35.964
+v 100.325 74.1059 65.5874
+v 100.325 -74.1059 65.5874
+v 110.578 74.1059 46.2523
+v 110.578 -74.1059 46.2523
+v 119.806 74.1059 3.6521
+v 119.806 -74.1059 3.6521
+v 34.3767 74.1059 114.826
+v 34.3767 -74.1059 114.826
+v 119.361 74.1059 10.9427
+v 119.361 -74.1059 10.9427
+v -34.0585 74.1059 114.921
+v -34.0585 -74.1059 114.921
+v -40.9951 74.1059 112.633
+v -40.9951 -74.1059 112.633
+v 119.639 74.1059 7.30081
+v 119.639 -74.1059 7.30081
+v 20.1594 74.1059 118.154
+v 20.1594 -74.1059 118.154
+v -37.5443 74.1059 113.83
+v 51.4069 74.1059 108.278
+v -37.5443 -74.1059 113.83
+v 51.4069 -74.1059 108.278
+v 116.317 74.1059 28.9327
+v 116.317 -74.1059 28.9327
+v 109.118 74.1059 49.6001
+v 109.118 -74.1059 49.6001
+v 41.307 74.1059 112.519
+v 41.307 -74.1059 112.519
+v 1.99227 74.1059 119.845
+v 1.99227 -74.1059 119.845
+v 54.6822 74.1059 106.662
+v 54.6822 -74.1059 106.662
+v 70.2379 74.1059 97.1261
+v 27.3188 74.1059 116.707
+v 70.2379 -74.1059 97.1261
+v 27.3188 -74.1059 116.707
+v 23.7502 74.1059 117.485
+v 23.7502 -74.1059 117.485
+v -19.832 74.1059 118.21
+v -19.832 -74.1059 118.21
+v -8.95728 74.1059 119.527
+v -8.95728 -74.1059 119.527
+v 104.134 74.1059 59.3548
+v 84.166 74.1059 85.34
+v 104.134 -74.1059 59.3548
+v 84.166 -74.1059 85.34
+v 76.0235 74.1059 92.6676
+v 76.0235 -74.1059 92.6676
+v 93.9184 74.1059 74.4727
+v 91.6056 74.1059 77.2997
+v 73.1646 74.1059 94.9409
+v 93.9184 -74.1059 74.4727
+v 91.6056 -74.1059 77.2997
+v 73.1646 -74.1059 94.9409
+v 81.5267 74.1059 87.8649
+v 81.5267 -74.1059 87.8649
+v 96.1439 74.1059 71.5765
+v 89.2078 74.1059 80.055
+v -12.595 74.1059 119.198
+v 96.1439 -74.1059 71.5765
+v 89.2078 -74.1059 80.055
+v -12.595 -74.1059 119.198
+v 16.55 74.1059 118.714
+v 16.55 -74.1059 118.714
+v 86.7272 74.1059 82.7359
+v 78.8117 74.1059 90.3082
+v 67.2459 74.1059 99.2211
+v 86.7272 -74.1059 82.7359
+v 78.8117 -74.1059 90.3082
+v 67.2459 -74.1059 99.2211
+v 98.2802 74.1059 68.6138
+v 98.2802 -74.1059 68.6138
+v -30.5411 74.1059 115.906
+v -30.5411 -74.1059 115.906
+v 64.1915 74.1059 101.224
+v 64.1915 -74.1059 101.224
+v -16.2211 74.1059 118.759
+v -16.2211 -74.1059 118.759
+v 44.7162 74.1059 111.208
+v 44.7162 -74.1059 111.208
+v 118.972 74.1059 14.5745
+v 118.972 -74.1059 14.5745
+v 48.0839 74.1059 109.794
+v 48.0839 -74.1059 109.794
+v 107.556 74.1059 52.9018
+v 107.556 -74.1059 52.9018
+v 117.145 74.1059 25.3752
+v 117.145 -74.1059 25.3752
+v 118.473 74.1059 18.1928
+v 118.473 -74.1059 18.1928
+v 37.8595 74.1059 113.726
+v 37.8595 -74.1059 113.726
+v 119.862 74.1059 0
+v 119.862 -74.1059 0
+v 5.64295 74.1059 119.729
+v 5.64295 -74.1059 119.729
+v 61.0775 74.1059 103.133
+v 61.0775 -74.1059 103.133
+v 111.936 74.1059 42.8616
+v 111.936 -74.1059 42.8616
+v -1.66025 74.1059 119.85
+v -1.66025 -74.1059 119.85
+v 57.9067 74.1059 104.946
+v 102.277 74.1059 62.5001
+v 57.9067 -74.1059 104.946
+v 102.277 -74.1059 62.5001
+v 105.894 74.1059 56.1544
+v 105.894 -74.1059 56.1544
+v 113.19 74.1059 39.4311
+v 113.19 -74.1059 39.4311
+v -23.4246 74.1059 117.551
+v -23.4246 -74.1059 117.551
+v -123.817 -49.6488 47.8054
+v -123.817 49.6488 47.8054
+v 87.2704 -49.6488 -100
+v 87.2704 49.6488 -100
+v -124.72 -52.8122 50.2852
+v -124.72 52.8122 50.2852
+v 89.9094 -52.8122 -100
+v 89.9094 52.8122 -100
+v -1.71364 75.5591 123.705
+v -1.71364 -75.5591 123.705
+v 122.283 75.5591 18.7778
+v 122.283 -75.5591 18.7778
+v -27.8636 75.5591 120.538
+v -27.8636 -75.5591 120.538
+v 111.015 75.5591 54.6031
+v 111.015 -75.5591 54.6031
+v 20.8078 75.5591 121.954
+v 20.8078 -75.5591 121.954
+v 116.83 75.5591 40.6992
+v 69.4086 75.5591 102.412
+v 116.83 -75.5591 40.6992
+v 69.4086 -75.5591 102.412
+v 49.6303 75.5591 113.325
+v 49.6303 -75.5591 113.325
+v 5.82443 75.5591 123.579
+v 5.82443 -75.5591 123.579
+v 120.912 75.5591 26.1913
+v 120.912 -75.5591 26.1913
+v 121.654 75.5591 22.495
+v 121.654 -75.5591 22.495
+v 46.1543 75.5591 114.785
+v 46.1543 -75.5591 114.785
+v 56.4408 75.5591 110.092
+v 107.483 75.5591 61.2637
+v 56.4408 -75.5591 110.092
+v 107.483 -75.5591 61.2637
+v 2.05634 75.5591 123.7
+v 2.05634 -75.5591 123.7
+v 122.799 75.5591 15.0432
+v 122.799 -75.5591 15.0432
+v 53.0602 75.5591 111.76
+v 53.0602 -75.5591 111.76
+v 112.627 75.5591 51.1953
+v 66.2559 75.5591 104.479
+v 112.627 -75.5591 51.1953
+v 66.2559 -75.5591 104.479
+v -20.4698 75.5591 122.011
+v -20.4698 -75.5591 122.011
+v 42.6355 75.5591 116.138
+v 42.6355 -75.5591 116.138
+v 24.514 75.5591 121.264
+v 24.514 -75.5591 121.264
+v 17.0823 75.5591 122.532
+v 17.0823 -75.5591 122.532
+v 35.4823 75.5591 118.519
+v 35.4823 -75.5591 118.519
+v 123.717 75.5591 0
+v 123.717 -75.5591 0
+v 115.536 75.5591 44.2401
+v 115.536 -75.5591 44.2401
+v 119.093 75.5591 33.5075
+v 114.135 75.5591 47.7398
+v 119.093 -75.5591 33.5075
+v 114.135 -75.5591 47.7398
+v 31.8547 75.5591 119.545
+v 31.8547 -75.5591 119.545
+v 13.3409 75.5591 122.995
+v 13.3409 -75.5591 122.995
+v 101.441 75.5591 70.8205
+v 101.441 -75.5591 70.8205
+v 84.1487 75.5591 90.6907
+v 81.3463 75.5591 93.2125
+v 84.1487 -75.5591 90.6907
+v 81.3463 -75.5591 93.2125
+v 59.7691 75.5591 108.321
+v 99.236 75.5591 73.8784
+v 94.5518 75.5591 79.7858
+v 89.5164 75.5591 85.3968
+v 86.8729 75.5591 88.0846
+v 59.7691 -75.5591 108.321
+v 99.236 -75.5591 73.8784
+v 94.5518 -75.5591 79.7858
+v 89.5164 -75.5591 85.3968
+v 86.8729 -75.5591 88.0846
+v 123.487 75.5591 7.53561
+v 123.487 -75.5591 7.53561
+v 78.4684 75.5591 95.6478
+v 75.5177 75.5591 97.9943
+v 78.4684 -75.5591 95.6478
+v 75.5177 -75.5591 97.9943
+v -31.5233 75.5591 119.633
+v -31.5233 -75.5591 119.633
+v -13.0001 75.5591 123.032
+v -13.0001 -75.5591 123.032
+v 96.9389 75.5591 76.8678
+v 92.0768 75.5591 82.6296
+v 96.9389 -75.5591 76.8678
+v 92.0768 -75.5591 82.6296
+v -5.48205 75.5591 123.595
+v -5.48205 -75.5591 123.595
+v 9.5871 75.5591 123.345
+v 9.5871 -75.5591 123.345
+v -42.3136 75.5591 116.256
+v -42.3136 -75.5591 116.256
+v 28.1974 75.5591 120.46
+v 28.1974 -75.5591 120.46
+v 63.0418 75.5591 106.45
+v 63.0418 -75.5591 106.45
+v 109.3 75.5591 57.9604
+v 109.3 -75.5591 57.9604
+v -38.7517 75.5591 117.491
+v -9.24535 75.5591 123.371
+v -38.7517 -75.5591 117.491
+v -9.24535 -75.5591 123.371
+v 103.552 75.5591 67.6968
+v 103.552 -75.5591 67.6968
+v 120.058 75.5591 29.8632
+v 120.058 -75.5591 29.8632
+v -16.7427 75.5591 122.578
+v -16.7427 -75.5591 122.578
+v 118.016 75.5591 37.1206
+v 118.016 -75.5591 37.1206
+v 105.566 75.5591 64.5102
+v 105.566 -75.5591 64.5102
+v 123.659 75.5591 3.76956
+v 123.659 -75.5591 3.76956
+v -24.1779 75.5591 121.331
+v -24.1779 -75.5591 121.331
+v 39.077 75.5591 117.383
+v 39.077 -75.5591 117.383
+v 123.2 75.5591 11.2947
+v 123.2 -75.5591 11.2947
+v 72.4968 75.5591 100.25
+v 72.4968 -75.5591 100.25
+v -35.1539 75.5591 118.617
+v -35.1539 -75.5591 118.617
+v -125.677 -55.8355 52.9148
+v -125.677 55.8355 52.9148
+v 92.7078 -55.8355 -100
+v 92.7078 55.8355 -100
+v 51.2047 76.812 116.92
+v 51.2047 -76.812 116.92
+v 25.2916 76.812 125.11
+v 25.2916 -76.812 125.11
+v -43.6558 76.812 119.943
+v 43.988 76.812 119.822
+v -43.6558 -76.812 119.943
+v 43.988 -76.812 119.822
+v 125.513 76.812 23.2086
+v 125.513 -76.812 23.2086
+v 29.0919 76.812 124.282
+v 29.0919 -76.812 124.282
+v 120.537 76.812 41.9903
+v 120.537 -76.812 41.9903
+v -9.53864 76.812 127.284
+v -9.53864 -76.812 127.284
+v 126.694 76.812 15.5204
+v 126.694 -76.812 15.5204
+v -24.9449 76.812 125.18
+v -36.269 76.812 122.38
+v -24.9449 -76.812 125.18
+v -36.269 -76.812 122.38
+v 47.6184 76.812 118.426
+v 47.6184 -76.812 118.426
+v 108.915 76.812 66.5566
+v 108.915 -76.812 66.5566
+v 9.89122 76.812 127.257
+v 9.89122 -76.812 127.257
+v 104.659 76.812 73.067
+v 104.659 -76.812 73.067
+v 106.837 76.812 69.8443
+v 32.8652 76.812 123.338
+v 106.837 -76.812 69.8443
+v 32.8652 -76.812 123.338
+v 2.12158 76.812 127.623
+v 2.12158 -76.812 127.623
+v 102.384 76.812 76.222
+v 102.384 -76.812 76.222
+v 6.00919 76.812 127.5
+v 6.00919 -76.812 127.5
+v 124.748 76.812 27.0221
+v 124.748 -76.812 27.0221
+v -39.981 76.812 121.218
+v -39.981 -76.812 121.218
+v 126.162 76.812 19.3735
+v 126.162 -76.812 19.3735
+v 68.3577 76.812 107.794
+v 68.3577 -76.812 107.794
+v 127.108 76.812 11.653
+v 127.108 -76.812 11.653
+v 89.6286 76.812 90.8789
+v 89.6286 -76.812 90.8789
+v -1.76801 76.812 127.629
+v -1.76801 -76.812 127.629
+v -13.4125 76.812 126.935
+v -13.4125 -76.812 126.935
+v 97.5511 76.812 82.3167
+v 97.5511 -76.812 82.3167
+v 86.818 76.812 93.5676
+v -32.5233 76.812 123.428
+v 86.818 -76.812 93.5676
+v -32.5233 -76.812 123.428
+v -17.2738 76.812 126.467
+v -17.2738 -76.812 126.467
+v 94.9977 76.812 85.2508
+v 92.3561 76.812 88.1057
+v 80.9576 76.812 98.682
+v 94.9977 -76.812 85.2508
+v 92.3561 -76.812 88.1057
+v 80.9576 -76.812 98.682
+v 83.9268 76.812 96.1694
+v 83.9268 -76.812 96.1694
+v 40.3167 76.812 121.107
+v 40.3167 -76.812 121.107
+v 110.892 76.812 63.2071
+v 110.892 -76.812 63.2071
+v 54.7434 76.812 115.306
+v 54.7434 -76.812 115.306
+v 74.7965 76.812 103.43
+v 74.7965 -76.812 103.43
+v 127.582 76.812 3.88913
+v 127.582 -76.812 3.88913
+v 117.755 76.812 49.2542
+v 117.755 -76.812 49.2542
+v 65.0416 76.812 109.826
+v 36.6079 76.812 122.279
+v 65.0416 -76.812 109.826
+v 36.6079 -76.812 122.279
+v 121.76 76.812 38.2981
+v 121.76 -76.812 38.2981
+v 112.767 76.812 59.799
+v 112.767 -76.812 59.799
+v -5.65595 76.812 127.516
+v -5.65595 -76.812 127.516
+v 116.2 76.812 52.8193
+v 71.6104 76.812 105.661
+v 116.2 -76.812 52.8193
+v 71.6104 -76.812 105.661
+v 100.014 76.812 79.3062
+v 21.4678 76.812 125.823
+v 100.014 -76.812 79.3062
+v 21.4678 -76.812 125.823
+v 122.87 76.812 34.5704
+v 77.9133 76.812 101.103
+v 122.87 -76.812 34.5704
+v 77.9133 -76.812 101.103
+v 58.2313 76.812 113.584
+v 58.2313 -76.812 113.584
+v -21.1192 76.812 125.882
+v -21.1192 -76.812 125.882
+v 13.7641 76.812 126.897
+v 13.7641 -76.812 126.897
+v 61.6651 76.812 111.757
+v 61.6651 -76.812 111.757
+v 114.536 76.812 56.3353
+v 114.536 -76.812 56.3353
+v 17.6241 76.812 126.419
+v 17.6241 -76.812 126.419
+v 119.201 76.812 45.6434
+v 119.201 -76.812 45.6434
+v 123.867 76.812 30.8106
+v 123.867 -76.812 30.8106
+v 127.404 76.812 7.77466
+v 127.404 -76.812 7.77466
+v -28.7475 76.812 124.362
+v -28.7475 -76.812 124.362
+v 127.641 76.812 0
+v 127.641 -76.812 0
+v 95.6581 -58.7108 -100
+v 95.6581 58.7108 -100
+v -126.686 -58.7108 55.6872
+v -126.686 58.7108 55.6872
+v -37.401 77.8612 126.199
+v -37.401 -77.8612 126.199
+v 49.1047 77.8612 122.122
+v 49.1047 -77.8612 122.122
+v -25.7235 77.8612 129.087
+v -25.7235 -77.8612 129.087
+v 107.925 77.8612 75.3476
+v 107.925 -77.8612 75.3476
+v -29.6447 77.8612 128.243
+v -29.6447 -77.8612 128.243
+v 33.8909 77.8612 127.187
+v 18.1742 77.8612 130.364
+v 33.8909 -77.8612 127.187
+v 18.1742 -77.8612 130.364
+v 83.4844 77.8612 101.762
+v -33.5384 77.8612 127.28
+v 83.4844 -77.8612 101.762
+v -33.5384 -77.8612 127.28
+v -9.83635 77.8612 131.257
+v -9.83635 -77.8612 131.257
+v 45.3609 77.8612 123.562
+v 45.3609 -77.8612 123.562
+v 6.19674 77.8612 131.479
+v 6.19674 -77.8612 131.479
+v -45.0184 77.8612 123.687
+v -45.0184 -77.8612 123.687
+v 63.5897 77.8612 115.245
+v 63.5897 -77.8612 115.245
+v 124.299 77.8612 43.3008
+v 124.299 -77.8612 43.3008
+v 110.171 77.8612 72.0242
+v 110.171 -77.8612 72.0242
+v 29.9999 77.8612 128.161
+v 29.9999 -77.8612 128.161
+v 56.452 77.8612 118.905
+v 56.452 -77.8612 118.905
+v 103.135 77.8612 81.7814
+v 86.5462 77.8612 99.171
+v 103.135 -77.8612 81.7814
+v 86.5462 -77.8612 99.171
+v 92.4261 77.8612 93.7153
+v 80.345 77.8612 104.258
+v 92.4261 -77.8612 93.7153
+v 80.345 -77.8612 104.258
+v 130.648 77.8612 16.0049
+v 130.648 -77.8612 16.0049
+v 119.826 77.8612 54.4678
+v 97.9627 77.8612 87.9116
+v 119.826 -77.8612 54.4678
+v 97.9627 -77.8612 87.9116
+v 131.075 77.8612 12.0167
+v 131.075 -77.8612 12.0167
+v 100.596 77.8612 84.8859
+v 100.596 -77.8612 84.8859
+v 126.705 77.8612 35.6494
+v 126.705 -77.8612 35.6494
+v 2.18779 77.8612 131.607
+v 2.18779 -77.8612 131.607
+v 67.0716 77.8612 113.254
+v 95.2386 77.8612 90.8556
+v 89.5277 77.8612 96.4879
+v 95.2386 -77.8612 90.8556
+v 89.5277 -77.8612 96.4879
+v 67.0716 -77.8612 113.254
+v -5.83248 77.8612 131.496
+v -5.83248 -77.8612 131.496
+v 112.314 77.8612 68.6339
+v 70.4912 77.8612 111.158
+v 112.314 -77.8612 68.6339
+v 70.4912 -77.8612 111.158
+v -17.813 77.8612 130.414
+v -17.813 -77.8612 130.414
+v 131.381 77.8612 8.01731
+v 131.381 -77.8612 8.01731
+v 26.081 77.8612 129.015
+v 26.081 -77.8612 129.015
+v 130.1 77.8612 19.9782
+v 130.1 -77.8612 19.9782
+v 131.625 77.8612 0
+v 131.625 -77.8612 0
+v -13.8311 77.8612 130.896
+v -13.8311 -77.8612 130.896
+v 114.354 77.8612 65.1799
+v 114.354 -77.8612 65.1799
+v 41.575 77.8612 124.887
+v 41.575 -77.8612 124.887
+v 118.111 77.8612 58.0936
+v -21.7783 77.8612 129.811
+v 118.111 -77.8612 58.0936
+v -21.7783 -77.8612 129.811
+v -41.2288 77.8612 125.001
+v -41.2288 -77.8612 125.001
+v 127.733 77.8612 31.7722
+v 127.733 -77.8612 31.7722
+v 129.431 77.8612 23.933
+v 129.431 -77.8612 23.933
+v 10.1999 77.8612 131.229
+v 10.1999 -77.8612 131.229
+v 121.43 77.8612 50.7915
+v 116.286 77.8612 61.6654
+v 121.43 -77.8612 50.7915
+v 116.286 -77.8612 61.6654
+v 122.922 77.8612 47.068
+v 122.922 -77.8612 47.068
+v 77.131 77.8612 106.658
+v 77.131 -77.8612 106.658
+v 131.564 77.8612 4.01052
+v 131.564 -77.8612 4.01052
+v 73.8454 77.8612 108.959
+v 52.8028 77.8612 120.57
+v 73.8454 -77.8612 108.959
+v 52.8028 -77.8612 120.57
+v 14.1937 77.8612 130.857
+v 14.1937 -77.8612 130.857
+v 60.0487 77.8612 117.129
+v 125.56 77.8612 39.4934
+v 60.0487 -77.8612 117.129
+v 125.56 -77.8612 39.4934
+v 105.579 77.8612 78.601
+v 105.579 -77.8612 78.601
+v -1.82319 77.8612 131.612
+v -1.82319 -77.8612 131.612
+v 37.7505 77.8612 126.095
+v 37.7505 -77.8612 126.095
+v 22.1379 77.8612 129.75
+v 22.1379 -77.8612 129.75
+v 128.642 77.8612 27.8655
+v 128.642 -77.8612 27.8655
+v -127.745 -61.4304 58.595
+v -127.745 61.4304 58.595
+v 98.7525 -61.4304 -100
+v 98.7525 61.4304 -100
+v 101.983 -63.9871 -100
+v 101.983 63.9871 -100
+v -128.85 -63.9871 61.6305
+v -128.85 63.9871 61.6305
+v 134.651 78.7038 16.4952
+v 134.651 -78.7038 16.4952
+v -26.5116 78.7038 133.042
+v -26.5116 -78.7038 133.042
+v -18.3587 78.7038 134.41
+v -18.3587 -78.7038 134.41
+v 135.658 78.7038 0
+v 135.658 -78.7038 0
+v 106.295 78.7038 84.2869
+v 106.295 -78.7038 84.2869
+v 115.755 78.7038 70.7366
+v 100.964 78.7038 90.6049
+v 115.755 -78.7038 70.7366
+v 100.964 -78.7038 90.6049
+v 130.587 78.7038 36.7416
+v 130.587 -78.7038 36.7416
+v 30.919 78.7038 132.087
+v 30.919 -78.7038 132.087
+v 69.1265 78.7038 116.724
+v 82.8065 78.7038 107.452
+v 82.8065 -78.7038 107.452
+v 69.1265 -78.7038 116.724
+v 34.9292 78.7038 131.084
+v 34.9292 -78.7038 131.084
+v 128.107 78.7038 44.6274
+v 128.107 -78.7038 44.6274
+v 134.086 78.7038 20.5903
+v 134.086 -78.7038 20.5903
+v -1.87904 78.7038 135.645
+v -1.87904 -78.7038 135.645
+v 103.678 78.7038 87.4865
+v 103.678 -78.7038 87.4865
+v -14.2548 78.7038 134.906
+v -14.2548 -78.7038 134.906
+v 111.232 78.7038 77.656
+v 111.232 -78.7038 77.656
+v 6.38659 78.7038 135.507
+v 6.38659 -78.7038 135.507
+v 61.8884 78.7038 120.718
+v 121.73 78.7038 59.8734
+v 61.8884 -78.7038 120.718
+v 121.73 -78.7038 59.8734
+v 54.4206 78.7038 124.263
+v 54.4206 -78.7038 124.263
+v 135.091 78.7038 12.3848
+v 135.091 -78.7038 12.3848
+v -10.1377 78.7038 135.278
+v -10.1377 -78.7038 135.278
+v 98.1564 78.7038 93.6391
+v 98.1564 -78.7038 93.6391
+v 129.407 78.7038 40.7034
+v 129.407 -78.7038 40.7034
+v 133.396 78.7038 24.6662
+v 133.396 -78.7038 24.6662
+v 14.6285 78.7038 134.867
+v 14.6285 -78.7038 134.867
+v 10.5124 78.7038 135.25
+v 10.5124 -78.7038 135.25
+v -42.492 78.7038 128.831
+v 72.6509 78.7038 114.564
+v -42.492 -78.7038 128.831
+v 72.6509 -78.7038 114.564
+v 79.4941 78.7038 109.926
+v 79.4941 -78.7038 109.926
+v 2.25482 78.7038 135.639
+v 2.25482 -78.7038 135.639
+v 119.849 78.7038 63.5546
+v 119.849 -78.7038 63.5546
+v 38.907 78.7038 129.958
+v 38.907 -78.7038 129.958
+v 123.498 78.7038 56.1365
+v 123.498 -78.7038 56.1365
+v 132.583 78.7038 28.7192
+v 132.583 -78.7038 28.7192
+v 113.546 78.7038 74.2308
+v 113.546 -78.7038 74.2308
+v 76.1078 78.7038 112.297
+v 76.1078 -78.7038 112.297
+v 125.151 78.7038 52.3476
+v -34.5659 78.7038 131.18
+v 125.151 -78.7038 52.3476
+v -34.5659 -78.7038 131.18
+v 92.2706 78.7038 99.444
+v 92.2706 -78.7038 99.444
+v -30.5529 78.7038 132.172
+v -30.5529 -78.7038 132.172
+v -38.5468 78.7038 130.066
+v -38.5468 -78.7038 130.066
+v 117.857 78.7038 67.1768
+v 86.0421 78.7038 104.88
+v 117.857 -78.7038 67.1768
+v 86.0421 -78.7038 104.88
+v 131.646 78.7038 32.7456
+v 131.646 -78.7038 32.7456
+v -46.3976 78.7038 127.476
+v 95.2577 78.7038 96.5864
+v -46.3976 -78.7038 127.476
+v 95.2577 -78.7038 96.5864
+v -6.01116 78.7038 135.524
+v -6.01116 -78.7038 135.524
+v 126.688 78.7038 48.51
+v 42.8487 78.7038 128.713
+v 126.688 -78.7038 48.51
+v 42.8487 -78.7038 128.713
+v 65.5379 78.7038 118.776
+v 65.5379 -78.7038 118.776
+v 26.88 78.7038 132.968
+v 26.88 -78.7038 132.968
+v 50.6091 78.7038 125.864
+v 50.6091 -78.7038 125.864
+v 18.731 78.7038 134.358
+v 18.731 -78.7038 134.358
+v 89.1977 78.7038 102.209
+v 89.1977 -78.7038 102.209
+v 58.1815 78.7038 122.548
+v 58.1815 -78.7038 122.548
+v -22.4456 78.7038 133.788
+v -22.4456 -78.7038 133.788
+v 22.8161 78.7038 133.725
+v 22.8161 -78.7038 133.725
+v 108.814 78.7038 81.0091
+v 46.7506 78.7038 127.347
+v 108.814 -78.7038 81.0091
+v 46.7506 -78.7038 127.347
+v 135.406 78.7038 8.26294
+v 135.406 -78.7038 8.26294
+v 135.595 78.7038 4.13339
+v 135.595 -78.7038 4.13339
+v -129.998 -66.3742 64.7857
+v -129.998 66.3742 64.7857
+v 105.34 -66.3742 -100
+v 105.34 66.3742 -100
+v -27.3071 79.3378 137.034
+v -27.3071 -79.3378 137.034
+v 74.8308 79.3378 118.001
+v 74.8308 -79.3378 118.001
+v -23.1191 79.3378 137.802
+v -23.1191 -79.3378 137.802
+v 121.393 79.3378 69.1925
+v 121.393 -79.3378 69.1925
+v 137.399 79.3378 25.4063
+v 137.399 -79.3378 25.4063
+v 119.229 79.3378 72.8592
+v 119.229 -79.3378 72.8592
+v 88.6239 79.3378 108.027
+v 88.6239 -79.3378 108.027
+v 123.445 79.3378 65.4616
+v 123.445 -79.3378 65.4616
+v 138.691 79.3378 16.9902
+v 138.691 -79.3378 16.9902
+v 2.32248 79.3378 139.709
+v 2.32248 -79.3378 139.709
+v 136.561 79.3378 29.581
+v 136.561 -79.3378 29.581
+v 139.728 79.3378 0
+v 139.728 -79.3378 0
+v 106.789 79.3378 90.1117
+v 106.789 -79.3378 90.1117
+v -35.6031 79.3378 135.116
+v -35.6031 -79.3378 135.116
+v 63.7455 79.3378 124.34
+v 63.7455 -79.3378 124.34
+v 135.596 79.3378 33.7282
+v 135.596 -79.3378 33.7282
+v 130.489 79.3378 49.9656
+v 130.489 -79.3378 49.9656
+v -1.93543 79.3378 139.715
+v -1.93543 -79.3378 139.715
+v -10.4419 79.3378 139.337
+v -10.4419 -79.3378 139.337
+v 101.102 79.3378 96.4489
+v 101.102 -79.3378 96.4489
+v 67.5044 79.3378 122.34
+v 116.953 79.3378 76.4582
+v 67.5044 -79.3378 122.34
+v 116.953 -79.3378 76.4582
+v 56.0535 79.3378 127.992
+v 56.0535 -79.3378 127.992
+v 128.906 79.3378 53.9184
+v 127.203 79.3378 57.821
+v 128.906 -79.3378 53.9184
+v 127.203 -79.3378 57.821
+v 78.3915 79.3378 115.666
+v 78.3915 -79.3378 115.666
+v 98.116 79.3378 99.4846
+v 48.1534 79.3378 131.169
+v 98.116 -79.3378 99.4846
+v 48.1534 -79.3378 131.169
+v 139.145 79.3378 12.7564
+v 139.145 -79.3378 12.7564
+v 85.2912 79.3378 110.677
+v 85.2912 -79.3378 110.677
+v 103.993 79.3378 93.3236
+v 103.993 -79.3378 93.3236
+v 71.2007 79.3378 120.227
+v 71.2007 -79.3378 120.227
+v 6.57823 79.3378 139.573
+v 6.57823 -79.3378 139.573
+v -31.4697 79.3378 136.138
+v -31.4697 -79.3378 136.138
+v 40.0745 79.3378 133.858
+v 40.0745 -79.3378 133.858
+v 91.8742 79.3378 105.276
+v 91.8742 -79.3378 105.276
+v -47.7898 79.3378 131.301
+v 52.1277 79.3378 129.641
+v -47.7898 -79.3378 131.301
+v 52.1277 -79.3378 129.641
+v 114.57 79.3378 79.9861
+v -39.7035 79.3378 133.969
+v 114.57 -79.3378 79.9861
+v -39.7035 -79.3378 133.969
+v 44.1344 79.3378 132.575
+v 44.1344 -79.3378 132.575
+v 125.382 79.3378 61.6699
+v 125.382 -79.3378 61.6699
+v -6.19154 79.3378 139.591
+v -6.19154 -79.3378 139.591
+v 139.469 79.3378 8.51088
+v 139.469 -79.3378 8.51088
+v 81.8794 79.3378 113.224
+v 81.8794 -79.3378 113.224
+v 31.8467 79.3378 136.051
+v 31.8467 -79.3378 136.051
+v -18.9096 79.3378 138.443
+v -18.9096 -79.3378 138.443
+v 134.506 79.3378 37.844
+v 134.506 -79.3378 37.844
+v 109.485 79.3378 86.8161
+v 109.485 -79.3378 86.8161
+v 35.9773 79.3378 135.017
+v 35.9773 -79.3378 135.017
+v 112.079 79.3378 83.4399
+v 112.079 -79.3378 83.4399
+v 59.9273 79.3378 126.225
+v 59.9273 -79.3378 126.225
+v 95.0393 79.3378 102.428
+v 95.0393 -79.3378 102.428
+v 19.2931 79.3378 138.39
+v 19.2931 -79.3378 138.39
+v 23.5007 79.3378 137.738
+v 23.5007 -79.3378 137.738
+v 27.6866 79.3378 136.958
+v 27.6866 -79.3378 136.958
+v -14.6826 79.3378 138.955
+v -14.6826 -79.3378 138.955
+v 138.109 79.3378 21.2081
+v 138.109 -79.3378 21.2081
+v 10.8279 79.3378 139.308
+v 10.8279 -79.3378 139.308
+v 15.0675 79.3378 138.913
+v 15.0675 -79.3378 138.913
+v -43.767 79.3378 132.697
+v -43.767 -79.3378 132.697
+v 131.951 79.3378 45.9665
+v 131.951 -79.3378 45.9665
+v 139.663 79.3378 4.25742
+v 139.663 -79.3378 4.25742
+v 133.29 79.3378 41.9248
+v 133.29 -79.3378 41.9248
+v -131.187 -68.5852 68.0521
+v -131.187 68.5852 68.0521
+v 108.817 -68.5852 -100
+v 108.817 68.5852 -100
+v 19.8589 79.7614 142.448
+v 19.8589 -79.7614 142.448
+v 37.0324 79.7614 138.977
+v 37.0324 -79.7614 138.977
+v 107.043 79.7614 96.0605
+v 100.993 79.7614 102.402
+v 107.043 -79.7614 96.0605
+v 100.993 -79.7614 102.402
+v 115.366 79.7614 85.8869
+v 87.7926 79.7614 113.923
+v 115.366 -79.7614 85.8869
+v 87.7926 -79.7614 113.923
+v -32.3926 79.7614 140.131
+v -32.3926 -79.7614 140.131
+v 94.5686 79.7614 108.364
+v 94.5686 -79.7614 108.364
+v 143.225 79.7614 13.1306
+v 143.225 -79.7614 13.1306
+v 127.065 79.7614 67.3814
+v 45.4288 79.7614 136.463
+v 127.065 -79.7614 67.3814
+v 45.4288 -79.7614 136.463
+v 104.067 79.7614 99.2775
+v 104.067 -79.7614 99.2775
+v 120.383 79.7614 78.7004
+v 120.383 -79.7614 78.7004
+v 24.1899 79.7614 141.777
+v 24.1899 -79.7614 141.777
+v 109.921 79.7614 92.7544
+v 109.921 -79.7614 92.7544
+v -15.1132 79.7614 143.03
+v -15.1132 -79.7614 143.03
+v 84.2807 79.7614 116.545
+v 84.2807 -79.7614 116.545
+v 130.934 79.7614 59.5167
+v 130.934 -79.7614 59.5167
+v 143.559 79.7614 8.76048
+v 143.559 -79.7614 8.76048
+v -19.4642 79.7614 142.503
+v -19.4642 -79.7614 142.503
+v 142.16 79.7614 21.8301
+v 142.16 -79.7614 21.8301
+v 49.5656 79.7614 135.015
+v 49.5656 -79.7614 135.015
+v -40.8679 79.7614 137.898
+v -40.8679 -79.7614 137.898
+v -23.7971 79.7614 141.844
+v -23.7971 -79.7614 141.844
+v 69.4841 79.7614 125.928
+v 69.4841 -79.7614 125.928
+v -10.7481 79.7614 143.424
+v -10.7481 -79.7614 143.424
+v 73.2888 79.7614 123.752
+v 129.06 79.7614 63.4785
+v 129.06 -79.7614 63.4785
+v 73.2888 -79.7614 123.752
+v -6.37312 79.7614 143.685
+v -6.37312 -79.7614 143.685
+v 135.821 79.7614 47.3146
+v 135.821 -79.7614 47.3146
+v 15.5093 79.7614 142.987
+v 15.5093 -79.7614 142.987
+v -36.6473 79.7614 139.079
+v -36.6473 -79.7614 139.079
+v 134.316 79.7614 51.431
+v 134.316 -79.7614 51.431
+v 117.929 79.7614 82.3319
+v 77.0254 79.7614 121.462
+v 117.929 -79.7614 82.3319
+v 77.0254 -79.7614 121.462
+v 97.8265 79.7614 105.432
+v 97.8265 -79.7614 105.432
+v 2.39059 79.7614 143.806
+v 2.39059 -79.7614 143.806
+v 61.6848 79.7614 129.926
+v 61.6848 -79.7614 129.926
+v 140.566 79.7614 30.4485
+v 140.566 -79.7614 30.4485
+v 80.6905 79.7614 119.059
+v 80.6905 -79.7614 119.059
+v -49.1914 79.7614 135.152
+v -49.1914 -79.7614 135.152
+v 143.759 79.7614 4.38228
+v 143.759 -79.7614 4.38228
+v 122.725 79.7614 74.9959
+v 122.725 -79.7614 74.9959
+v 6.77115 79.7614 143.667
+v 6.77115 -79.7614 143.667
+v 139.573 79.7614 34.7173
+v 139.573 -79.7614 34.7173
+v 11.1454 79.7614 143.393
+v 11.1454 -79.7614 143.393
+v 137.199 79.7614 43.1543
+v 53.6564 79.7614 133.443
+v 137.199 -79.7614 43.1543
+v 53.6564 -79.7614 133.443
+v 132.686 79.7614 55.4996
+v 132.686 -79.7614 55.4996
+v 124.953 79.7614 71.2217
+v 124.953 -79.7614 71.2217
+v 32.7807 79.7614 140.04
+v 32.7807 -79.7614 140.04
+v 65.6149 79.7614 127.987
+v 65.6149 -79.7614 127.987
+v 91.223 79.7614 111.195
+v 91.223 -79.7614 111.195
+v -1.99219 79.7614 143.812
+v -1.99219 -79.7614 143.812
+v -45.0505 79.7614 136.588
+v -45.0505 -79.7614 136.588
+v 41.2497 79.7614 137.784
+v 41.2497 -79.7614 137.784
+v 141.428 79.7614 26.1514
+v 141.428 -79.7614 26.1514
+v 112.696 79.7614 89.3622
+v 112.696 -79.7614 89.3622
+v 138.45 79.7614 38.9539
+v 138.45 -79.7614 38.9539
+v 57.6974 79.7614 131.746
+v 57.6974 -79.7614 131.746
+v -28.1079 79.7614 141.053
+v -28.1079 -79.7614 141.053
+v 143.826 79.7614 0
+v 143.826 -79.7614 0
+v 142.759 79.7614 17.4884
+v 142.759 -79.7614 17.4884
+v 28.4986 79.7614 140.974
+v 28.4986 -79.7614 140.974
+v -132.413 -70.6143 71.4212
+v -132.413 70.6143 71.4212
+v 112.402 -70.6143 -100
+v 112.402 70.6143 -100
+v -15.5455 79.9735 147.121
+v -15.5455 -79.9735 147.121
+v 20.4269 79.9735 146.523
+v 20.4269 -79.9735 146.523
+v 134.679 79.9735 61.2192
+v 134.679 -79.9735 61.2192
+v -28.9119 79.9735 145.087
+v -28.9119 -79.9735 145.087
+v 90.3039 79.9735 117.181
+v 90.3039 -79.9735 117.181
+v 6.96484 79.9735 147.776
+v 6.96484 -79.9735 147.776
+v 144.587 79.9735 31.3195
+v 144.587 -79.9735 31.3195
+v 2.45898 79.9735 147.92
+v 2.45898 -79.9735 147.92
+v 93.8324 79.9735 114.376
+v 86.6916 79.9735 119.879
+v 93.8324 -79.9735 114.376
+v 86.6916 -79.9735 119.879
+v 118.666 79.9735 88.3437
+v 118.666 -79.9735 88.3437
+v -46.3392 79.9735 140.495
+v 38.0918 79.9735 142.952
+v -46.3392 -79.9735 140.495
+v 38.0918 -79.9735 142.952
+v 136.482 79.9735 57.0872
+v 136.482 -79.9735 57.0872
+v 71.4718 79.9735 129.53
+v 42.4297 79.9735 141.725
+v -42.0369 79.9735 141.842
+v 71.4718 -79.9735 129.53
+v 42.4297 -79.9735 141.725
+v -42.0369 -79.9735 141.842
+v 46.7283 79.9735 140.367
+v 46.7283 -79.9735 140.367
+v 141.124 79.9735 44.3887
+v 141.124 -79.9735 44.3887
+v 97.2738 79.9735 111.463
+v 97.2738 -79.9735 111.463
+v 146.842 79.9735 17.9887
+v 146.842 -79.9735 17.9887
+v 24.8819 79.9735 145.833
+v 24.8819 -79.9735 145.833
+v 128.528 79.9735 73.2591
+v 128.528 -79.9735 73.2591
+v 15.953 79.9735 147.077
+v 15.953 -79.9735 147.077
+v 143.566 79.9735 35.7104
+v 143.566 -79.9735 35.7104
+v 139.706 79.9735 48.6681
+v 139.706 -79.9735 48.6681
+v -37.6956 79.9735 143.057
+v -37.6956 -79.9735 143.057
+v 121.303 79.9735 84.687
+v 82.9987 79.9735 122.464
+v 121.303 -79.9735 84.687
+v 82.9987 -79.9735 122.464
+v -24.4778 79.9735 145.901
+v -24.4778 -79.9735 145.901
+v 11.4642 79.9735 147.495
+v 11.4642 -79.9735 147.495
+v 132.751 79.9735 65.2944
+v 132.751 -79.9735 65.2944
+v 130.7 79.9735 69.3089
+v 130.7 -79.9735 69.3089
+v 59.3479 79.9735 135.514
+v 59.3479 -79.9735 135.514
+v 75.3853 79.9735 127.292
+v 75.3853 -79.9735 127.292
+v 126.236 79.9735 77.1412
+v 63.4493 79.9735 133.643
+v 126.236 -79.9735 77.1412
+v 63.4493 -79.9735 133.643
+v 142.411 79.9735 40.0682
+v 142.411 -79.9735 40.0682
+v -50.5985 79.9735 139.018
+v 100.625 79.9735 108.448
+v -50.5985 -79.9735 139.018
+v 100.625 -79.9735 108.448
+v -11.0556 79.9735 147.527
+v -11.0556 -79.9735 147.527
+v 67.4919 79.9735 131.648
+v 107.044 79.9735 102.117
+v 67.4919 -79.9735 131.648
+v 107.044 -79.9735 102.117
+v 33.7184 79.9735 144.046
+v 33.7184 -79.9735 144.046
+v -20.0209 79.9735 146.579
+v -20.0209 -79.9735 146.579
+v 29.3138 79.9735 145.007
+v 29.3138 -79.9735 145.007
+v 145.474 79.9735 26.8995
+v 145.474 -79.9735 26.8995
+v 50.9835 79.9735 138.878
+v 50.9835 -79.9735 138.878
+v -2.04918 79.9735 147.926
+v -2.04918 -79.9735 147.926
+v 103.882 79.9735 105.331
+v 103.882 -79.9735 105.331
+v 147.665 79.9735 9.01108
+v 147.665 -79.9735 9.01108
+v 115.919 79.9735 91.9184
+v 113.065 79.9735 95.4077
+v 110.105 79.9735 98.8084
+v 115.919 -79.9735 91.9184
+v 113.065 -79.9735 95.4077
+v 110.105 -79.9735 98.8084
+v 147.872 79.9735 4.50763
+v 147.872 -79.9735 4.50763
+v 147.94 79.9735 0
+v 147.94 -79.9735 0
+v 138.158 79.9735 52.9022
+v 55.1913 79.9735 137.26
+v 138.158 -79.9735 52.9022
+v 55.1913 -79.9735 137.26
+v 79.2288 79.9735 124.936
+v 79.2288 -79.9735 124.936
+v 146.226 79.9735 22.4545
+v 146.226 -79.9735 22.4545
+v 123.827 79.9735 80.9517
+v 123.827 -79.9735 80.9517
+v 147.322 79.9735 13.5062
+v 147.322 -79.9735 13.5062
+v -6.55542 79.9735 147.795
+v -6.55542 -79.9735 147.795
+v -33.3192 79.9735 144.139
+v -33.3192 -79.9735 144.139
+v 116.087 -72.4562 -100
+v 116.087 72.4562 -100
+v -133.673 -72.4562 74.8839
+v -133.673 72.4562 74.8839
+v -2.10624 79.9735 152.045
+v -2.10624 -79.9735 152.045
+v -11.3635 79.9735 151.635
+v -11.3635 -79.9735 151.635
+v 85.31 79.9735 125.874
+v 85.31 -79.9735 125.874
+v -20.5784 79.9735 150.661
+v -20.5784 -79.9735 150.661
+v 113.171 79.9735 101.56
+v 110.024 79.9735 104.961
+v 113.171 -79.9735 101.56
+v 110.024 -79.9735 104.961
+v 61.0005 79.9735 139.288
+v 61.0005 -79.9735 139.288
+v 152.06 79.9735 0
+v 152.06 -79.9735 0
+v 138.43 79.9735 62.924
+v 81.435 79.9735 128.415
+v 65.2162 79.9735 137.365
+v 138.43 -79.9735 62.924
+v 81.435 -79.9735 128.415
+v 65.2162 -79.9735 137.365
+v 151.989 79.9735 4.63315
+v 151.989 -79.9735 4.63315
+v 127.275 79.9735 83.206
+v 96.4454 79.9735 117.561
+v 127.275 -79.9735 83.206
+v 96.4454 -79.9735 117.561
+v 73.462 79.9735 133.137
+v 73.462 -79.9735 133.137
+v 150.932 79.9735 18.4896
+v 150.932 -79.9735 18.4896
+v 99.9826 79.9735 114.567
+v 99.9826 -79.9735 114.567
+v 142.005 79.9735 54.3754
+v 142.005 -79.9735 54.3754
+v 2.52745 79.9735 152.039
+v 2.52745 -79.9735 152.039
+v 7.15879 79.9735 151.891
+v 7.15879 -79.9735 151.891
+v 34.6574 79.9735 148.058
+v 34.6574 -79.9735 148.058
+v 140.283 79.9735 58.6769
+v 140.283 -79.9735 58.6769
+v 148.613 79.9735 32.1917
+v 148.613 -79.9735 32.1917
+v 43.6113 79.9735 145.672
+v 43.6113 -79.9735 145.672
+v 151.425 79.9735 13.8823
+v 151.425 -79.9735 13.8823
+v 56.7282 79.9735 141.082
+v 56.7282 -79.9735 141.082
+v 121.971 79.9735 90.8038
+v 121.971 -79.9735 90.8038
+v 124.681 79.9735 87.0453
+v 106.775 79.9735 108.265
+v 124.681 -79.9735 87.0453
+v 106.775 -79.9735 108.265
+v 132.107 79.9735 75.2991
+v 132.107 -79.9735 75.2991
+v -52.0075 79.9735 142.889
+v 136.448 79.9735 67.1126
+v -52.0075 -79.9735 142.889
+v 136.448 -79.9735 67.1126
+v 103.427 79.9735 111.468
+v 103.427 -79.9735 111.468
+v 25.5748 79.9735 149.894
+v 25.5748 -79.9735 149.894
+v 151.777 79.9735 9.26201
+v 151.777 -79.9735 9.26201
+v -15.9784 79.9735 151.218
+v -15.9784 -79.9735 151.218
+v -38.7453 79.9735 147.041
+v -38.7453 -79.9735 147.041
+v 150.298 79.9735 23.0798
+v 150.298 -79.9735 23.0798
+v 77.4845 79.9735 130.837
+v 77.4845 -79.9735 130.837
+v 48.0295 79.9735 144.275
+v 48.0295 -79.9735 144.275
+v 146.376 79.9735 41.184
+v 39.1525 79.9735 146.933
+v 146.376 -79.9735 41.184
+v 39.1525 -79.9735 146.933
+v 89.1057 79.9735 123.217
+v 89.1057 -79.9735 123.217
+v -47.6296 79.9735 144.408
+v -47.6296 -79.9735 144.408
+v 11.7835 79.9735 151.603
+v 11.7835 -79.9735 151.603
+v 92.8186 79.9735 120.445
+v 92.8186 -79.9735 120.445
+v -43.2075 79.9735 145.792
+v -43.2075 -79.9735 145.792
+v 145.054 79.9735 45.6248
+v 145.054 -79.9735 45.6248
+v 149.525 79.9735 27.6486
+v 134.34 79.9735 71.239
+v 149.525 -79.9735 27.6486
+v 134.34 -79.9735 71.239
+v 129.751 79.9735 79.2894
+v 129.751 -79.9735 79.2894
+v -25.1594 79.9735 149.964
+v -25.1594 -79.9735 149.964
+v 119.147 79.9735 94.478
+v 119.147 -79.9735 94.478
+v 52.4032 79.9735 142.745
+v 52.4032 -79.9735 142.745
+v 116.213 79.9735 98.0645
+v 116.213 -79.9735 98.0645
+v -6.73797 79.9735 151.911
+v -6.73797 -79.9735 151.911
+v 147.563 79.9735 36.7048
+v 147.563 -79.9735 36.7048
+v 143.596 79.9735 50.0233
+v 143.596 -79.9735 50.0233
+v 69.3713 79.9735 135.314
+v 69.3713 -79.9735 135.314
+v 20.9958 79.9735 150.603
+v 20.9958 -79.9735 150.603
+v -34.2471 79.9735 148.153
+v -34.2471 -79.9735 148.153
+v 30.1301 79.9735 149.045
+v 30.1301 -79.9735 149.045
+v -29.7171 79.9735 149.128
+v -29.7171 -79.9735 149.128
+v 16.3972 79.9735 151.173
+v 16.3972 -79.9735 151.173
+v -134.964 -74.1059 78.4312
+v -134.964 74.1059 78.4312
+v 119.862 -74.1059 -100
+v 119.862 74.1059 -100
+v 21.5638 79.7614 154.678
+v 21.5638 -79.7614 154.678
+v 142.175 79.7614 64.6265
+v 142.175 -79.7614 64.6265
+v 156.174 79.7614 0
+v 156.174 -79.7614 0
+v -11.6709 79.7614 155.737
+v -11.6709 -79.7614 155.737
+v -30.5211 79.7614 153.163
+v -30.5211 -79.7614 153.163
+v 155.522 79.7614 14.2579
+v 155.522 -79.7614 14.2579
+v -6.92028 79.7614 156.021
+v -6.92028 -79.7614 156.021
+v 128.054 79.7614 89.4005
+v 128.054 -79.7614 89.4005
+v 154.365 79.7614 23.7043
+v 154.365 -79.7614 23.7043
+v 109.664 79.7614 111.194
+v 35.5951 79.7614 152.064
+v 109.664 -79.7614 111.194
+v 35.5951 -79.7614 152.064
+v -16.4107 79.7614 155.309
+v -16.4107 -79.7614 155.309
+v 140.14 79.7614 68.9285
+v 140.14 -79.7614 68.9285
+v 66.9807 79.7614 141.081
+v 66.9807 -79.7614 141.081
+v 156.102 79.7614 4.75851
+v 156.102 -79.7614 4.75851
+v 83.6384 79.7614 131.89
+v 83.6384 -79.7614 131.89
+v 151.556 79.7614 37.6979
+v 151.556 -79.7614 37.6979
+v 150.337 79.7614 42.2982
+v 150.337 -79.7614 42.2982
+v 148.978 79.7614 46.8593
+v 125.271 79.7614 93.2607
+v 148.978 -79.7614 46.8593
+v 125.271 -79.7614 93.2607
+v 155.015 79.7614 18.9899
+v 155.015 -79.7614 18.9899
+v -39.7936 79.7614 151.019
+v -39.7936 -79.7614 151.019
+v 26.2668 79.7614 153.949
+v 26.2668 -79.7614 153.949
+v 12.1023 79.7614 155.704
+v 12.1023 -79.7614 155.704
+v 113.001 79.7614 107.801
+v 99.0549 79.7614 120.741
+v 113.001 -79.7614 107.801
+v 99.0549 -79.7614 120.741
+v 153.571 79.7614 28.3966
+v 153.571 -79.7614 28.3966
+v -44.3766 79.7614 149.737
+v -44.3766 -79.7614 149.737
+v 102.688 79.7614 117.667
+v 102.688 -79.7614 117.667
+v -21.1352 79.7614 154.737
+v -21.1352 -79.7614 154.737
+v 58.2631 79.7614 144.899
+v 30.9453 79.7614 153.077
+v 58.2631 -79.7614 144.899
+v 30.9453 -79.7614 153.077
+v 91.5165 79.7614 126.551
+v 91.5165 -79.7614 126.551
+v 95.33 79.7614 123.703
+v 95.33 -79.7614 123.703
+v 145.848 79.7614 55.8466
+v 62.651 79.7614 143.057
+v 145.848 -79.7614 55.8466
+v 62.651 -79.7614 143.057
+v 44.7912 79.7614 149.613
+v 44.7912 -79.7614 149.613
+v -53.4147 79.7614 146.756
+v 119.358 79.7614 100.718
+v 106.225 79.7614 114.484
+v -53.4147 -79.7614 146.756
+v 119.358 -79.7614 100.718
+v 106.225 -79.7614 114.484
+v 133.262 79.7614 81.4346
+v 133.262 -79.7614 81.4346
+v 40.2118 79.7614 150.908
+v 40.2118 -79.7614 150.908
+v 147.481 79.7614 51.3768
+v 147.481 -79.7614 51.3768
+v 87.6181 79.7614 129.28
+v 87.6181 -79.7614 129.28
+v -25.8402 79.7614 154.021
+v -25.8402 -79.7614 154.021
+v 49.329 79.7614 148.179
+v 49.329 -79.7614 148.179
+v 79.581 79.7614 134.377
+v 71.2483 79.7614 138.975
+v 122.371 79.7614 97.0343
+v 71.2483 -79.7614 138.975
+v 122.371 -79.7614 97.0343
+v 79.581 -79.7614 134.377
+v 152.634 79.7614 33.0626
+v 152.634 -79.7614 33.0626
+v 16.8409 79.7614 155.263
+v 16.8409 -79.7614 155.263
+v 144.078 79.7614 60.2645
+v 144.078 -79.7614 60.2645
+v 135.681 79.7614 77.3364
+v 135.681 -79.7614 77.3364
+v 2.59583 79.7614 156.152
+v 2.59583 -79.7614 156.152
+v 7.35248 79.7614 156.001
+v 7.35248 -79.7614 156.001
+v 155.884 79.7614 9.5126
+v 155.884 -79.7614 9.5126
+v 130.719 79.7614 85.4572
+v 130.719 -79.7614 85.4572
+v -35.1737 79.7614 152.162
+v -35.1737 -79.7614 152.162
+v 75.4497 79.7614 136.74
+v 75.4497 -79.7614 136.74
+v 137.975 79.7614 73.1664
+v 116.233 79.7614 104.308
+v 137.975 -79.7614 73.1664
+v 116.233 -79.7614 104.308
+v -48.9183 79.7614 148.315
+v -48.9183 -79.7614 148.315
+v -2.16322 79.7614 156.159
+v -2.16322 -79.7614 156.159
+v 53.821 79.7614 146.607
+v 53.821 -79.7614 146.607
+v -136.283 -75.5591 82.0536
+v -136.283 75.5591 82.0536
+v 123.717 -75.5591 -100
+v 123.717 75.5591 -100
+v 160.197 79.3378 4.88337
+v 160.197 -79.3378 4.88337
+v 41.2669 79.3378 154.868
+v 41.2669 -79.3378 154.868
+v -7.10186 79.3378 160.114
+v -7.10186 -79.3378 160.114
+v 101.654 79.3378 123.909
+v 101.654 -79.3378 123.909
+v 77.4294 79.3378 140.327
+v 77.4294 -79.3378 140.327
+v 152.887 79.3378 48.0888
+v 152.887 -79.3378 48.0888
+v -21.6898 79.3378 158.797
+v -21.6898 -79.3378 158.797
+v 22.1296 79.3378 158.737
+v 22.1296 -79.3378 158.737
+v 89.9172 79.3378 132.672
+v 89.9172 -79.3378 132.672
+v 159.083 79.3378 19.4882
+v 159.083 -79.3378 19.4882
+v 131.414 79.3378 91.7462
+v 131.414 -79.3378 91.7462
+v 2.66395 79.3378 160.25
+v 2.66395 -79.3378 160.25
+v 125.582 79.3378 99.5804
+v 125.582 -79.3378 99.5804
+v 143.817 79.3378 70.7371
+v 143.817 -79.3378 70.7371
+v -45.541 79.3378 153.665
+v -45.541 -79.3378 153.665
+v 93.9178 79.3378 129.871
+v 93.9178 -79.3378 129.871
+v 64.2949 79.3378 146.81
+v 64.2949 -79.3378 146.81
+v -26.5182 79.3378 158.063
+v -26.5182 -79.3378 158.063
+v 156.639 79.3378 33.9302
+v 156.639 -79.3378 33.9302
+v 50.6234 79.3378 152.067
+v 50.6234 -79.3378 152.067
+v 36.529 79.3378 156.053
+v 36.529 -79.3378 156.053
+v -36.0966 79.3378 156.154
+v -36.0966 -79.3378 156.154
+v 157.6 79.3378 29.1417
+v 157.6 -79.3378 29.1417
+v 12.4199 79.3378 159.79
+v 12.4199 -79.3378 159.79
+v 97.8313 79.3378 126.949
+v 97.8313 -79.3378 126.949
+v 151.351 79.3378 52.7248
+v 147.859 79.3378 61.8458
+v 151.351 -79.3378 52.7248
+v 147.859 -79.3378 61.8458
+v 136.758 79.3378 83.5714
+v 136.758 -79.3378 83.5714
+v -11.9771 79.3378 159.824
+v -11.9771 -79.3378 159.824
+v 73.1177 79.3378 142.621
+v 73.1177 -79.3378 142.621
+v 17.2828 79.3378 159.337
+v 17.2828 -79.3378 159.337
+v 115.966 79.3378 110.63
+v 115.966 -79.3378 110.63
+v 122.49 79.3378 103.36
+v 112.542 79.3378 114.112
+v 122.49 -79.3378 103.36
+v 112.542 -79.3378 114.112
+v 139.241 79.3378 79.3656
+v 139.241 -79.3378 79.3656
+v -54.8162 79.3378 150.606
+v -54.8162 -79.3378 150.606
+v 119.283 79.3378 107.045
+v 119.283 -79.3378 107.045
+v -2.21999 79.3378 160.257
+v -2.21999 -79.3378 160.257
+v 59.7918 79.3378 148.701
+v 59.7918 -79.3378 148.701
+v 158.415 79.3378 24.3262
+v 158.415 -79.3378 24.3262
+v 154.282 79.3378 43.4081
+v 154.282 -79.3378 43.4081
+v 81.6691 79.3378 137.903
+v 128.558 79.3378 95.7077
+v 128.558 -79.3378 95.7077
+v 81.6691 -79.3378 137.903
+v -40.8377 79.3378 154.982
+v -40.8377 -79.3378 154.982
+v 159.974 79.3378 9.7622
+v 159.974 -79.3378 9.7622
+v 145.906 79.3378 66.3222
+v 134.149 79.3378 87.6995
+v 145.906 -79.3378 66.3222
+v 134.149 -79.3378 87.6995
+v -16.8413 79.3378 159.385
+v -16.8413 -79.3378 159.385
+v 155.533 79.3378 38.6871
+v 155.533 -79.3378 38.6871
+v -50.2019 79.3378 152.207
+v -50.2019 -79.3378 152.207
+v 31.7572 79.3378 157.094
+v 31.7572 -79.3378 157.094
+v 160.272 79.3378 0
+v 149.674 79.3378 57.3119
+v 160.272 -79.3378 0
+v 149.674 -79.3378 57.3119
+v 105.382 79.3378 120.755
+v 105.382 -79.3378 120.755
+v 45.9665 79.3378 153.539
+v 45.9665 -79.3378 153.539
+v 7.5454 79.3378 160.094
+v 7.5454 -79.3378 160.094
+v 85.833 79.3378 135.351
+v 85.833 -79.3378 135.351
+v 26.956 79.3378 157.989
+v 26.956 -79.3378 157.989
+v 159.603 79.3378 14.632
+v 159.603 -79.3378 14.632
+v 141.595 79.3378 75.0862
+v 109.013 79.3378 117.488
+v 141.595 -79.3378 75.0862
+v 109.013 -79.3378 117.488
+v 68.7382 79.3378 144.783
+v 68.7382 -79.3378 144.783
+v 55.2332 79.3378 150.454
+v 55.2332 -79.3378 150.454
+v -31.3219 79.3378 157.182
+v -31.3219 -79.3378 157.182
+v -137.625 -76.812 85.7414
+v -137.625 76.812 85.7414
+v 127.641 -76.812 -100
+v 127.641 76.812 -100
+v 160.617 78.7038 34.7919
+v 160.617 -78.7038 34.7919
+v 115.4 78.7038 117.01
+v 115.4 -78.7038 117.01
+v 155.195 78.7038 54.0639
+v 155.195 -78.7038 54.0639
+v 22.6917 78.7038 162.768
+v 22.6917 -78.7038 162.768
+v 158.2 78.7038 44.5106
+v 158.2 -78.7038 44.5106
+v 142.778 78.7038 81.3814
+v 142.778 -78.7038 81.3814
+v -7.28223 78.7038 164.181
+v -7.28223 -78.7038 164.181
+v -17.269 78.7038 163.433
+v -17.269 -78.7038 163.433
+v 7.73704 78.7038 164.16
+v 7.73704 -78.7038 164.16
+v 164.037 78.7038 10.0101
+v 164.037 -78.7038 10.0101
+v -51.4769 78.7038 156.072
+v -51.4769 -78.7038 156.072
+v 74.9748 78.7038 146.244
+v 151.614 78.7038 63.4165
+v 74.9748 -78.7038 146.244
+v 151.614 -78.7038 63.4165
+v -46.6976 78.7038 157.568
+v -46.6976 -78.7038 157.568
+v -12.2813 78.7038 163.883
+v -12.2813 -78.7038 163.883
+v -37.0134 78.7038 160.12
+v -37.0134 -78.7038 160.12
+v 51.9091 78.7038 155.929
+v 51.9091 -78.7038 155.929
+v 65.9278 78.7038 150.539
+v 65.9278 -78.7038 150.539
+v -27.1917 78.7038 162.077
+v -27.1917 -78.7038 162.077
+v 163.123 78.7038 19.9831
+v 163.123 -78.7038 19.9831
+v 100.316 78.7038 130.173
+v 100.316 -78.7038 130.173
+v 140.232 78.7038 85.6939
+v 140.232 -78.7038 85.6939
+v -41.8749 78.7038 158.918
+v -41.8749 -78.7038 158.918
+v 147.47 78.7038 72.5337
+v 111.781 78.7038 120.471
+v 147.47 -78.7038 72.5337
+v 111.781 -78.7038 120.471
+v 162.438 78.7038 24.9441
+v 162.438 -78.7038 24.9441
+v 96.3032 78.7038 133.17
+v 61.3104 78.7038 152.478
+v 96.3032 -78.7038 133.17
+v 61.3104 -78.7038 152.478
+v 88.013 78.7038 138.788
+v 88.013 -78.7038 138.788
+v 153.476 78.7038 58.7675
+v 153.476 -78.7038 58.7675
+v -56.2084 78.7038 154.431
+v 118.912 78.7038 113.439
+v -56.2084 -78.7038 154.431
+v 118.912 -78.7038 113.439
+v 145.191 78.7038 76.9933
+v 145.191 -78.7038 76.9933
+v 134.752 78.7038 94.0764
+v 134.752 -78.7038 94.0764
+v 131.823 78.7038 98.1385
+v 131.823 -78.7038 98.1385
+v 79.3959 78.7038 143.891
+v 159.483 78.7038 39.6697
+v 122.313 78.7038 109.763
+v 108.059 78.7038 123.822
+v 79.3959 -78.7038 143.891
+v 159.483 -78.7038 39.6697
+v 122.313 -78.7038 109.763
+v 108.059 -78.7038 123.822
+v -2.27637 78.7038 164.327
+v -2.27637 -78.7038 164.327
+v 42.315 78.7038 158.801
+v 42.315 -78.7038 158.801
+v 56.6361 78.7038 154.275
+v 56.6361 -78.7038 154.275
+v 128.771 78.7038 102.109
+v 128.771 -78.7038 102.109
+v 149.611 78.7038 68.0067
+v 149.611 -78.7038 68.0067
+v -22.2407 78.7038 162.831
+v -22.2407 -78.7038 162.831
+v 137.556 78.7038 89.9269
+v 137.556 -78.7038 89.9269
+v 12.7353 78.7038 163.848
+v 12.7353 -78.7038 163.848
+v 156.77 78.7038 49.3102
+v 156.77 -78.7038 49.3102
+v 37.4568 78.7038 160.017
+v 37.4568 -78.7038 160.017
+v 92.2009 78.7038 136.042
+v 92.2009 -78.7038 136.042
+v 125.601 78.7038 105.986
+v 125.601 -78.7038 105.986
+v 2.73161 78.7038 164.32
+v 2.73161 -78.7038 164.32
+v 17.7217 78.7038 163.384
+v 17.7217 -78.7038 163.384
+v 161.603 78.7038 29.8819
+v 161.603 -78.7038 29.8819
+v 164.342 78.7038 0
+v 32.5638 78.7038 161.084
+v 164.342 -78.7038 0
+v 32.5638 -78.7038 161.084
+v 27.6406 78.7038 162.001
+v 27.6406 -78.7038 162.001
+v 70.484 78.7038 148.46
+v 70.484 -78.7038 148.46
+v 104.236 78.7038 127.057
+v 104.236 -78.7038 127.057
+v 83.7433 78.7038 141.406
+v 83.7433 -78.7038 141.406
+v 47.1339 78.7038 157.438
+v 47.1339 -78.7038 157.438
+v -32.1174 78.7038 161.174
+v -32.1174 -78.7038 161.174
+v 164.266 78.7038 5.0074
+v 164.266 -78.7038 5.0074
+v 163.656 78.7038 15.0036
+v 163.656 -78.7038 15.0036
+v 131.625 -77.8612 -100
+v 131.625 77.8612 -100
+v -138.988 -77.8612 89.485
+v -138.988 77.8612 89.485
+v 106.793 77.8612 130.174
+v 106.793 -77.8612 130.174
+v 102.777 77.8612 133.368
+v 102.777 -77.8612 133.368
+v -7.46092 77.8612 168.21
+v -7.46092 -77.8612 168.21
+v 168.297 77.8612 5.13027
+v 168.297 -77.8612 5.13027
+v 160.617 77.8612 50.5201
+v 160.617 -77.8612 50.5201
+v 125.314 77.8612 112.457
+v 125.314 -77.8612 112.457
+v 62.8148 77.8612 156.219
+v 62.8148 -77.8612 156.219
+v -22.7864 77.8612 166.826
+v -22.7864 -77.8612 166.826
+v 53.1828 77.8612 159.755
+v 53.1828 -77.8612 159.755
+v 7.92689 77.8612 168.188
+v 7.92689 -77.8612 168.188
+v 81.3441 77.8612 147.422
+v 81.3441 -77.8612 147.422
+v 58.0258 77.8612 158.061
+v 58.0258 -77.8612 158.061
+v 131.931 77.8612 104.615
+v 131.931 -77.8612 104.615
+v 168.375 77.8612 0
+v 90.1726 77.8612 142.194
+v 168.375 -77.8612 0
+v 90.1726 -77.8612 142.194
+v 157.242 77.8612 60.2095
+v 157.242 -77.8612 60.2095
+v 148.754 77.8612 78.8825
+v 148.754 -77.8612 78.8825
+v 114.524 77.8612 123.428
+v 114.524 -77.8612 123.428
+v 164.559 77.8612 35.6456
+v 164.559 -77.8612 35.6456
+v 13.0478 77.8612 167.869
+v 13.0478 -77.8612 167.869
+v 18.1566 77.8612 167.393
+v 18.1566 -77.8612 167.393
+v 128.682 77.8612 108.586
+v 128.682 -77.8612 108.586
+v -12.5827 77.8612 167.904
+v -12.5827 -77.8612 167.904
+v 48.2905 77.8612 161.301
+v 48.2905 -77.8612 161.301
+v 165.568 77.8612 30.6151
+v 165.568 -77.8612 30.6151
+v 135.057 77.8612 100.547
+v 135.057 -77.8612 100.547
+v 163.396 77.8612 40.6431
+v 163.396 -77.8612 40.6431
+v 72.2135 77.8612 152.103
+v 72.2135 -77.8612 152.103
+v 85.7982 77.8612 144.875
+v 94.4633 77.8612 139.38
+v 94.4633 -77.8612 139.38
+v 85.7982 -77.8612 144.875
+v 168.062 77.8612 10.2558
+v 168.062 -77.8612 10.2558
+v 38.3759 77.8612 163.943
+v 38.3759 -77.8612 163.943
+v 43.3533 77.8612 162.698
+v 43.3533 -77.8612 162.698
+v 138.058 77.8612 96.3848
+v 138.058 -77.8612 96.3848
+v -27.8589 77.8612 166.054
+v -27.8589 -77.8612 166.054
+v 76.8145 77.8612 149.832
+v 153.282 77.8612 69.6754
+v 76.8145 -77.8612 149.832
+v 153.282 -77.8612 69.6754
+v 162.082 77.8612 45.6028
+v 162.082 -77.8612 45.6028
+v -37.9216 77.8612 164.049
+v -37.9216 -77.8612 164.049
+v 28.3188 77.8612 165.977
+v 28.3188 -77.8612 165.977
+v 155.334 77.8612 64.9726
+v 146.281 77.8612 83.3783
+v -47.8434 77.8612 161.435
+v 155.334 -77.8612 64.9726
+v 146.281 -77.8612 83.3783
+v -47.8434 -77.8612 161.435
+v 143.673 77.8612 87.7967
+v 143.673 -77.8612 87.7967
+v 23.2485 77.8612 166.762
+v 23.2485 -77.8612 166.762
+v 67.5455 77.8612 154.233
+v 67.5455 -77.8612 154.233
+v 110.71 77.8612 126.86
+v 98.6662 77.8612 136.437
+v 110.71 -77.8612 126.86
+v 98.6662 -77.8612 136.437
+v -57.5877 77.8612 158.221
+v -57.5877 -77.8612 158.221
+v 167.672 77.8612 15.3717
+v 167.672 -77.8612 15.3717
+v -52.74 77.8612 159.902
+v -52.74 -77.8612 159.902
+v -42.9024 77.8612 162.818
+v -42.9024 -77.8612 162.818
+v -17.6928 77.8612 167.443
+v -17.6928 -77.8612 167.443
+v 140.931 77.8612 92.1335
+v 140.931 -77.8612 92.1335
+v -2.33223 77.8612 168.359
+v -2.33223 -77.8612 168.359
+v 159.003 77.8612 55.3905
+v 159.003 -77.8612 55.3905
+v -32.9055 77.8612 165.128
+v -32.9055 -77.8612 165.128
+v 167.126 77.8612 20.4734
+v 167.126 -77.8612 20.4734
+v 2.79863 77.8612 168.352
+v 2.79863 -77.8612 168.352
+v 33.3629 77.8612 165.037
+v 33.3629 -77.8612 165.037
+v 118.232 77.8612 119.881
+v 118.232 -77.8612 119.881
+v 151.088 77.8612 74.3135
+v 151.088 -77.8612 74.3135
+v 166.424 77.8612 25.5562
+v 166.424 -77.8612 25.5562
+v 121.829 77.8612 116.223
+v 121.829 -77.8612 116.223
+v 135.658 -78.7038 -100
+v 135.658 78.7038 -100
+v -140.367 -78.7038 93.2744
+v -140.367 78.7038 93.2744
+v 113.33 76.812 129.861
+v 113.33 -76.812 129.861
+v 149.742 76.812 85.3511
+v 149.742 -76.812 85.3511
+v 159.009 76.812 66.5099
+v 159.009 -76.812 66.5099
+v 144.266 76.812 94.3134
+v 144.266 -76.812 94.3134
+v 23.7986 76.812 170.708
+v 23.7986 -76.812 170.708
+v 8.11444 76.812 172.168
+v 8.11444 -76.812 172.168
+v -18.1114 76.812 171.405
+v -18.1114 -76.812 171.405
+v -58.9502 76.812 161.964
+v -58.9502 -76.812 161.964
+v 167.262 76.812 41.6047
+v 167.262 -76.812 41.6047
+v 168.452 76.812 36.489
+v 168.452 -76.812 36.489
+v 109.32 76.812 133.254
+v 109.32 -76.812 133.254
+v 171.08 76.812 20.9579
+v 171.08 -76.812 20.9579
+v 172.279 76.812 5.25165
+v 172.279 -76.812 5.25165
+v 170.362 76.812 26.1608
+v 170.362 -76.812 26.1608
+v 124.712 76.812 118.973
+v 124.712 -76.812 118.973
+v 160.962 76.812 61.6341
+v 160.962 -76.812 61.6341
+v 2.86485 76.812 172.335
+v 2.86485 -76.812 172.335
+v 147.072 76.812 89.874
+v 147.072 -76.812 89.874
+v 73.9221 76.812 155.702
+v 73.9221 -76.812 155.702
+v 54.4412 76.812 163.535
+v 54.4412 -76.812 163.535
+v -23.3256 76.812 170.773
+v -23.3256 -76.812 170.773
+v 128.279 76.812 115.118
+v 128.279 -76.812 115.118
+v 172.039 76.812 10.4984
+v 172.039 -76.812 10.4984
+v 169.486 76.812 31.3395
+v 169.486 -76.812 31.3395
+v 101.001 76.812 139.665
+v 101.001 -76.812 139.665
+v -28.518 76.812 169.983
+v -28.518 -76.812 169.983
+v 165.917 76.812 46.6818
+v 164.417 76.812 51.7154
+v 165.917 -76.812 46.6818
+v 164.417 -76.812 51.7154
+v 87.8282 76.812 148.303
+v 87.8282 -76.812 148.303
+v -2.38741 76.812 172.342
+v -2.38741 -76.812 172.342
+v 135.053 76.812 107.09
+v 135.053 -76.812 107.09
+v 83.2687 76.812 150.91
+v 83.2687 -76.812 150.91
+v 156.909 76.812 71.3239
+v 156.909 -76.812 71.3239
+v -53.9879 76.812 163.685
+v 59.3987 76.812 161.8
+v -53.9879 -76.812 163.685
+v 59.3987 -76.812 161.8
+v 96.6983 76.812 142.678
+v 96.6983 -76.812 142.678
+v -43.9175 76.812 166.67
+v -43.9175 -76.812 166.67
+v 141.325 76.812 98.6653
+v 141.325 -76.812 98.6653
+v 18.5862 76.812 171.354
+v 18.5862 -76.812 171.354
+v 138.253 76.812 102.926
+v 131.727 76.812 111.156
+v 138.253 -76.812 102.926
+v 131.727 -76.812 111.156
+v 34.1522 76.812 168.941
+v 34.1522 -76.812 168.941
+v 44.3791 76.812 166.548
+v 44.3791 -76.812 166.548
+v 152.273 76.812 80.7489
+v 152.273 -76.812 80.7489
+v -12.8804 76.812 171.877
+v -12.8804 -76.812 171.877
+v 69.1437 76.812 157.882
+v 69.1437 -76.812 157.882
+v 105.209 76.812 136.523
+v 105.209 -76.812 136.523
+v -48.9754 76.812 165.254
+v -48.9754 -76.812 165.254
+v 121.029 76.812 122.717
+v 92.3061 76.812 145.558
+v 121.029 -76.812 122.717
+v 92.3061 -76.812 145.558
+v 78.6319 76.812 153.377
+v 78.6319 -76.812 153.377
+v 49.4331 76.812 165.118
+v 49.4331 -76.812 165.118
+v 117.234 76.812 126.348
+v 117.234 -76.812 126.348
+v -33.6841 76.812 169.035
+v -33.6841 -76.812 169.035
+v 154.663 76.812 76.0717
+v 154.663 -76.812 76.0717
+v 39.2839 76.812 167.822
+v 39.2839 -76.812 167.822
+v 171.639 76.812 15.7354
+v 171.639 -76.812 15.7354
+v 28.9889 76.812 169.904
+v 28.9889 -76.812 169.904
+v -38.8188 76.812 167.931
+v -38.8188 -76.812 167.931
+v 13.3565 76.812 171.841
+v 13.3565 -76.812 171.841
+v 64.301 76.812 159.915
+v 64.301 -76.812 159.915
+v 162.765 76.812 56.7011
+v 162.765 -76.812 56.7011
+v -7.63745 76.812 172.19
+v -7.63745 -76.812 172.19
+v 172.359 76.812 0
+v 172.359 -76.812 0
+v 139.728 -79.3378 -100
+v 139.728 79.3378 -100
+v -141.759 -79.3378 97.0995
+v -141.759 79.3378 97.0995
+v -18.5238 75.5591 175.307
+v -18.5238 -75.5591 175.307
+v 174.975 75.5591 21.4351
+v 174.975 -75.5591 21.4351
+v 55.6808 75.5591 167.259
+v 55.6808 -75.5591 167.259
+v 173.345 75.5591 32.0531
+v 173.345 -75.5591 32.0531
+v 50.5587 75.5591 168.878
+v 50.5587 -75.5591 168.878
+v -7.81135 75.5591 176.11
+v -7.81135 -75.5591 176.11
+v 176.202 75.5591 5.37123
+v 176.202 -75.5591 5.37123
+v 166.471 75.5591 57.9922
+v 166.471 -75.5591 57.9922
+v 2.93008 75.5591 176.259
+v 2.93008 -75.5591 176.259
+v -34.451 75.5591 172.884
+v -34.451 -75.5591 172.884
+v 60.7512 75.5591 165.484
+v 60.7512 -75.5591 165.484
+v 168.161 75.5591 52.893
+v 168.161 -75.5591 52.893
+v 34.9299 75.5591 172.788
+v 34.9299 -75.5591 172.788
+v 141.401 75.5591 105.269
+v 107.605 75.5591 139.632
+v 141.401 -75.5591 105.269
+v 107.605 -75.5591 139.632
+v 171.071 75.5591 42.552
+v 171.071 -75.5591 42.552
+v 162.63 75.5591 68.0243
+v 153.152 75.5591 87.2945
+v 162.63 -75.5591 68.0243
+v 153.152 -75.5591 87.2945
+v 172.288 75.5591 37.3199
+v 172.288 -75.5591 37.3199
+v 80.4224 75.5591 156.87
+v 80.4224 -75.5591 156.87
+v 175.547 75.5591 16.0937
+v 175.547 -75.5591 16.0937
+v 98.9001 75.5591 145.927
+v 98.9001 -75.5591 145.927
+v 8.29921 75.5591 176.088
+v 8.29921 -75.5591 176.088
+v 147.55 75.5591 96.4609
+v 115.91 75.5591 132.818
+v 147.55 -75.5591 96.4609
+v 115.91 -75.5591 132.818
+v 40.1784 75.5591 171.644
+v 40.1784 -75.5591 171.644
+v 150.421 75.5591 91.9204
+v 150.421 -75.5591 91.9204
+v 45.3896 75.5591 170.34
+v 45.3896 -75.5591 170.34
+v -44.9175 75.5591 170.465
+v -44.9175 -75.5591 170.465
+v 89.828 75.5591 151.68
+v 89.828 -75.5591 151.68
+v 155.741 75.5591 82.5875
+v 155.741 -75.5591 82.5875
+v 144.543 75.5591 100.912
+v 75.6053 75.5591 159.247
+v 144.543 -75.5591 100.912
+v 75.6053 -75.5591 159.247
+v 70.7181 75.5591 161.477
+v 70.7181 -75.5591 161.477
+v 13.6606 75.5591 175.753
+v 13.6606 -75.5591 175.753
+v 24.3404 75.5591 174.595
+v 24.3404 -75.5591 174.595
+v 174.241 75.5591 26.7565
+v 174.241 -75.5591 26.7565
+v -60.2925 75.5591 165.652
+v -60.2925 -75.5591 165.652
+v 29.6489 75.5591 173.772
+v 29.6489 -75.5591 173.772
+v 123.785 75.5591 125.511
+v 123.785 -75.5591 125.511
+v 176.283 75.5591 0
+v 158.185 75.5591 77.8039
+v 103.3 75.5591 142.846
+v 176.283 -75.5591 0
+v 158.185 -75.5591 77.8039
+v 103.3 -75.5591 142.846
+v -2.44177 75.5591 176.266
+v -2.44177 -75.5591 176.266
+v 131.2 75.5591 117.739
+v 131.2 -75.5591 117.739
+v 175.956 75.5591 10.7375
+v 175.956 -75.5591 10.7375
+v 164.627 75.5591 63.0375
+v 164.627 -75.5591 63.0375
+v 111.809 75.5591 136.288
+v 94.4079 75.5591 148.872
+v 111.809 -75.5591 136.288
+v 94.4079 -75.5591 148.872
+v 85.1647 75.5591 154.346
+v 85.1647 -75.5591 154.346
+v 19.0094 75.5591 175.255
+v 19.0094 -75.5591 175.255
+v -13.1737 75.5591 175.79
+v -13.1737 -75.5591 175.79
+v 169.695 75.5591 47.7447
+v 169.695 -75.5591 47.7447
+v 160.482 75.5591 72.948
+v 160.482 -75.5591 72.948
+v -29.1674 75.5591 173.854
+v -29.1674 -75.5591 173.854
+v -39.7027 75.5591 171.754
+v -39.7027 -75.5591 171.754
+v 127.552 75.5591 121.682
+v 127.552 -75.5591 121.682
+v -55.2172 75.5591 167.412
+v 65.7651 75.5591 163.557
+v -55.2172 -75.5591 167.412
+v 65.7651 -75.5591 163.557
+v -23.8567 75.5591 174.662
+v -23.8567 -75.5591 174.662
+v -50.0906 75.5591 169.017
+v -50.0906 -75.5591 169.017
+v 134.727 75.5591 113.687
+v 134.727 -75.5591 113.687
+v 119.903 75.5591 129.225
+v 119.903 -75.5591 129.225
+v 138.128 75.5591 109.529
+v 138.128 -75.5591 109.529
+v -143.161 -79.7614 100.95
+v -143.161 79.7614 100.95
+v 143.826 -79.7614 -100
+v 143.826 79.7614 -100
+v 141.148 74.1059 111.924
+v 141.148 -74.1059 111.924
+v 2.99415 74.1059 180.113
+v 2.99415 -74.1059 180.113
+v 150.777 74.1059 98.5702
+v 150.777 -74.1059 98.5702
+v 13.9593 74.1059 179.596
+v 13.9593 -74.1059 179.596
+v -35.2044 74.1059 176.665
+v -35.2044 -74.1059 176.665
+v 56.8983 74.1059 170.916
+v 56.8983 -74.1059 170.916
+v 35.6937 74.1059 176.566
+v 35.6937 -74.1059 176.566
+v 51.6642 74.1059 172.57
+v 51.6642 -74.1059 172.57
+v 82.181 74.1059 160.3
+v 159.146 74.1059 84.3935
+v 82.181 -74.1059 160.3
+v 159.146 -74.1059 84.3935
+v 62.0796 74.1059 169.103
+v 62.0796 -74.1059 169.103
+v 118.445 74.1059 135.723
+v 118.445 -74.1059 135.723
+v 173.405 74.1059 48.7887
+v 173.405 -74.1059 48.7887
+v 156.501 74.1059 89.2034
+v 156.501 -74.1059 89.2034
+v 180.138 74.1059 0
+v 91.7923 74.1059 154.997
+v 180.138 -74.1059 0
+v 91.7923 -74.1059 154.997
+v 19.4251 74.1059 179.088
+v 19.4251 -74.1059 179.088
+v -24.3783 74.1059 178.481
+v -24.3783 -74.1059 178.481
+v 105.559 74.1059 145.969
+v 105.559 -74.1059 145.969
+v 170.112 74.1059 59.2603
+v 170.112 -74.1059 59.2603
+v 168.227 74.1059 64.416
+v 168.227 -74.1059 64.416
+v 30.2973 74.1059 177.572
+v 30.2973 -74.1059 177.572
+v -13.4618 74.1059 179.635
+v -13.4618 -74.1059 179.635
+v 24.8727 74.1059 178.413
+v 24.8727 -74.1059 178.413
+v 177.135 74.1059 32.754
+v 177.135 -74.1059 32.754
+v 87.027 74.1059 157.721
+v 87.027 -74.1059 157.721
+v -56.4246 74.1059 171.073
+v -56.4246 -74.1059 171.073
+v 153.71 74.1059 93.9304
+v 96.4723 74.1059 152.128
+v 153.71 -74.1059 93.9304
+v 96.4723 -74.1059 152.128
+v -45.8997 74.1059 174.192
+v -45.8997 -74.1059 174.192
+v 147.704 74.1059 103.118
+v 147.704 -74.1059 103.118
+v 126.492 74.1059 128.256
+v 109.958 74.1059 142.685
+v 101.063 74.1059 149.118
+v 126.492 -74.1059 128.256
+v 109.958 -74.1059 142.685
+v 101.063 -74.1059 149.118
+v 166.186 74.1059 69.5118
+v 166.186 -74.1059 69.5118
+v 67.2032 74.1059 167.133
+v 67.2032 -74.1059 167.133
+v -51.186 74.1059 172.713
+v -51.186 -74.1059 172.713
+v 114.254 74.1059 139.268
+v 114.254 -74.1059 139.268
+v 130.341 74.1059 124.342
+v 130.341 -74.1059 124.342
+v 77.2586 74.1059 162.73
+v 77.2586 -74.1059 162.73
+v 180.055 74.1059 5.48868
+v 180.055 -74.1059 5.48868
+v 41.057 74.1059 175.397
+v 41.057 -74.1059 175.397
+v -7.98216 74.1059 179.961
+v -7.98216 -74.1059 179.961
+v 134.069 74.1059 120.313
+v 134.069 -74.1059 120.313
+v 176.055 74.1059 38.136
+v 176.055 -74.1059 38.136
+v 178.051 74.1059 27.3416
+v 178.051 -74.1059 27.3416
+v 174.811 74.1059 43.4825
+v 174.811 -74.1059 43.4825
+v 122.525 74.1059 132.051
+v 122.525 -74.1059 132.051
+v 8.48069 74.1059 179.939
+v 8.48069 -74.1059 179.939
+v 46.3821 74.1059 174.065
+v 46.3821 -74.1059 174.065
+v 163.991 74.1059 74.5431
+v 163.991 -74.1059 74.5431
+v -29.8052 74.1059 177.655
+v -29.8052 -74.1059 177.655
+v 178.802 74.1059 21.9038
+v 178.802 -74.1059 21.9038
+v -61.6109 74.1059 169.275
+v -61.6109 -74.1059 169.275
+v -40.5709 74.1059 175.51
+v -40.5709 -74.1059 175.51
+v 171.838 74.1059 54.0496
+v 72.2645 74.1059 165.008
+v 171.838 -74.1059 54.0496
+v 72.2645 -74.1059 165.008
+v 137.673 74.1059 116.173
+v 137.673 -74.1059 116.173
+v 161.644 74.1059 79.5052
+v 161.644 -74.1059 79.5052
+v 144.493 74.1059 107.571
+v 144.493 -74.1059 107.571
+v 179.386 74.1059 16.4457
+v 179.386 -74.1059 16.4457
+v 179.804 74.1059 10.9723
+v 179.804 -74.1059 10.9723
+v -18.9288 74.1059 179.141
+v -18.9288 -74.1059 179.141
+v -2.49516 74.1059 180.121
+v -2.49516 -74.1059 180.121
+v 147.94 -79.9735 -100
+v 147.94 79.9735 -100
+v -144.568 -79.9735 104.816
+v -144.568 79.9735 104.816
+v 183.913 72.4562 0
+v 183.913 -72.4562 0
+v 3.0569 72.4562 183.888
+v 3.0569 -72.4562 183.888
+v 175.439 72.4562 55.1823
+v 162.481 72.4562 86.162
+v 175.439 -72.4562 55.1823
+v 162.481 -72.4562 86.162
+v 133.072 72.4562 126.948
+v 133.072 -72.4562 126.948
+v 171.752 72.4562 65.7658
+v 171.752 -72.4562 65.7658
+v -62.902 72.4562 172.822
+v -62.902 -72.4562 172.822
+v -46.8616 72.4562 177.843
+v -46.8616 -72.4562 177.843
+v 19.8321 72.4562 182.841
+v 19.8321 -72.4562 182.841
+v 173.676 72.4562 60.5022
+v 173.676 -72.4562 60.5022
+v 140.558 72.4562 118.607
+v 129.142 72.4562 130.944
+v 140.558 -72.4562 118.607
+v 129.142 -72.4562 130.944
+v 8.65841 72.4562 183.709
+v 8.65841 -72.4562 183.709
+v 47.3541 72.4562 177.712
+v 47.3541 -72.4562 177.712
+v 180.847 72.4562 33.4404
+v 180.847 -72.4562 33.4404
+v 83.9031 72.4562 163.659
+v 83.9031 -72.4562 163.659
+v 183.145 72.4562 16.7903
+v -24.8892 72.4562 182.221
+v 183.145 -72.4562 16.7903
+v -24.8892 -72.4562 182.221
+v 156.931 72.4562 95.8988
+v 147.521 72.4562 109.825
+v 156.931 -72.4562 95.8988
+v 147.521 -72.4562 109.825
+v -2.54745 72.4562 183.895
+v -2.54745 -72.4562 183.895
+v 159.781 72.4562 91.0727
+v -52.2586 72.4562 176.332
+v 159.781 -72.4562 91.0727
+v -52.2586 -72.4562 176.332
+v 167.428 72.4562 76.1052
+v 167.428 -72.4562 76.1052
+v 73.7788 72.4562 168.466
+v 73.7788 -72.4562 168.466
+v 58.0907 72.4562 174.498
+v 58.0907 -72.4562 174.498
+v 36.4417 72.4562 180.267
+v 36.4417 -72.4562 180.267
+v 165.031 72.4562 81.1713
+v 63.3805 72.4562 172.647
+v 165.031 -72.4562 81.1713
+v 63.3805 -72.4562 172.647
+v 78.8776 72.4562 166.14
+v 78.8776 -72.4562 166.14
+v 14.2519 72.4562 183.36
+v 14.2519 -72.4562 183.36
+v 103.181 72.4562 152.243
+v 103.181 -72.4562 152.243
+v -8.14943 72.4562 183.732
+v -8.14943 -72.4562 183.732
+v -41.4211 72.4562 179.188
+v -41.4211 -72.4562 179.188
+v 182.548 72.4562 22.3628
+v 182.548 -72.4562 22.3628
+v 144.106 72.4562 114.269
+v 144.106 -72.4562 114.269
+v -13.7438 72.4562 183.399
+v -13.7438 -72.4562 183.399
+v 125.093 72.4562 134.818
+v 125.093 -72.4562 134.818
+v 150.799 72.4562 105.28
+v 150.799 -72.4562 105.28
+v 93.7159 72.4562 158.245
+v 120.927 72.4562 138.567
+v 107.771 72.4562 149.028
+v 120.927 -72.4562 138.567
+v 107.771 -72.4562 149.028
+v 93.7159 -72.4562 158.245
+v 68.6115 72.4562 170.636
+v 68.6115 -72.4562 170.636
+v -35.9421 72.4562 180.367
+v -35.9421 -72.4562 180.367
+v 25.3939 72.4562 182.152
+v 25.3939 -72.4562 182.152
+v 178.475 72.4562 44.3937
+v 178.475 -72.4562 44.3937
+v -19.3255 72.4562 182.895
+v -19.3255 -72.4562 182.895
+v 88.8508 72.4562 161.027
+v 88.8508 -72.4562 161.027
+v 98.494 72.4562 155.316
+v 98.494 -72.4562 155.316
+v -30.4298 72.4562 181.378
+v -30.4298 -72.4562 181.378
+v -57.607 72.4562 174.658
+v -57.607 -72.4562 174.658
+v 183.572 72.4562 11.2022
+v 183.572 -72.4562 11.2022
+v 52.7469 72.4562 176.187
+v 52.7469 -72.4562 176.187
+v 30.9322 72.4562 181.293
+v 30.9322 -72.4562 181.293
+v 41.9174 72.4562 179.073
+v 41.9174 -72.4562 179.073
+v 181.782 72.4562 27.9145
+v 181.782 -72.4562 27.9145
+v 153.937 72.4562 100.636
+v 116.649 72.4562 142.187
+v 153.937 -72.4562 100.636
+v 116.649 -72.4562 142.187
+v 183.828 72.4562 5.6037
+v 183.828 -72.4562 5.6037
+v 136.878 72.4562 122.835
+v 136.878 -72.4562 122.835
+v 169.669 72.4562 70.9685
+v 169.669 -72.4562 70.9685
+v 177.039 72.4562 49.8111
+v 177.039 -72.4562 49.8111
+v 112.262 72.4562 145.675
+v 112.262 -72.4562 145.675
+v 179.745 72.4562 38.9351
+v 179.745 -72.4562 38.9351
+v 152.06 -79.9735 -100
+v 152.06 79.9735 -100
+v -145.977 -79.9735 108.688
+v -145.977 79.9735 108.688
+v 139.621 70.6143 125.296
+v 100.467 70.6143 158.428
+v 139.621 -70.6143 125.296
+v 100.467 -70.6143 158.428
+v -2.59849 70.6143 187.58
+v -2.59849 -70.6143 187.58
+v 59.2546 70.6143 177.994
+v 59.2546 -70.6143 177.994
+v 187.598 70.6143 0
+v 187.598 -70.6143 0
+v 37.1718 70.6143 183.878
+v 37.1718 -70.6143 183.878
+v 186.206 70.6143 22.8109
+v 186.206 -70.6143 22.8109
+v 187.511 70.6143 5.71598
+v 187.511 -70.6143 5.71598
+v 20.2295 70.6143 186.504
+v 20.2295 -70.6143 186.504
+v 150.477 70.6143 112.026
+v 150.477 -70.6143 112.026
+v 69.9863 70.6143 174.055
+v 69.9863 -70.6143 174.055
+v 14.5374 70.6143 187.034
+v 14.5374 -70.6143 187.034
+v 146.994 70.6143 116.559
+v 146.994 -70.6143 116.559
+v 173.068 70.6143 72.3905
+v 173.068 -70.6143 72.3905
+v 8.83189 70.6143 187.39
+v 8.83189 -70.6143 187.39
+v 183.346 70.6143 39.7152
+v 183.346 -70.6143 39.7152
+v 3.11815 70.6143 187.572
+v 3.11815 -70.6143 187.572
+v 186.815 70.6143 17.1267
+v 186.815 -70.6143 17.1267
+v 165.737 70.6143 87.8884
+v 165.737 -70.6143 87.8884
+v -58.7613 70.6143 178.158
+v -58.7613 -70.6143 178.158
+v -53.3057 70.6143 179.865
+v -53.3057 -70.6143 179.865
+v 180.587 70.6143 50.8092
+v 180.587 -70.6143 50.8092
+v 187.25 70.6143 11.4267
+v 187.25 -70.6143 11.4267
+v -25.3879 70.6143 185.872
+v -25.3879 -70.6143 185.872
+v 105.248 70.6143 155.293
+v 105.248 -70.6143 155.293
+v 177.156 70.6143 61.7144
+v 177.156 -70.6143 61.7144
+v 143.374 70.6143 120.983
+v 118.986 70.6143 145.036
+v 114.511 70.6143 148.594
+v 143.374 -70.6143 120.983
+v 118.986 -70.6143 145.036
+v 114.511 -70.6143 148.594
+v 153.82 70.6143 107.389
+v 127.599 70.6143 137.519
+v 153.82 -70.6143 107.389
+v 127.599 -70.6143 137.519
+v -42.251 70.6143 182.778
+v -42.251 -70.6143 182.778
+v 85.5843 70.6143 166.938
+v 75.2571 70.6143 171.841
+v 85.5843 -70.6143 166.938
+v 75.2571 -70.6143 171.841
+v -36.6623 70.6143 183.981
+v -36.6623 -70.6143 183.981
+v 170.782 70.6143 77.6301
+v 170.782 -70.6143 77.6301
+v 182.051 70.6143 45.2832
+v 182.051 -70.6143 45.2832
+v 90.631 70.6143 164.253
+v -47.8005 70.6143 181.406
+v 90.631 -70.6143 164.253
+v -47.8005 -70.6143 181.406
+v 184.471 70.6143 34.1104
+v 184.471 -70.6143 34.1104
+v -14.0192 70.6143 187.074
+v -14.0192 -70.6143 187.074
+v 160.076 70.6143 97.8203
+v 135.739 70.6143 129.492
+v 109.931 70.6143 152.014
+v 160.076 -70.6143 97.8203
+v 135.739 -70.6143 129.492
+v 109.931 -70.6143 152.014
+v -64.1624 70.6143 176.285
+v 162.982 70.6143 92.8975
+v -64.1624 -70.6143 176.285
+v 162.982 -70.6143 92.8975
+v -8.31272 70.6143 187.414
+v -8.31272 -70.6143 187.414
+v 131.73 70.6143 133.568
+v 131.73 -70.6143 133.568
+v 48.3029 70.6143 181.273
+v 48.3029 -70.6143 181.273
+v 80.4581 70.6143 169.469
+v 80.4581 -70.6143 169.469
+v 123.35 70.6143 141.343
+v 123.35 -70.6143 141.343
+v 95.5936 70.6143 161.415
+v 168.338 70.6143 82.7977
+v 168.338 -70.6143 82.7977
+v 95.5936 -70.6143 161.415
+v 175.194 70.6143 67.0836
+v 175.194 -70.6143 67.0836
+v 31.5519 70.6143 184.926
+v -19.7127 70.6143 186.56
+v 31.5519 -70.6143 184.926
+v -19.7127 -70.6143 186.56
+v 42.7572 70.6143 182.661
+v 42.7572 -70.6143 182.661
+v -31.0395 70.6143 185.012
+v -31.0395 -70.6143 185.012
+v 25.9027 70.6143 185.801
+v 25.9027 -70.6143 185.801
+v 64.6505 70.6143 176.106
+v 64.6505 -70.6143 176.106
+v 53.8037 70.6143 179.717
+v 53.8037 -70.6143 179.717
+v 178.955 70.6143 56.2879
+v 178.955 -70.6143 56.2879
+v 185.425 70.6143 28.4739
+v 185.425 -70.6143 28.4739
+v 157.021 70.6143 102.652
+v 157.021 -70.6143 102.652
+v 156.174 -79.7614 -100
+v 156.174 79.7614 -100
+v -147.384 -79.7614 112.554
+v -147.384 79.7614 112.554
+v 190.828 68.5852 11.645
+v 190.828 -68.5852 11.645
+v 87.2199 68.5852 170.129
+v 87.2199 -68.5852 170.129
+v 142.289 68.5852 127.69
+v 76.6954 68.5852 175.125
+v 142.289 -68.5852 127.69
+v 76.6954 -68.5852 175.125
+v 182.375 68.5852 57.3637
+v 182.375 -68.5852 57.3637
+v 180.542 68.5852 62.8939
+v 180.542 -68.5852 62.8939
+v -14.2872 68.5852 190.649
+v -14.2872 -68.5852 190.649
+v -8.47159 68.5852 190.996
+v -8.47159 -68.5852 190.996
+v 190.385 68.5852 17.454
+v 190.385 -68.5852 17.454
+v 37.8823 68.5852 187.393
+v 37.8823 -68.5852 187.393
+v -48.7141 68.5852 184.873
+v -48.7141 -68.5852 184.873
+v 191.183 68.5852 0
+v 112.032 68.5852 154.919
+v 191.183 -68.5852 0
+v 112.032 -68.5852 154.919
+v -31.6327 68.5852 188.548
+v -31.6327 -68.5852 188.548
+v 9.00068 68.5852 190.971
+v 9.00068 -68.5852 190.971
+v 125.707 68.5852 144.044
+v 107.259 68.5852 158.261
+v 125.707 -68.5852 144.044
+v 107.259 -68.5852 158.261
+v 176.376 68.5852 73.7739
+v 176.376 -68.5852 73.7739
+v 186.85 68.5852 40.4743
+v 186.85 -68.5852 40.4743
+v 156.76 68.5852 109.441
+v 156.76 -68.5852 109.441
+v 14.8153 68.5852 190.609
+v 14.8153 -68.5852 190.609
+v 3.17774 68.5852 191.157
+v 3.17774 -68.5852 191.157
+v 92.3631 68.5852 167.392
+v 92.3631 -68.5852 167.392
+v 189.765 68.5852 23.2468
+v 189.765 -68.5852 23.2468
+v 138.333 68.5852 131.967
+v 138.333 -68.5852 131.967
+v -54.3244 68.5852 183.303
+v -54.3244 -68.5852 183.303
+v -25.8731 68.5852 189.425
+v -25.8731 -68.5852 189.425
+v 65.886 68.5852 179.472
+v 54.832 68.5852 183.152
+v 65.886 -68.5852 179.472
+v 54.832 -68.5852 183.152
+v 20.6161 68.5852 190.069
+v 20.6161 -68.5852 190.069
+v 174.046 68.5852 79.1137
+v 174.046 -68.5852 79.1137
+v 168.904 68.5852 89.5681
+v 168.904 -68.5852 89.5681
+v 184.038 68.5852 51.7802
+v 184.038 -68.5852 51.7802
+v 166.097 68.5852 94.6729
+v 26.3978 68.5852 189.352
+v 166.097 -68.5852 94.6729
+v 26.3978 -68.5852 189.352
+v 188.968 68.5852 29.018
+v 188.968 -68.5852 29.018
+v 134.248 68.5852 136.12
+v 134.248 -68.5852 136.12
+v -20.0895 68.5852 190.125
+v -20.0895 -68.5852 190.125
+v 187.997 68.5852 34.7623
+v 187.997 -68.5852 34.7623
+v 71.3238 68.5852 177.381
+v 71.3238 -68.5852 177.381
+v 60.3871 68.5852 181.396
+v 60.3871 -68.5852 181.396
+v 146.114 68.5852 123.296
+v 146.114 -68.5852 123.296
+v -2.64815 68.5852 191.165
+v -2.64815 -68.5852 191.165
+v -43.0585 68.5852 186.271
+v -43.0585 -68.5852 186.271
+v 102.387 68.5852 161.456
+v 102.387 -68.5852 161.456
+v -59.8843 68.5852 181.563
+v 178.542 68.5852 68.3656
+v -59.8843 -68.5852 181.563
+v 178.542 -68.5852 68.3656
+v 121.26 68.5852 147.808
+v 43.5744 68.5852 186.152
+v 121.26 -68.5852 147.808
+v 43.5744 -68.5852 186.152
+v 49.2261 68.5852 184.737
+v 49.2261 -68.5852 184.737
+v 163.135 68.5852 99.6898
+v 153.353 68.5852 114.167
+v 163.135 -68.5852 99.6898
+v 153.353 -68.5852 114.167
+v 81.9957 68.5852 172.707
+v 81.9957 -68.5852 172.707
+v -37.363 68.5852 187.497
+v -37.363 -68.5852 187.497
+v 171.555 68.5852 84.3801
+v 171.555 -68.5852 84.3801
+v 97.4206 68.5852 164.5
+v 97.4206 -68.5852 164.5
+v 116.7 68.5852 151.434
+v 116.7 -68.5852 151.434
+v 32.1549 68.5852 188.46
+v 32.1549 -68.5852 188.46
+v 191.095 68.5852 5.82522
+v 191.095 -68.5852 5.82522
+v 160.022 68.5852 104.614
+v 160.022 -68.5852 104.614
+v 149.803 68.5852 118.786
+v 149.803 -68.5852 118.786
+v -65.3886 68.5852 179.654
+v -65.3886 -68.5852 179.654
+v 130.038 68.5852 140.147
+v 130.038 -68.5852 140.147
+v 185.53 68.5852 46.1487
+v 185.53 -68.5852 46.1487
+v 160.272 -79.3378 -100
+v 160.272 79.3378 -100
+v -148.786 -79.3378 116.404
+v -148.786 79.3378 116.404
+v 15.0846 66.3742 194.074
+v 15.0846 -66.3742 194.074
+v 9.16433 66.3742 194.444
+v 9.16433 -66.3742 194.444
+v -43.8414 66.3742 189.658
+v -43.8414 -66.3742 189.658
+v 188.903 66.3742 46.9877
+v 148.771 66.3742 125.537
+v 188.903 -66.3742 46.9877
+v 148.771 -66.3742 125.537
+v 159.61 66.3742 111.431
+v 159.61 -66.3742 111.431
+v -60.9731 66.3742 184.864
+v -60.9731 -66.3742 184.864
+v 191.415 66.3742 35.3943
+v 191.415 -66.3742 35.3943
+v 174.674 66.3742 85.9143
+v 50.1211 66.3742 188.096
+v 174.674 -66.3742 85.9143
+v 50.1211 -66.3742 188.096
+v 104.249 66.3742 164.391
+v 104.249 -66.3742 164.391
+v 183.825 66.3742 64.0374
+v 183.825 -66.3742 64.0374
+v -2.6963 66.3742 194.641
+v -2.6963 -66.3742 194.641
+v -20.4547 66.3742 193.582
+v -20.4547 -66.3742 193.582
+v 32.7396 66.3742 191.887
+v 32.7396 -66.3742 191.887
+v 123.465 66.3742 150.495
+v 123.465 -66.3742 150.495
+v 20.9909 66.3742 193.524
+v 20.9909 -66.3742 193.524
+v 94.0425 66.3742 170.436
+v 118.822 66.3742 154.187
+v 114.069 66.3742 157.736
+v 94.0425 -66.3742 170.436
+v 118.822 -66.3742 154.187
+v 114.069 -66.3742 157.736
+v 83.4866 66.3742 175.847
+v 83.4866 -66.3742 175.847
+v 181.788 66.3742 69.6087
+v 181.788 -66.3742 69.6087
+v 190.247 66.3742 41.2102
+v 190.247 -66.3742 41.2102
+v 194.569 66.3742 5.93114
+v 194.569 -66.3742 5.93114
+v -55.3121 66.3742 186.636
+v -55.3121 -66.3742 186.636
+v 3.23552 66.3742 194.633
+v 3.23552 -66.3742 194.633
+v 72.6206 66.3742 180.606
+v 72.6206 -66.3742 180.606
+v -26.3435 66.3742 192.869
+v -26.3435 -66.3742 192.869
+v -38.0423 66.3742 190.906
+v -38.0423 -66.3742 190.906
+v 171.975 66.3742 91.1966
+v 144.876 66.3742 130.012
+v 136.688 66.3742 138.595
+v 171.975 -66.3742 91.1966
+v 144.876 -66.3742 130.012
+v 136.688 -66.3742 138.595
+v 193.215 66.3742 23.6695
+v 193.215 -66.3742 23.6695
+v 194.66 66.3742 0
+v 132.402 66.3742 142.695
+v 194.66 -66.3742 0
+v 132.402 -66.3742 142.695
+v 88.8057 66.3742 173.222
+v 88.8057 -66.3742 173.222
+v 109.21 66.3742 161.138
+v 109.21 -66.3742 161.138
+v 61.485 66.3742 184.694
+v 61.485 -66.3742 184.694
+v 156.141 66.3742 116.243
+v 152.527 66.3742 120.946
+v 156.141 -66.3742 116.243
+v 152.527 -66.3742 120.946
+v -32.2079 66.3742 191.977
+v -32.2079 -66.3742 191.977
+v 26.8777 66.3742 192.795
+v 26.8777 -66.3742 192.795
+v -8.62562 66.3742 194.468
+v -8.62562 -66.3742 194.468
+v 99.1918 66.3742 167.491
+v 166.101 66.3742 101.502
+v 166.101 -66.3742 101.502
+v 99.1918 -66.3742 167.491
+v 177.211 66.3742 80.5522
+v 177.211 -66.3742 80.5522
+v 192.404 66.3742 29.5456
+v 192.404 -66.3742 29.5456
+v -14.5469 66.3742 194.115
+v -14.5469 -66.3742 194.115
+v -66.5775 66.3742 182.92
+v -66.5775 -66.3742 182.92
+v 193.847 66.3742 17.7714
+v 193.847 -66.3742 17.7714
+v 38.571 66.3742 190.8
+v 38.571 -66.3742 190.8
+v 179.583 66.3742 75.1153
+v 179.583 -66.3742 75.1153
+v 140.848 66.3742 134.366
+v 140.848 -66.3742 134.366
+v -49.5998 66.3742 188.234
+v -49.5998 -66.3742 188.234
+v 194.298 66.3742 11.8568
+v 194.298 -66.3742 11.8568
+v 185.691 66.3742 58.4067
+v 185.691 -66.3742 58.4067
+v 44.3667 66.3742 189.536
+v 44.3667 -66.3742 189.536
+v 55.829 66.3742 186.482
+v 55.829 -66.3742 186.482
+v 169.117 66.3742 96.3942
+v 169.117 -66.3742 96.3942
+v 127.993 66.3742 146.663
+v 127.993 -66.3742 146.663
+v 78.0898 66.3742 178.31
+v 78.0898 -66.3742 178.31
+v 187.384 66.3742 52.7217
+v 187.384 -66.3742 52.7217
+v 162.931 66.3742 106.516
+v 67.084 66.3742 182.735
+v 162.931 -66.3742 106.516
+v 67.084 -66.3742 182.735
+v -150.178 -78.7038 120.229
+v -150.178 78.7038 120.229
+v 164.342 -78.7038 -100
+v 164.342 78.7038 -100
+v 111.093 63.9871 163.918
+v 111.093 -63.9871 163.918
+v -67.7259 63.9871 186.075
+v 158.834 63.9871 118.248
+v -67.7259 -63.9871 186.075
+v 158.834 -63.9871 118.248
+v -56.2662 63.9871 189.855
+v -56.2662 -63.9871 189.855
+v -14.7978 63.9871 197.463
+v -14.7978 -63.9871 197.463
+v -2.74281 63.9871 197.998
+v -2.74281 -63.9871 197.998
+v 165.742 63.9871 108.353
+v 165.742 -63.9871 108.353
+v -8.7744 63.9871 197.823
+v -8.7744 -63.9871 197.823
+v 195.723 63.9871 30.0553
+v 195.723 -63.9871 30.0553
+v 56.792 63.9871 189.698
+v 56.792 -63.9871 189.698
+v 73.8733 63.9871 183.721
+v 73.8733 -63.9871 183.721
+v 198.017 63.9871 0
+v 198.017 -63.9871 0
+v 33.3043 63.9871 195.196
+v 33.3043 -63.9871 195.196
+v 45.1319 63.9871 192.805
+v 45.1319 -63.9871 192.805
+v 184.924 63.9871 70.8093
+v 184.924 -63.9871 70.8093
+v -44.5976 63.9871 192.93
+v -44.5976 -63.9871 192.93
+v 95.6646 63.9871 173.376
+v 95.6646 -63.9871 173.376
+v 151.337 63.9871 127.703
+v 151.337 -63.9871 127.703
+v 196.548 63.9871 24.0778
+v 196.548 -63.9871 24.0778
+v 168.966 63.9871 103.253
+v 168.966 -63.9871 103.253
+v 172.034 63.9871 98.0569
+v 172.034 -63.9871 98.0569
+v 194.716 63.9871 36.0048
+v 194.716 -63.9871 36.0048
+v -62.0248 63.9871 188.052
+v -62.0248 -63.9871 188.052
+v 130.201 63.9871 149.193
+v -38.6985 63.9871 194.199
+v 130.201 -63.9871 149.193
+v -38.6985 -63.9871 194.199
+v 188.893 63.9871 59.4141
+v 188.893 -63.9871 59.4141
+v 116.036 63.9871 160.457
+v 116.036 -63.9871 160.457
+v 125.594 63.9871 153.091
+v 125.594 -63.9871 153.091
+v 192.162 63.9871 47.7982
+v 134.686 63.9871 145.157
+v 192.162 -63.9871 47.7982
+v 134.686 -63.9871 145.157
+v 68.2411 63.9871 185.887
+v 68.2411 -63.9871 185.887
+v 197.19 63.9871 18.0779
+v 197.19 -63.9871 18.0779
+v 162.363 63.9871 113.353
+v 162.363 -63.9871 113.353
+v 100.903 63.9871 170.38
+v 143.277 63.9871 136.684
+v 143.277 -63.9871 136.684
+v 100.903 -63.9871 170.38
+v 197.925 63.9871 6.03344
+v 197.925 -63.9871 6.03344
+v 190.616 63.9871 53.6311
+v 190.616 -63.9871 53.6311
+v 186.995 63.9871 65.142
+v 186.995 -63.9871 65.142
+v -50.4553 63.9871 191.481
+v -50.4553 -63.9871 191.481
+v 147.376 63.9871 132.255
+v 147.376 -63.9871 132.255
+v -20.8075 63.9871 196.921
+v -20.8075 -63.9871 196.921
+v 50.9856 63.9871 191.341
+v 50.9856 -63.9871 191.341
+v 21.353 63.9871 196.863
+v 21.353 -63.9871 196.863
+v 15.3448 63.9871 197.422
+v 15.3448 -63.9871 197.422
+v 84.9266 63.9871 178.881
+v 84.9266 -63.9871 178.881
+v 155.158 63.9871 123.032
+v 155.158 -63.9871 123.032
+v 182.68 63.9871 76.4109
+v 79.4368 63.9871 181.385
+v 182.68 -63.9871 76.4109
+v 79.4368 -63.9871 181.385
+v 3.29133 63.9871 197.99
+v 3.29133 -63.9871 197.99
+v 90.3375 63.9871 176.21
+v 90.3375 -63.9871 176.21
+v 27.3414 63.9871 196.12
+v 27.3414 -63.9871 196.12
+v 106.047 63.9871 167.227
+v 106.047 -63.9871 167.227
+v 177.687 63.9871 87.3962
+v 177.687 -63.9871 87.3962
+v -26.7979 63.9871 196.195
+v -26.7979 -63.9871 196.195
+v 174.942 63.9871 92.7696
+v 174.942 -63.9871 92.7696
+v 9.3224 63.9871 197.798
+v 9.3224 -63.9871 197.798
+v 180.268 63.9871 81.9416
+v 180.268 -63.9871 81.9416
+v 62.5456 63.9871 187.88
+v 62.5456 -63.9871 187.88
+v 197.65 63.9871 12.0613
+v 197.65 -63.9871 12.0613
+v 193.529 63.9871 41.921
+v 193.529 -63.9871 41.921
+v -32.7634 63.9871 195.288
+v -32.7634 -63.9871 195.288
+v 39.2363 63.9871 194.091
+v 39.2363 -63.9871 194.091
+v 120.871 63.9871 156.847
+v 120.871 -63.9871 156.847
+v 139.046 63.9871 140.986
+v 139.046 -63.9871 140.986
+v 161.425 61.4304 120.177
+v 161.425 -61.4304 120.177
+v 149.78 61.4304 134.412
+v 149.78 -61.4304 134.412
+v 27.7874 61.4304 199.32
+v 27.7874 -61.4304 199.32
+v 196.686 61.4304 42.6049
+v 196.686 -61.4304 42.6049
+v -33.2979 61.4304 198.474
+v -33.2979 -61.4304 198.474
+v 168.445 61.4304 110.121
+v 136.883 61.4304 147.525
+v 168.445 -61.4304 110.121
+v 136.883 -61.4304 147.525
+v -2.78755 61.4304 201.228
+v -2.78755 -61.4304 201.228
+v 69.3543 61.4304 188.919
+v 69.3543 -61.4304 188.919
+v -68.8307 61.4304 189.111
+v 75.0784 61.4304 186.718
+v -68.8307 -61.4304 189.111
+v 75.0784 -61.4304 186.718
+v 177.796 61.4304 94.283
+v 177.796 -61.4304 94.283
+v -39.3298 61.4304 197.367
+v -39.3298 -61.4304 197.367
+v 91.8112 61.4304 179.084
+v 91.8112 -61.4304 179.084
+v 33.8476 61.4304 198.381
+v 33.8476 -61.4304 198.381
+v 180.586 61.4304 88.8219
+v 180.586 -61.4304 88.8219
+v 200.407 61.4304 18.3728
+v 200.407 -61.4304 18.3728
+v -15.0392 61.4304 200.685
+v -15.0392 -61.4304 200.685
+v 165.012 61.4304 115.202
+v 165.012 -61.4304 115.202
+v 198.916 61.4304 30.5456
+v 198.916 -61.4304 30.5456
+v 171.723 61.4304 104.938
+v 171.723 -61.4304 104.938
+v 45.8682 61.4304 195.951
+v 39.8764 61.4304 197.257
+v 45.8682 -61.4304 195.951
+v 39.8764 -61.4304 197.257
+v 183.208 61.4304 83.2784
+v 183.208 -61.4304 83.2784
+v 122.843 61.4304 159.405
+v 122.843 -61.4304 159.405
+v 201.154 61.4304 6.13187
+v 201.154 -61.4304 6.13187
+v -21.147 61.4304 200.133
+v -21.147 -61.4304 200.133
+v 153.805 61.4304 129.786
+v 153.805 -61.4304 129.786
+v 86.312 61.4304 181.799
+v -57.1841 61.4304 192.952
+v 86.312 -61.4304 181.799
+v -57.1841 -61.4304 192.952
+v 63.5659 61.4304 190.945
+v 63.5659 -61.4304 190.945
+v 102.549 61.4304 173.16
+v 195.296 61.4304 48.578
+v 195.296 -61.4304 48.578
+v 102.549 -61.4304 173.16
+v 112.906 61.4304 166.592
+v 112.906 -61.4304 166.592
+v 190.046 61.4304 66.2046
+v 190.046 -61.4304 66.2046
+v 9.47448 61.4304 201.024
+v 9.47448 -61.4304 201.024
+v 15.5951 61.4304 200.642
+v 15.5951 -61.4304 200.642
+v 200.874 61.4304 12.258
+v 200.874 -61.4304 12.258
+v 185.661 61.4304 77.6575
+v 127.643 61.4304 155.589
+v 185.661 -61.4304 77.6575
+v 127.643 -61.4304 155.589
+v 193.726 61.4304 54.506
+v 193.726 -61.4304 54.506
+v 157.689 61.4304 125.039
+v 145.615 61.4304 138.913
+v 157.689 -61.4304 125.039
+v 145.615 -61.4304 138.913
+v 107.777 61.4304 169.955
+v 107.777 -61.4304 169.955
+v -8.91754 61.4304 201.05
+v -8.91754 -61.4304 201.05
+v 199.754 61.4304 24.4706
+v 199.754 -61.4304 24.4706
+v 51.8174 61.4304 194.462
+v 51.8174 -61.4304 194.462
+v 80.7327 61.4304 184.344
+v 80.7327 -61.4304 184.344
+v -51.2784 61.4304 194.605
+v -51.2784 -61.4304 194.605
+v 191.975 61.4304 60.3833
+v 191.975 -61.4304 60.3833
+v -63.0367 61.4304 191.12
+v -63.0367 -61.4304 191.12
+v 141.314 61.4304 143.286
+v 132.324 61.4304 151.627
+v 141.314 -61.4304 143.286
+v 132.324 -61.4304 151.627
+v 187.941 61.4304 71.9645
+v 174.84 61.4304 99.6565
+v 187.941 -61.4304 71.9645
+v 174.84 -61.4304 99.6565
+v 197.893 61.4304 36.5922
+v 197.893 -61.4304 36.5922
+v 97.2252 61.4304 176.204
+v 97.2252 -61.4304 176.204
+v -27.2351 61.4304 199.396
+v -27.2351 -61.4304 199.396
+v 201.247 61.4304 0
+v 201.247 -61.4304 0
+v 117.929 61.4304 163.074
+v 117.929 -61.4304 163.074
+v 3.34502 61.4304 201.22
+v 3.34502 -61.4304 201.22
+v 57.7184 61.4304 192.793
+v 57.7184 -61.4304 192.793
+v -45.3251 61.4304 196.077
+v -45.3251 -61.4304 196.077
+v 21.7013 61.4304 200.074
+v 21.7013 -61.4304 200.074
+v -151.557 -77.8612 124.019
+v -151.557 77.8612 124.019
+v 168.375 -77.8612 -100
+v 168.375 77.8612 -100
+v 203.962 58.7108 12.4465
+v 203.962 -58.7108 12.4465
+v -69.889 58.7108 192.018
+v -69.889 -58.7108 192.018
+v 183.362 58.7108 90.1877
+v 163.907 58.7108 122.024
+v 183.362 -58.7108 90.1877
+v 163.907 -58.7108 122.024
+v 3.39645 58.7108 204.314
+v 3.39645 -58.7108 204.314
+v 188.515 58.7108 78.8515
+v 188.515 -58.7108 78.8515
+v 22.035 58.7108 203.15
+v 22.035 -58.7108 203.15
+v 134.359 58.7108 153.958
+v 134.359 -58.7108 153.958
+v 203.488 58.7108 18.6553
+v 203.488 -58.7108 18.6553
+v 199.71 58.7108 43.26
+v 199.71 -58.7108 43.26
+v 196.704 58.7108 55.3441
+v 196.704 -58.7108 55.3441
+v 114.642 58.7108 169.153
+v 114.642 -58.7108 169.153
+v 202.826 58.7108 24.8468
+v 202.826 -58.7108 24.8468
+v 109.435 58.7108 172.568
+v 109.435 -58.7108 172.568
+v 194.927 58.7108 61.3118
+v 194.927 -58.7108 61.3118
+v 28.2146 58.7108 202.385
+v 28.2146 -58.7108 202.385
+v 98.7201 58.7108 178.913
+v 98.7201 -58.7108 178.913
+v 198.299 58.7108 49.3249
+v 198.299 -58.7108 49.3249
+v 200.936 58.7108 37.1549
+v -33.8099 58.7108 201.525
+v 200.936 -58.7108 37.1549
+v -33.8099 -58.7108 201.525
+v 177.529 58.7108 101.189
+v 177.529 -58.7108 101.189
+v 143.487 58.7108 145.489
+v 143.487 -58.7108 145.489
+v -27.6539 58.7108 202.462
+v -27.6539 -58.7108 202.462
+v 46.5735 58.7108 198.964
+v 46.5735 -58.7108 198.964
+v -21.4721 58.7108 203.211
+v -21.4721 -58.7108 203.211
+v 119.743 58.7108 165.582
+v 64.5433 58.7108 193.881
+v 119.743 -58.7108 165.582
+v 64.5433 -58.7108 193.881
+v 204.247 58.7108 6.22615
+v 204.247 -58.7108 6.22615
+v 15.835 58.7108 203.727
+v 15.835 -58.7108 203.727
+v 201.974 58.7108 31.0152
+v 201.974 -58.7108 31.0152
+v 124.732 58.7108 161.857
+v 124.732 -58.7108 161.857
+v -15.2705 58.7108 203.77
+v -15.2705 -58.7108 203.77
+v 9.62017 58.7108 204.115
+v 9.62017 -58.7108 204.115
+v 70.4207 58.7108 191.824
+v 70.4207 -58.7108 191.824
+v 192.968 58.7108 67.2226
+v 81.974 58.7108 187.179
+v 192.968 -58.7108 67.2226
+v 81.974 -58.7108 187.179
+v 174.363 58.7108 106.551
+v 174.363 -58.7108 106.551
+v 87.6392 58.7108 184.594
+v 40.4896 58.7108 200.29
+v 87.6392 -58.7108 184.594
+v 40.4896 -58.7108 200.29
+v 104.126 58.7108 175.822
+v 138.988 58.7108 149.793
+v 138.988 -58.7108 149.793
+v 104.126 -58.7108 175.822
+v -39.9345 58.7108 200.402
+v -39.9345 -58.7108 200.402
+v 186.025 58.7108 84.5589
+v 186.025 -58.7108 84.5589
+v 52.6141 58.7108 197.452
+v 52.6141 -58.7108 197.452
+v 34.368 58.7108 201.431
+v 34.368 -58.7108 201.431
+v 76.2328 58.7108 189.589
+v -58.0634 58.7108 195.919
+v 76.2328 -58.7108 189.589
+v -58.0634 -58.7108 195.919
+v -2.83042 58.7108 204.322
+v -2.83042 -58.7108 204.322
+v -64.0059 58.7108 194.059
+v 204.342 58.7108 0
+v 190.83 58.7108 73.071
+v 171.036 58.7108 111.814
+v 152.083 58.7108 136.479
+v 204.342 -58.7108 0
+v -64.0059 -58.7108 194.059
+v 190.83 -58.7108 73.071
+v 171.036 -58.7108 111.814
+v 152.083 -58.7108 136.479
+v -52.0669 58.7108 197.597
+v -52.0669 -58.7108 197.597
+v 58.6059 58.7108 195.757
+v 58.6059 -58.7108 195.757
+v 93.2229 58.7108 181.838
+v 180.529 58.7108 95.7327
+v 167.549 58.7108 116.974
+v 93.2229 -58.7108 181.838
+v 180.529 -58.7108 95.7327
+v 167.549 -58.7108 116.974
+v 160.113 58.7108 126.962
+v 160.113 -58.7108 126.962
+v 156.171 58.7108 131.782
+v 156.171 -58.7108 131.782
+v -46.0221 58.7108 199.092
+v -46.0221 -58.7108 199.092
+v -9.05466 58.7108 204.141
+v -9.05466 -58.7108 204.141
+v 147.854 58.7108 141.049
+v 147.854 -58.7108 141.049
+v 129.606 58.7108 157.981
+v 129.606 -58.7108 157.981
+v -152.919 -76.812 127.762
+v -152.919 76.812 127.762
+v 172.359 -76.812 -100
+v 172.359 76.812 -100
+v -15.491 55.8355 206.712
+v -15.491 -55.8355 206.712
+v 105.629 55.8355 178.361
+v 186.01 55.8355 91.4898
+v 186.01 -55.8355 91.4898
+v 105.629 -55.8355 178.361
+v 16.0636 55.8355 206.669
+v 16.0636 -55.8355 206.669
+v 205.754 55.8355 25.2056
+v 176.88 55.8355 108.089
+v 205.754 -55.8355 25.2056
+v 176.88 -55.8355 108.089
+v 34.8643 55.8355 204.339
+v 34.8643 -55.8355 204.339
+v 191.237 55.8355 79.99
+v 191.237 -55.8355 79.99
+v 3.44549 55.8355 207.264
+v 3.44549 -55.8355 207.264
+v 59.4521 55.8355 198.584
+v 59.4521 -55.8355 198.584
+v -70.8981 55.8355 194.791
+v -70.8981 -55.8355 194.791
+v 22.3532 55.8355 206.083
+v 22.3532 -55.8355 206.083
+v 9.75906 55.8355 207.062
+v 9.75906 -55.8355 207.062
+v 203.837 55.8355 37.6913
+v 203.837 -55.8355 37.6913
+v 207.196 55.8355 6.31604
+v 207.196 -55.8355 6.31604
+v 180.092 55.8355 102.65
+v 169.968 55.8355 118.663
+v 180.092 -55.8355 102.65
+v 169.968 -55.8355 118.663
+v 121.471 55.8355 167.973
+v 121.471 -55.8355 167.973
+v 204.891 55.8355 31.463
+v 204.891 -55.8355 31.463
+v 158.425 55.8355 133.684
+v 158.425 -55.8355 133.684
+v 206.426 55.8355 18.9247
+v 206.426 -55.8355 18.9247
+v 188.711 55.8355 85.7797
+v 188.711 -55.8355 85.7797
+v 136.299 55.8355 156.181
+v 136.299 -55.8355 156.181
+v 111.015 55.8355 175.059
+v 111.015 -55.8355 175.059
+v -64.93 55.8355 196.861
+v -64.93 -55.8355 196.861
+v 140.995 55.8355 151.956
+v 131.477 55.8355 160.262
+v 140.995 -55.8355 151.956
+v 131.477 -55.8355 160.262
+v 53.3738 55.8355 200.303
+v 53.3738 -55.8355 200.303
+v -40.5111 55.8355 203.295
+v -40.5111 -55.8355 203.295
+v 126.533 55.8355 164.193
+v 126.533 -55.8355 164.193
+v -2.87128 55.8355 207.272
+v -2.87128 -55.8355 207.272
+v 41.0742 55.8355 203.182
+v 41.0742 -55.8355 203.182
+v -52.8186 55.8355 200.45
+v -52.8186 -55.8355 200.45
+v 197.741 55.8355 62.197
+v 197.741 -55.8355 62.197
+v 193.586 55.8355 74.126
+v 193.586 -55.8355 74.126
+v 83.1576 55.8355 189.881
+v 83.1576 -55.8355 189.881
+v 199.544 55.8355 56.1431
+v 199.544 -55.8355 56.1431
+v 206.907 55.8355 12.6262
+v 206.907 -55.8355 12.6262
+v 145.559 55.8355 147.589
+v 116.297 55.8355 171.596
+v 145.559 -55.8355 147.589
+v 116.297 -55.8355 171.596
+v -9.18539 55.8355 207.089
+v -9.18539 -55.8355 207.089
+v 195.754 55.8355 68.1932
+v 195.754 -55.8355 68.1932
+v 166.274 55.8355 123.786
+v -28.0531 55.8355 205.385
+v 166.274 -55.8355 123.786
+v -28.0531 -55.8355 205.385
+v 88.9045 55.8355 187.259
+v 88.9045 -55.8355 187.259
+v 173.505 55.8355 113.429
+v 173.505 -55.8355 113.429
+v -58.9017 55.8355 198.748
+v -58.9017 -55.8355 198.748
+v 71.4375 55.8355 194.594
+v 71.4375 -55.8355 194.594
+v 207.292 55.8355 0
+v 94.5689 55.8355 184.464
+v 207.292 -55.8355 0
+v 94.5689 -55.8355 184.464
+v 28.622 55.8355 205.307
+v 28.622 -55.8355 205.307
+v 77.3334 55.8355 192.327
+v 77.3334 -55.8355 192.327
+v -21.7822 55.8355 206.145
+v -21.7822 -55.8355 206.145
+v -46.6866 55.8355 201.966
+v -46.6866 -55.8355 201.966
+v 65.4752 55.8355 196.68
+v 65.4752 -55.8355 196.68
+v 162.425 55.8355 128.795
+v 162.425 -55.8355 128.795
+v 183.136 55.8355 97.1149
+v 183.136 -55.8355 97.1149
+v 100.146 55.8355 181.496
+v 100.146 -55.8355 181.496
+v 201.163 55.8355 50.0371
+v 201.163 -55.8355 50.0371
+v 154.279 55.8355 138.449
+v 154.279 -55.8355 138.449
+v 202.594 55.8355 43.8846
+v 202.594 -55.8355 43.8846
+v -34.298 55.8355 204.435
+v -34.298 -55.8355 204.435
+v 149.988 55.8355 143.086
+v 149.988 -55.8355 143.086
+v 47.2459 55.8355 201.836
+v 47.2459 -55.8355 201.836
+v -154.262 -75.5591 131.45
+v -154.262 75.5591 131.45
+v 176.283 -75.5591 -100
+v 176.283 75.5591 -100
+v -47.3168 52.8122 204.693
+v -47.3168 -52.8122 204.693
+v 60.2547 52.8122 201.264
+v 60.2547 -52.8122 201.264
+v 185.608 52.8122 98.4259
+v 185.608 -52.8122 98.4259
+v -71.8552 52.8122 197.421
+v -71.8552 -52.8122 197.421
+v 29.0084 52.8122 208.078
+v 29.0084 -52.8122 208.078
+v 3.492 52.8122 210.061
+v 3.492 -52.8122 210.061
+v 200.411 52.8122 63.0367
+v 200.411 -52.8122 63.0367
+v 196.199 52.8122 75.1267
+v 196.199 -52.8122 75.1267
+v 78.3774 52.8122 194.923
+v 78.3774 -52.8122 194.923
+v 205.329 52.8122 44.477
+v 205.329 -52.8122 44.477
+v 72.4019 52.8122 197.221
+v 72.4019 -52.8122 197.221
+v 123.111 52.8122 170.24
+v 112.513 52.8122 177.423
+v 123.111 -52.8122 170.24
+v 112.513 -52.8122 177.423
+v 188.521 52.8122 92.7249
+v 128.241 52.8122 166.41
+v 188.521 -52.8122 92.7249
+v 128.241 -52.8122 166.41
+v 209.993 52.8122 6.40131
+v 209.993 -52.8122 6.40131
+v -41.058 52.8122 206.04
+v -41.058 -52.8122 206.04
+v 54.0943 52.8122 203.007
+v 54.0943 -52.8122 203.007
+v -59.6968 52.8122 201.431
+v -59.6968 -52.8122 201.431
+v 84.2802 52.8122 192.445
+v 84.2802 -52.8122 192.445
+v 101.497 52.8122 183.947
+v 101.497 -52.8122 183.947
+v 209.213 52.8122 19.1802
+v 209.213 -52.8122 19.1802
+v 22.6549 52.8122 208.865
+v 22.6549 -52.8122 208.865
+v 90.1047 52.8122 189.787
+v 90.1047 -52.8122 189.787
+v -53.5317 52.8122 203.156
+v -53.5317 -52.8122 203.156
+v -15.7001 52.8122 209.503
+v -15.7001 -52.8122 209.503
+v 198.397 52.8122 69.1138
+v 198.397 -52.8122 69.1138
+v 203.878 52.8122 50.7126
+v 203.878 -52.8122 50.7126
+v 16.2804 52.8122 209.459
+v 16.2804 -52.8122 209.459
+v -28.4318 52.8122 208.158
+v -28.4318 -52.8122 208.158
+v 168.518 52.8122 125.457
+v 168.518 -52.8122 125.457
+v -2.91004 52.8122 210.07
+v -2.91004 -52.8122 210.07
+v 9.89081 52.8122 209.858
+v 9.89081 -52.8122 209.858
+v 138.139 52.8122 158.29
+v 138.139 -52.8122 158.29
+v -9.30939 52.8122 209.884
+v -9.30939 -52.8122 209.884
+v 193.819 52.8122 81.0698
+v 147.524 52.8122 149.582
+v 133.252 52.8122 162.425
+v 193.819 -52.8122 81.0698
+v 147.524 -52.8122 149.582
+v 133.252 -52.8122 162.425
+v 66.3591 52.8122 199.335
+v 66.3591 -52.8122 199.335
+v 41.6286 52.8122 205.925
+v 41.6286 -52.8122 205.925
+v 207.656 52.8122 31.8878
+v 207.656 -52.8122 31.8878
+v 182.523 52.8122 104.036
+v 156.361 52.8122 140.318
+v 47.8837 52.8122 204.561
+v 182.523 -52.8122 104.036
+v 156.361 -52.8122 140.318
+v 47.8837 -52.8122 204.561
+v 35.3349 52.8122 207.098
+v 35.3349 -52.8122 207.098
+v 175.847 52.8122 114.96
+v 175.847 -52.8122 114.96
+v 202.238 52.8122 56.901
+v 202.238 -52.8122 56.901
+v 208.532 52.8122 25.5458
+v 208.532 -52.8122 25.5458
+v 172.263 52.8122 120.265
+v 172.263 -52.8122 120.265
+v 209.701 52.8122 12.7967
+v 209.701 -52.8122 12.7967
+v 179.268 52.8122 109.549
+v 179.268 -52.8122 109.549
+v -65.8066 52.8122 199.518
+v 95.8456 52.8122 186.954
+v 152.013 52.8122 145.017
+v 142.898 52.8122 154.007
+v 95.8456 -52.8122 186.954
+v -65.8066 -52.8122 199.518
+v 152.013 -52.8122 145.017
+v 142.898 -52.8122 154.007
+v -34.7611 52.8122 207.195
+v -34.7611 -52.8122 207.195
+v 206.589 52.8122 38.2001
+v 206.589 -52.8122 38.2001
+v 191.259 52.8122 86.9377
+v 191.259 -52.8122 86.9377
+v 117.867 52.8122 173.912
+v 117.867 -52.8122 173.912
+v 107.055 52.8122 180.769
+v 164.618 52.8122 130.534
+v 164.618 -52.8122 130.534
+v 107.055 -52.8122 180.769
+v -22.0762 52.8122 208.928
+v -22.0762 -52.8122 208.928
+v 210.091 52.8122 0
+v 210.091 -52.8122 0
+v 160.564 52.8122 135.489
+v 160.564 -52.8122 135.489
+v 102.772 49.6488 186.257
+v 102.772 -49.6488 186.257
+v -9.42633 49.6488 212.521
+v -9.42633 -49.6488 212.521
+v 210.265 49.6488 32.2883
+v 210.265 -49.6488 32.2883
+v 149.377 49.6488 151.461
+v 22.9395 49.6488 211.489
+v 149.377 -49.6488 151.461
+v 22.9395 -49.6488 211.489
+v -54.2041 49.6488 205.708
+v -54.2041 -49.6488 205.708
+v 79.3619 49.6488 197.372
+v 79.3619 -49.6488 197.372
+v 184.816 49.6488 105.342
+v 184.816 -49.6488 105.342
+v 200.889 49.6488 69.9819
+v 193.661 49.6488 88.0298
+v 200.889 -49.6488 69.9819
+v 193.661 -49.6488 88.0298
+v 187.94 49.6488 99.6623
+v 170.635 49.6488 127.033
+v 187.94 -49.6488 99.6623
+v 170.635 -49.6488 127.033
+v 178.056 49.6488 116.404
+v 178.056 -49.6488 116.404
+v 61.0115 49.6488 203.793
+v 61.0115 -49.6488 203.793
+v 212.631 49.6488 6.48172
+v 212.631 -49.6488 6.48172
+v 207.908 49.6488 45.0357
+v 67.1926 49.6488 201.839
+v 207.908 -49.6488 45.0357
+v 67.1926 -49.6488 201.839
+v -72.7578 49.6488 199.9
+v 129.852 49.6488 168.5
+v -72.7578 -49.6488 199.9
+v 129.852 -49.6488 168.5
+v -35.1977 49.6488 209.798
+v -35.1977 -49.6488 209.798
+v 181.52 49.6488 110.925
+v 174.427 49.6488 121.775
+v 181.52 -49.6488 110.925
+v 174.427 -49.6488 121.775
+v 10.015 49.6488 212.494
+v 10.015 -49.6488 212.494
+v 196.253 49.6488 82.0882
+v 196.253 -49.6488 82.0882
+v 113.926 49.6488 179.651
+v 113.926 -49.6488 179.651
+v 211.151 49.6488 25.8667
+v 211.151 -49.6488 25.8667
+v 119.348 49.6488 176.097
+v 119.348 -49.6488 176.097
+v 211.841 49.6488 19.4211
+v 211.841 -49.6488 19.4211
+v 212.335 49.6488 12.9574
+v 212.335 -49.6488 12.9574
+v 190.889 49.6488 93.8896
+v 190.889 -49.6488 93.8896
+v 3.53587 49.6488 212.7
+v 3.53587 -49.6488 212.7
+v 209.184 49.6488 38.68
+v 209.184 -49.6488 38.68
+v 35.7788 49.6488 209.699
+v 35.7788 -49.6488 209.699
+v 85.3389 49.6488 194.862
+v 85.3389 -49.6488 194.862
+v 91.2365 49.6488 192.171
+v 91.2365 -49.6488 192.171
+v 206.439 49.6488 51.3496
+v 206.439 -49.6488 51.3496
+v 108.4 49.6488 183.039
+v 144.693 49.6488 155.942
+v 144.693 -49.6488 155.942
+v 108.4 -49.6488 183.039
+v 29.3728 49.6488 210.692
+v 29.3728 -49.6488 210.692
+v 73.3113 49.6488 199.698
+v 73.3113 -49.6488 199.698
+v 16.4849 49.6488 212.09
+v 16.4849 -49.6488 212.09
+v 42.1516 49.6488 208.512
+v 42.1516 -49.6488 208.512
+v 212.73 49.6488 0
+v 158.325 49.6488 142.081
+v 212.73 -49.6488 0
+v 158.325 -49.6488 142.081
+v -22.3535 49.6488 211.552
+v -22.3535 -49.6488 211.552
+v -2.9466 49.6488 212.709
+v -2.9466 -49.6488 212.709
+v -66.6332 49.6488 202.025
+v -66.6332 -49.6488 202.025
+v -47.9112 49.6488 207.264
+v -47.9112 -49.6488 207.264
+v 198.663 49.6488 76.0704
+v 54.7738 49.6488 205.557
+v 198.663 -49.6488 76.0704
+v 54.7738 -49.6488 205.557
+v 97.0495 49.6488 189.302
+v 97.0495 -49.6488 189.302
+v 202.928 49.6488 63.8285
+v 166.686 49.6488 132.173
+v 202.928 -49.6488 63.8285
+v 166.686 -49.6488 132.173
+v 153.923 49.6488 146.839
+v 139.874 49.6488 160.278
+v 153.923 -49.6488 146.839
+v 139.874 -49.6488 160.278
+v -41.5737 49.6488 208.628
+v -41.5737 -49.6488 208.628
+v 162.581 49.6488 137.191
+v 162.581 -49.6488 137.191
+v 204.779 49.6488 57.6158
+v 204.779 -49.6488 57.6158
+v -28.789 49.6488 210.773
+v -28.789 -49.6488 210.773
+v -60.4467 49.6488 203.961
+v -60.4467 -49.6488 203.961
+v -15.8973 49.6488 212.135
+v -15.8973 -49.6488 212.135
+v 48.4852 49.6488 207.131
+v 48.4852 -49.6488 207.131
+v 124.658 49.6488 172.379
+v 124.658 -49.6488 172.379
+v 134.926 49.6488 164.466
+v 134.926 -49.6488 164.466
+v 180.138 -74.1059 -100
+v 180.138 74.1059 -100
+v -155.58 -74.1059 135.073
+v -155.58 74.1059 135.073
+v 109.66 46.3537 185.167
+v 109.66 -46.3537 185.167
+v 183.63 46.3537 112.214
+v 183.63 -46.3537 112.214
+v 164.471 46.3537 138.786
+v 164.471 -46.3537 138.786
+v 49.0488 46.3537 209.538
+v 49.0488 -46.3537 209.538
+v 213.605 46.3537 26.1674
+v 213.605 -46.3537 26.1674
+v 16.6765 46.3537 214.555
+v 16.6765 -46.3537 214.555
+v 3.57697 46.3537 215.173
+v 3.57697 -46.3537 215.173
+v -67.4077 46.3537 204.373
+v -67.4077 -46.3537 204.373
+v 146.375 46.3537 157.754
+v 146.375 -46.3537 157.754
+v 42.6415 46.3537 210.935
+v 42.6415 -46.3537 210.935
+v 126.106 46.3537 174.382
+v 126.106 -46.3537 174.382
+v -2.98085 46.3537 215.182
+v -2.98085 -46.3537 215.182
+v 98.1776 46.3537 191.502
+v 98.1776 -46.3537 191.502
+v -16.0821 46.3537 214.6
+v -16.0821 -46.3537 214.6
+v 176.454 46.3537 123.191
+v 176.454 -46.3537 123.191
+v -48.4681 46.3537 209.673
+v -48.4681 -46.3537 209.673
+v -35.6068 46.3537 212.236
+v -35.6068 -46.3537 212.236
+v 115.251 46.3537 181.74
+v 115.251 -46.3537 181.74
+v 193.108 46.3537 94.981
+v 193.108 -46.3537 94.981
+v 103.967 46.3537 188.422
+v 205.287 46.3537 64.5704
+v 103.967 -46.3537 188.422
+v 205.287 -46.3537 64.5704
+v 61.7207 46.3537 206.161
+v 61.7207 -46.3537 206.161
+v 207.159 46.3537 58.2855
+v 172.619 46.3537 128.51
+v 136.494 46.3537 166.377
+v 67.9736 46.3537 204.185
+v 207.159 -46.3537 58.2855
+v 172.619 -46.3537 128.51
+v 136.494 -46.3537 166.377
+v 67.9736 -46.3537 204.185
+v -61.1493 46.3537 206.332
+v -61.1493 -46.3537 206.332
+v 120.735 46.3537 178.144
+v 120.735 -46.3537 178.144
+v 180.126 46.3537 117.757
+v 180.126 -46.3537 117.757
+v 92.297 46.3537 194.405
+v 92.297 -46.3537 194.405
+v 141.5 46.3537 162.141
+v 74.1635 46.3537 202.019
+v 141.5 -46.3537 162.141
+v 74.1635 -46.3537 202.019
+v 23.2061 46.3537 213.947
+v 23.2061 -46.3537 213.947
+v 80.2844 46.3537 199.666
+v -29.1236 46.3537 213.223
+v 80.2844 -46.3537 199.666
+v -29.1236 -46.3537 213.223
+v 55.4104 46.3537 207.946
+v 55.4104 -46.3537 207.946
+v 198.535 46.3537 83.0424
+v 198.535 -46.3537 83.0424
+v 29.7142 46.3537 213.141
+v 29.7142 -46.3537 213.141
+v -9.53589 46.3537 214.991
+v -9.53589 -46.3537 214.991
+v -73.6035 46.3537 202.224
+v 155.712 46.3537 148.546
+v -54.8342 46.3537 208.099
+v -73.6035 -46.3537 202.224
+v 155.712 -46.3537 148.546
+v -54.8342 -46.3537 208.099
+v 214.803 46.3537 13.108
+v 214.803 -46.3537 13.108
+v 203.224 46.3537 70.7954
+v 203.224 -46.3537 70.7954
+v 168.623 46.3537 133.71
+v 160.166 46.3537 143.732
+v 151.113 46.3537 153.221
+v 131.361 46.3537 170.459
+v 168.623 -46.3537 133.71
+v 160.166 -46.3537 143.732
+v 151.113 -46.3537 153.221
+v 131.361 -46.3537 170.459
+v 210.324 46.3537 45.5592
+v 210.324 -46.3537 45.5592
+v -22.6133 46.3537 214.011
+v -22.6133 -46.3537 214.011
+v 195.912 46.3537 89.053
+v 190.124 46.3537 100.821
+v 86.3308 46.3537 197.127
+v 195.912 -46.3537 89.053
+v 190.124 -46.3537 100.821
+v 86.3308 -46.3537 197.127
+v 212.709 46.3537 32.6636
+v 212.709 -46.3537 32.6636
+v -42.057 46.3537 211.053
+v -42.057 -46.3537 211.053
+v 215.202 46.3537 0
+v 215.202 -46.3537 0
+v 211.615 46.3537 39.1296
+v 211.615 -46.3537 39.1296
+v 214.304 46.3537 19.6468
+v 36.1946 46.3537 212.137
+v 214.304 -46.3537 19.6468
+v 36.1946 -46.3537 212.137
+v 208.839 46.3537 51.9464
+v 208.839 -46.3537 51.9464
+v 200.973 46.3537 76.9546
+v 200.973 -46.3537 76.9546
+v 10.1315 46.3537 214.964
+v 10.1315 -46.3537 214.964
+v 215.102 46.3537 6.55706
+v 215.102 -46.3537 6.55706
+v 186.964 46.3537 106.567
+v 186.964 -46.3537 106.567
+v 183.913 -72.4562 -100
+v 183.913 72.4562 -100
+v -156.871 -72.4562 138.62
+v -156.871 72.4562 138.62
+v 192.156 42.9357 101.898
+v 192.156 -42.9357 101.898
+v 157.376 42.9357 150.133
+v 137.953 42.9357 168.155
+v 157.376 -42.9357 150.133
+v 137.953 -42.9357 168.155
+v 68.7001 42.9357 206.367
+v 68.7001 -42.9357 206.367
+v 110.832 42.9357 187.146
+v 110.832 -42.9357 187.146
+v 209.373 42.9357 58.9084
+v 209.373 -42.9357 58.9084
+v 217.502 42.9357 0
+v 174.463 42.9357 129.883
+v 217.502 -42.9357 0
+v 174.463 -42.9357 129.883
+v 30.0317 42.9357 215.419
+v 30.0317 -42.9357 215.419
+v 216.594 42.9357 19.8568
+v 216.594 -42.9357 19.8568
+v 93.2834 42.9357 196.482
+v 81.1424 42.9357 201.799
+v 93.2834 -42.9357 196.482
+v 81.1424 -42.9357 201.799
+v 182.051 42.9357 119.015
+v 182.051 -42.9357 119.015
+v 99.2268 42.9357 193.549
+v 207.481 42.9357 65.2604
+v 185.592 42.9357 113.413
+v 99.2268 -42.9357 193.549
+v 207.481 -42.9357 65.2604
+v 185.592 -42.9357 113.413
+v 43.0972 42.9357 213.189
+v 43.0972 -42.9357 213.189
+v 211.07 42.9357 52.5016
+v 211.07 -42.9357 52.5016
+v -48.986 42.9357 211.914
+v -48.986 -42.9357 211.914
+v -29.4348 42.9357 215.501
+v -29.4348 -42.9357 215.501
+v 56.0026 42.9357 210.169
+v 56.0026 -42.9357 210.169
+v -22.855 42.9357 216.298
+v -22.855 -42.9357 216.298
+v 212.572 42.9357 46.046
+v 212.572 -42.9357 46.046
+v 161.877 42.9357 145.268
+v 161.877 -42.9357 145.268
+v -9.6378 42.9357 217.288
+v -9.6378 -42.9357 217.288
+v 198.006 42.9357 90.0047
+v 198.006 -42.9357 90.0047
+v -35.9873 42.9357 214.504
+v -35.9873 -42.9357 214.504
+v 195.171 42.9357 95.996
+v 178.34 42.9357 124.507
+v 195.171 -42.9357 95.996
+v 178.34 -42.9357 124.507
+v 3.61519 42.9357 217.472
+v 3.61519 -42.9357 217.472
+v 213.876 42.9357 39.5477
+v 213.876 -42.9357 39.5477
+v -68.1281 42.9357 206.557
+v 105.078 42.9357 190.436
+v -61.8028 42.9357 208.537
+v 105.078 -42.9357 190.436
+v -68.1281 -42.9357 206.557
+v -61.8028 -42.9357 208.537
+v 49.5729 42.9357 211.777
+v 49.5729 -42.9357 211.777
+v 16.8548 42.9357 216.848
+v 16.8548 -42.9357 216.848
+v 122.025 42.9357 180.047
+v 122.025 -42.9357 180.047
+v 87.2534 42.9357 199.234
+v 87.2534 -42.9357 199.234
+v -42.5064 42.9357 213.308
+v -42.5064 -42.9357 213.308
+v 214.982 42.9357 33.0127
+v 214.982 -42.9357 33.0127
+v 217.098 42.9357 13.2481
+v 217.098 -42.9357 13.2481
+v 132.765 42.9357 172.281
+v 74.956 42.9357 204.178
+v 132.765 -42.9357 172.281
+v 74.956 -42.9357 204.178
+v 143.012 42.9357 163.874
+v 62.3803 42.9357 208.365
+v 143.012 -42.9357 163.874
+v 62.3803 -42.9357 208.365
+v 10.2397 42.9357 217.261
+v 10.2397 -42.9357 217.261
+v 116.482 42.9357 183.682
+v 116.482 -42.9357 183.682
+v 170.425 42.9357 135.139
+v 170.425 -42.9357 135.139
+v -3.0127 42.9357 217.481
+v -3.0127 -42.9357 217.481
+v 23.4541 42.9357 216.234
+v 23.4541 -42.9357 216.234
+v 36.5815 42.9357 214.404
+v 36.5815 -42.9357 214.404
+v 152.728 42.9357 154.859
+v 152.728 -42.9357 154.859
+v 217.401 42.9357 6.62713
+v 217.401 -42.9357 6.62713
+v -74.3901 42.9357 204.385
+v -74.3901 -42.9357 204.385
+v -55.4202 42.9357 210.323
+v -55.4202 -42.9357 210.323
+v 203.12 42.9357 77.777
+v 203.12 -42.9357 77.777
+v -16.254 42.9357 216.894
+v -16.254 -42.9357 216.894
+v 205.396 42.9357 71.5519
+v 205.396 -42.9357 71.5519
+v 127.454 42.9357 176.246
+v 127.454 -42.9357 176.246
+v 200.656 42.9357 83.9298
+v 166.228 42.9357 140.269
+v 147.939 42.9357 159.44
+v 200.656 -42.9357 83.9298
+v 166.228 -42.9357 140.269
+v 147.939 -42.9357 159.44
+v 188.962 42.9357 107.706
+v 188.962 -42.9357 107.706
+v 215.888 42.9357 26.447
+v 215.888 -42.9357 26.447
+v 219.521 39.4039 6.69175
+v 219.521 -39.4039 6.69175
+v -3.04208 39.4039 219.602
+v -3.04208 -39.4039 219.602
+v 134.06 39.4039 173.96
+v 134.06 -39.4039 173.96
+v 211.414 39.4039 59.4827
+v 50.0563 39.4039 213.842
+v 211.414 -39.4039 59.4827
+v 50.0563 -39.4039 213.842
+v 43.5174 39.4039 215.268
+v 43.5174 -39.4039 215.268
+v -75.1154 39.4039 206.378
+v 158.91 39.4039 151.597
+v -75.1154 -39.4039 206.378
+v 158.91 -39.4039 151.597
+v 36.9381 39.4039 216.494
+v 36.9381 -39.4039 216.494
+v -36.3382 39.4039 216.596
+v -36.3382 -39.4039 216.596
+v 88.1042 39.4039 201.176
+v 88.1042 -39.4039 201.176
+v 219.215 39.4039 13.3773
+v 219.215 -39.4039 13.3773
+v -68.7924 39.4039 208.571
+v -68.7924 -39.4039 208.571
+v 197.074 39.4039 96.932
+v 197.074 -39.4039 96.932
+v 187.402 39.4039 114.519
+v 187.402 -39.4039 114.519
+v -55.9605 39.4039 212.374
+v -55.9605 -39.4039 212.374
+v 183.826 39.4039 120.176
+v 144.407 39.4039 165.472
+v 183.826 -39.4039 120.176
+v 144.407 -39.4039 165.472
+v 117.618 39.4039 185.473
+v 117.618 -39.4039 185.473
+v 215.962 39.4039 39.9333
+v 215.962 -39.4039 39.9333
+v 219.623 39.4039 0
+v 111.912 39.4039 188.97
+v 219.623 -39.4039 0
+v 111.912 -39.4039 188.97
+v -16.4124 39.4039 219.009
+v -16.4124 -39.4039 219.009
+v 154.217 39.4039 156.369
+v 154.217 -39.4039 156.369
+v -49.4637 39.4039 213.98
+v -49.4637 -39.4039 213.98
+v 81.9336 39.4039 203.767
+v 81.9336 -39.4039 203.767
+v 217.078 39.4039 33.3346
+v 217.078 -39.4039 33.3346
+v 214.645 39.4039 46.495
+v 214.645 -39.4039 46.495
+v 30.3246 39.4039 217.519
+v 30.3246 -39.4039 217.519
+v 209.504 39.4039 65.8968
+v 209.504 -39.4039 65.8968
+v 217.993 39.4039 26.7049
+v 217.993 -39.4039 26.7049
+v 205.101 39.4039 78.5353
+v 172.087 39.4039 136.456
+v 128.697 39.4039 177.964
+v 123.215 39.4039 181.803
+v 205.101 -39.4039 78.5353
+v 172.087 -39.4039 136.456
+v 128.697 -39.4039 177.964
+v 123.215 -39.4039 181.803
+v 213.128 39.4039 53.0135
+v 213.128 -39.4039 53.0135
+v -9.73177 39.4039 219.407
+v -9.73177 -39.4039 219.407
+v 10.3396 39.4039 219.379
+v 10.3396 -39.4039 219.379
+v 56.5487 39.4039 212.218
+v 56.5487 -39.4039 212.218
+v 17.0191 39.4039 218.962
+v 17.0191 -39.4039 218.962
+v 207.399 39.4039 72.2496
+v 207.399 -39.4039 72.2496
+v 23.6828 39.4039 218.342
+v 23.6828 -39.4039 218.342
+v 199.936 39.4039 90.8823
+v 194.03 39.4039 102.892
+v 199.936 -39.4039 90.8823
+v 194.03 -39.4039 102.892
+v 167.849 39.4039 141.636
+v 149.382 39.4039 160.995
+v 167.849 -39.4039 141.636
+v 149.382 -39.4039 160.995
+v -29.7218 39.4039 217.602
+v -29.7218 -39.4039 217.602
+v 3.65044 39.4039 219.592
+v 3.65044 -39.4039 219.592
+v 180.079 39.4039 125.721
+v 163.456 39.4039 146.685
+v 180.079 -39.4039 125.721
+v 163.456 -39.4039 146.685
+v -42.9209 39.4039 215.388
+v -42.9209 -39.4039 215.388
+v 62.9885 39.4039 210.396
+v 62.9885 -39.4039 210.396
+v 202.613 39.4039 84.7482
+v 202.613 -39.4039 84.7482
+v 94.1929 39.4039 198.398
+v 94.1929 -39.4039 198.398
+v 75.6869 39.4039 206.169
+v 75.6869 -39.4039 206.169
+v 69.3699 39.4039 208.38
+v 69.3699 -39.4039 208.38
+v -62.4054 39.4039 210.57
+v -62.4054 -39.4039 210.57
+v 218.706 39.4039 20.0504
+v 218.706 -39.4039 20.0504
+v -23.0779 39.4039 218.407
+v -23.0779 -39.4039 218.407
+v 190.805 39.4039 108.756
+v 190.805 -39.4039 108.756
+v 100.194 39.4039 195.436
+v 100.194 -39.4039 195.436
+v 106.103 39.4039 192.293
+v 106.103 -39.4039 192.293
+v 176.165 39.4039 131.15
+v 176.165 -39.4039 131.15
+v 139.298 39.4039 169.795
+v 139.298 -39.4039 169.795
+v 187.598 -70.6143 -100
+v 187.598 70.6143 -100
+v -158.132 -70.6143 142.083
+v -158.132 70.6143 142.083
+v 155.577 35.7675 157.747
+v 155.577 -35.7675 157.747
+v 189.054 35.7675 115.529
+v 189.054 -35.7675 115.529
+v -69.3988 35.7675 210.41
+v -69.3988 -35.7675 210.41
+v -9.81757 35.7675 221.341
+v -9.81757 -35.7675 221.341
+v 50.4976 35.7675 215.727
+v 50.4976 -35.7675 215.727
+v 213.278 35.7675 60.0071
+v 213.278 -35.7675 60.0071
+v 23.8916 35.7675 220.267
+v 23.8916 -35.7675 220.267
+v 206.909 35.7675 79.2277
+v 206.909 -35.7675 79.2277
+v -16.5571 35.7675 220.939
+v -16.5571 -35.7675 220.939
+v 211.351 35.7675 66.4777
+v 211.351 -35.7675 66.4777
+v -75.7776 35.7675 208.197
+v 169.329 35.7675 142.885
+v -75.7776 -35.7675 208.197
+v 169.329 -35.7675 142.885
+v 220.634 35.7675 20.2272
+v 220.634 -35.7675 20.2272
+v 112.899 35.7675 190.636
+v 173.604 35.7675 137.659
+v 160.311 35.7675 152.934
+v 173.604 -35.7675 137.659
+v 160.311 -35.7675 152.934
+v 112.899 -35.7675 190.636
+v 17.1691 35.7675 220.893
+v 17.1691 -35.7675 220.893
+v 192.486 35.7675 109.715
+v 192.486 -35.7675 109.715
+v 145.68 35.7675 166.93
+v 145.68 -35.7675 166.93
+v -49.8997 35.7675 215.867
+v -49.8997 -35.7675 215.867
+v 181.666 35.7675 126.829
+v 181.666 -35.7675 126.829
+v 218.992 35.7675 33.6285
+v 218.992 -35.7675 33.6285
+v 177.718 35.7675 132.306
+v 135.242 35.7675 175.494
+v 177.718 -35.7675 132.306
+v 135.242 -35.7675 175.494
+v -3.0689 35.7675 221.538
+v -3.0689 -35.7675 221.538
+v -29.9839 35.7675 219.521
+v -29.9839 -35.7675 219.521
+v 118.655 35.7675 187.108
+v 95.0233 35.7675 200.147
+v 118.655 -35.7675 187.108
+v 95.0233 -35.7675 200.147
+v 30.5919 35.7675 219.437
+v 30.5919 -35.7675 219.437
+v 43.9011 35.7675 217.166
+v 43.9011 -35.7675 217.166
+v 10.4307 35.7675 221.313
+v 10.4307 -35.7675 221.313
+v 37.2638 35.7675 218.403
+v 37.2638 -35.7675 218.403
+v 140.526 35.7675 171.292
+v -36.6586 35.7675 218.505
+v 140.526 -35.7675 171.292
+v -36.6586 -35.7675 218.505
+v 217.866 35.7675 40.2854
+v 217.866 -35.7675 40.2854
+v 76.3541 35.7675 207.987
+v 76.3541 -35.7675 207.987
+v 221.456 35.7675 6.75074
+v 221.456 -35.7675 6.75074
+v 107.038 35.7675 193.988
+v 195.74 35.7675 103.799
+v 107.038 -35.7675 193.988
+v 195.74 -35.7675 103.799
+v 198.812 35.7675 97.7865
+v 164.897 35.7675 147.978
+v 150.698 35.7675 162.414
+v 198.812 -35.7675 97.7865
+v 164.897 -35.7675 147.978
+v 150.698 -35.7675 162.414
+v -62.9556 35.7675 212.426
+v -62.9556 -35.7675 212.426
+v -43.2993 35.7675 217.287
+v -43.2993 -35.7675 217.287
+v 216.537 35.7675 46.9049
+v 216.537 -35.7675 46.9049
+v 221.148 35.7675 13.4952
+v 221.148 -35.7675 13.4952
+v 215.007 35.7675 53.4808
+v 215.007 -35.7675 53.4808
+v -56.4539 35.7675 214.246
+v -56.4539 -35.7675 214.246
+v -23.2813 35.7675 220.332
+v -23.2813 -35.7675 220.332
+v 219.915 35.7675 26.9403
+v 69.9815 35.7675 210.217
+v 219.915 -35.7675 26.9403
+v 69.9815 -35.7675 210.217
+v 201.699 35.7675 91.6835
+v 201.699 -35.7675 91.6835
+v 185.446 35.7675 121.235
+v 129.831 35.7675 179.533
+v 185.446 -35.7675 121.235
+v 129.831 -35.7675 179.533
+v 209.227 35.7675 72.8865
+v 82.6559 35.7675 205.564
+v 209.227 -35.7675 72.8865
+v 82.6559 -35.7675 205.564
+v 88.8809 35.7675 202.95
+v 88.8809 -35.7675 202.95
+v 101.078 35.7675 197.159
+v 124.301 35.7675 183.406
+v 101.078 -35.7675 197.159
+v 124.301 -35.7675 183.406
+v 63.5438 35.7675 212.251
+v 63.5438 -35.7675 212.251
+v 3.68262 35.7675 221.528
+v 3.68262 -35.7675 221.528
+v 221.559 35.7675 0
+v 221.559 -35.7675 0
+v 57.0472 35.7675 214.089
+v 57.0472 -35.7675 214.089
+v 204.399 35.7675 85.4953
+v 204.399 -35.7675 85.4953
+v 156.803 32.0363 158.99
+v 156.803 -32.0363 158.99
+v 10.5129 32.0363 223.058
+v 10.5129 -32.0363 223.058
+v -16.6876 32.0363 222.681
+v -16.6876 -32.0363 222.681
+v 107.882 32.0363 195.517
+v 107.882 -32.0363 195.517
+v 208.54 32.0363 79.8522
+v 208.54 -32.0363 79.8522
+v 24.0799 32.0363 222.003
+v 24.0799 -32.0363 222.003
+v -30.2202 32.0363 221.251
+v -30.2202 -32.0363 221.251
+v 216.702 32.0363 53.9024
+v -36.9475 32.0363 220.227
+v 216.702 -32.0363 53.9024
+v -36.9475 -32.0363 220.227
+v 222.891 32.0363 13.6016
+v 222.891 -32.0363 13.6016
+v -50.293 32.0363 217.568
+v -50.293 -32.0363 217.568
+v -3.09309 32.0363 223.284
+v -3.09309 -32.0363 223.284
+v 101.874 32.0363 198.713
+v 203.289 32.0363 92.4062
+v 101.874 -32.0363 198.713
+v 203.289 -32.0363 92.4062
+v -56.8988 32.0363 215.935
+v -56.8988 -32.0363 215.935
+v 37.5575 32.0363 220.124
+v 37.5575 -32.0363 220.124
+v -9.89495 32.0363 223.086
+v -9.89495 -32.0363 223.086
+v 179.118 32.0363 133.349
+v 151.886 32.0363 163.694
+v 95.7723 32.0363 201.725
+v 179.118 -32.0363 133.349
+v 151.886 -32.0363 163.694
+v 95.7723 -32.0363 201.725
+v 136.307 32.0363 176.877
+v 136.307 -32.0363 176.877
+v 119.59 32.0363 188.583
+v 186.908 32.0363 122.191
+v 174.972 32.0363 138.744
+v 141.633 32.0363 172.642
+v 119.59 -32.0363 188.583
+v 186.908 -32.0363 122.191
+v 174.972 -32.0363 138.744
+v 141.633 -32.0363 172.642
+v 222.373 32.0363 20.3866
+v 222.373 -32.0363 20.3866
+v 190.544 32.0363 116.439
+v 190.544 -32.0363 116.439
+v -43.6405 32.0363 218.999
+v -43.6405 -32.0363 218.999
+v 3.71165 32.0363 223.275
+v 3.71165 -32.0363 223.275
+v -76.3749 32.0363 209.838
+v 76.956 32.0363 209.626
+v -76.3749 -32.0363 209.838
+v 76.956 -32.0363 209.626
+v 221.648 32.0363 27.1527
+v 221.648 -32.0363 27.1527
+v 125.281 32.0363 184.851
+v 161.575 32.0363 154.139
+v 146.828 32.0363 168.246
+v 125.281 -32.0363 184.851
+v 161.575 -32.0363 154.139
+v 146.828 -32.0363 168.246
+v -63.4518 32.0363 214.101
+v -63.4518 -32.0363 214.101
+v -23.4648 32.0363 222.069
+v -23.4648 -32.0363 222.069
+v 170.663 32.0363 144.011
+v 170.663 -32.0363 144.011
+v 206.01 32.0363 86.1692
+v 206.01 -32.0363 86.1692
+v 200.379 32.0363 98.5573
+v 64.0447 32.0363 213.924
+v 200.379 -32.0363 98.5573
+v 64.0447 -32.0363 213.924
+v 218.244 32.0363 47.2746
+v 218.244 -32.0363 47.2746
+v 219.583 32.0363 40.6029
+v 219.583 -32.0363 40.6029
+v 83.3074 32.0363 207.184
+v 83.3074 -32.0363 207.184
+v 89.5815 32.0363 204.549
+v 89.5815 -32.0363 204.549
+v 113.789 32.0363 192.139
+v 113.789 -32.0363 192.139
+v 183.098 32.0363 127.829
+v 166.196 32.0363 149.144
+v 183.098 -32.0363 127.829
+v 166.196 -32.0363 149.144
+v 223.202 32.0363 6.80396
+v 223.202 -32.0363 6.80396
+v 130.855 32.0363 180.948
+v 130.855 -32.0363 180.948
+v 220.718 32.0363 33.8935
+v 220.718 -32.0363 33.8935
+v 50.8956 32.0363 217.428
+v 50.8956 -32.0363 217.428
+v 17.3045 32.0363 222.634
+v 17.3045 -32.0363 222.634
+v 30.833 32.0363 221.167
+v 30.833 -32.0363 221.167
+v 197.283 32.0363 104.617
+v 194.004 32.0363 110.579
+v 197.283 -32.0363 104.617
+v 194.004 -32.0363 110.579
+v 70.5331 32.0363 211.874
+v 70.5331 -32.0363 211.874
+v -69.9458 32.0363 212.068
+v -69.9458 -32.0363 212.068
+v 210.876 32.0363 73.4611
+v 210.876 -32.0363 73.4611
+v 44.2471 32.0363 218.878
+v 44.2471 -32.0363 218.878
+v 213.017 32.0363 67.0017
+v 213.017 -32.0363 67.0017
+v 57.4968 32.0363 215.776
+v 57.4968 -32.0363 215.776
+v 214.959 32.0363 60.4801
+v 214.959 -32.0363 60.4801
+v 223.305 32.0363 0
+v 223.305 -32.0363 0
+v 129.334 29.9857 183.096
+v 127.819 -29.9857 184.156
+v 129.597 -29.9742 182.915
+v 127.559 29.9742 184.342
+v 130.748 29.8843 182.139
+v 126.436 -29.8843 185.158
+v 131.391 -29.8064 181.714
+v 125.816 29.8064 185.617
+v 132.166 29.6864 181.21
+v 125.079 -29.6864 186.173
+v 133.188 -29.4849 180.561
+v 124.119 29.4849 186.911
+v 123.752 -29.3939 187.197
+v 133.582 29.3939 180.314
+v 122.781 -29.114 187.967
+v 134.637 29.114 179.665
+v -159.358 -68.5852 145.452
+v -159.358 68.5852 145.452
+v 191.183 -68.5852 -100
+v 191.183 68.5852 -100
+v 134.972 -29.0143 179.462
+v 122.477 29.0143 188.212
+v 121.832 -28.7837 188.736
+v 135.685 28.7837 179.036
+v 137.002 -28.2928 178.266
+v 120.658 28.2928 189.71
+v 157.893 28.2202 160.096
+v 157.893 -28.2202 160.096
+v -30.4302 28.2202 222.789
+v -30.4302 -28.2202 222.789
+v 224.857 28.2202 0
+v -50.6426 28.2202 219.08
+v 224.857 -28.2202 0
+v -50.6426 -28.2202 219.08
+v -70.432 28.2202 213.542
+v 214.497 28.2202 67.4674
+v -70.432 -28.2202 213.542
+v 214.497 -28.2202 67.4674
+v 224.753 28.2202 6.85124
+v 224.753 -28.2202 6.85124
+v 191.869 28.2202 117.248
+v 191.869 -28.2202 117.248
+v 216.453 28.2202 60.9005
+v 216.453 -28.2202 60.9005
+v 224.44 28.2202 13.6961
+v 224.44 -28.2202 13.6961
+v 137.255 28.2202 178.107
+v 162.698 28.2202 155.21
+v 137.255 -28.2202 178.107
+v 162.698 -28.2202 155.21
+v 57.8965 28.2202 217.276
+v 57.8965 -28.2202 217.276
+v 83.8864 28.2202 208.624
+v 83.8864 -28.2202 208.624
+v 201.772 28.2202 99.2423
+v 201.772 -28.2202 99.2423
+v 218.208 28.2202 54.277
+v 218.208 -28.2202 54.277
+v 102.582 28.2202 200.094
+v 102.582 -28.2202 200.094
+v 184.371 28.2202 128.718
+v 184.371 -28.2202 128.718
+v 223.918 28.2202 20.5283
+v 223.918 -28.2202 20.5283
+v 77.4908 28.2202 211.083
+v 77.4908 -28.2202 211.083
+v 10.586 28.2202 224.608
+v 10.586 -28.2202 224.608
+v -37.2043 28.2202 221.758
+v -37.2043 -28.2202 221.758
+v 195.352 28.2202 111.348
+v 152.942 28.2202 164.832
+v 96.438 28.2202 203.127
+v 195.352 -28.2202 111.348
+v 152.942 -28.2202 164.832
+v 96.438 -28.2202 203.127
+v 71.0233 28.2202 213.346
+v 71.0233 -28.2202 213.346
+v 209.989 28.2202 80.4072
+v 209.989 -28.2202 80.4072
+v 167.351 28.2202 150.181
+v 167.351 -28.2202 150.181
+v 90.2041 28.2202 205.971
+v 90.2041 -28.2202 205.971
+v 147.848 28.2202 169.416
+v 108.631 28.2202 196.876
+v 171.85 28.2202 145.012
+v 147.848 -28.2202 169.416
+v 108.631 -28.2202 196.876
+v 171.85 -28.2202 145.012
+v -63.8928 28.2202 215.589
+v -63.8928 -28.2202 215.589
+v 204.702 28.2202 93.0484
+v 204.702 -28.2202 93.0484
+v 51.2493 28.2202 218.939
+v 51.2493 -28.2202 218.939
+v 37.8185 28.2202 221.654
+v 37.8185 -28.2202 221.654
+v 221.109 28.2202 40.8851
+v 219.761 28.2202 47.6032
+v 31.0473 28.2202 222.704
+v 221.109 -28.2202 40.8851
+v 219.761 -28.2202 47.6032
+v 31.0473 -28.2202 222.704
+v -23.6279 28.2202 223.613
+v -23.6279 -28.2202 223.613
+v 114.58 28.2202 193.474
+v 180.363 28.2202 134.275
+v 114.58 -28.2202 193.474
+v 180.363 -28.2202 134.275
+v -76.9057 28.2202 211.297
+v -76.9057 -28.2202 211.297
+v 198.654 28.2202 105.344
+v 198.654 -28.2202 105.344
+v -16.8036 28.2202 224.229
+v -16.8036 -28.2202 224.229
+v 3.73745 28.2202 224.826
+v 3.73745 -28.2202 224.826
+v -57.2943 28.2202 217.436
+v -57.2943 -28.2202 217.436
+v 17.4247 28.2202 224.181
+v 17.4247 -28.2202 224.181
+v 44.5546 28.2202 220.399
+v 44.5546 -28.2202 220.399
+v 64.4898 28.2202 215.411
+v 64.4898 -28.2202 215.411
+v 176.188 28.2202 139.709
+v 176.188 -28.2202 139.709
+v -9.96372 28.2202 224.637
+v -9.96372 -28.2202 224.637
+v 222.252 28.2202 34.1291
+v 222.252 -28.2202 34.1291
+v 207.442 28.2202 86.7681
+v 207.442 -28.2202 86.7681
+v 223.189 28.2202 27.3414
+v 223.189 -28.2202 27.3414
+v 24.2473 28.2202 223.546
+v 24.2473 -28.2202 223.546
+v -3.11458 28.2202 224.836
+v -3.11458 -28.2202 224.836
+v 142.618 28.2202 173.842
+v 142.618 -28.2202 173.842
+v 212.342 28.2202 73.9716
+v 212.342 -28.2202 73.9716
+v 188.207 28.2202 123.04
+v 188.207 -28.2202 123.04
+v -43.9439 28.2202 220.522
+v -43.9439 -28.2202 220.522
+v 120.422 28.2202 189.893
+v 120.422 -28.2202 189.893
+v 120.372 -28.1585 189.952
+v 137.327 28.1585 178.08
+v 118.978 -27.4165 191.152
+v 138.931 27.4165 177.181
+v 118.938 27.3927 191.188
+v 138.979 -27.3927 177.155
+v 140.49 26.5651 176.338
+v 117.653 -26.5651 192.328
+v 117.322 26.3275 192.628
+v 140.885 -26.3275 176.129
+v 116.401 -25.6118 193.473
+v 141.994 25.6118 175.553
+v 115.971 25.2482 193.873
+v 142.516 -25.2482 175.286
+v 115.091 -24.4383 194.704
+v 143.598 24.4383 174.743
+v 189.34 24.3292 123.781
+v 189.34 -24.3292 123.781
+v -77.3687 24.3292 212.569
+v -77.3687 -24.3292 212.569
+v -10.0237 24.3292 225.989
+v -10.0237 -24.3292 225.989
+v 103.2 24.3292 201.299
+v 103.2 -24.3292 201.299
+v 226.211 24.3292 0
+v 226.211 -24.3292 0
+v 44.8228 24.3292 221.726
+v 44.8228 -24.3292 221.726
+v 177.249 24.3292 140.55
+v 177.249 -24.3292 140.55
+v 217.756 24.3292 61.2671
+v 217.756 -24.3292 61.2671
+v -3.13333 24.3292 226.189
+v -3.13333 -24.3292 226.189
+v 208.691 24.3292 87.2903
+v 208.691 -24.3292 87.2903
+v 193.024 24.3292 117.954
+v 168.359 24.3292 151.085
+v 193.024 -24.3292 117.954
+v 168.359 -24.3292 151.085
+v 224.532 24.3292 27.506
+v 224.532 -24.3292 27.506
+v -70.8559 24.3292 214.827
+v 222.44 24.3292 41.1312
+v 196.528 24.3292 112.018
+v -70.8559 -24.3292 214.827
+v 222.44 -24.3292 41.1312
+v 196.528 -24.3292 112.018
+v 225.791 24.3292 13.7786
+v 225.791 -24.3292 13.7786
+v 31.2342 24.3292 224.044
+v 31.2342 -24.3292 224.044
+v 211.253 24.3292 80.8912
+v 153.862 24.3292 165.824
+v 211.253 -24.3292 80.8912
+v 153.862 -24.3292 165.824
+v 17.5296 24.3292 225.531
+v 17.5296 -24.3292 225.531
+v 213.62 24.3292 74.4169
+v 213.62 -24.3292 74.4169
+v 148.738 24.3292 170.435
+v 185.481 24.3292 129.492
+v 148.738 -24.3292 170.435
+v 185.481 -24.3292 129.492
+v 97.0184 24.3292 204.35
+v 97.0184 -24.3292 204.35
+v -16.9048 24.3292 225.578
+v -16.9048 -24.3292 225.578
+v 90.747 24.3292 207.211
+v 90.747 -24.3292 207.211
+v 221.083 24.3292 47.8897
+v 64.878 24.3292 216.708
+v 221.083 -24.3292 47.8897
+v 64.878 -24.3292 216.708
+v 38.0462 24.3292 222.988
+v 38.0462 -24.3292 222.988
+v 84.3913 24.3292 209.88
+v 84.3913 -24.3292 209.88
+v -57.6392 24.3292 218.744
+v -57.6392 -24.3292 218.744
+v 77.9573 24.3292 212.354
+v -64.2774 24.3292 216.887
+v 77.9573 -24.3292 212.354
+v -64.2774 -24.3292 216.887
+v 71.4508 24.3292 214.63
+v 71.4508 -24.3292 214.63
+v 172.884 24.3292 145.885
+v 172.884 -24.3292 145.885
+v 226.106 24.3292 6.89248
+v 226.106 -24.3292 6.89248
+v 10.6497 24.3292 225.96
+v 10.6497 -24.3292 225.96
+v -23.7701 24.3292 224.958
+v -23.7701 -24.3292 224.958
+v 219.522 24.3292 54.6037
+v 219.522 -24.3292 54.6037
+v 181.449 24.3292 135.084
+v 181.449 -24.3292 135.084
+v 3.75994 24.3292 226.18
+v 3.75994 -24.3292 226.18
+v 223.59 24.3292 34.3345
+v 223.59 -24.3292 34.3345
+v 24.3932 24.3292 224.892
+v 24.3932 -24.3292 224.892
+v 215.788 24.3292 67.8735
+v 215.788 -24.3292 67.8735
+v -30.6134 24.3292 224.13
+v -30.6134 -24.3292 224.13
+v 58.2449 24.3292 218.584
+v 58.2449 -24.3292 218.584
+v 158.844 24.3292 161.059
+v 158.844 -24.3292 161.059
+v -44.2084 24.3292 221.849
+v -44.2084 -24.3292 221.849
+v 51.5578 24.3292 220.257
+v 51.5578 -24.3292 220.257
+v 202.986 24.3292 99.8397
+v 202.986 -24.3292 99.8397
+v 109.285 24.3292 198.061
+v -50.9474 24.3292 220.399
+v 109.285 -24.3292 198.061
+v -50.9474 -24.3292 220.399
+v 199.85 24.3292 105.978
+v 199.85 -24.3292 105.978
+v 205.934 24.3292 93.6085
+v 205.934 -24.3292 93.6085
+v 225.266 24.3292 20.6518
+v 225.266 -24.3292 20.6518
+v -37.4283 24.3292 223.093
+v -37.4283 -24.3292 223.093
+v 163.677 24.3292 156.145
+v 163.677 -24.3292 156.145
+v 114.71 24.0583 195.069
+v 144.072 -24.0583 174.51
+v 113.874 -23.1575 195.88
+v 145.12 23.1575 174.002
+v 113.539 22.7673 196.21
+v 145.544 -22.7673 173.799
+v 146.551 21.7792 173.326
+v 112.75 -21.7792 196.994
+v 112.457 21.3845 197.288
+v 146.928 -21.3845 173.152
+v 78.354 20.3737 213.434
+v 78.354 -20.3737 213.434
+v 204.019 20.3737 100.348
+v 204.019 -20.3737 100.348
+v 71.8145 20.3737 215.723
+v 71.8145 -20.3737 215.723
+v -44.4334 20.3737 222.978
+v -44.4334 -20.3737 222.978
+v 58.5414 20.3737 219.696
+v 58.5414 -20.3737 219.696
+v 209.753 20.3737 87.7346
+v 206.982 20.3737 94.0849
+v 209.753 -20.3737 87.7346
+v 206.982 -20.3737 94.0849
+v 226.413 20.3737 20.757
+v 226.413 -20.3737 20.757
+v 224.728 20.3737 34.5093
+v 224.728 -20.3737 34.5093
+v 17.6189 20.3737 226.678
+v 17.6189 -20.3737 226.678
+v -64.6046 20.3737 217.99
+v -64.6046 -20.3737 217.99
+v 65.2082 20.3737 217.811
+v 65.2082 -20.3737 217.811
+v 97.5123 20.3737 205.39
+v 97.5123 -20.3737 205.39
+v 220.639 20.3737 54.8817
+v 220.639 -20.3737 54.8817
+v 214.707 20.3737 74.7956
+v 214.707 -20.3737 74.7956
+v 227.362 20.3737 0
+v 159.652 20.3737 161.879
+v 227.362 -20.3737 0
+v 159.652 -20.3737 161.879
+v 3.77908 20.3737 227.331
+v 3.77908 -20.3737 227.331
+v 103.725 20.3737 202.323
+v 103.725 -20.3737 202.323
+v 182.372 20.3737 135.771
+v 182.372 -20.3737 135.771
+v 223.572 20.3737 41.3406
+v 223.572 -20.3737 41.3406
+v -3.14928 20.3737 227.34
+v -3.14928 -20.3737 227.34
+v 10.7039 20.3737 227.11
+v 10.7039 -20.3737 227.11
+v -23.8911 20.3737 226.104
+v -23.8911 -20.3737 226.104
+v 197.528 20.3737 112.588
+v 197.528 -20.3737 112.588
+v 222.209 20.3737 48.1335
+v 178.151 20.3737 141.265
+v 173.764 20.3737 146.628
+v 222.209 -20.3737 48.1335
+v 178.151 -20.3737 141.265
+v 173.764 -20.3737 146.628
+v 38.2398 20.3737 224.123
+v 38.2398 -20.3737 224.123
+v 216.887 20.3737 68.2189
+v 216.887 -20.3737 68.2189
+v -10.0747 20.3737 227.139
+v -10.0747 -20.3737 227.139
+v -77.7625 20.3737 213.651
+v 186.425 20.3737 130.152
+v 164.51 20.3737 156.939
+v -77.7625 -20.3737 213.651
+v 186.425 -20.3737 130.152
+v 164.51 -20.3737 156.939
+v 91.2089 20.3737 208.266
+v 91.2089 -20.3737 208.266
+v 45.0509 20.3737 222.854
+v 45.0509 -20.3737 222.854
+v 218.864 20.3737 61.5789
+v 194.006 20.3737 118.555
+v 218.864 -20.3737 61.5789
+v 194.006 -20.3737 118.555
+v -57.9325 20.3737 219.858
+v -57.9325 -20.3737 219.858
+v 154.646 20.3737 166.668
+v 154.646 -20.3737 166.668
+v 31.3932 20.3737 225.184
+v 31.3932 -20.3737 225.184
+v 149.495 20.3737 171.303
+v 149.495 -20.3737 171.303
+v -30.7692 20.3737 225.271
+v -30.7692 -20.3737 225.271
+v 200.867 20.3737 106.518
+v 200.867 -20.3737 106.518
+v 226.94 20.3737 13.8487
+v 226.94 -20.3737 13.8487
+v 169.216 20.3737 151.854
+v 169.216 -20.3737 151.854
+v 212.329 20.3737 81.3029
+v 212.329 -20.3737 81.3029
+v -16.9908 20.3737 226.727
+v -16.9908 -20.3737 226.727
+v -37.6188 20.3737 224.229
+v -37.6188 -20.3737 224.229
+v -71.2166 20.3737 215.921
+v -71.2166 -20.3737 215.921
+v -51.2067 20.3737 221.521
+v -51.2067 -20.3737 221.521
+v 225.675 20.3737 27.646
+v 225.675 -20.3737 27.646
+v 227.257 20.3737 6.92757
+v 227.257 -20.3737 6.92757
+v 84.8209 20.3737 210.948
+v 84.8209 -20.3737 210.948
+v 51.8202 20.3737 221.378
+v 51.8202 -20.3737 221.378
+v 109.842 20.3737 199.069
+v 109.842 -20.3737 199.069
+v 24.5174 20.3737 226.036
+v 24.5174 -20.3737 226.036
+v 190.304 20.3737 124.411
+v 190.304 -20.3737 124.411
+v 147.887 20.3127 172.714
+v 111.718 -20.3127 198.04
+v 111.262 19.5911 198.51
+v 148.484 -19.5911 172.447
+v 149.38 18.4181 172.051
+v 110.584 -18.4181 199.217
+v -160.547 -66.3742 148.718
+v -160.547 66.3742 148.718
+v 194.66 -66.3742 -100
+v 194.66 66.3742 -100
+v 110.198 17.6893 199.623
+v 149.894 -17.6893 171.828
+v 150.718 16.4201 171.474
+v 109.585 -16.4201 200.276
+v -3.16239 16.3642 228.286
+v -3.16239 -16.3642 228.286
+v 31.5238 16.3642 226.122
+v 31.5238 -16.3642 226.122
+v 91.5885 16.3642 209.132
+v 91.5885 -16.3642 209.132
+v 217.789 16.3642 68.5029
+v 217.789 -16.3642 68.5029
+v 183.132 16.3642 136.336
+v 183.132 -16.3642 136.336
+v 227.885 16.3642 13.9063
+v 227.885 -16.3642 13.9063
+v 178.892 16.3642 141.853
+v 178.892 -16.3642 141.853
+v -44.6183 16.3642 223.906
+v -44.6183 -16.3642 223.906
+v 201.703 16.3642 106.961
+v 201.703 -16.3642 106.961
+v 227.355 16.3642 20.8434
+v 227.355 -16.3642 20.8434
+v 72.1134 16.3642 216.62
+v 72.1134 -16.3642 216.62
+v 155.289 16.3642 167.362
+v 213.212 16.3642 81.6413
+v 155.289 -16.3642 167.362
+v 213.212 -16.3642 81.6413
+v 187.201 16.3642 130.693
+v 78.6802 16.3642 214.323
+v 187.201 -16.3642 130.693
+v 78.6802 -16.3642 214.323
+v 17.6922 16.3642 227.622
+v 17.6922 -16.3642 227.622
+v 3.79481 16.3642 228.277
+v 3.79481 -16.3642 228.277
+v 204.868 16.3642 100.766
+v 204.868 -16.3642 100.766
+v -30.8973 16.3642 226.208
+v -30.8973 -16.3642 226.208
+v 174.487 16.3642 147.238
+v 174.487 -16.3642 147.238
+v 10.7485 16.3642 228.055
+v 10.7485 -16.3642 228.055
+v -10.1166 16.3642 228.084
+v -10.1166 -16.3642 228.084
+v 97.9181 16.3642 206.245
+v 97.9181 -16.3642 206.245
+v -23.9905 16.3642 227.044
+v -23.9905 -16.3642 227.044
+v 225.663 16.3642 34.6529
+v 225.663 -16.3642 34.6529
+v 65.4796 16.3642 218.717
+v 65.4796 -16.3642 218.717
+v 194.814 16.3642 119.048
+v 165.195 16.3642 157.592
+v 194.814 -16.3642 119.048
+v 165.195 -16.3642 157.592
+v 215.601 16.3642 75.1069
+v 52.0359 16.3642 222.299
+v 215.601 -16.3642 75.1069
+v 52.0359 -16.3642 222.299
+v 191.096 16.3642 124.929
+v 169.92 16.3642 152.486
+v 191.096 -16.3642 124.929
+v 169.92 -16.3642 152.486
+v -71.513 16.3642 216.819
+v 221.557 16.3642 55.1101
+v -71.513 -16.3642 216.819
+v 221.557 -16.3642 55.1101
+v 210.626 16.3642 88.0998
+v 210.626 -16.3642 88.0998
+v 224.503 16.3642 41.5126
+v 224.503 -16.3642 41.5126
+v -51.4198 16.3642 222.443
+v -51.4198 -16.3642 222.443
+v 85.1739 16.3642 211.826
+v -58.1736 16.3642 220.773
+v 85.1739 -16.3642 211.826
+v -58.1736 -16.3642 220.773
+v 223.134 16.3642 48.3338
+v 223.134 -16.3642 48.3338
+v 160.316 16.3642 162.553
+v 160.316 -16.3642 162.553
+v 226.614 16.3642 27.761
+v 226.614 -16.3642 27.761
+v -78.0861 16.3642 214.54
+v -78.0861 -16.3642 214.54
+v 45.2384 16.3642 223.782
+v 45.2384 -16.3642 223.782
+v 58.785 16.3642 220.611
+v 58.785 -16.3642 220.611
+v -37.7753 16.3642 225.162
+v -37.7753 -16.3642 225.162
+v 207.844 16.3642 94.4765
+v 198.35 16.3642 113.057
+v 207.844 -16.3642 94.4765
+v 198.35 -16.3642 113.057
+v -64.8734 16.3642 218.898
+v -64.8734 -16.3642 218.898
+v 24.6194 16.3642 226.977
+v 24.6194 -16.3642 226.977
+v 228.202 16.3642 6.9564
+v 228.202 -16.3642 6.9564
+v -17.0615 16.3642 227.67
+v -17.0615 -16.3642 227.67
+v 219.775 16.3642 61.8352
+v 219.775 -16.3642 61.8352
+v 228.309 16.3642 0
+v 228.309 -16.3642 0
+v 38.399 16.3642 225.056
+v 38.399 -16.3642 225.056
+v 104.157 16.3642 203.165
+v 104.157 -16.3642 203.165
+v 109.264 15.6929 200.621
+v 151.152 -15.6929 171.291
+v 151.895 14.3329 170.98
+v 108.718 -14.3329 201.213
+v 108.456 13.6152 201.499
+v 152.253 -13.6152 170.832
+v 225.229 12.3112 41.6469
+v 225.229 -12.3112 41.6469
+v 216.298 12.3112 75.3499
+v 216.298 -12.3112 75.3499
+v 58.9752 12.3112 221.324
+v 58.9752 -12.3112 221.324
+v 228.622 12.3112 13.9513
+v 228.622 -12.3112 13.9513
+v 179.471 12.3112 142.312
+v 170.47 12.3112 152.979
+v 179.471 -12.3112 142.312
+v 170.47 -12.3112 152.979
+v 31.6258 12.3112 226.853
+v 31.6258 -12.3112 226.853
+v 24.6991 12.3112 227.711
+v 24.6991 -12.3112 227.711
+v 195.444 12.3112 119.433
+v 195.444 -12.3112 119.433
+v 229.047 12.3112 0
+v 85.4494 12.3112 212.511
+v 229.047 -12.3112 0
+v 85.4494 -12.3112 212.511
+v 208.516 12.3112 94.7821
+v 160.835 12.3112 163.079
+v 208.516 -12.3112 94.7821
+v 160.835 -12.3112 163.079
+v 183.724 12.3112 136.777
+v 183.724 -12.3112 136.777
+v 226.393 12.3112 34.765
+v 226.393 -12.3112 34.765
+v 223.855 12.3112 48.4901
+v 222.274 12.3112 55.2883
+v 223.855 -12.3112 48.4901
+v 222.274 -12.3112 55.2883
+v 52.2042 12.3112 223.018
+v 52.2042 -12.3112 223.018
+v 220.486 12.3112 62.0352
+v 165.729 12.3112 158.102
+v 220.486 -12.3112 62.0352
+v 165.729 -12.3112 158.102
+v 187.806 12.3112 131.116
+v 98.2349 12.3112 206.912
+v 187.806 -12.3112 131.116
+v 98.2349 -12.3112 206.912
+v -78.3387 12.3112 215.234
+v -78.3387 -12.3112 215.234
+v 228.09 12.3112 20.9108
+v 228.09 -12.3112 20.9108
+v 38.5232 12.3112 225.784
+v 38.5232 -12.3112 225.784
+v 72.3466 12.3112 217.321
+v 72.3466 -12.3112 217.321
+v 104.494 12.3112 203.822
+v 104.494 -12.3112 203.822
+v -71.7443 12.3112 217.521
+v -71.7443 -12.3112 217.521
+v 155.792 12.3112 167.903
+v 155.792 -12.3112 167.903
+v -30.9972 12.3112 226.94
+v -30.9972 -12.3112 226.94
+v 45.3848 12.3112 224.506
+v 45.3848 -12.3112 224.506
+v 3.80709 12.3112 229.015
+v 3.80709 -12.3112 229.015
+v 205.531 12.3112 101.091
+v 205.531 -12.3112 101.091
+v -65.0833 12.3112 219.606
+v -65.0833 -12.3112 219.606
+v -51.5862 12.3112 223.162
+v -51.5862 -12.3112 223.162
+v 218.494 12.3112 68.7245
+v 218.494 -12.3112 68.7245
+v -58.3618 12.3112 221.487
+v -58.3618 -12.3112 221.487
+v 213.902 12.3112 81.9054
+v 213.902 -12.3112 81.9054
+v 175.052 12.3112 147.714
+v 175.052 -12.3112 147.714
+v 91.8848 12.3112 209.809
+v 91.8848 -12.3112 209.809
+v 228.941 12.3112 6.9789
+v 228.941 -12.3112 6.9789
+v -24.0681 12.3112 227.779
+v -24.0681 -12.3112 227.779
+v -44.7626 12.3112 224.63
+v -44.7626 -12.3112 224.63
+v 227.348 12.3112 27.8508
+v 227.348 -12.3112 27.8508
+v -17.1167 12.3112 228.407
+v -17.1167 -12.3112 228.407
+v 17.7494 12.3112 228.358
+v 17.7494 -12.3112 228.358
+v -10.1494 12.3112 228.822
+v -10.1494 -12.3112 228.822
+v 211.307 12.3112 88.3848
+v 211.307 -12.3112 88.3848
+v -3.17262 12.3112 229.025
+v -3.17262 -12.3112 229.025
+v 65.6914 12.3112 219.425
+v 65.6914 -12.3112 219.425
+v 202.356 12.3112 107.307
+v -37.8975 12.3112 225.89
+v 202.356 -12.3112 107.307
+v -37.8975 -12.3112 225.89
+v 10.7832 12.3112 228.793
+v 10.7832 -12.3112 228.793
+v 198.992 12.3112 113.423
+v 198.992 -12.3112 113.423
+v 78.9347 12.3112 215.016
+v 78.9347 -12.3112 215.016
+v 191.714 12.3112 125.333
+v 191.714 -12.3112 125.333
+v 107.982 -12.17 202.021
+v 152.905 12.17 170.565
+v 153.191 -11.4687 170.449
+v 107.775 11.4687 202.25
+v 153.746 9.94438 170.226
+v 107.376 -9.94438 202.695
+v 107.214 9.24381 202.876
+v 153.972 -9.24381 170.136
+v 222.787 8.22568 55.416
+v 222.787 -8.22568 55.416
+v 211.795 8.22568 88.5889
+v 211.795 -8.22568 88.5889
+v 10.8082 8.22568 229.321
+v 10.8082 -8.22568 229.321
+v 31.6989 8.22568 227.377
+v 31.6989 -8.22568 227.377
+v 17.7904 8.22568 228.886
+v 17.7904 -8.22568 228.886
+v -71.91 8.22568 218.023
+v -71.91 -8.22568 218.023
+v -24.1237 8.22568 228.305
+v -24.1237 -8.22568 228.305
+v -37.9851 8.22568 226.412
+v -37.9851 -8.22568 226.412
+v 170.863 8.22568 153.333
+v 170.863 -8.22568 153.333
+v -44.866 8.22568 225.149
+v -44.866 -8.22568 225.149
+v 38.6121 8.22568 226.306
+v 38.6121 -8.22568 226.306
+v 229.15 8.22568 13.9835
+v 229.15 -8.22568 13.9835
+v 206.006 8.22568 101.325
+v 206.006 -8.22568 101.325
+v 156.151 8.22568 168.291
+v 156.151 -8.22568 168.291
+v 199.452 8.22568 113.685
+v 92.097 8.22568 210.293
+v 199.452 -8.22568 113.685
+v 92.097 -8.22568 210.293
+v 85.6467 8.22568 213.002
+v 85.6467 -8.22568 213.002
+v 227.872 8.22568 27.9151
+v 227.872 -8.22568 27.9151
+v 104.735 8.22568 204.293
+v 220.995 8.22568 62.1785
+v 195.895 8.22568 119.709
+v 79.117 8.22568 215.512
+v 220.995 -8.22568 62.1785
+v 195.895 -8.22568 119.709
+v 104.735 -8.22568 204.293
+v 79.117 -8.22568 215.512
+v 24.7561 8.22568 228.237
+v 24.7561 -8.22568 228.237
+v 192.157 8.22568 125.622
+v 184.148 8.22568 137.093
+v 192.157 -8.22568 125.622
+v 184.148 -8.22568 137.093
+v -10.1728 8.22568 229.35
+v -10.1728 -8.22568 229.35
+v 161.206 8.22568 163.455
+v 161.206 -8.22568 163.455
+v 229.469 8.22568 6.99502
+v 229.469 -8.22568 6.99502
+v 65.8431 8.22568 219.931
+v 65.8431 -8.22568 219.931
+v 229.576 8.22568 0
+v 229.576 -8.22568 0
+v 225.749 8.22568 41.7431
+v 179.886 8.22568 142.641
+v 225.749 -8.22568 41.7431
+v 179.886 -8.22568 142.641
+v 3.81588 8.22568 229.544
+v 3.81588 -8.22568 229.544
+v -58.4966 8.22568 221.998
+v -58.4966 -8.22568 221.998
+v 224.372 8.22568 48.6021
+v 224.372 -8.22568 48.6021
+v 208.997 8.22568 95.001
+v 175.456 8.22568 148.055
+v 208.997 -8.22568 95.001
+v 175.456 -8.22568 148.055
+v 72.5137 8.22568 217.823
+v 72.5137 -8.22568 217.823
+v 202.823 8.22568 107.555
+v 202.823 -8.22568 107.555
+v -31.0688 8.22568 227.464
+v -31.0688 -8.22568 227.464
+v 59.1114 8.22568 221.835
+v 59.1114 -8.22568 221.835
+v 45.4896 8.22568 225.024
+v 45.4896 -8.22568 225.024
+v 218.998 8.22568 68.8832
+v 218.998 -8.22568 68.8832
+v 228.617 8.22568 20.9591
+v 228.617 -8.22568 20.9591
+v 216.798 8.22568 75.5239
+v 216.798 -8.22568 75.5239
+v -3.17994 8.22568 229.554
+v -3.17994 -8.22568 229.554
+v -78.5196 8.22568 215.731
+v -78.5196 -8.22568 215.731
+v 166.112 8.22568 158.467
+v 166.112 -8.22568 158.467
+v 52.3248 8.22568 223.534
+v 52.3248 -8.22568 223.534
+v 214.396 8.22568 82.0945
+v 214.396 -8.22568 82.0945
+v 226.916 8.22568 34.8453
+v 226.916 -8.22568 34.8453
+v -51.7053 8.22568 223.678
+v -51.7053 -8.22568 223.678
+v 188.24 8.22568 131.419
+v 188.24 -8.22568 131.419
+v -17.1562 8.22568 228.934
+v -17.1562 -8.22568 228.934
+v -65.2336 8.22568 220.113
+v -65.2336 -8.22568 220.113
+v 98.4617 8.22568 207.39
+v 98.4617 -8.22568 207.39
+v 106.959 -7.99956 203.163
+v 154.329 7.99956 169.995
+v 106.779 6.97284 203.367
+v 154.582 -6.97284 169.895
+v 106.636 -6.02528 203.53
+v 154.784 6.02528 169.816
+v 155.019 -4.66752 169.724
+v 106.469 4.66752 203.72
+v 184.403 4.1183 137.283
+v 184.403 -4.1183 137.283
+v 92.2245 4.1183 210.585
+v 92.2245 -4.1183 210.585
+v 72.6141 4.1183 218.125
+v 72.6141 -4.1183 218.125
+v 31.7428 4.1183 227.692
+v -44.9282 4.1183 225.461
+v 31.7428 -4.1183 227.692
+v -44.9282 -4.1183 225.461
+v 38.6656 4.1183 226.619
+v 38.6656 -4.1183 226.619
+v 52.3973 4.1183 223.843
+v 52.3973 -4.1183 223.843
+v 180.135 4.1183 142.838
+v 180.135 -4.1183 142.838
+v 206.291 4.1183 101.465
+v -51.7769 4.1183 223.987
+v 229.894 4.1183 0
+v 206.291 -4.1183 101.465
+v -51.7769 -4.1183 223.987
+v 229.894 -4.1183 0
+v -78.6284 4.1183 216.03
+v -78.6284 -4.1183 216.03
+v 224.683 4.1183 48.6694
+v 224.683 -4.1183 48.6694
+v 226.062 4.1183 41.8009
+v -58.5776 4.1183 222.306
+v 226.062 -4.1183 41.8009
+v -58.5776 -4.1183 222.306
+v -10.1869 4.1183 229.668
+v -10.1869 -4.1183 229.668
+v 188.501 4.1183 131.601
+v 188.501 -4.1183 131.601
+v 17.815 4.1183 229.203
+v 17.815 -4.1183 229.203
+v 209.287 4.1183 95.1326
+v 209.287 -4.1183 95.1326
+v 227.23 4.1183 34.8936
+v 227.23 -4.1183 34.8936
+v 161.43 4.1183 163.682
+v 161.43 -4.1183 163.682
+v 217.098 4.1183 75.6285
+v 217.098 -4.1183 75.6285
+v 104.88 4.1183 204.576
+v 104.88 -4.1183 204.576
+v 45.5526 4.1183 225.336
+v 45.5526 -4.1183 225.336
+v 10.8231 4.1183 229.639
+v 10.8231 -4.1183 229.639
+v 171.1 4.1183 153.545
+v 171.1 -4.1183 153.545
+v -17.18 4.1183 229.251
+v -17.18 -4.1183 229.251
+v 85.7654 4.1183 213.297
+v 85.7654 -4.1183 213.297
+v 199.728 4.1183 113.842
+v 192.423 4.1183 125.796
+v 199.728 -4.1183 113.842
+v 192.423 -4.1183 125.796
+v -24.1571 4.1183 228.621
+v -24.1571 -4.1183 228.621
+v 175.699 4.1183 148.26
+v 175.699 -4.1183 148.26
+v 196.166 4.1183 119.875
+v 196.166 -4.1183 119.875
+v 229.787 4.1183 7.0047
+v 229.787 -4.1183 7.0047
+v -38.0377 4.1183 226.725
+v -38.0377 -4.1183 226.725
+v 59.1933 4.1183 222.143
+v 59.1933 -4.1183 222.143
+v -31.1118 4.1183 227.779
+v -31.1118 -4.1183 227.779
+v 228.188 4.1183 27.9538
+v 228.188 -4.1183 27.9538
+v 24.7904 4.1183 228.553
+v 24.7904 -4.1183 228.553
+v -65.3239 4.1183 220.418
+v -65.3239 -4.1183 220.418
+v 65.9343 4.1183 220.236
+v 65.9343 -4.1183 220.236
+v 166.342 4.1183 158.687
+v 166.342 -4.1183 158.687
+v 223.096 4.1183 55.4928
+v 223.096 -4.1183 55.4928
+v 221.301 4.1183 62.2646
+v -72.0096 4.1183 218.325
+v 221.301 -4.1183 62.2646
+v -72.0096 -4.1183 218.325
+v -3.18435 4.1183 229.872
+v -3.18435 -4.1183 229.872
+v 3.82116 4.1183 229.862
+v 3.82116 -4.1183 229.862
+v 228.934 4.1183 20.9881
+v 228.934 -4.1183 20.9881
+v 156.368 4.1183 168.524
+v 212.088 4.1183 88.7116
+v 156.368 -4.1183 168.524
+v 212.088 -4.1183 88.7116
+v 214.693 4.1183 82.2082
+v 214.693 -4.1183 82.2082
+v 229.467 4.1183 14.0029
+v 229.467 -4.1183 14.0029
+v 79.2265 4.1183 215.811
+v 79.2265 -4.1183 215.811
+v 219.302 4.1183 68.9786
+v 98.5981 4.1183 207.677
+v 219.302 -4.1183 68.9786
+v 98.5981 -4.1183 207.677
+v 203.104 4.1183 107.704
+v 203.104 -4.1183 107.704
+v 106.405 -4.02901 203.792
+v 155.109 4.02901 169.689
+v 106.283 2.33943 203.932
+v 155.282 -2.33943 169.622
+v 155.305 2.01815 169.613
+v 106.267 -2.01815 203.95
+v 32.6111 1.95944e-14 227.676
+v 221.272 1.95944e-14 62.76
+v 53.4178 1.95944e-14 223.711
+v 195.749 1.95944e-14 120.757
+v -58.4483 1.95944e-14 222.449
+v -30.7524 1.95944e-14 227.935
+v -9.65326 1.95944e-14 229.797
+v 224.707 1.95944e-14 49.0605
+v 226.107 1.95944e-14 42.1381
+v 39.5861 1.95944e-14 226.568
+v 211.915 1.95944e-14 89.3983
+v 202.792 1.95944e-14 108.514
+v 11.5278 1.95944e-14 229.711
+v 165.486 1.95944e-14 159.732
+v -16.7043 1.95944e-14 229.393
+v 155.37 1.95944e-14 169.588
+v -51.5908 1.95944e-14 224.139
+v 80.4253 1.95944e-14 215.48
+v -78.6646 1.95944e-14 216.129
+v 93.4995 1.95944e-14 210.138
+v 230 0 0
+v 179.479 1.95944e-14 143.831
+v 227.294 1.95944e-14 35.1759
+v 106.221 1.95944e-14 204.003
+v -65.2507 1.95944e-14 220.55
+v 87.0034 1.95944e-14 212.909
+v -2.59314 1.95944e-14 229.985
+v 174.978 1.95944e-14 149.274
+v 206.028 1.95944e-14 102.237
+v 25.6052 1.95944e-14 228.57
+v 46.5239 1.95944e-14 225.245
+v 191.949 1.95944e-14 126.71
+v 67.048 1.95944e-14 220.01
+v 18.5753 1.95944e-14 229.249
+v 229.025 1.95944e-14 21.1588
+v 160.504 1.95944e-14 164.738
+v 199.365 1.95944e-14 114.689
+v -71.9916 1.95944e-14 218.443
+v 99.9073 1.95944e-14 207.168
+v 209.07 1.95944e-14 95.8627
+v 219.24 1.95944e-14 69.5242
+v 217.003 1.95944e-14 76.2229
+v 4.46943 1.95944e-14 229.957
+v -37.7363 1.95944e-14 226.883
+v -23.7395 1.95944e-14 228.772
+v 183.81 1.95944e-14 138.253
+v 60.2613 1.95944e-14 221.965
+v 223.094 1.95944e-14 55.9366
+v -44.6846 1.95944e-14 225.618
+v 229.892 1.95944e-14 7.0618
+v 73.7714 1.95944e-14 217.848
+v 228.267 1.95944e-14 28.1806
+v 214.56 1.95944e-14 82.8497
+v 229.566 1.95944e-14 14.1169
+v 187.969 1.95944e-14 132.544
+v 170.312 1.95944e-14 154.576
+v -161.695 -63.9871 151.873
+v -161.695 63.9871 151.873
+v 198.017 -63.9871 -100
+v 198.017 63.9871 -100
+v -162.8 -61.4304 154.909
+v -162.8 61.4304 154.909
+v 201.247 -61.4304 -100
+v 201.247 61.4304 -100
+v -163.858 -58.7108 157.816
+v -163.858 58.7108 157.816
+v 204.342 -58.7108 -100
+v 204.342 58.7108 -100
+v -164.867 -55.8355 160.589
+v -164.867 55.8355 160.589
+v 207.292 -55.8355 -100
+v 207.292 55.8355 -100
+v -165.824 -52.8122 163.219
+v -165.824 52.8122 163.219
+v 210.091 -52.8122 -100
+v 210.091 52.8122 -100
+v -166.727 -49.6488 165.698
+v -166.727 49.6488 165.698
+v 212.73 -49.6488 -100
+v 212.73 49.6488 -100
+v 215.202 -46.3537 -100
+v 215.202 46.3537 -100
+v -167.573 -46.3537 168.022
+v -167.573 46.3537 168.022
+v 217.502 -42.9357 -100
+v 217.502 42.9357 -100
+v -168.359 -42.9357 170.183
+v -168.359 42.9357 170.183
+v 219.623 -39.4039 -100
+v 219.623 39.4039 -100
+v -169.085 -39.4039 172.176
+v -169.085 39.4039 172.176
+v -169.747 -35.7675 173.995
+v -169.747 35.7675 173.995
+v 221.559 -35.7675 -100
+v 221.559 35.7675 -100
+v -170.344 -32.0363 175.636
+v -170.344 32.0363 175.636
+v 223.305 -32.0363 -100
+v 223.305 32.0363 -100
+v 224.857 -28.2202 -100
+v 224.857 28.2202 -100
+v -170.875 -28.2202 177.095
+v -170.875 28.2202 177.095
+v -171.338 -24.3292 178.367
+v -171.338 24.3292 178.367
+v 226.211 -24.3292 -100
+v 226.211 24.3292 -100
+v 227.362 -20.3737 -100
+v 227.362 20.3737 -100
+v -171.732 -20.3737 179.449
+v -171.732 20.3737 179.449
+v 228.309 -16.3642 -100
+v 228.309 16.3642 -100
+v -172.055 -16.3642 180.338
+v -172.055 16.3642 180.338
+v 229.047 -12.3112 -100
+v 229.047 12.3112 -100
+v -172.308 -12.3112 181.032
+v -172.308 12.3112 181.032
+v 229.576 -8.22568 -100
+v 229.576 8.22568 -100
+v -172.489 -8.22568 181.529
+v -172.489 8.22568 181.529
+v -172.598 -4.1183 181.828
+v -172.598 4.1183 181.828
+v 229.894 -4.1183 -100
+v 229.894 4.1183 -100
+v 230 0 -100
+v -172.634 0 181.927
+g CATIASTL
+f 17 1 39
+f 5 163 27
+f 7904 7807 7919
+f 7904 7877 7807
+f 7141 7089 7145
+f 7141 7137 7089
+f 7896 7859 7879
+f 7896 7916 7859
+f 7865 7934 7930
+f 7865 7930 7829
+f 14 61 1
+f 7857 7915 7934
+f 7857 7934 7865
+f 7837 7932 7915
+f 7837 7915 7857
+f 2 59 14
+f 7801 7903 7932
+f 7801 7932 7837
+f 7789 7889 7903
+f 7789 7903 7801
+f 7 93 2
+f 7787 7888 7889
+f 7787 7889 7789
+f 8 123 7
+f 7847 7928 7888
+f 7847 7888 7787
+f 7849 7882 7928
+f 7849 7928 7847
+f 29 147 8
+f 7869 7921 7882
+f 7869 7882 7849
+f 7805 7922 7921
+f 7805 7921 7869
+f 6 63 29
+f 7863 7933 7922
+f 7863 7922 7805
+f 7860 7891 7933
+f 7860 7933 7863
+f 30 77 6
+f 7799 7920 7891
+f 7799 7891 7860
+f 7779 7909 7920
+f 7779 7920 7799
+f 25 53 30
+f 7873 7892 7909
+f 7873 7909 7779
+f 11 101 25
+f 7819 7917 7892
+f 7819 7892 7873
+f 7827 7884 7917
+f 7827 7917 7819
+f 21 95 11
+f 7820 7912 7884
+f 7820 7884 7827
+f 7795 7935 7912
+f 7795 7912 7820
+f 4 113 21
+f 7763 7926 7935
+f 7763 7935 7795
+f 7777 7902 7926
+f 7777 7926 7763
+f 26 78 4
+f 7825 7908 7902
+f 7825 7902 7777
+f 7813 7936 7908
+f 7813 7908 7825
+f 33 79 26
+f 7845 7894 7936
+f 7845 7936 7813
+f 9 69 33
+f 7803 7916 7894
+f 7803 7894 7845
+f 7859 7916 7803
+f 12 80 9
+f 7357 7395 7403
+f 7357 7403 7353
+f 13 43 12
+f 7029 7006 7134
+f 6953 6987 6991
+f 28 102 13
+f 7131 7089 7137
+f 10 103 28
+f 7265 7145 7089
+f 32 127 10
+f 7517 7401 7385
+f 19 128 32
+f 7870 7900 7919
+f 7870 7919 7807
+f 7765 7906 7900
+f 7765 7900 7870
+f 15 44 19
+f 7817 7898 7906
+f 7817 7906 7765
+f 7867 7931 7898
+f 7867 7898 7817
+f 3 114 15
+f 7767 7913 7931
+f 7767 7931 7867
+f 7843 7927 7913
+f 7843 7913 7767
+f 35 57 3
+f 7833 7883 7927
+f 7833 7927 7843
+f 36 73 35
+f 7775 7911 7883
+f 7775 7883 7833
+f 7809 7890 7911
+f 7809 7911 7775
+f 34 135 36
+f 7773 7881 7890
+f 7773 7890 7809
+f 7769 7910 7881
+f 7769 7881 7773
+f 16 139 34
+f 7839 7914 7910
+f 7839 7910 7769
+f 7797 7893 7914
+f 7797 7914 7839
+f 22 153 16
+f 7811 7923 7893
+f 7811 7893 7797
+f 7855 7907 7923
+f 7855 7923 7811
+f 18 143 22
+f 7853 7887 7907
+f 7853 7907 7855
+f 20 119 18
+f 7793 7895 7887
+f 7793 7887 7853
+f 7815 7925 7895
+f 7815 7895 7793
+f 31 111 20
+f 7823 7886 7925
+f 7823 7925 7815
+f 7835 7924 7886
+f 7835 7886 7823
+f 23 67 31
+f 7831 7929 7924
+f 7831 7924 7835
+f 7770 7897 7929
+f 7770 7929 7831
+f 24 161 23
+f 7780 7885 7897
+f 7780 7897 7770
+f 7790 7905 7885
+f 7790 7885 7780
+f 27 37 24
+f 7841 7918 7905
+f 7841 7905 7790
+f 7850 7918 7841
+f 7859 7876 7879
+f 7519 7636 7579
+f 7579 7427 7519
+f 7519 7427 7403
+f 7353 7403 7427
+f 7357 7391 7395
+f 7268 7193 7148
+f 7067 7148 7193
+f 6953 6983 6987
+f 6897 7004 6994
+f 7385 7401 7393
+f 7251 7269 7265
+f 7757 7641 7679
+f 7123 7029 7134
+f 7123 7134 7136
+f 7123 7136 7139
+f 7123 7139 7144
+f 7123 7144 7148
+f 7123 7148 7067
+f 6895 6953 6991
+f 6895 6991 6996
+f 6895 6996 6998
+f 6895 6998 7006
+f 6895 7006 7029
+f 6919 6897 6994
+f 6919 6994 6990
+f 6919 6990 6986
+f 6919 6986 6983
+f 6919 6983 6953
+f 7899 7918 7785
+f 7785 7918 7850
+f 7785 7850 7735
+f 7735 7850 7653
+f 7735 7653 7567
+f 7567 7653 7577
+f 7567 7577 7489
+f 7489 7577 7469
+f 7489 7469 7337
+f 7337 7469 7373
+f 7337 7373 7151
+f 7151 7373 7175
+f 7151 7175 7093
+f 7093 7175 7017
+f 7093 7017 6913
+f 6913 7017 6969
+f 6913 6969 6747
+f 6747 6969 6731
+f 6747 6731 6607
+f 6607 6731 6619
+f 6607 6619 6573
+f 6573 6619 6529
+f 6573 6529 6413
+f 6413 6529 6349
+f 6413 6349 6237
+f 6237 6349 6295
+f 6237 6295 6081
+f 6081 6295 6177
+f 6081 6177 5963
+f 5963 6177 5991
+f 5963 5991 5813
+f 5813 5991 5907
+f 5813 5907 5697
+f 5697 5907 5779
+f 5697 5779 5553
+f 5553 5779 5595
+f 5553 5595 5515
+f 5515 5595 5431
+f 5515 5431 5409
+f 5409 5431 5377
+f 5409 5377 5243
+f 5243 5377 5193
+f 5243 5193 5035
+f 5035 5193 5123
+f 5035 5123 4997
+f 4997 5123 4943
+f 4997 4943 4833
+f 4833 4943 4873
+f 4833 4873 4641
+f 4641 4873 4693
+f 4641 4693 4591
+f 4591 4693 4595
+f 4591 4595 4423
+f 4423 4595 4383
+f 4423 4383 4301
+f 4301 4383 4329
+f 4301 4329 4173
+f 4173 4329 4221
+f 4173 4221 4027
+f 4027 4221 4053
+f 4027 4053 3911
+f 3911 4053 3857
+f 3911 3857 3783
+f 3783 3857 3811
+f 3783 3811 3643
+f 3643 3811 3691
+f 3643 3691 3533
+f 3533 3691 3497
+f 3533 3497 3327
+f 3327 3497 3393
+f 3327 3393 3175
+f 3175 3393 3213
+f 3175 3213 3133
+f 3133 3213 3141
+f 3133 3141 2931
+f 2931 3141 2937
+f 2931 2937 2893
+f 2893 2937 2894
+f 2893 2894 2701
+f 2701 2894 2665
+f 2701 2665 2521
+f 2521 2665 2505
+f 2521 2505 2417
+f 2417 2505 2435
+f 2417 2435 2283
+f 2283 2435 2219
+f 2283 2219 2185
+f 2185 2219 2205
+f 2185 2205 1967
+f 1967 2205 1989
+f 1967 1989 1881
+f 1881 1989 1843
+f 1881 1843 1763
+f 1763 1843 1769
+f 1763 1769 1599
+f 1599 1769 1693
+f 1599 1693 1549
+f 1549 1693 1455
+f 1549 1455 1349
+f 1349 1455 1327
+f 1349 1327 1283
+f 1283 1327 1279
+f 1283 1279 1077
+f 1077 1279 1145
+f 1077 1145 1007
+f 1007 1145 937
+f 1007 937 875
+f 875 937 855
+f 875 855 761
+f 761 855 753
+f 761 753 571
+f 571 753 557
+f 571 557 527
+f 527 557 437
+f 527 437 337
+f 337 437 329
+f 337 329 291
+f 291 329 249
+f 291 249 74
+f 74 249 163
+f 74 163 5
+f 7930 7901 7829
+f 7829 7901 7781
+f 7829 7781 7697
+f 7697 7781 7701
+f 7697 7701 7603
+f 7603 7701 7541
+f 7603 7541 7505
+f 7505 7541 7511
+f 7505 7511 7379
+f 7379 7511 7305
+f 7379 7305 7221
+f 7221 7305 7157
+f 7221 7157 7021
+f 7021 7157 7013
+f 7021 7013 6951
+f 6951 7013 6981
+f 6951 6981 6799
+f 6799 6981 6849
+f 6799 6849 6595
+f 6595 6849 6635
+f 6595 6635 6571
+f 6571 6635 6479
+f 6571 6479 6459
+f 6459 6479 6445
+f 6459 6445 6231
+f 6231 6445 6287
+f 6231 6287 6105
+f 6105 6287 6199
+f 6105 6199 5971
+f 5971 6199 6039
+f 5971 6039 5865
+f 5865 6039 5908
+f 5865 5908 5729
+f 5729 5908 5795
+f 5729 5795 5621
+f 5621 5795 5573
+f 5621 5573 5465
+f 5465 5573 5485
+f 5465 5485 5403
+f 5403 5485 5309
+f 5403 5309 5169
+f 5169 5309 5163
+f 5169 5163 5139
+f 5139 5163 5023
+f 5139 5023 4971
+f 4971 5023 4919
+f 4971 4919 4771
+f 4771 4919 4839
+f 4771 4839 4651
+f 4651 4839 4753
+f 4651 4753 4501
+f 4501 4753 4521
+f 4501 4521 4487
+f 4487 4521 4471
+f 4487 4471 4231
+f 4231 4471 4333
+f 4231 4333 4127
+f 4127 4333 4103
+f 4127 4103 3989
+f 3989 4103 3981
+f 3989 3981 3943
+f 3943 3981 3945
+f 3943 3945 3785
+f 3785 3945 3825
+f 3785 3825 3695
+f 3695 3825 3593
+f 3695 3593 3565
+f 3565 3593 3445
+f 3565 3445 3409
+f 3409 3445 3381
+f 3409 3381 3251
+f 3251 3381 3297
+f 3251 3297 3155
+f 3155 3297 3087
+f 3155 3087 2923
+f 2923 3087 3011
+f 2923 3011 2897
+f 2897 3011 2773
+f 2897 2773 2737
+f 2737 2773 2755
+f 2737 2755 2623
+f 2623 2755 2609
+f 2623 2609 2463
+f 2463 2609 2405
+f 2463 2405 2223
+f 2223 2405 2339
+f 2223 2339 2211
+f 2211 2339 2155
+f 2211 2155 2067
+f 2067 2155 1968
+f 2067 1968 1907
+f 1907 1968 1831
+f 1907 1831 1723
+f 1723 1831 1771
+f 1723 1771 1619
+f 1619 1771 1623
+f 1619 1623 1533
+f 1533 1623 1467
+f 1533 1467 1339
+f 1339 1467 1439
+f 1339 1439 1233
+f 1233 1439 1261
+f 1233 1261 1179
+f 1179 1261 1111
+f 1179 1111 1039
+f 1039 1111 1021
+f 1039 1021 927
+f 927 1021 813
+f 927 813 779
+f 779 813 715
+f 779 715 623
+f 623 715 581
+f 623 581 451
+f 451 581 439
+f 451 439 389
+f 389 439 293
+f 389 293 195
+f 195 293 251
+f 195 251 39
+f 39 251 81
+f 39 81 17
+f 7251 7265 7068
+f 7068 7265 7089
+f 7068 7089 6861
+f 6861 7089 6945
+f 6861 6945 6801
+f 6801 6945 6753
+f 6801 6753 6717
+f 6717 6753 6636
+f 6717 6636 6530
+f 6530 6636 6475
+f 6530 6475 6373
+f 6373 6475 6335
+f 6373 6335 6203
+f 6203 6335 6275
+f 6203 6275 6115
+f 6115 6275 6193
+f 6115 6193 6057
+f 6057 6193 5945
+f 6057 5945 5843
+f 5843 5945 5889
+f 5843 5889 5791
+f 5791 5889 5741
+f 5791 5741 5583
+f 5583 5741 5617
+f 5583 5617 5453
+f 5453 5617 5505
+f 5453 5505 5331
+f 5331 5505 5397
+f 5331 5397 5229
+f 5229 5397 5257
+f 5229 5257 5117
+f 5117 5257 5101
+f 5117 5101 4941
+f 4941 5101 4920
+f 4941 4920 4857
+f 4857 4920 4817
+f 4857 4817 4689
+f 4689 4817 4683
+f 4689 4683 4515
+f 4515 4683 4551
+f 4515 4551 4433
+f 4433 4551 4481
+f 4433 4481 4239
+f 4239 4481 4313
+f 4239 4313 4215
+f 4215 4313 4191
+f 4215 4191 3995
+f 3995 4191 4043
+f 3995 4043 3863
+f 3863 4043 3903
+f 3863 3903 3751
+f 3751 3903 3755
+f 3751 3755 3611
+f 3611 3755 3633
+f 3611 3633 3543
+f 3543 3633 3457
+f 3543 3457 3329
+f 3329 3457 3361
+f 3329 3361 3283
+f 3283 3361 3255
+f 3283 3255 3105
+f 3105 3255 3137
+f 3105 3137 3021
+f 3021 3137 3015
+f 3021 3015 2863
+f 2863 3015 2864
+f 2863 2864 2717
+f 2717 2864 2683
+f 2717 2683 2591
+f 2591 2683 2559
+f 2591 2559 2395
+f 2395 2559 2397
+f 2395 2397 2237
+f 2237 2397 2305
+f 2237 2305 2186
+f 2186 2305 2109
+f 2186 2109 1963
+f 1963 2109 2039
+f 1963 2039 1882
+f 1882 2039 1955
+f 1882 1955 1707
+f 1707 1955 1789
+f 1707 1789 1647
+f 1647 1789 1683
+f 1647 1683 1507
+f 1507 1683 1517
+f 1507 1517 1440
+f 1440 1517 1381
+f 1440 1381 1227
+f 1227 1381 1309
+f 1227 1309 1183
+f 1183 1309 1171
+f 1183 1171 949
+f 949 1171 991
+f 949 991 867
+f 867 991 817
+f 867 817 727
+f 727 817 762
+f 727 762 659
+f 659 762 572
+f 659 572 453
+f 453 572 465
+f 453 465 379
+f 379 465 399
+f 379 399 241
+f 241 399 197
+f 241 197 127
+f 127 197 103
+f 127 103 10
+f 7575 7521 7515
+f 7515 7521 7517
+f 7515 7517 7311
+f 7311 7517 7385
+f 7311 7385 7155
+f 7155 7385 7251
+f 7155 7251 7041
+f 7041 7251 7068
+f 7041 7068 6879
+f 6879 7068 6861
+f 6879 6861 6841
+f 6841 6861 6801
+f 6841 6801 6715
+f 6715 6801 6717
+f 6715 6717 6493
+f 6493 6717 6530
+f 6493 6530 6359
+f 6359 6530 6373
+f 6359 6373 6303
+f 6303 6373 6203
+f 6303 6203 6178
+f 6178 6203 6115
+f 6178 6115 6040
+f 6040 6115 6057
+f 6040 6057 5921
+f 5921 6057 5843
+f 5921 5843 5705
+f 5705 5843 5791
+f 5705 5791 5649
+f 5649 5791 5583
+f 5649 5583 5489
+f 5489 5583 5453
+f 5489 5453 5289
+f 5289 5453 5331
+f 5289 5331 5219
+f 5219 5331 5229
+f 5219 5229 5053
+f 5053 5229 5117
+f 5053 5117 4907
+f 4907 5117 4941
+f 4907 4941 4797
+f 4797 4941 4857
+f 4797 4857 4727
+f 4727 4857 4689
+f 4727 4689 4565
+f 4565 4689 4515
+f 4565 4515 4385
+f 4385 4515 4433
+f 4385 4433 4289
+f 4289 4433 4239
+f 4289 4239 4192
+f 4192 4239 4215
+f 4192 4215 4083
+f 4083 4215 3995
+f 4083 3995 3917
+f 3917 3995 3863
+f 3917 3863 3805
+f 3805 3863 3751
+f 3805 3751 3599
+f 3599 3751 3611
+f 3599 3611 3477
+f 3477 3611 3543
+f 3477 3543 3417
+f 3417 3543 3329
+f 3417 3329 3277
+f 3277 3329 3283
+f 3277 3283 3063
+f 3063 3283 3105
+f 3063 3105 2949
+f 2949 3105 3021
+f 2949 3021 2813
+f 2813 3021 2863
+f 2813 2863 2641
+f 2641 2863 2717
+f 2641 2717 2567
+f 2567 2717 2591
+f 2567 2591 2406
+f 2406 2591 2395
+f 2406 2395 2299
+f 2299 2395 2237
+f 2299 2237 2195
+f 2195 2237 2186
+f 2195 2186 1957
+f 1957 2186 1963
+f 1957 1963 1873
+f 1873 1963 1882
+f 1873 1882 1799
+f 1799 1882 1707
+f 1799 1707 1579
+f 1579 1707 1647
+f 1579 1647 1463
+f 1463 1647 1507
+f 1463 1507 1441
+f 1441 1507 1440
+f 1441 1440 1305
+f 1305 1440 1227
+f 1305 1227 1172
+f 1172 1227 1183
+f 1172 1183 1037
+f 1037 1183 949
+f 1037 949 909
+f 909 949 867
+f 909 867 769
+f 769 867 727
+f 769 727 573
+f 573 727 659
+f 573 659 440
+f 440 659 453
+f 440 453 363
+f 363 453 379
+f 363 379 242
+f 242 379 241
+f 242 241 155
+f 155 241 127
+f 155 127 32
+f 7865 7829 7665
+f 7665 7829 7697
+f 7665 7697 7529
+f 7529 7697 7603
+f 7529 7603 7415
+f 7415 7603 7505
+f 7415 7505 7363
+f 7363 7505 7379
+f 7363 7379 7181
+f 7181 7379 7221
+f 7181 7221 7027
+f 7027 7221 7021
+f 7027 7021 6873
+f 6873 7021 6951
+f 6873 6951 6817
+f 6817 6951 6799
+f 6817 6799 6617
+f 6617 6799 6595
+f 6617 6595 6547
+f 6547 6595 6571
+f 6547 6571 6419
+f 6419 6571 6459
+f 6419 6459 6259
+f 6259 6459 6231
+f 6259 6231 6173
+f 6173 6231 6105
+f 6173 6105 6017
+f 6017 6105 5971
+f 6017 5971 5811
+f 5811 5971 5865
+f 5811 5865 5753
+f 5753 5865 5729
+f 5753 5729 5667
+f 5667 5729 5621
+f 5667 5621 5527
+f 5527 5621 5465
+f 5527 5465 5287
+f 5287 5465 5403
+f 5287 5403 5199
+f 5199 5403 5169
+f 5199 5169 5125
+f 5125 5169 5139
+f 5125 5139 5013
+f 5013 5139 4971
+f 5013 4971 4849
+f 4849 4971 4771
+f 4849 4771 4671
+f 4671 4771 4651
+f 4671 4651 4555
+f 4555 4651 4501
+f 4555 4501 4381
+f 4381 4501 4487
+f 4381 4487 4319
+f 4319 4487 4231
+f 4319 4231 4209
+f 4209 4231 4127
+f 4209 4127 4035
+f 4035 4127 3989
+f 4035 3989 3935
+f 3935 3989 3943
+f 3935 3943 3739
+f 3739 3943 3785
+f 3739 3785 3657
+f 3657 3785 3695
+f 3657 3695 3563
+f 3563 3695 3565
+f 3563 3565 3375
+f 3375 3565 3409
+f 3375 3409 3293
+f 3293 3409 3251
+f 3293 3251 3115
+f 3115 3251 3155
+f 3115 3155 2933
+f 2933 3155 2923
+f 2933 2923 2827
+f 2827 2923 2897
+f 2827 2897 2753
+f 2753 2897 2737
+f 2753 2737 2531
+f 2531 2737 2623
+f 2531 2623 2385
+f 2385 2623 2463
+f 2385 2463 2269
+f 2269 2463 2223
+f 2269 2223 2105
+f 2105 2223 2211
+f 2105 2211 2053
+f 2053 2211 2067
+f 2053 2067 1879
+f 1879 2067 1907
+f 1879 1907 1797
+f 1797 1907 1723
+f 1797 1723 1689
+f 1689 1723 1619
+f 1689 1619 1475
+f 1475 1619 1533
+f 1475 1533 1401
+f 1401 1533 1339
+f 1401 1339 1303
+f 1303 1339 1233
+f 1303 1233 1101
+f 1101 1233 1179
+f 1101 1179 1057
+f 1057 1179 1039
+f 1057 1039 929
+f 929 1039 927
+f 929 927 723
+f 723 927 779
+f 723 779 555
+f 555 779 623
+f 555 623 499
+f 499 623 451
+f 499 451 387
+f 387 451 389
+f 387 389 239
+f 239 389 195
+f 239 195 137
+f 137 195 39
+f 137 39 1
+f 7857 7865 7729
+f 7729 7865 7665
+f 7729 7665 7569
+f 7569 7665 7529
+f 7569 7529 7423
+f 7423 7529 7415
+f 7423 7415 7289
+f 7289 7415 7363
+f 7289 7363 7259
+f 7259 7363 7181
+f 7259 7181 7045
+f 7045 7181 7027
+f 7045 7027 6905
+f 6905 7027 6873
+f 6905 6873 6751
+f 6751 6873 6817
+f 6751 6817 6709
+f 6709 6817 6617
+f 6709 6617 6485
+f 6485 6617 6547
+f 6485 6547 6449
+f 6449 6547 6419
+f 6449 6419 6257
+f 6257 6419 6259
+f 6257 6259 6117
+f 6117 6259 6173
+f 6117 6173 5983
+f 5983 6173 6017
+f 5983 6017 5827
+f 5827 6017 5811
+f 5827 5811 5711
+f 5711 5811 5753
+f 5711 5753 5613
+f 5613 5753 5667
+f 5613 5667 5517
+f 5517 5667 5527
+f 5517 5527 5303
+f 5303 5527 5287
+f 5303 5287 5189
+f 5189 5287 5199
+f 5189 5199 5055
+f 5055 5199 5125
+f 5055 5125 5011
+f 5011 5125 5013
+f 5011 5013 4799
+f 4799 5013 4849
+f 4799 4849 4739
+f 4739 4849 4671
+f 4739 4671 4593
+f 4593 4671 4555
+f 4593 4555 4489
+f 4489 4555 4381
+f 4489 4381 4347
+f 4347 4381 4319
+f 4347 4319 4109
+f 4109 4319 4209
+f 4109 4209 4015
+f 4015 4209 4035
+f 4015 4035 3957
+f 3957 4035 3935
+f 3957 3935 3719
+f 3719 3935 3739
+f 3719 3739 3627
+f 3627 3739 3657
+f 3627 3657 3483
+f 3483 3657 3563
+f 3483 3563 3353
+f 3353 3563 3375
+f 3353 3375 3219
+f 3219 3375 3293
+f 3219 3293 3161
+f 3161 3293 3115
+f 3161 3115 2927
+f 2927 3115 2933
+f 2927 2933 2891
+f 2891 2933 2827
+f 2891 2827 2751
+f 2751 2827 2753
+f 2751 2753 2625
+f 2625 2753 2531
+f 2625 2531 2441
+f 2441 2531 2385
+f 2441 2385 2329
+f 2329 2385 2269
+f 2329 2269 2189
+f 2189 2269 2105
+f 2189 2105 2027
+f 2027 2105 2053
+f 2027 2053 1935
+f 1935 2053 1879
+f 1935 1879 1729
+f 1729 1879 1797
+f 1729 1797 1659
+f 1659 1797 1689
+f 1659 1689 1537
+f 1537 1689 1475
+f 1537 1475 1317
+f 1317 1475 1401
+f 1317 1401 1281
+f 1281 1401 1303
+f 1281 1303 1099
+f 1099 1303 1101
+f 1099 1101 1027
+f 1027 1101 1057
+f 1027 1057 856
+f 856 1057 929
+f 856 929 701
+f 701 929 723
+f 701 723 629
+f 629 723 555
+f 629 555 523
+f 523 555 499
+f 523 499 317
+f 317 499 387
+f 317 387 205
+f 205 387 239
+f 205 239 61
+f 61 239 137
+f 61 137 1
+f 7837 7857 7677
+f 7677 7857 7729
+f 7677 7729 7609
+f 7609 7729 7569
+f 7609 7569 7487
+f 7487 7569 7423
+f 7487 7423 7377
+f 7377 7423 7289
+f 7377 7289 7173
+f 7173 7289 7259
+f 7173 7259 7117
+f 7117 7259 7045
+f 7117 7045 6917
+f 6917 7045 6905
+f 6917 6905 6825
+f 6825 6905 6751
+f 6825 6751 6655
+f 6655 6751 6709
+f 6655 6709 6593
+f 6593 6709 6485
+f 6593 6485 6343
+f 6343 6485 6449
+f 6343 6449 6253
+f 6253 6449 6257
+f 6253 6257 6169
+f 6169 6257 6117
+f 6169 6117 5951
+f 5951 6117 5983
+f 5951 5983 5835
+f 5835 5983 5827
+f 5835 5827 5769
+f 5769 5827 5711
+f 5769 5711 5587
+f 5587 5711 5613
+f 5587 5613 5483
+f 5483 5613 5517
+f 5483 5517 5333
+f 5333 5517 5303
+f 5333 5303 5167
+f 5167 5303 5189
+f 5167 5189 5091
+f 5091 5189 5055
+f 5091 5055 4995
+f 4995 5055 5011
+f 4995 5011 4761
+f 4761 5011 4799
+f 4761 4799 4649
+f 4649 4799 4739
+f 4649 4739 4609
+f 4609 4739 4593
+f 4609 4593 4401
+f 4401 4593 4489
+f 4401 4489 4249
+f 4249 4489 4347
+f 4249 4347 4139
+f 4139 4347 4109
+f 4139 4109 3997
+f 3997 4109 4015
+f 3997 4015 3875
+f 3875 4015 3957
+f 3875 3957 3827
+f 3827 3957 3719
+f 3827 3719 3587
+f 3587 3719 3627
+f 3587 3627 3439
+f 3439 3627 3483
+f 3439 3483 3347
+f 3347 3483 3353
+f 3347 3353 3187
+f 3187 3353 3219
+f 3187 3219 3069
+f 3069 3219 3161
+f 3069 3161 2999
+f 2999 3161 2927
+f 2999 2927 2887
+f 2887 2927 2891
+f 2887 2891 2657
+f 2657 2891 2751
+f 2657 2751 2509
+f 2509 2751 2625
+f 2509 2625 2477
+f 2477 2625 2441
+f 2477 2441 2215
+f 2215 2441 2329
+f 2215 2329 2135
+f 2135 2329 2189
+f 2135 2189 2047
+f 2047 2189 2027
+f 2047 2027 1909
+f 1909 2027 1935
+f 1909 1935 1809
+f 1809 1935 1729
+f 1809 1729 1679
+f 1679 1729 1659
+f 1679 1659 1569
+f 1569 1659 1537
+f 1569 1537 1399
+f 1399 1537 1317
+f 1399 1317 1221
+f 1221 1317 1281
+f 1221 1281 1165
+f 1165 1281 1099
+f 1165 1099 945
+f 945 1099 1027
+f 945 1027 823
+f 823 1027 856
+f 823 856 801
+f 801 856 701
+f 801 701 587
+f 587 701 629
+f 587 629 427
+f 427 629 523
+f 427 523 377
+f 377 523 317
+f 377 317 259
+f 259 317 205
+f 259 205 97
+f 97 205 61
+f 97 61 14
+f 7801 7837 7743
+f 7743 7837 7677
+f 7743 7677 7551
+f 7551 7677 7609
+f 7551 7609 7453
+f 7453 7609 7487
+f 7453 7487 7291
+f 7291 7487 7377
+f 7291 7377 7233
+f 7233 7377 7173
+f 7233 7173 7113
+f 7113 7173 7117
+f 7113 7117 6955
+f 6955 7117 6917
+f 6955 6917 6769
+f 6769 6917 6825
+f 6769 6825 6647
+f 6647 6825 6655
+f 6647 6655 6545
+f 6545 6655 6593
+f 6545 6593 6441
+f 6441 6593 6343
+f 6441 6343 6207
+f 6207 6343 6253
+f 6207 6253 6155
+f 6155 6253 6169
+f 6155 6169 5979
+f 5979 6169 5951
+f 5979 5951 5869
+f 5869 5951 5835
+f 5869 5835 5717
+f 5717 5835 5769
+f 5717 5769 5567
+f 5567 5769 5587
+f 5567 5587 5511
+f 5511 5587 5483
+f 5511 5483 5357
+f 5357 5483 5333
+f 5357 5333 5279
+f 5279 5333 5167
+f 5279 5167 5133
+f 5133 5167 5091
+f 5133 5091 4981
+f 4981 5091 4995
+f 4981 4995 4831
+f 4831 4995 4761
+f 4831 4761 4653
+f 4653 4761 4649
+f 4653 4649 4619
+f 4619 4649 4609
+f 4619 4609 4413
+f 4413 4609 4401
+f 4413 4401 4309
+f 4309 4401 4249
+f 4309 4249 4115
+f 4115 4249 4139
+f 4115 4139 4041
+f 4041 4139 3997
+f 4041 3997 3953
+f 3953 3997 3875
+f 3953 3875 3743
+f 3743 3875 3827
+f 3743 3827 3685
+f 3685 3827 3587
+f 3685 3587 3465
+f 3465 3587 3439
+f 3465 3439 3379
+f 3379 3439 3347
+f 3379 3347 3215
+f 3215 3347 3187
+f 3215 3187 3041
+f 3041 3187 3069
+f 3041 3069 3007
+f 3007 3069 2999
+f 3007 2999 2875
+f 2875 2999 2887
+f 2875 2887 2727
+f 2727 2887 2657
+f 2727 2657 2511
+f 2511 2657 2509
+f 2511 2509 2365
+f 2365 2509 2477
+f 2365 2477 2293
+f 2293 2477 2215
+f 2293 2215 2167
+f 2167 2215 2135
+f 2167 2135 1987
+f 1987 2135 2047
+f 1987 2047 1835
+f 1835 2047 1909
+f 1835 1909 1779
+f 1779 1909 1809
+f 1779 1809 1699
+f 1699 1809 1679
+f 1699 1679 1485
+f 1485 1679 1569
+f 1485 1569 1319
+f 1319 1569 1399
+f 1319 1399 1231
+f 1231 1399 1221
+f 1231 1221 1135
+f 1135 1221 1165
+f 1135 1165 1059
+f 1059 1165 945
+f 1059 945 821
+f 821 945 823
+f 821 823 711
+f 711 823 801
+f 711 801 609
+f 609 801 587
+f 609 587 487
+f 487 587 427
+f 487 427 297
+f 297 427 377
+f 297 377 277
+f 277 377 259
+f 277 259 59
+f 59 259 97
+f 59 97 14
+f 7789 7801 7703
+f 7703 7801 7743
+f 7703 7743 7523
+f 7523 7743 7551
+f 7523 7551 7475
+f 7475 7551 7453
+f 7475 7453 7315
+f 7315 7453 7291
+f 7315 7291 7176
+f 7176 7291 7233
+f 7176 7233 7081
+f 7081 7233 7113
+f 7081 7113 6939
+f 6939 7113 6955
+f 6939 6955 6795
+f 6795 6955 6769
+f 6795 6769 6633
+f 6633 6769 6647
+f 6633 6647 6527
+f 6527 6647 6545
+f 6527 6545 6447
+f 6447 6545 6441
+f 6447 6441 6265
+f 6265 6441 6207
+f 6265 6207 6187
+f 6187 6207 6155
+f 6187 6155 5969
+f 5969 6155 5979
+f 5969 5979 5847
+f 5847 5979 5869
+f 5847 5869 5789
+f 5789 5869 5717
+f 5789 5717 5593
+f 5593 5717 5567
+f 5593 5567 5433
+f 5433 5567 5511
+f 5433 5511 5363
+f 5363 5511 5357
+f 5363 5357 5233
+f 5233 5357 5279
+f 5233 5279 5051
+f 5051 5279 5133
+f 5051 5133 4939
+f 4939 5133 4981
+f 4939 4981 4765
+f 4765 4981 4831
+f 4765 4831 4673
+f 4673 4831 4653
+f 4673 4653 4543
+f 4543 4653 4619
+f 4543 4619 4469
+f 4469 4619 4413
+f 4469 4413 4275
+f 4275 4413 4309
+f 4275 4309 4151
+f 4151 4309 4115
+f 4151 4115 4063
+f 4063 4115 4041
+f 4063 4041 3927
+f 3927 4041 3953
+f 3927 3953 3815
+f 3815 3953 3743
+f 3815 3743 3579
+f 3579 3743 3685
+f 3579 3685 3491
+f 3491 3685 3465
+f 3491 3465 3397
+f 3397 3465 3379
+f 3397 3379 3179
+f 3179 3379 3215
+f 3179 3215 3059
+f 3059 3215 3041
+f 3059 3041 2913
+f 2913 3041 3007
+f 2913 3007 2783
+f 2783 3007 2875
+f 2783 2875 2729
+f 2729 2875 2727
+f 2729 2727 2613
+f 2613 2727 2511
+f 2613 2511 2375
+f 2375 2511 2365
+f 2375 2365 2335
+f 2335 2365 2293
+f 2335 2293 2107
+f 2107 2293 2167
+f 2107 2167 2059
+f 2059 2167 1987
+f 2059 1987 1903
+f 1903 1987 1835
+f 1903 1835 1825
+f 1825 1835 1779
+f 1825 1779 1631
+f 1631 1779 1699
+f 1631 1699 1491
+f 1491 1699 1485
+f 1491 1485 1350
+f 1350 1485 1319
+f 1350 1319 1262
+f 1262 1319 1231
+f 1262 1231 1079
+f 1079 1231 1135
+f 1079 1135 1019
+f 1019 1135 1059
+f 1019 1059 893
+f 893 1059 821
+f 893 821 703
+f 703 821 711
+f 703 711 591
+f 591 711 609
+f 591 609 537
+f 537 609 487
+f 537 487 303
+f 303 487 297
+f 303 297 189
+f 189 297 277
+f 189 277 148
+f 148 277 59
+f 148 59 2
+f 7787 7789 7711
+f 7711 7789 7703
+f 7711 7703 7553
+f 7553 7703 7523
+f 7553 7523 7483
+f 7483 7523 7475
+f 7483 7475 7325
+f 7325 7475 7315
+f 7325 7315 7203
+f 7203 7315 7176
+f 7203 7176 7082
+f 7082 7176 7081
+f 7082 7081 6937
+f 6937 7081 6939
+f 6937 6939 6815
+f 6815 6939 6795
+f 6815 6795 6649
+f 6649 6795 6633
+f 6649 6633 6511
+f 6511 6633 6527
+f 6511 6527 6431
+f 6431 6527 6447
+f 6431 6447 6233
+f 6233 6447 6265
+f 6233 6265 6093
+f 6093 6265 6187
+f 6093 6187 6063
+f 6063 6187 5969
+f 6063 5969 5829
+f 5829 5969 5847
+f 5829 5847 5685
+f 5685 5847 5789
+f 5685 5789 5669
+f 5669 5789 5593
+f 5669 5593 5463
+f 5463 5593 5433
+f 5463 5433 5323
+f 5323 5433 5363
+f 5323 5363 5185
+f 5185 5363 5233
+f 5185 5233 5149
+f 5149 5233 5051
+f 5149 5051 4979
+f 4979 5051 4939
+f 4979 4939 4795
+f 4795 4939 4765
+f 4795 4765 4645
+f 4645 4765 4673
+f 4645 4673 4531
+f 4531 4673 4543
+f 4531 4543 4363
+f 4363 4543 4469
+f 4363 4469 4267
+f 4267 4469 4275
+f 4267 4275 4197
+f 4197 4275 4151
+f 4197 4151 4011
+f 4011 4151 4063
+f 4011 4063 3847
+f 3847 4063 3927
+f 3847 3927 3779
+f 3779 3927 3815
+f 3779 3815 3591
+f 3591 3815 3579
+f 3591 3579 3511
+f 3511 3579 3491
+f 3511 3491 3429
+f 3429 3491 3397
+f 3429 3397 3211
+f 3211 3397 3179
+f 3211 3179 3057
+f 3057 3179 3059
+f 3057 3059 3005
+f 3005 3059 2913
+f 3005 2913 2819
+f 2819 2913 2783
+f 2819 2783 2639
+f 2639 2783 2729
+f 2639 2729 2535
+f 2535 2729 2613
+f 2535 2613 2361
+f 2361 2613 2375
+f 2361 2375 2273
+f 2273 2375 2335
+f 2273 2335 2203
+f 2203 2335 2107
+f 2203 2107 1995
+f 1995 2107 2059
+f 1995 2059 1949
+f 1949 2059 1903
+f 1949 1903 1701
+f 1701 1903 1825
+f 1701 1825 1691
+f 1691 1825 1631
+f 1691 1631 1449
+f 1449 1631 1491
+f 1449 1491 1321
+f 1321 1491 1350
+f 1321 1350 1293
+f 1293 1350 1262
+f 1293 1262 1129
+f 1129 1262 1079
+f 1129 1079 1049
+f 1049 1079 1019
+f 1049 1019 889
+f 889 1019 893
+f 889 893 707
+f 707 893 703
+f 707 703 641
+f 641 703 591
+f 641 591 425
+f 425 591 537
+f 425 537 411
+f 411 537 303
+f 411 303 185
+f 185 303 189
+f 185 189 93
+f 93 189 148
+f 93 148 2
+f 7847 7787 7643
+f 7643 7787 7711
+f 7643 7711 7554
+f 7554 7711 7553
+f 7554 7553 7470
+f 7470 7553 7483
+f 7470 7483 7301
+f 7301 7483 7325
+f 7301 7325 7227
+f 7227 7325 7203
+f 7227 7203 7039
+f 7039 7203 7082
+f 7039 7082 6869
+f 6869 7082 6937
+f 6869 6937 6819
+f 6819 6937 6815
+f 6819 6815 6665
+f 6665 6815 6649
+f 6665 6649 6501
+f 6501 6649 6511
+f 6501 6511 6453
+f 6453 6511 6431
+f 6453 6431 6273
+f 6273 6431 6233
+f 6273 6233 6129
+f 6129 6233 6093
+f 6129 6093 6059
+f 6059 6093 6063
+f 6059 6063 5845
+f 5845 6063 5829
+f 5845 5829 5742
+f 5742 5829 5685
+f 5742 5685 5607
+f 5607 5685 5669
+f 5607 5669 5425
+f 5425 5669 5463
+f 5425 5463 5413
+f 5413 5463 5323
+f 5413 5323 5227
+f 5227 5323 5185
+f 5227 5185 5113
+f 5113 5185 5149
+f 5113 5149 4983
+f 4983 5149 4979
+f 4983 4979 4789
+f 4789 4979 4795
+f 4789 4795 4643
+f 4643 4795 4645
+f 4643 4645 4547
+f 4547 4645 4531
+f 4547 4531 4434
+f 4434 4531 4363
+f 4434 4363 4327
+f 4327 4363 4267
+f 4327 4267 4131
+f 4131 4267 4197
+f 4131 4197 4079
+f 4079 4197 4011
+f 4079 4011 3883
+f 3883 4011 3847
+f 3883 3847 3791
+f 3791 3847 3779
+f 3791 3779 3601
+f 3601 3779 3591
+f 3601 3591 3531
+f 3531 3591 3511
+f 3531 3511 3395
+f 3395 3511 3429
+f 3395 3429 3291
+f 3291 3429 3211
+f 3291 3211 3147
+f 3147 3211 3057
+f 3147 3057 2941
+f 2941 3057 3005
+f 2941 3005 2805
+f 2805 3005 2819
+f 2805 2819 2723
+f 2723 2819 2639
+f 2723 2639 2529
+f 2529 2639 2535
+f 2529 2535 2369
+f 2369 2535 2361
+f 2369 2361 2317
+f 2317 2361 2273
+f 2317 2273 2191
+f 2191 2273 2203
+f 2191 2203 1973
+f 1973 2203 1995
+f 1973 1995 1939
+f 1939 1995 1949
+f 1939 1949 1815
+f 1815 1949 1701
+f 1815 1701 1635
+f 1635 1701 1691
+f 1635 1691 1518
+f 1518 1691 1449
+f 1518 1449 1341
+f 1341 1449 1321
+f 1341 1321 1253
+f 1253 1321 1293
+f 1253 1293 1187
+f 1187 1293 1129
+f 1187 1129 995
+f 995 1129 1049
+f 995 1049 807
+f 807 1049 889
+f 807 889 716
+f 716 889 707
+f 716 707 595
+f 595 707 641
+f 595 641 535
+f 535 641 425
+f 535 425 313
+f 313 425 411
+f 313 411 289
+f 289 411 185
+f 289 185 123
+f 123 185 93
+f 123 93 7
+f 7849 7847 7680
+f 7680 7847 7643
+f 7680 7643 7559
+f 7559 7643 7554
+f 7559 7554 7509
+f 7509 7554 7470
+f 7509 7470 7347
+f 7347 7470 7301
+f 7347 7301 7163
+f 7163 7301 7227
+f 7163 7227 7025
+f 7025 7227 7039
+f 7025 7039 6979
+f 6979 7039 6869
+f 6979 6869 6737
+f 6737 6869 6819
+f 6737 6819 6601
+f 6601 6819 6665
+f 6601 6665 6477
+f 6477 6665 6501
+f 6477 6501 6379
+f 6379 6501 6453
+f 6379 6453 6317
+f 6317 6453 6273
+f 6317 6273 6167
+f 6167 6273 6129
+f 6167 6129 6015
+f 6015 6129 6059
+f 6015 6059 5831
+f 5831 6059 5845
+f 5831 5845 5759
+f 5759 5845 5742
+f 5759 5742 5623
+f 5623 5742 5607
+f 5623 5607 5541
+f 5541 5607 5425
+f 5541 5425 5351
+f 5351 5425 5413
+f 5351 5413 5197
+f 5197 5413 5227
+f 5197 5227 5145
+f 5145 5227 5113
+f 5145 5113 4915
+f 4915 5113 4983
+f 4915 4983 4863
+f 4863 4983 4789
+f 4863 4789 4679
+f 4679 4789 4643
+f 4679 4643 4569
+f 4569 4643 4547
+f 4569 4547 4371
+f 4371 4547 4434
+f 4371 4434 4311
+f 4311 4434 4327
+f 4311 4327 4133
+f 4133 4327 4131
+f 4133 4131 4047
+f 4047 4131 4079
+f 4047 4079 3909
+f 3909 4079 3883
+f 3909 3883 3819
+f 3819 3883 3791
+f 3819 3791 3665
+f 3665 3791 3601
+f 3665 3601 3453
+f 3453 3601 3531
+f 3453 3531 3357
+f 3357 3531 3395
+f 3357 3395 3273
+f 3273 3395 3291
+f 3273 3291 3091
+f 3091 3291 3147
+f 3091 3147 2903
+f 2903 3147 2941
+f 2903 2941 2815
+f 2815 2941 2805
+f 2815 2805 2756
+f 2756 2805 2723
+f 2756 2723 2607
+f 2607 2723 2529
+f 2607 2529 2379
+f 2379 2529 2369
+f 2379 2369 2245
+f 2245 2369 2317
+f 2245 2317 2110
+f 2110 2317 2191
+f 2110 2191 1991
+f 1991 2191 1973
+f 1991 1973 1855
+f 1855 1973 1939
+f 1855 1939 1772
+f 1772 1939 1815
+f 1772 1815 1661
+f 1661 1815 1635
+f 1661 1635 1550
+f 1550 1635 1518
+f 1550 1518 1435
+f 1435 1518 1341
+f 1435 1341 1189
+f 1189 1341 1253
+f 1189 1253 1103
+f 1103 1253 1187
+f 1103 1187 1041
+f 1041 1187 995
+f 1041 995 825
+f 825 995 807
+f 825 807 725
+f 725 807 716
+f 725 716 603
+f 603 716 595
+f 603 595 431
+f 431 595 535
+f 431 535 333
+f 333 535 313
+f 333 313 265
+f 265 313 289
+f 265 289 141
+f 141 289 123
+f 141 123 8
+f 7869 7849 7727
+f 7727 7849 7680
+f 7727 7680 7593
+f 7593 7680 7559
+f 7593 7559 7411
+f 7411 7559 7509
+f 7411 7509 7333
+f 7333 7509 7347
+f 7333 7347 7237
+f 7237 7347 7163
+f 7237 7163 7018
+f 7018 7163 7025
+f 7018 7025 6975
+f 6975 7025 6979
+f 6975 6979 6745
+f 6745 6979 6737
+f 6745 6737 6653
+f 6653 6737 6601
+f 6653 6601 6494
+f 6494 6601 6477
+f 6494 6477 6374
+f 6374 6477 6379
+f 6374 6379 6305
+f 6305 6379 6317
+f 6305 6317 6087
+f 6087 6317 6167
+f 6087 6167 6009
+f 6009 6167 6015
+f 6009 6015 5839
+f 5839 6015 5831
+f 5839 5831 5777
+f 5777 5831 5759
+f 5777 5759 5601
+f 5601 5759 5623
+f 5601 5623 5529
+f 5529 5623 5541
+f 5529 5541 5295
+f 5295 5541 5351
+f 5295 5351 5277
+f 5277 5351 5197
+f 5277 5197 5027
+f 5027 5197 5145
+f 5027 5145 5001
+f 5001 5145 4915
+f 5001 4915 4781
+f 4781 4915 4863
+f 4781 4863 4680
+f 4680 4863 4679
+f 4680 4679 4503
+f 4503 4679 4569
+f 4503 4569 4457
+f 4457 4569 4371
+f 4457 4371 4241
+f 4241 4371 4311
+f 4241 4311 4135
+f 4135 4311 4133
+f 4135 4133 4061
+f 4061 4133 4047
+f 4061 4047 3871
+f 3871 4047 3909
+f 3871 3909 3795
+f 3795 3909 3819
+f 3795 3819 3697
+f 3697 3819 3665
+f 3697 3665 3489
+f 3489 3665 3453
+f 3489 3453 3418
+f 3418 3453 3357
+f 3418 3357 3259
+f 3259 3357 3273
+f 3259 3273 3151
+f 3151 3273 3091
+f 3151 3091 2917
+f 2917 3091 2903
+f 2917 2903 2779
+f 2779 2903 2815
+f 2779 2815 2637
+f 2637 2815 2756
+f 2637 2756 2499
+f 2499 2756 2607
+f 2499 2607 2371
+f 2371 2607 2379
+f 2371 2379 2253
+f 2253 2379 2245
+f 2253 2245 2175
+f 2175 2245 2110
+f 2175 2110 2011
+f 2011 2110 1991
+f 2011 1991 1904
+f 1904 1991 1855
+f 1904 1855 1783
+f 1783 1855 1772
+f 1783 1772 1611
+f 1611 1772 1661
+f 1611 1661 1535
+f 1535 1661 1550
+f 1535 1550 1343
+f 1343 1550 1435
+f 1343 1435 1213
+f 1213 1435 1189
+f 1213 1189 1071
+f 1071 1189 1103
+f 1071 1103 1008
+f 1008 1103 1041
+f 1008 1041 879
+f 879 1041 825
+f 879 825 803
+f 803 825 725
+f 803 725 596
+f 596 725 603
+f 596 603 511
+f 511 603 431
+f 511 431 315
+f 315 431 333
+f 315 333 225
+f 225 333 265
+f 225 265 147
+f 147 265 141
+f 147 141 8
+f 7805 7869 7731
+f 7731 7869 7727
+f 7731 7727 7525
+f 7525 7727 7593
+f 7525 7593 7461
+f 7461 7593 7411
+f 7461 7411 7303
+f 7303 7411 7333
+f 7303 7333 7191
+f 7191 7333 7237
+f 7191 7237 7125
+f 7125 7237 7018
+f 7125 7018 6971
+f 6971 7018 6975
+f 6971 6975 6835
+f 6835 6975 6745
+f 6835 6745 6675
+f 6675 6745 6653
+f 6675 6653 6581
+f 6581 6653 6494
+f 6581 6494 6421
+f 6421 6494 6374
+f 6421 6374 6219
+f 6219 6374 6305
+f 6219 6305 6127
+f 6127 6305 6087
+f 6127 6087 6025
+f 6025 6087 6009
+f 6025 6009 5879
+f 5879 6009 5839
+f 5879 5839 5747
+f 5747 5839 5777
+f 5747 5777 5625
+f 5625 5777 5601
+f 5625 5601 5441
+f 5441 5601 5529
+f 5441 5529 5297
+f 5297 5529 5295
+f 5297 5295 5205
+f 5205 5295 5277
+f 5205 5277 5041
+f 5041 5277 5027
+f 5041 5027 4929
+f 4929 5027 5001
+f 4929 5001 4773
+f 4773 5001 4781
+f 4773 4781 4749
+f 4749 4781 4680
+f 4749 4680 4605
+f 4605 4680 4503
+f 4605 4503 4367
+f 4367 4503 4457
+f 4367 4457 4281
+f 4281 4457 4241
+f 4281 4241 4183
+f 4183 4241 4135
+f 4183 4135 4081
+f 4081 4135 4061
+f 4081 4061 3885
+f 3885 4061 3871
+f 3885 3871 3761
+f 3761 3871 3795
+f 3761 3795 3693
+f 3693 3795 3697
+f 3693 3697 3463
+f 3463 3697 3489
+f 3463 3489 3331
+f 3331 3489 3418
+f 3331 3418 3183
+f 3183 3418 3259
+f 3183 3259 3049
+f 3049 3259 3151
+f 3049 3151 3027
+f 3027 3151 2917
+f 3027 2917 2774
+f 2774 2917 2779
+f 2774 2779 2745
+f 2745 2779 2637
+f 2745 2637 2523
+f 2523 2637 2499
+f 2523 2499 2423
+f 2423 2499 2371
+f 2423 2371 2235
+f 2235 2371 2253
+f 2235 2253 2093
+f 2093 2253 2175
+f 2093 2175 2007
+f 2007 2175 2011
+f 2007 2011 1874
+f 1874 2011 1904
+f 1874 1904 1811
+f 1811 1904 1783
+f 1811 1783 1669
+f 1669 1783 1611
+f 1669 1611 1468
+f 1468 1611 1535
+f 1468 1535 1373
+f 1373 1535 1343
+f 1373 1343 1284
+f 1284 1343 1213
+f 1284 1213 1085
+f 1085 1213 1071
+f 1085 1071 1033
+f 1033 1071 1008
+f 1033 1008 915
+f 915 1008 879
+f 915 879 754
+f 754 879 803
+f 754 803 588
+f 588 803 596
+f 588 596 461
+f 461 596 511
+f 461 511 391
+f 391 511 315
+f 391 315 229
+f 229 315 225
+f 229 225 45
+f 45 225 147
+f 45 147 29
+f 7863 7805 7741
+f 7741 7805 7731
+f 7741 7731 7597
+f 7597 7731 7525
+f 7597 7525 7428
+f 7428 7525 7461
+f 7428 7461 7367
+f 7367 7461 7303
+f 7367 7303 7185
+f 7185 7303 7191
+f 7185 7191 7061
+f 7061 7191 7125
+f 7061 7125 6863
+f 6863 7125 6971
+f 6863 6971 6741
+f 6741 6971 6835
+f 6741 6835 6657
+f 6657 6835 6675
+f 6657 6675 6577
+f 6577 6675 6581
+f 6577 6581 6455
+f 6455 6581 6421
+f 6455 6421 6299
+f 6299 6421 6219
+f 6299 6219 6089
+f 6089 6219 6127
+f 6089 6127 6011
+f 6011 6127 6025
+f 6011 6025 5909
+f 5909 6025 5879
+f 5909 5879 5785
+f 5785 5879 5747
+f 5785 5747 5579
+f 5579 5747 5625
+f 5579 5625 5461
+f 5461 5625 5441
+f 5461 5441 5378
+f 5378 5441 5297
+f 5378 5297 5261
+f 5261 5297 5205
+f 5261 5205 5033
+f 5033 5205 5041
+f 5033 5041 4931
+f 4931 5041 4929
+f 4931 4929 4851
+f 4851 4929 4773
+f 4851 4773 4657
+f 4657 4773 4749
+f 4657 4749 4525
+f 4525 4749 4605
+f 4525 4605 4421
+f 4421 4605 4367
+f 4421 4367 4334
+f 4334 4367 4281
+f 4334 4281 4167
+f 4167 4281 4183
+f 4167 4183 4001
+f 4001 4183 4081
+f 4001 4081 3947
+f 3947 4081 3885
+f 3947 3885 3767
+f 3767 3885 3761
+f 3767 3761 3603
+f 3603 3761 3693
+f 3603 3693 3539
+f 3539 3693 3463
+f 3539 3463 3405
+f 3405 3463 3331
+f 3405 3331 3289
+f 3289 3331 3183
+f 3289 3183 3089
+f 3089 3183 3049
+f 3089 3049 3017
+f 3017 3049 3027
+f 3017 3027 2777
+f 2777 3027 2774
+f 2777 2774 2659
+f 2659 2774 2745
+f 2659 2745 2577
+f 2577 2745 2523
+f 2577 2523 2467
+f 2467 2523 2423
+f 2467 2423 2271
+f 2271 2423 2235
+f 2271 2235 2089
+f 2089 2235 2093
+f 2089 2093 2012
+f 2012 2093 2007
+f 2012 2007 1943
+f 1943 2007 1874
+f 1943 1874 1741
+f 1741 1874 1811
+f 1741 1811 1694
+f 1694 1811 1669
+f 1694 1669 1459
+f 1459 1669 1468
+f 1459 1468 1397
+f 1397 1468 1373
+f 1397 1373 1273
+f 1273 1373 1284
+f 1273 1284 1095
+f 1095 1284 1085
+f 1095 1085 1034
+f 1034 1085 1033
+f 1034 1033 811
+f 811 1033 915
+f 811 915 755
+f 755 915 754
+f 755 754 627
+f 627 754 588
+f 627 588 539
+f 539 588 461
+f 539 461 339
+f 339 461 391
+f 339 391 279
+f 279 391 229
+f 279 229 63
+f 63 229 45
+f 63 45 29
+f 7860 7863 7645
+f 7645 7863 7741
+f 7645 7741 7617
+f 7617 7741 7597
+f 7617 7597 7473
+f 7473 7597 7428
+f 7473 7428 7285
+f 7285 7428 7367
+f 7285 7367 7167
+f 7167 7367 7185
+f 7167 7185 7115
+f 7115 7185 7061
+f 7115 7061 6931
+f 6931 7061 6863
+f 6931 6863 6853
+f 6853 6863 6741
+f 6853 6741 6699
+f 6699 6741 6657
+f 6699 6657 6585
+f 6585 6657 6577
+f 6585 6577 6407
+f 6407 6577 6455
+f 6407 6455 6249
+f 6249 6455 6299
+f 6249 6299 6145
+f 6145 6299 6089
+f 6145 6089 5957
+f 5957 6089 6011
+f 5957 6011 5821
+f 5821 6011 5909
+f 5821 5909 5755
+f 5755 5909 5785
+f 5755 5785 5643
+f 5643 5785 5579
+f 5643 5579 5521
+f 5521 5579 5461
+f 5521 5461 5321
+f 5321 5461 5378
+f 5321 5378 5181
+f 5181 5378 5261
+f 5181 5261 5143
+f 5143 5261 5033
+f 5143 5033 4959
+f 4959 5033 4931
+f 4959 4931 4791
+f 4791 4931 4851
+f 4791 4851 4631
+f 4631 4851 4657
+f 4631 4657 4575
+f 4575 4657 4525
+f 4575 4525 4386
+f 4386 4525 4421
+f 4386 4421 4282
+f 4282 4421 4334
+f 4282 4334 4201
+f 4201 4334 4167
+f 4201 4167 4009
+f 4009 4167 4001
+f 4009 4001 3861
+f 3861 4001 3947
+f 3861 3947 3799
+f 3799 3947 3767
+f 3799 3767 3617
+f 3617 3767 3603
+f 3617 3603 3517
+f 3517 3603 3539
+f 3517 3539 3401
+f 3401 3539 3405
+f 3401 3405 3253
+f 3253 3405 3289
+f 3253 3289 3092
+f 3092 3289 3089
+f 3092 3089 2921
+f 2921 3089 3017
+f 2921 3017 2877
+f 2877 3017 2777
+f 2877 2777 2681
+f 2681 2777 2659
+f 2681 2659 2585
+f 2585 2659 2577
+f 2585 2577 2469
+f 2469 2577 2467
+f 2469 2467 2255
+f 2255 2467 2271
+f 2255 2271 2156
+f 2156 2271 2089
+f 2156 2089 1996
+f 1996 2089 2012
+f 1996 2012 1856
+f 1856 2012 1943
+f 1856 1943 1751
+f 1751 1943 1741
+f 1751 1741 1684
+f 1684 1741 1694
+f 1684 1694 1479
+f 1479 1694 1459
+f 1479 1459 1419
+f 1419 1459 1397
+f 1419 1397 1294
+f 1294 1397 1273
+f 1294 1273 1072
+f 1072 1273 1095
+f 1072 1095 950
+f 950 1095 1034
+f 950 1034 841
+f 841 1034 811
+f 841 811 763
+f 763 811 755
+f 763 755 549
+f 549 755 627
+f 549 627 473
+f 473 627 539
+f 473 539 340
+f 340 539 339
+f 340 339 177
+f 177 339 279
+f 177 279 70
+f 70 279 63
+f 70 63 6
+f 7799 7860 7713
+f 7713 7860 7645
+f 7713 7645 7545
+f 7545 7645 7617
+f 7545 7617 7497
+f 7497 7617 7473
+f 7497 7473 7286
+f 7286 7473 7285
+f 7286 7285 7257
+f 7257 7285 7167
+f 7257 7167 7075
+f 7075 7167 7115
+f 7075 7115 6880
+f 6880 7115 6931
+f 6880 6931 6829
+f 6829 6931 6853
+f 6829 6853 6679
+f 6679 6853 6699
+f 6679 6699 6517
+f 6517 6699 6585
+f 6517 6585 6435
+f 6435 6585 6407
+f 6435 6407 6220
+f 6220 6407 6249
+f 6220 6249 6189
+f 6189 6249 6145
+f 6189 6145 5985
+f 5985 6145 5957
+f 5985 5957 5895
+f 5895 5957 5821
+f 5895 5821 5725
+f 5725 5821 5755
+f 5725 5755 5663
+f 5663 5755 5643
+f 5663 5643 5509
+f 5509 5643 5521
+f 5509 5521 5347
+f 5347 5521 5321
+f 5347 5321 5225
+f 5225 5321 5181
+f 5225 5181 5069
+f 5069 5181 5143
+f 5069 5143 4991
+f 4991 5143 4959
+f 4991 4959 4865
+f 4865 4959 4791
+f 4865 4791 4691
+f 4691 4791 4631
+f 4691 4631 4566
+f 4566 4631 4575
+f 4566 4575 4449
+f 4449 4575 4386
+f 4449 4386 4321
+f 4321 4386 4282
+f 4321 4282 4101
+f 4101 4282 4201
+f 4101 4201 3983
+f 3983 4201 4009
+f 3983 4009 3839
+f 3839 4009 3861
+f 3839 3861 3737
+f 3737 3861 3799
+f 3737 3799 3618
+f 3618 3799 3617
+f 3618 3617 3509
+f 3509 3617 3517
+f 3509 3517 3349
+f 3349 3517 3401
+f 3349 3401 3265
+f 3265 3401 3253
+f 3265 3253 3073
+f 3073 3253 3092
+f 3073 3092 2943
+f 2943 3092 2921
+f 2943 2921 2881
+f 2881 2921 2877
+f 2881 2877 2731
+f 2731 2877 2681
+f 2731 2681 2545
+f 2545 2681 2585
+f 2545 2585 2418
+f 2418 2585 2469
+f 2418 2469 2309
+f 2309 2469 2255
+f 2309 2255 2145
+f 2145 2255 2156
+f 2145 2156 1979
+f 1979 2156 1996
+f 1979 1996 1947
+f 1947 1996 1856
+f 1947 1856 1773
+f 1773 1856 1751
+f 1773 1751 1573
+f 1573 1751 1684
+f 1573 1684 1547
+f 1547 1684 1479
+f 1547 1479 1361
+f 1361 1479 1419
+f 1361 1419 1306
+f 1306 1419 1294
+f 1306 1294 1155
+f 1155 1294 1072
+f 1155 1072 983
+f 983 1072 950
+f 983 950 903
+f 903 950 841
+f 903 841 747
+f 747 841 763
+f 747 763 617
+f 617 763 549
+f 617 549 501
+f 501 549 473
+f 501 473 392
+f 392 473 340
+f 392 340 243
+f 243 340 177
+f 243 177 77
+f 77 177 70
+f 77 70 6
+f 7779 7799 7667
+f 7667 7799 7713
+f 7667 7713 7587
+f 7587 7713 7545
+f 7587 7545 7439
+f 7439 7545 7497
+f 7439 7497 7277
+f 7277 7497 7286
+f 7277 7286 7249
+f 7249 7286 7257
+f 7249 7257 7037
+f 7037 7257 7075
+f 7037 7075 6933
+f 6933 7075 6880
+f 6933 6880 6805
+f 6805 6880 6829
+f 6805 6829 6621
+f 6621 6829 6679
+f 6621 6679 6521
+f 6521 6679 6517
+f 6521 6517 6371
+f 6371 6517 6435
+f 6371 6435 6261
+f 6261 6435 6220
+f 6261 6220 6101
+f 6101 6220 6189
+f 6101 6189 5946
+f 5946 6189 5985
+f 5946 5985 5815
+f 5815 5985 5895
+f 5815 5895 5709
+f 5709 5895 5725
+f 5709 5725 5655
+f 5655 5725 5663
+f 5655 5663 5435
+f 5435 5663 5509
+f 5435 5509 5395
+f 5395 5509 5347
+f 5395 5347 5258
+f 5258 5347 5225
+f 5258 5225 5077
+f 5077 5225 5069
+f 5077 5069 5007
+f 5007 5069 4991
+f 5007 4991 4840
+f 4840 4991 4865
+f 4840 4865 4735
+f 4735 4865 4691
+f 4735 4691 4617
+f 4617 4691 4566
+f 4617 4566 4409
+f 4409 4566 4449
+f 4409 4449 4257
+f 4257 4449 4321
+f 4257 4321 4123
+f 4123 4321 4101
+f 4123 4101 4028
+f 4028 4101 3983
+f 4028 3983 3897
+f 3897 3983 3839
+f 3897 3839 3756
+f 3756 3839 3737
+f 3756 3737 3653
+f 3653 3737 3618
+f 3653 3618 3478
+f 3478 3618 3509
+f 3478 3509 3389
+f 3389 3509 3349
+f 3389 3349 3285
+f 3285 3349 3265
+f 3285 3265 3045
+f 3045 3265 3073
+f 3045 3073 3003
+f 3003 3073 2943
+f 3003 2943 2821
+f 2821 2943 2881
+f 2821 2881 2743
+f 2743 2881 2731
+f 2743 2731 2561
+f 2561 2731 2545
+f 2561 2545 2461
+f 2461 2545 2418
+f 2461 2418 2297
+f 2297 2418 2309
+f 2297 2309 2137
+f 2137 2309 2145
+f 2137 2145 2029
+f 2029 2145 1979
+f 2029 1979 1833
+f 1833 1979 1947
+f 1833 1947 1764
+f 1764 1947 1773
+f 1764 1773 1639
+f 1639 1773 1573
+f 1639 1573 1508
+f 1508 1573 1547
+f 1508 1547 1362
+f 1362 1547 1361
+f 1362 1361 1235
+f 1235 1361 1306
+f 1235 1306 1112
+f 1112 1306 1155
+f 1112 1155 1022
+f 1022 1155 983
+f 1022 983 837
+f 837 983 903
+f 837 903 695
+f 695 903 747
+f 695 747 660
+f 660 747 617
+f 660 617 491
+f 491 617 501
+f 491 501 355
+f 355 501 392
+f 355 392 213
+f 213 392 243
+f 213 243 159
+f 159 243 77
+f 159 77 30
+f 7873 7779 7719
+f 7719 7779 7667
+f 7719 7667 7623
+f 7623 7667 7587
+f 7623 7587 7421
+f 7421 7587 7439
+f 7421 7439 7361
+f 7361 7439 7277
+f 7361 7277 7255
+f 7255 7277 7249
+f 7255 7249 7095
+f 7095 7249 7037
+f 7095 7037 6963
+f 6963 7037 6933
+f 6963 6933 6802
+f 6802 6933 6805
+f 6802 6805 6680
+f 6680 6805 6621
+f 6680 6621 6467
+f 6467 6621 6521
+f 6467 6521 6436
+f 6436 6521 6371
+f 6436 6371 6223
+f 6223 6371 6261
+f 6223 6261 6079
+f 6079 6261 6101
+f 6079 6101 6055
+f 6055 6101 5946
+f 6055 5946 5922
+f 5922 5946 5815
+f 5922 5815 5701
+f 5701 5815 5709
+f 5701 5709 5659
+f 5659 5709 5655
+f 5659 5655 5477
+f 5477 5655 5435
+f 5477 5435 5349
+f 5349 5435 5395
+f 5349 5395 5191
+f 5191 5395 5258
+f 5191 5258 5028
+f 5028 5258 5077
+f 5028 5077 4908
+f 4908 5077 5007
+f 4908 5007 4819
+f 4819 5007 4840
+f 4819 4840 4713
+f 4713 4840 4735
+f 4713 4735 4527
+f 4527 4735 4617
+f 4527 4617 4427
+f 4427 4617 4409
+f 4427 4409 4349
+f 4349 4409 4257
+f 4349 4257 4217
+f 4217 4257 4123
+f 4217 4123 4064
+f 4064 4123 4028
+f 4064 4028 3899
+f 3899 4028 3897
+f 3899 3897 3721
+f 3721 3897 3756
+f 3721 3756 3585
+f 3585 3756 3653
+f 3585 3653 3505
+f 3505 3653 3478
+f 3505 3478 3402
+f 3402 3478 3389
+f 3402 3389 3261
+f 3261 3389 3285
+f 3261 3285 3139
+f 3139 3285 3045
+f 3139 3045 3025
+f 3025 3045 3003
+f 3025 3003 2793
+f 2793 3003 2821
+f 2793 2821 2713
+f 2713 2821 2743
+f 2713 2743 2571
+f 2571 2743 2561
+f 2571 2561 2398
+f 2398 2561 2461
+f 2398 2461 2256
+f 2256 2461 2297
+f 2256 2297 2087
+f 2087 2297 2137
+f 2087 2137 2035
+f 2035 2137 2029
+f 2035 2029 1839
+f 1839 2029 1833
+f 1839 1833 1742
+f 1742 1833 1764
+f 1742 1764 1681
+f 1681 1764 1639
+f 1681 1639 1519
+f 1519 1639 1508
+f 1519 1508 1374
+f 1374 1508 1362
+f 1374 1362 1315
+f 1315 1362 1235
+f 1315 1235 1104
+f 1104 1235 1112
+f 1104 1112 951
+f 951 1112 1022
+f 951 1022 904
+f 904 1022 837
+f 904 837 797
+f 797 837 695
+f 797 695 582
+f 582 695 660
+f 582 660 541
+f 541 660 491
+f 541 491 413
+f 413 491 355
+f 413 355 230
+f 230 355 213
+f 230 213 53
+f 53 213 159
+f 53 159 30
+f 7819 7873 7671
+f 7671 7873 7719
+f 7671 7719 7629
+f 7629 7719 7623
+f 7629 7623 7498
+f 7498 7623 7421
+f 7498 7421 7323
+f 7323 7421 7361
+f 7323 7361 7177
+f 7177 7361 7255
+f 7177 7255 7053
+f 7053 7255 7095
+f 7053 7095 6964
+f 6964 7095 6963
+f 6964 6963 6761
+f 6761 6963 6802
+f 6761 6802 6713
+f 6713 6802 6680
+f 6713 6680 6591
+f 6591 6680 6467
+f 6591 6467 6461
+f 6461 6467 6436
+f 6461 6436 6217
+f 6217 6436 6223
+f 6217 6223 6157
+f 6157 6223 6079
+f 6157 6079 5973
+f 5973 6079 6055
+f 5973 6055 5851
+f 5851 6055 5922
+f 5851 5922 5786
+f 5786 5922 5701
+f 5786 5701 5591
+f 5591 5701 5659
+f 5591 5659 5535
+f 5535 5659 5477
+f 5535 5477 5353
+f 5353 5477 5349
+f 5353 5349 5244
+f 5244 5349 5191
+f 5244 5191 5065
+f 5065 5191 5028
+f 5065 5028 4917
+f 4917 5028 4908
+f 4917 4908 4792
+f 4792 4908 4819
+f 4792 4819 4629
+f 4629 4819 4713
+f 4629 4713 4576
+f 4576 4713 4527
+f 4576 4527 4373
+f 4373 4527 4427
+f 4373 4427 4299
+f 4299 4427 4349
+f 4299 4349 4203
+f 4203 4349 4217
+f 4203 4217 4025
+f 4025 4217 4064
+f 4025 4064 3879
+f 3879 4064 3899
+f 3879 3899 3801
+f 3801 3899 3721
+f 3801 3721 3577
+f 3577 3721 3585
+f 3577 3585 3527
+f 3527 3585 3505
+f 3527 3505 3385
+f 3385 3505 3402
+f 3385 3402 3245
+f 3245 3402 3261
+f 3245 3261 3064
+f 3064 3261 3139
+f 3064 3139 2961
+f 2961 3139 3025
+f 2961 3025 2807
+f 2807 3025 2793
+f 2807 2793 2691
+f 2691 2793 2713
+f 2691 2713 2579
+f 2579 2713 2571
+f 2579 2571 2429
+f 2429 2571 2398
+f 2429 2398 2279
+f 2279 2398 2256
+f 2279 2256 2157
+f 2157 2256 2087
+f 2157 2087 2040
+f 2040 2087 2035
+f 2040 2035 1857
+f 1857 2035 1839
+f 1857 1839 1743
+f 1743 1839 1742
+f 1743 1742 1624
+f 1624 1742 1681
+f 1624 1681 1457
+f 1457 1681 1519
+f 1457 1519 1427
+f 1427 1519 1374
+f 1427 1374 1193
+f 1193 1374 1315
+f 1193 1315 1089
+f 1089 1315 1104
+f 1089 1104 1031
+f 1031 1104 951
+f 1031 951 916
+f 916 951 904
+f 916 904 798
+f 798 904 797
+f 798 797 631
+f 631 797 582
+f 631 582 503
+f 503 582 541
+f 503 541 295
+f 295 541 413
+f 295 413 173
+f 173 413 230
+f 173 230 101
+f 101 230 53
+f 101 53 25
+f 7827 7819 7681
+f 7681 7819 7671
+f 7681 7671 7539
+f 7539 7671 7629
+f 7539 7629 7457
+f 7457 7629 7498
+f 7457 7498 7348
+f 7348 7498 7323
+f 7348 7323 7169
+f 7169 7323 7177
+f 7169 7177 7023
+f 7023 7177 7053
+f 7023 7053 6907
+f 6907 7053 6964
+f 6907 6964 6729
+f 6729 6964 6761
+f 6729 6761 6623
+f 6623 6761 6713
+f 6623 6713 6495
+f 6495 6713 6591
+f 6495 6591 6337
+f 6337 6591 6461
+f 6337 6461 6243
+f 6243 6461 6217
+f 6243 6217 6175
+f 6175 6217 6157
+f 6175 6157 5952
+f 5952 6157 5973
+f 5952 5973 5883
+f 5883 5973 5851
+f 5883 5851 5719
+f 5719 5851 5786
+f 5719 5786 5589
+f 5589 5786 5591
+f 5589 5591 5506
+f 5506 5591 5535
+f 5506 5535 5387
+f 5387 5535 5353
+f 5387 5353 5237
+f 5237 5353 5244
+f 5237 5244 5059
+f 5059 5244 5065
+f 5059 5065 4945
+f 4945 5065 4917
+f 4945 4917 4811
+f 4811 4917 4792
+f 4811 4792 4661
+f 4661 4792 4629
+f 4661 4629 4581
+f 4581 4629 4576
+f 4581 4576 4405
+f 4405 4576 4373
+f 4405 4373 4285
+f 4285 4373 4299
+f 4285 4299 4179
+f 4179 4299 4203
+f 4179 4203 4067
+f 4067 4203 4025
+f 4067 4025 3905
+f 3905 4025 3879
+f 3905 3879 3787
+f 3787 3879 3801
+f 3787 3801 3581
+f 3581 3801 3577
+f 3581 3577 3449
+f 3449 3577 3527
+f 3449 3527 3369
+f 3369 3527 3385
+f 3369 3385 3195
+f 3195 3385 3245
+f 3195 3245 3153
+f 3153 3245 3064
+f 3153 3064 3022
+f 3022 3064 2961
+f 3022 2961 2825
+f 2825 2961 2807
+f 2825 2807 2714
+f 2714 2807 2691
+f 2714 2691 2603
+f 2603 2691 2579
+f 2603 2579 2451
+f 2451 2579 2429
+f 2451 2429 2231
+f 2231 2429 2279
+f 2231 2279 2127
+f 2127 2279 2157
+f 2127 2157 1975
+f 1975 2157 2040
+f 1975 2040 1915
+f 1915 2040 1857
+f 1915 1857 1752
+f 1752 1857 1743
+f 1752 1743 1625
+f 1625 1743 1624
+f 1625 1624 1486
+f 1486 1624 1457
+f 1486 1457 1403
+f 1403 1457 1427
+f 1403 1427 1255
+f 1255 1427 1193
+f 1255 1193 1173
+f 1173 1193 1089
+f 1173 1089 992
+f 992 1089 1031
+f 992 1031 931
+f 931 1031 916
+f 931 916 770
+f 770 916 798
+f 770 798 661
+f 661 798 631
+f 661 631 495
+f 495 631 503
+f 495 503 380
+f 380 503 295
+f 380 295 281
+f 281 295 173
+f 281 173 46
+f 46 173 101
+f 46 101 11
+f 7820 7827 7689
+f 7689 7827 7681
+f 7689 7681 7633
+f 7633 7681 7539
+f 7633 7539 7465
+f 7465 7539 7457
+f 7465 7457 7389
+f 7389 7457 7348
+f 7389 7348 7149
+f 7149 7348 7169
+f 7149 7169 7127
+f 7127 7169 7023
+f 7127 7023 6898
+f 6898 7023 6907
+f 6898 6907 6831
+f 6831 6907 6729
+f 6831 6729 6627
+f 6627 6729 6623
+f 6627 6623 6491
+f 6491 6623 6495
+f 6491 6495 6391
+f 6391 6495 6337
+f 6391 6337 6227
+f 6227 6337 6243
+f 6227 6243 6165
+f 6165 6243 6175
+f 6165 6175 6033
+f 6033 6175 5952
+f 6033 5952 5910
+f 5910 5952 5883
+f 5910 5883 5689
+f 5689 5883 5719
+f 5689 5719 5563
+f 5563 5719 5589
+f 5563 5589 5543
+f 5543 5589 5506
+f 5543 5506 5405
+f 5405 5506 5387
+f 5405 5387 5281
+f 5281 5387 5237
+f 5281 5237 5135
+f 5135 5237 5059
+f 5135 5059 4895
+f 4895 5059 4945
+f 4895 4945 4805
+f 4805 4945 4811
+f 4805 4811 4633
+f 4633 4811 4661
+f 4633 4661 4601
+f 4601 4661 4581
+f 4601 4581 4453
+f 4453 4581 4405
+f 4453 4405 4322
+f 4322 4405 4285
+f 4322 4285 4211
+f 4211 4285 4179
+f 4211 4179 3991
+f 3991 4179 4067
+f 3991 4067 3955
+f 3955 4067 3905
+f 3955 3905 3727
+f 3727 3905 3787
+f 3727 3787 3612
+f 3612 3787 3581
+f 3612 3581 3513
+f 3513 3581 3449
+f 3513 3449 3333
+f 3333 3449 3369
+f 3333 3369 3201
+f 3201 3369 3195
+f 3201 3195 3145
+f 3145 3195 3153
+f 3145 3153 2919
+f 2919 3153 3022
+f 2919 3022 2855
+f 2855 3022 2825
+f 2855 2825 2699
+f 2699 2825 2714
+f 2699 2714 2580
+f 2580 2714 2603
+f 2580 2603 2424
+f 2424 2603 2451
+f 2424 2451 2246
+f 2246 2451 2231
+f 2246 2231 2111
+f 2111 2231 2127
+f 2111 2127 2013
+f 2013 2127 1975
+f 2013 1975 1844
+f 1844 1975 1915
+f 1844 1915 1753
+f 1753 1915 1752
+f 1753 1752 1589
+f 1589 1752 1625
+f 1589 1625 1492
+f 1492 1625 1486
+f 1492 1486 1329
+f 1329 1486 1403
+f 1329 1403 1263
+f 1263 1403 1255
+f 1263 1255 1167
+f 1167 1255 1173
+f 1167 1173 959
+f 959 1173 992
+f 959 992 842
+f 842 992 931
+f 842 931 748
+f 748 931 770
+f 748 770 611
+f 611 770 661
+f 611 661 481
+f 481 661 495
+f 481 495 414
+f 414 495 380
+f 414 380 169
+f 169 380 281
+f 169 281 95
+f 95 281 46
+f 95 46 11
+f 7795 7820 7747
+f 7747 7820 7689
+f 7747 7689 7563
+f 7563 7689 7633
+f 7563 7633 7431
+f 7431 7633 7465
+f 7431 7465 7338
+f 7338 7465 7389
+f 7338 7389 7194
+f 7194 7389 7149
+f 7194 7149 7043
+f 7043 7149 7127
+f 7043 7127 6947
+f 6947 7127 6898
+f 6947 6898 6767
+f 6767 6898 6831
+f 6767 6831 6691
+f 6691 6831 6627
+f 6691 6627 6522
+f 6522 6627 6491
+f 6522 6491 6363
+f 6363 6491 6391
+f 6363 6391 6244
+f 6244 6391 6227
+f 6244 6227 6171
+f 6171 6227 6165
+f 6171 6165 5974
+f 5974 6165 6033
+f 5974 6033 5923
+f 5923 6033 5910
+f 5923 5910 5715
+f 5715 5910 5689
+f 5715 5689 5615
+f 5615 5689 5563
+f 5615 5563 5429
+f 5429 5563 5543
+f 5429 5543 5325
+f 5325 5543 5405
+f 5325 5405 5213
+f 5213 5405 5281
+f 5213 5281 5099
+f 5099 5281 5135
+f 5099 5135 4951
+f 4951 5135 4895
+f 4951 4895 4821
+f 4821 4895 4805
+f 4821 4805 4701
+f 4701 4805 4633
+f 4701 4633 4561
+f 4561 4633 4601
+f 4561 4601 4429
+f 4429 4601 4453
+f 4429 4453 4251
+f 4251 4453 4322
+f 4251 4322 4113
+f 4113 4322 4211
+f 4113 4211 4021
+f 4021 4211 3991
+f 4021 3991 3889
+f 3889 3991 3955
+f 3889 3955 3769
+f 3769 3955 3727
+f 3769 3727 3647
+f 3647 3727 3612
+f 3647 3612 3473
+f 3473 3612 3513
+f 3473 3513 3309
+f 3309 3513 3333
+f 3309 3333 3199
+f 3199 3333 3201
+f 3199 3201 3099
+f 3099 3201 3145
+f 3099 3145 2989
+f 2989 3145 2919
+f 2989 2919 2859
+f 2859 2919 2855
+f 2859 2855 2702
+f 2702 2855 2699
+f 2702 2699 2546
+f 2546 2699 2580
+f 2546 2580 2430
+f 2430 2580 2424
+f 2430 2424 2221
+f 2221 2424 2246
+f 2221 2246 2169
+f 2169 2246 2111
+f 2169 2111 1980
+f 1980 2111 2013
+f 1980 2013 1889
+f 1889 2013 1844
+f 1889 1844 1731
+f 1731 1844 1753
+f 1731 1753 1603
+f 1603 1753 1589
+f 1603 1589 1539
+f 1539 1589 1492
+f 1539 1492 1423
+f 1423 1492 1329
+f 1423 1329 1285
+f 1285 1329 1263
+f 1285 1263 1090
+f 1090 1263 1167
+f 1090 1167 977
+f 977 1167 959
+f 977 959 843
+f 843 959 842
+f 843 842 771
+f 771 842 748
+f 771 748 597
+f 597 748 611
+f 597 611 515
+f 515 611 481
+f 515 481 364
+f 364 481 414
+f 364 414 260
+f 260 414 169
+f 260 169 157
+f 157 169 95
+f 157 95 21
+f 7763 7795 7690
+f 7690 7795 7747
+f 7690 7747 7549
+f 7549 7747 7563
+f 7549 7563 7413
+f 7413 7563 7431
+f 7413 7431 7313
+f 7313 7431 7338
+f 7313 7338 7229
+f 7229 7338 7194
+f 7229 7194 7090
+f 7090 7194 7043
+f 7090 7043 6889
+f 6889 7043 6947
+f 6889 6947 6771
+f 6771 6947 6767
+f 6771 6767 6719
+f 6719 6767 6691
+f 6719 6691 6480
+f 6480 6691 6522
+f 6480 6522 6380
+f 6380 6522 6363
+f 6380 6363 6224
+f 6224 6363 6244
+f 6224 6244 6135
+f 6135 6244 6171
+f 6135 6171 6027
+f 6027 6171 5974
+f 6027 5974 5816
+f 5816 5974 5923
+f 5816 5923 5679
+f 5679 5923 5715
+f 5679 5715 5554
+f 5554 5715 5615
+f 5554 5615 5495
+f 5495 5615 5429
+f 5495 5429 5388
+f 5388 5429 5325
+f 5388 5325 5173
+f 5173 5325 5213
+f 5173 5213 5060
+f 5060 5213 5099
+f 5060 5099 5009
+f 5009 5099 4951
+f 5009 4951 4785
+f 4785 4951 4821
+f 4785 4821 4705
+f 4705 4821 4701
+f 4705 4701 4545
+f 4545 4701 4561
+f 4545 4561 4431
+f 4431 4561 4429
+f 4431 4429 4314
+f 4314 4429 4251
+f 4314 4251 4136
+f 4136 4251 4113
+f 4136 4113 4019
+f 4019 4113 4021
+f 4019 4021 3855
+f 3855 4021 3889
+f 3855 3889 3711
+f 3711 3889 3769
+f 3711 3769 3671
+f 3671 3769 3647
+f 3671 3647 3559
+f 3559 3647 3473
+f 3559 3473 3421
+f 3421 3473 3309
+f 3421 3309 3207
+f 3207 3309 3199
+f 3207 3199 3106
+f 3106 3199 3099
+f 3106 3099 2975
+f 2975 3099 2989
+f 2975 2989 2831
+f 2831 2989 2859
+f 2831 2859 2673
+f 2673 2859 2702
+f 2673 2702 2572
+f 2572 2702 2546
+f 2572 2546 2452
+f 2452 2546 2430
+f 2452 2430 2287
+f 2287 2430 2221
+f 2287 2221 2128
+f 2128 2221 2169
+f 2128 2169 2041
+f 2041 2169 1980
+f 2041 1980 1916
+f 1916 1980 1889
+f 1916 1889 1732
+f 1732 1889 1731
+f 1732 1731 1685
+f 1685 1731 1603
+f 1685 1603 1520
+f 1520 1603 1539
+f 1520 1539 1337
+f 1337 1539 1423
+f 1337 1423 1207
+f 1207 1423 1285
+f 1207 1285 1113
+f 1113 1285 1090
+f 1113 1090 967
+f 967 1090 977
+f 967 977 910
+f 910 977 843
+f 910 843 696
+f 696 843 771
+f 696 771 574
+f 574 771 597
+f 574 597 454
+f 454 597 515
+f 454 515 311
+f 311 515 364
+f 311 364 191
+f 191 364 260
+f 191 260 113
+f 113 260 157
+f 113 157 21
+f 7777 7763 7704
+f 7704 7763 7690
+f 7704 7690 7531
+f 7531 7690 7549
+f 7531 7549 7417
+f 7417 7549 7413
+f 7417 7413 7326
+f 7326 7413 7313
+f 7326 7313 7161
+f 7161 7313 7229
+f 7161 7229 7109
+f 7109 7229 7090
+f 7109 7090 6899
+f 6899 7090 6889
+f 6899 6889 6754
+f 6754 6889 6771
+f 6754 6771 6658
+f 6658 6771 6719
+f 6658 6719 6561
+f 6561 6719 6480
+f 6561 6480 6423
+f 6423 6480 6380
+f 6423 6380 6306
+f 6306 6380 6224
+f 6306 6224 6194
+f 6194 6224 6135
+f 6194 6135 6053
+f 6053 6135 6027
+f 6053 6027 5927
+f 5927 6027 5816
+f 5927 5816 5761
+f 5761 5816 5679
+f 5761 5679 5641
+f 5641 5679 5554
+f 5641 5554 5496
+f 5496 5554 5495
+f 5496 5495 5407
+f 5407 5495 5388
+f 5407 5388 5179
+f 5179 5388 5173
+f 5179 5173 5093
+f 5093 5173 5060
+f 5093 5060 4891
+f 4891 5060 5009
+f 4891 5009 4885
+f 4885 5009 4785
+f 4885 4785 4687
+f 4687 4785 4705
+f 4687 4705 4519
+f 4519 4705 4545
+f 4519 4545 4447
+f 4447 4545 4431
+f 4447 4431 4255
+f 4255 4431 4314
+f 4255 4314 4193
+f 4193 4314 4136
+f 4193 4136 4071
+f 4071 4136 4019
+f 4071 4019 3937
+f 3937 4019 3855
+f 3937 3855 3817
+f 3817 3855 3711
+f 3817 3711 3667
+f 3667 3711 3671
+f 3667 3671 3447
+f 3447 3671 3559
+f 3447 3559 3339
+f 3339 3559 3421
+f 3339 3421 3269
+f 3269 3421 3207
+f 3269 3207 3125
+f 3125 3207 3106
+f 3125 3106 2967
+f 2967 3106 2975
+f 2967 2975 2832
+f 2832 2975 2831
+f 2832 2831 2674
+f 2674 2831 2673
+f 2674 2673 2553
+f 2553 2673 2572
+f 2553 2572 2457
+f 2457 2572 2452
+f 2457 2452 2301
+f 2301 2452 2287
+f 2301 2287 2112
+f 2112 2287 2128
+f 2112 2128 2014
+f 2014 2128 2041
+f 2014 2041 1845
+f 1845 2041 1916
+f 1845 1916 1819
+f 1819 1916 1732
+f 1819 1732 1648
+f 1648 1732 1685
+f 1648 1685 1567
+f 1567 1685 1520
+f 1567 1520 1351
+f 1351 1520 1337
+f 1351 1337 1236
+f 1236 1337 1207
+f 1236 1207 1091
+f 1091 1207 1113
+f 1091 1113 1045
+f 1045 1113 967
+f 1045 967 844
+f 844 967 910
+f 844 910 691
+f 691 910 696
+f 691 696 553
+f 553 696 574
+f 553 574 466
+f 466 574 454
+f 466 454 351
+f 351 454 311
+f 351 311 252
+f 252 311 191
+f 252 191 115
+f 115 191 113
+f 115 113 4
+f 7825 7777 7714
+f 7714 7777 7704
+f 7714 7704 7599
+f 7599 7704 7531
+f 7599 7531 7443
+f 7443 7531 7417
+f 7443 7417 7327
+f 7327 7417 7326
+f 7327 7326 7219
+f 7219 7326 7161
+f 7219 7161 7069
+f 7069 7161 7109
+f 7069 7109 6929
+f 6929 7109 6899
+f 6929 6899 6748
+f 6748 6899 6754
+f 6748 6754 6683
+f 6683 6754 6658
+f 6683 6658 6586
+f 6586 6658 6561
+f 6586 6561 6339
+f 6339 6561 6423
+f 6339 6423 6315
+f 6315 6423 6306
+f 6315 6306 6201
+f 6201 6306 6194
+f 6201 6194 5981
+f 5981 6194 6053
+f 5981 6053 5929
+f 5929 6053 5927
+f 5929 5927 5733
+f 5733 5927 5761
+f 5733 5761 5585
+f 5585 5761 5641
+f 5585 5641 5426
+f 5426 5641 5496
+f 5426 5496 5369
+f 5369 5496 5407
+f 5369 5407 5207
+f 5207 5407 5179
+f 5207 5179 5043
+f 5043 5179 5093
+f 5043 5093 5005
+f 5005 5093 4891
+f 5005 4891 4881
+f 4881 4891 4885
+f 4881 4885 4706
+f 4706 4885 4687
+f 4706 4687 4537
+f 4537 4687 4519
+f 4537 4519 4463
+f 4463 4519 4447
+f 4463 4447 4295
+f 4295 4447 4255
+f 4295 4255 4174
+f 4174 4255 4193
+f 4174 4193 4075
+f 4075 4193 4071
+f 4075 4071 3938
+f 3938 4071 3937
+f 3938 3937 3731
+f 3731 3937 3817
+f 3731 3817 3595
+f 3595 3817 3667
+f 3595 3667 3469
+f 3469 3667 3447
+f 3469 3447 3355
+f 3355 3447 3339
+f 3355 3339 3227
+f 3227 3339 3269
+f 3227 3269 3107
+f 3107 3269 3125
+f 3107 3125 2968
+f 2968 3125 2967
+f 2968 2967 2823
+f 2823 2967 2832
+f 2823 2832 2669
+f 2669 2832 2674
+f 2669 2674 2573
+f 2573 2674 2553
+f 2573 2553 2407
+f 2407 2553 2457
+f 2407 2457 2257
+f 2257 2457 2301
+f 2257 2301 2091
+f 2091 2301 2112
+f 2091 2112 2061
+f 2061 2112 2014
+f 2061 2014 1890
+f 1890 2014 1845
+f 1890 1845 1713
+f 1713 1845 1819
+f 1713 1819 1590
+f 1590 1819 1648
+f 1590 1648 1521
+f 1521 1648 1567
+f 1521 1567 1383
+f 1383 1567 1351
+f 1383 1351 1194
+f 1194 1351 1236
+f 1194 1236 1114
+f 1114 1236 1091
+f 1114 1091 999
+f 999 1091 1045
+f 999 1045 845
+f 845 1045 844
+f 845 844 781
+f 781 844 691
+f 781 691 632
+f 632 691 553
+f 632 553 482
+f 482 553 466
+f 482 466 365
+f 365 466 351
+f 365 351 269
+f 269 351 252
+f 269 252 78
+f 78 252 115
+f 78 115 4
+f 7813 7825 7659
+f 7659 7825 7714
+f 7659 7714 7532
+f 7532 7714 7599
+f 7532 7599 7466
+f 7466 7599 7443
+f 7466 7443 7365
+f 7365 7443 7327
+f 7365 7327 7170
+f 7170 7327 7219
+f 7170 7219 7063
+f 7063 7219 7069
+f 7063 7069 6948
+f 6948 7069 6929
+f 6948 6929 6806
+f 6806 6929 6748
+f 6806 6748 6692
+f 6692 6748 6683
+f 6692 6683 6513
+f 6513 6683 6586
+f 6513 6586 6424
+f 6424 6586 6339
+f 6424 6339 6288
+f 6288 6339 6315
+f 6288 6315 6158
+f 6158 6315 6201
+f 6158 6201 6061
+f 6061 6201 5981
+f 6061 5981 5911
+f 5911 5981 5929
+f 5911 5929 5681
+f 5681 5929 5733
+f 5681 5733 5629
+f 5629 5733 5585
+f 5629 5585 5478
+f 5478 5585 5426
+f 5478 5426 5291
+f 5291 5426 5369
+f 5291 5369 5155
+f 5155 5369 5207
+f 5155 5207 5141
+f 5141 5207 5043
+f 5141 5043 4977
+f 4977 5043 5005
+f 4977 5005 4847
+f 4847 5005 4881
+f 4847 4881 4669
+f 4669 4881 4706
+f 4669 4706 4505
+f 4505 4706 4537
+f 4505 4537 4435
+f 4435 4537 4463
+f 4435 4463 4303
+f 4303 4463 4295
+f 4303 4295 4218
+f 4218 4295 4174
+f 4218 4174 3975
+f 3975 4174 4075
+f 3975 4075 3939
+f 3939 4075 3938
+f 3939 3938 3707
+f 3707 3938 3731
+f 3707 3731 3631
+f 3631 3731 3595
+f 3631 3595 3450
+f 3450 3595 3469
+f 3450 3469 3350
+f 3350 3469 3355
+f 3350 3355 3235
+f 3235 3355 3227
+f 3235 3227 3126
+f 3126 3227 3107
+f 3126 3107 2976
+f 2976 3107 2968
+f 2976 2968 2847
+f 2847 2968 2823
+f 2847 2823 2703
+f 2703 2823 2669
+f 2703 2669 2599
+f 2599 2669 2573
+f 2599 2573 2408
+f 2408 2573 2407
+f 2408 2407 2258
+f 2258 2407 2257
+f 2258 2257 2201
+f 2201 2257 2091
+f 2201 2091 2069
+f 2069 2091 2061
+f 2069 2061 1917
+f 1917 2061 1890
+f 1917 1890 1717
+f 1717 1890 1713
+f 1717 1713 1575
+f 1575 1713 1590
+f 1575 1590 1522
+f 1522 1590 1521
+f 1522 1521 1325
+f 1325 1521 1383
+f 1325 1383 1264
+f 1264 1383 1194
+f 1264 1194 1136
+f 1136 1194 1114
+f 1136 1114 1051
+f 1051 1114 999
+f 1051 999 826
+f 826 999 845
+f 826 845 679
+f 679 845 781
+f 679 781 651
+f 651 781 632
+f 651 632 433
+f 433 632 482
+f 433 482 319
+f 319 482 365
+f 319 365 178
+f 178 365 269
+f 178 269 129
+f 129 269 78
+f 129 78 26
+f 7845 7813 7737
+f 7737 7813 7659
+f 7737 7659 7560
+f 7560 7659 7532
+f 7560 7532 7458
+f 7458 7532 7466
+f 7458 7466 7339
+f 7339 7466 7365
+f 7339 7365 7263
+f 7263 7365 7170
+f 7263 7170 7030
+f 7030 7170 7063
+f 7030 7063 6920
+f 6920 7063 6948
+f 6920 6948 6755
+f 6755 6948 6806
+f 6755 6806 6608
+f 6608 6806 6692
+f 6608 6692 6469
+f 6469 6692 6513
+f 6469 6513 6414
+f 6414 6513 6424
+f 6414 6424 6309
+f 6309 6424 6288
+f 6309 6288 6179
+f 6179 6288 6158
+f 6179 6158 6067
+f 6067 6158 6061
+f 6067 6061 5935
+f 5935 6061 5911
+f 5935 5911 5762
+f 5762 5911 5681
+f 5762 5681 5618
+f 5618 5681 5629
+f 5618 5629 5523
+f 5523 5629 5478
+f 5523 5478 5335
+f 5335 5478 5291
+f 5335 5291 5238
+f 5238 5291 5155
+f 5238 5155 5031
+f 5031 5155 5141
+f 5031 5141 4967
+f 4967 5141 4977
+f 4967 4977 4871
+f 4871 4977 4847
+f 4871 4847 4655
+f 4655 4847 4669
+f 4655 4669 4621
+f 4621 4669 4505
+f 4621 4505 4424
+f 4424 4505 4435
+f 4424 4435 4293
+f 4293 4435 4303
+f 4293 4303 4147
+f 4147 4303 4218
+f 4147 4218 3976
+f 3976 4218 3975
+f 3976 3975 3918
+f 3918 3975 3939
+f 3918 3939 3725
+f 3725 3939 3707
+f 3725 3707 3609
+f 3609 3707 3631
+f 3609 3631 3487
+f 3487 3631 3450
+f 3487 3450 3362
+f 3362 3450 3350
+f 3362 3350 3236
+f 3236 3350 3235
+f 3236 3235 3108
+f 3108 3235 3126
+f 3108 3126 2983
+f 2983 3126 2976
+f 2983 2976 2848
+f 2848 2976 2847
+f 2848 2847 2684
+f 2684 2847 2703
+f 2684 2703 2554
+f 2554 2703 2599
+f 2554 2599 2458
+f 2458 2599 2408
+f 2458 2408 2238
+f 2238 2408 2258
+f 2238 2258 2085
+f 2085 2258 2201
+f 2085 2201 2042
+f 2042 2201 2069
+f 2042 2069 1891
+f 1891 2069 1917
+f 1891 1917 1803
+f 1803 1917 1717
+f 1803 1717 1649
+f 1649 1717 1575
+f 1649 1575 1540
+f 1540 1575 1522
+f 1540 1522 1384
+f 1384 1522 1325
+f 1384 1325 1215
+f 1215 1325 1264
+f 1215 1264 1137
+f 1137 1264 1136
+f 1137 1136 939
+f 939 1136 1051
+f 939 1051 868
+f 868 1051 826
+f 868 826 717
+f 717 826 679
+f 717 679 652
+f 652 679 651
+f 652 651 529
+f 529 651 433
+f 529 433 415
+f 415 433 319
+f 415 319 231
+f 231 319 178
+f 231 178 79
+f 79 178 129
+f 79 129 26
+f 7803 7845 7695
+f 7695 7845 7737
+f 7695 7737 7546
+f 7546 7737 7560
+f 7546 7560 7485
+f 7485 7560 7458
+f 7485 7458 7306
+f 7306 7458 7339
+f 7306 7339 7243
+f 7243 7339 7263
+f 7243 7263 7009
+f 7009 7263 7030
+f 7009 7030 6855
+f 6855 7030 6920
+f 6855 6920 6727
+f 6727 6920 6755
+f 6727 6755 6641
+f 6641 6755 6608
+f 6641 6608 6569
+f 6569 6608 6469
+f 6569 6469 6425
+f 6425 6469 6414
+f 6425 6414 6209
+f 6209 6414 6309
+f 6209 6309 6146
+f 6146 6309 6179
+f 6146 6179 6019
+f 6019 6179 6067
+f 6019 6067 5853
+f 5853 6067 5935
+f 5853 5935 5781
+f 5781 5935 5762
+f 5781 5762 5677
+f 5677 5762 5618
+f 5677 5618 5479
+f 5479 5618 5523
+f 5479 5523 5359
+f 5359 5523 5335
+f 5359 5335 5249
+f 5249 5335 5238
+f 5249 5238 5044
+f 5044 5238 5031
+f 5044 5031 4953
+f 4953 5031 4967
+f 4953 4967 4837
+f 4837 4967 4871
+f 4837 4871 4723
+f 4723 4871 4655
+f 4723 4655 4615
+f 4615 4655 4621
+f 4615 4621 4365
+f 4365 4621 4424
+f 4365 4424 4296
+f 4296 4424 4293
+f 4296 4293 4117
+f 4117 4293 4147
+f 4117 4147 4022
+f 4022 4147 3976
+f 4022 3976 3933
+f 3933 3976 3918
+f 3933 3918 3708
+f 3708 3918 3725
+f 3708 3725 3623
+f 3623 3725 3609
+f 3623 3609 3534
+f 3534 3609 3487
+f 3534 3487 3343
+f 3343 3487 3362
+f 3343 3362 3221
+f 3221 3362 3236
+f 3221 3236 3109
+f 3109 3236 3108
+f 3109 3108 2962
+f 2962 3108 2983
+f 2962 2983 2839
+f 2839 2983 2848
+f 2839 2848 2685
+f 2685 2848 2684
+f 2685 2684 2600
+f 2600 2684 2554
+f 2600 2554 2409
+f 2409 2554 2458
+f 2409 2458 2288
+f 2288 2458 2238
+f 2288 2238 2129
+f 2129 2238 2085
+f 2129 2085 2075
+f 2075 2085 2042
+f 2075 2042 1931
+f 1931 2042 1891
+f 1931 1891 1804
+f 1804 1891 1803
+f 1804 1803 1591
+f 1591 1803 1649
+f 1591 1649 1557
+f 1557 1649 1540
+f 1557 1540 1385
+f 1385 1540 1384
+f 1385 1384 1237
+f 1237 1384 1215
+f 1237 1215 1115
+f 1115 1215 1137
+f 1115 1137 985
+f 985 1137 939
+f 985 939 827
+f 827 939 868
+f 827 868 735
+f 735 868 717
+f 735 717 669
+f 669 717 652
+f 669 652 530
+f 530 652 529
+f 530 529 320
+f 320 529 415
+f 320 415 207
+f 207 415 231
+f 207 231 69
+f 69 231 79
+f 69 79 33
+f 7859 7803 7669
+f 7669 7803 7695
+f 7669 7695 7579
+f 7579 7695 7546
+f 7579 7546 7427
+f 7427 7546 7485
+f 7427 7485 7353
+f 7353 7485 7306
+f 7353 7306 7186
+f 7186 7306 7243
+f 7186 7243 7054
+f 7054 7243 7009
+f 7054 7009 6890
+f 6890 7009 6855
+f 6890 6855 6807
+f 6807 6855 6727
+f 6807 6727 6684
+f 6684 6727 6641
+f 6684 6641 6587
+f 6587 6641 6569
+f 6587 6569 6351
+f 6351 6569 6425
+f 6351 6425 6276
+f 6276 6425 6209
+f 6276 6209 6180
+f 6180 6209 6146
+f 6180 6146 5993
+f 5993 6146 6019
+f 5993 6019 5890
+f 5890 6019 5853
+f 5890 5853 5690
+f 5690 5853 5781
+f 5690 5781 5608
+f 5608 5781 5677
+f 5608 5677 5486
+f 5486 5677 5479
+f 5486 5479 5411
+f 5411 5479 5359
+f 5411 5359 5214
+f 5214 5359 5249
+f 5214 5249 5097
+f 5097 5249 5044
+f 5097 5044 4985
+f 4985 5044 4953
+f 4985 4953 4883
+f 4883 4953 4837
+f 4883 4837 4731
+f 4731 4837 4723
+f 4731 4723 4529
+f 4529 4723 4615
+f 4529 4615 4410
+f 4410 4615 4365
+f 4410 4365 4350
+f 4350 4365 4296
+f 4350 4296 4175
+f 4175 4296 4117
+f 4175 4117 4031
+f 4031 4117 4022
+f 4031 4022 3912
+f 3912 4022 3933
+f 3912 3933 3773
+f 3773 3933 3708
+f 3773 3708 3675
+f 3675 3708 3623
+f 3675 3623 3521
+f 3521 3623 3534
+f 3521 3534 3363
+f 3363 3534 3343
+f 3363 3343 3229
+f 3229 3343 3221
+f 3229 3221 3101
+f 3101 3221 3109
+f 3101 3109 2973
+f 2973 3109 2962
+f 2973 2962 2833
+f 2833 2962 2839
+f 2833 2839 2692
+f 2692 2839 2685
+f 2692 2685 2595
+f 2595 2685 2600
+f 2595 2600 2389
+f 2389 2600 2409
+f 2389 2409 2259
+f 2259 2409 2288
+f 2259 2288 2158
+f 2158 2288 2129
+f 2158 2129 2076
+f 2076 2129 2075
+f 2076 2075 1892
+f 1892 2075 1931
+f 1892 1931 1733
+f 1733 1931 1804
+f 1733 1804 1626
+f 1626 1804 1591
+f 1626 1591 1493
+f 1493 1591 1557
+f 1493 1557 1386
+f 1386 1557 1385
+f 1386 1385 1216
+f 1216 1385 1237
+f 1216 1237 1159
+f 1159 1237 1115
+f 1159 1115 968
+f 968 1115 985
+f 968 985 895
+f 895 985 827
+f 895 827 736
+f 736 827 735
+f 736 735 583
+f 583 735 669
+f 583 669 434
+f 434 669 530
+f 434 530 321
+f 321 530 320
+f 321 320 208
+f 208 320 207
+f 208 207 130
+f 130 207 69
+f 130 69 9
+f 7669 7756 7859
+f 7859 7756 7760
+f 7859 7760 7876
+f 7579 7636 7669
+f 7669 7636 7639
+f 7669 7639 7756
+f 7357 7353 7193
+f 7193 7353 7186
+f 7193 7186 7067
+f 7067 7186 7054
+f 7067 7054 6921
+f 6921 7054 6890
+f 6921 6890 6763
+f 6763 6890 6807
+f 6763 6807 6628
+f 6628 6807 6684
+f 6628 6684 6553
+f 6553 6684 6587
+f 6553 6587 6395
+f 6395 6587 6351
+f 6395 6351 6310
+f 6310 6351 6276
+f 6310 6276 6141
+f 6141 6276 6180
+f 6141 6180 5987
+f 5987 6180 5993
+f 5987 5993 5825
+f 5825 5993 5890
+f 5825 5890 5782
+f 5782 5890 5690
+f 5782 5690 5597
+f 5597 5690 5608
+f 5597 5608 5537
+f 5537 5608 5486
+f 5537 5486 5317
+f 5317 5486 5411
+f 5317 5411 5255
+f 5255 5411 5214
+f 5255 5214 5102
+f 5102 5214 5097
+f 5102 5097 4913
+f 4913 5097 4985
+f 4913 4985 4806
+f 4806 4985 4883
+f 4806 4883 4627
+f 4627 4883 4731
+f 4627 4731 4587
+f 4587 4731 4529
+f 4587 4529 4436
+f 4436 4529 4410
+f 4436 4410 4337
+f 4337 4410 4350
+f 4337 4350 4155
+f 4155 4350 4175
+f 4155 4175 3999
+f 3999 4175 4031
+f 3999 4031 3873
+f 3873 4031 3912
+f 3873 3912 3717
+f 3717 3912 3773
+f 3717 3773 3641
+f 3641 3773 3675
+f 3641 3675 3551
+f 3551 3675 3521
+f 3551 3521 3340
+f 3340 3521 3363
+f 3340 3363 3241
+f 3241 3363 3229
+f 3241 3229 3102
+f 3102 3229 3101
+f 3102 3101 2984
+f 2984 3101 2973
+f 2984 2973 2834
+f 2834 2973 2833
+f 2834 2833 2675
+f 2675 2833 2692
+f 2675 2692 2547
+f 2547 2692 2595
+f 2547 2595 2443
+f 2443 2595 2389
+f 2443 2389 2260
+f 2260 2389 2259
+f 2260 2259 2130
+f 2130 2259 2158
+f 2130 2158 2062
+f 2062 2158 2076
+f 2062 2076 1846
+f 1846 2076 1892
+f 1846 1892 1708
+f 1708 1892 1733
+f 1708 1733 1604
+f 1604 1733 1626
+f 1604 1626 1558
+f 1558 1626 1493
+f 1558 1493 1404
+f 1404 1493 1386
+f 1404 1386 1208
+f 1208 1386 1216
+f 1208 1216 1138
+f 1138 1216 1159
+f 1138 1159 1000
+f 1000 1159 968
+f 1000 968 846
+f 846 968 895
+f 846 895 782
+f 782 895 736
+f 782 736 563
+f 563 736 583
+f 563 583 441
+f 441 583 434
+f 441 434 400
+f 400 434 321
+f 400 321 232
+f 232 321 208
+f 232 208 80
+f 80 208 130
+f 80 130 9
+f 7193 7268 7357
+f 7357 7268 7271
+f 7357 7271 7391
+f 7123 7067 6900
+f 6900 7067 6921
+f 6900 6921 6791
+f 6791 6921 6763
+f 6791 6763 6721
+f 6721 6763 6628
+f 6721 6628 6470
+f 6470 6628 6553
+f 6470 6553 6381
+f 6381 6553 6395
+f 6381 6395 6329
+f 6329 6395 6310
+f 6329 6310 6147
+f 6147 6310 6141
+f 6147 6141 5994
+f 5994 6141 5987
+f 5994 5987 5937
+f 5937 5987 5825
+f 5937 5825 5756
+f 5756 5825 5782
+f 5756 5782 5605
+f 5605 5782 5597
+f 5605 5597 5449
+f 5449 5597 5537
+f 5449 5537 5381
+f 5381 5537 5317
+f 5381 5317 5208
+f 5208 5317 5255
+f 5208 5255 5136
+f 5136 5255 5102
+f 5136 5102 4965
+f 4965 5102 4913
+f 4965 4913 4853
+f 4853 4913 4806
+f 4853 4806 4647
+f 4647 4806 4627
+f 4647 4627 4495
+f 4495 4627 4587
+f 4495 4587 4479
+f 4479 4587 4436
+f 4479 4436 4237
+f 4237 4436 4337
+f 4237 4337 4148
+f 4148 4337 4155
+f 4148 4155 3992
+f 3992 4155 3999
+f 3992 3999 3851
+f 3851 3999 3873
+f 3851 3873 3807
+f 3807 3873 3717
+f 3807 3717 3583
+f 3583 3717 3641
+f 3583 3641 3528
+f 3528 3641 3551
+f 3528 3551 3317
+f 3317 3551 3340
+f 3317 3340 3237
+f 3237 3340 3241
+f 3237 3241 3117
+f 3117 3241 3102
+f 3117 3102 2965
+f 2965 3102 2984
+f 2965 2984 2860
+f 2860 2984 2834
+f 2860 2834 2704
+f 2704 2834 2675
+f 2704 2675 2562
+f 2562 2675 2547
+f 2562 2547 2431
+f 2431 2547 2443
+f 2431 2443 2289
+f 2289 2443 2260
+f 2289 2260 2209
+f 2209 2260 2130
+f 2209 2130 2070
+f 2070 2130 2062
+f 2070 2062 1918
+f 1918 2062 1846
+f 1918 1846 1754
+f 1754 1846 1708
+f 1754 1708 1650
+f 1650 1708 1604
+f 1650 1604 1565
+f 1565 1604 1558
+f 1565 1558 1405
+f 1405 1558 1404
+f 1405 1404 1265
+f 1265 1404 1208
+f 1265 1208 1139
+f 1139 1208 1138
+f 1139 1138 969
+f 969 1138 1000
+f 969 1000 896
+f 896 1000 846
+f 896 846 737
+f 737 846 782
+f 737 782 633
+f 633 782 563
+f 633 563 504
+f 504 563 441
+f 504 441 341
+f 341 441 400
+f 341 400 214
+f 214 400 232
+f 214 232 151
+f 151 232 80
+f 151 80 12
+f 7029 7123 6895
+f 6895 7123 6900
+f 6895 6900 6772
+f 6772 6900 6791
+f 6772 6791 6599
+f 6599 6791 6721
+f 6599 6721 6549
+f 6549 6721 6470
+f 6549 6470 6426
+f 6426 6470 6381
+f 6426 6381 6238
+f 6238 6381 6329
+f 6238 6329 6102
+f 6102 6329 6147
+f 6102 6147 6001
+f 6001 6147 5994
+f 6001 5994 5871
+f 5871 5994 5937
+f 5871 5937 5727
+f 5727 5937 5756
+f 5727 5756 5675
+f 5675 5756 5605
+f 5675 5605 5454
+f 5454 5605 5449
+f 5454 5449 5399
+f 5399 5449 5381
+f 5399 5381 5209
+f 5209 5381 5208
+f 5209 5208 5147
+f 5147 5208 5136
+f 5147 5136 4954
+f 4954 5136 4965
+f 4954 4965 4786
+f 4786 4965 4853
+f 4786 4853 4719
+f 4719 4853 4647
+f 4719 4647 4497
+f 4497 4647 4495
+f 4497 4495 4403
+f 4403 4495 4479
+f 4403 4479 4279
+f 4279 4479 4237
+f 4279 4237 4165
+f 4165 4237 4148
+f 4165 4148 4057
+f 4057 4148 3992
+f 4057 3992 3843
+f 3843 3992 3851
+f 3843 3851 3712
+f 3712 3851 3807
+f 3712 3807 3629
+f 3629 3807 3583
+f 3629 3583 3458
+f 3458 3583 3528
+f 3458 3528 3344
+f 3344 3528 3317
+f 3344 3317 3274
+f 3274 3317 3237
+f 3274 3237 3118
+f 3118 3237 3117
+f 3118 3117 2969
+f 2969 3117 2965
+f 2969 2965 2849
+f 2849 2965 2860
+f 2849 2860 2705
+f 2705 2860 2704
+f 2705 2704 2555
+f 2555 2704 2562
+f 2555 2562 2444
+f 2444 2562 2431
+f 2444 2431 2247
+f 2247 2431 2289
+f 2247 2289 2159
+f 2159 2289 2209
+f 2159 2209 1997
+f 1997 2209 2070
+f 1997 2070 1919
+f 1919 2070 1918
+f 1919 1918 1718
+f 1718 1918 1754
+f 1718 1754 1673
+f 1673 1754 1650
+f 1673 1650 1494
+f 1494 1650 1565
+f 1494 1565 1429
+f 1429 1565 1405
+f 1429 1405 1286
+f 1286 1405 1265
+f 1286 1265 1116
+f 1116 1265 1139
+f 1116 1139 986
+f 986 1139 969
+f 986 969 911
+f 911 969 896
+f 911 896 791
+f 791 896 737
+f 791 737 662
+f 662 737 633
+f 662 633 442
+f 442 633 504
+f 442 504 401
+f 401 504 341
+f 401 341 270
+f 270 341 214
+f 270 214 43
+f 43 214 151
+f 43 151 12
+f 6953 6895 6832
+f 6832 6895 6772
+f 6832 6772 6659
+f 6659 6772 6599
+f 6659 6599 6583
+f 6583 6599 6549
+f 6583 6549 6355
+f 6355 6549 6426
+f 6355 6426 6327
+f 6327 6426 6238
+f 6327 6238 6097
+f 6097 6238 6102
+f 6097 6102 5977
+f 5977 6102 6001
+f 5977 6001 5861
+f 5861 6001 5871
+f 5861 5871 5797
+f 5797 5871 5727
+f 5797 5727 5603
+f 5603 5727 5675
+f 5603 5675 5455
+f 5455 5675 5454
+f 5455 5454 5310
+f 5310 5454 5399
+f 5310 5399 5239
+f 5239 5399 5209
+f 5239 5209 5103
+f 5103 5209 5147
+f 5103 5147 4927
+f 4927 5147 4954
+f 4927 4954 4841
+f 4841 4954 4786
+f 4841 4786 4675
+f 4675 4786 4719
+f 4675 4719 4588
+f 4588 4719 4497
+f 4588 4497 4415
+f 4415 4497 4403
+f 4415 4403 4261
+f 4261 4403 4279
+f 4261 4279 4163
+f 4163 4279 4165
+f 4163 4165 4051
+f 4051 4165 4057
+f 4051 4057 3852
+f 3852 4057 3843
+f 3852 3843 3735
+f 3735 3843 3712
+f 3735 3712 3659
+f 3659 3712 3629
+f 3659 3629 3501
+f 3501 3629 3458
+f 3501 3458 3407
+f 3407 3458 3344
+f 3407 3344 3249
+f 3249 3344 3274
+f 3249 3274 3163
+f 3163 3274 3118
+f 3163 3118 2951
+f 2951 3118 2969
+f 2951 2969 2867
+f 2867 2969 2849
+f 2867 2849 2676
+f 2676 2849 2705
+f 2676 2705 2541
+f 2541 2705 2555
+f 2541 2555 2465
+f 2465 2555 2444
+f 2465 2444 2306
+f 2306 2444 2247
+f 2306 2247 2170
+f 2170 2247 2159
+f 2170 2159 2071
+f 2071 2159 1997
+f 2071 1997 1953
+f 1953 1997 1919
+f 1953 1919 1813
+f 1813 1919 1718
+f 1813 1718 1651
+f 1651 1718 1673
+f 1651 1673 1451
+f 1451 1673 1494
+f 1451 1494 1430
+f 1430 1494 1429
+f 1430 1429 1238
+f 1238 1429 1286
+f 1238 1286 1117
+f 1117 1286 1116
+f 1117 1116 1001
+f 1001 1116 986
+f 1001 986 880
+f 880 986 911
+f 880 911 697
+f 697 911 791
+f 697 791 598
+f 598 791 662
+f 598 662 531
+f 531 662 442
+f 531 442 409
+f 409 442 401
+f 409 401 174
+f 174 401 270
+f 174 270 47
+f 47 270 43
+f 47 43 13
+f 6919 6953 6842
+f 6842 6953 6832
+f 6842 6832 6660
+f 6660 6832 6659
+f 6660 6659 6539
+f 6539 6659 6583
+f 6539 6583 6389
+f 6389 6583 6355
+f 6389 6355 6255
+f 6255 6355 6327
+f 6255 6327 6191
+f 6191 6327 6097
+f 6191 6097 6020
+f 6020 6097 5977
+f 6020 5977 5833
+f 5833 5977 5861
+f 5833 5861 5745
+f 5745 5861 5797
+f 5745 5797 5551
+f 5551 5797 5603
+f 5551 5603 5491
+f 5491 5603 5455
+f 5491 5455 5318
+f 5318 5455 5310
+f 5318 5310 5203
+f 5203 5310 5239
+f 5203 5239 5085
+f 5085 5239 5103
+f 5085 5103 4955
+f 4955 5103 4927
+f 4955 4927 4801
+f 4801 4927 4841
+f 4801 4841 4697
+f 4697 4841 4675
+f 4697 4675 4552
+f 4552 4675 4588
+f 4552 4588 4461
+f 4461 4588 4415
+f 4461 4415 4247
+f 4247 4415 4261
+f 4247 4261 4185
+f 4185 4261 4163
+f 4185 4163 3971
+f 3971 4163 4051
+f 3971 4051 3890
+f 3890 4051 3852
+f 3890 3852 3781
+f 3781 3852 3735
+f 3781 3735 3621
+f 3621 3735 3659
+f 3621 3659 3515
+f 3515 3659 3501
+f 3515 3501 3411
+f 3411 3501 3407
+f 3411 3407 3266
+f 3266 3407 3249
+f 3266 3249 3050
+f 3050 3249 3163
+f 3050 3163 2985
+f 2985 3163 2951
+f 2985 2951 2840
+f 2840 2951 2867
+f 2840 2867 2693
+f 2693 2867 2676
+f 2693 2676 2563
+f 2563 2676 2541
+f 2563 2541 2445
+f 2445 2541 2465
+f 2445 2465 2227
+f 2227 2465 2306
+f 2227 2306 2099
+f 2099 2306 2170
+f 2099 2170 2030
+f 2030 2170 2071
+f 2030 2071 1893
+f 1893 2071 1953
+f 1893 1953 1734
+f 1734 1953 1813
+f 1734 1813 1665
+f 1665 1813 1651
+f 1665 1651 1460
+f 1460 1651 1451
+f 1460 1451 1406
+f 1406 1451 1430
+f 1406 1430 1295
+f 1295 1430 1238
+f 1295 1238 1118
+f 1118 1238 1117
+f 1118 1117 1046
+f 1046 1117 1001
+f 1046 1001 828
+f 828 1001 880
+f 828 880 718
+f 718 880 697
+f 718 697 634
+f 634 697 598
+f 634 598 496
+f 496 598 531
+f 496 531 402
+f 402 531 409
+f 402 409 273
+f 273 409 174
+f 273 174 102
+f 102 174 47
+f 102 47 13
+f 7004 6897 7008
+f 7008 6897 7131
+f 7008 7131 7137
+f 6897 6919 6779
+f 6779 6919 6842
+f 6779 6842 6631
+f 6631 6842 6660
+f 6631 6660 6559
+f 6559 6660 6539
+f 6559 6539 6369
+f 6369 6539 6389
+f 6369 6389 6251
+f 6251 6389 6255
+f 6251 6255 6098
+f 6098 6255 6191
+f 6098 6191 5989
+f 5989 6191 6020
+f 5989 6020 5837
+f 5837 6020 5833
+f 5837 5833 5765
+f 5765 5833 5745
+f 5765 5745 5653
+f 5653 5745 5551
+f 5653 5551 5439
+f 5439 5551 5491
+f 5439 5491 5375
+f 5375 5491 5318
+f 5375 5318 5156
+f 5156 5318 5203
+f 5156 5203 5119
+f 5119 5203 5085
+f 5119 5085 4946
+f 4946 5085 4955
+f 4946 4955 4854
+f 4854 4955 4801
+f 4854 4801 4724
+f 4724 4801 4697
+f 4724 4697 4522
+f 4522 4697 4552
+f 4522 4552 4419
+f 4419 4552 4461
+f 4419 4461 4343
+f 4343 4461 4247
+f 4343 4247 4129
+f 4129 4247 4185
+f 4129 4185 3984
+f 3984 4185 3971
+f 3984 3971 3951
+f 3951 3971 3890
+f 3951 3890 3770
+f 3770 3890 3781
+f 3770 3781 3573
+f 3573 3781 3621
+f 3573 3621 3498
+f 3498 3621 3515
+f 3498 3515 3370
+f 3370 3515 3411
+f 3370 3411 3217
+f 3217 3411 3266
+f 3217 3266 3074
+f 3074 3266 3050
+f 3074 3050 2993
+f 2993 3050 2985
+f 2993 2985 2856
+f 2856 2985 2840
+f 2856 2840 2719
+f 2719 2840 2693
+f 2719 2693 2596
+f 2596 2693 2563
+f 2596 2563 2437
+f 2437 2563 2445
+f 2437 2445 2261
+f 2261 2445 2227
+f 2261 2227 2146
+f 2146 2227 2099
+f 2146 2099 2015
+f 2015 2099 2030
+f 2015 2030 1858
+f 1858 2030 1893
+f 1858 1893 1790
+f 1790 1893 1734
+f 1790 1734 1674
+f 1674 1734 1665
+f 1674 1665 1495
+f 1495 1665 1460
+f 1495 1460 1407
+f 1407 1460 1406
+f 1407 1406 1266
+f 1266 1406 1295
+f 1266 1295 1168
+f 1168 1295 1118
+f 1168 1118 978
+f 978 1118 1046
+f 978 1046 869
+f 869 1046 828
+f 869 828 772
+f 772 828 718
+f 772 718 564
+f 564 718 634
+f 564 634 516
+f 516 634 496
+f 516 496 381
+f 381 496 402
+f 381 402 215
+f 215 402 273
+f 215 273 82
+f 82 273 102
+f 82 102 28
+f 7089 7131 6945
+f 6945 7131 6897
+f 6945 6897 6753
+f 6753 6897 6779
+f 6753 6779 6636
+f 6636 6779 6631
+f 6636 6631 6475
+f 6475 6631 6559
+f 6475 6559 6335
+f 6335 6559 6369
+f 6335 6369 6275
+f 6275 6369 6251
+f 6275 6251 6193
+f 6193 6251 6098
+f 6193 6098 5945
+f 5945 6098 5989
+f 5945 5989 5889
+f 5889 5989 5837
+f 5889 5837 5741
+f 5741 5837 5765
+f 5741 5765 5617
+f 5617 5765 5653
+f 5617 5653 5505
+f 5505 5653 5439
+f 5505 5439 5397
+f 5397 5439 5375
+f 5397 5375 5257
+f 5257 5375 5156
+f 5257 5156 5101
+f 5101 5156 5119
+f 5101 5119 4920
+f 4920 5119 4946
+f 4920 4946 4817
+f 4817 4946 4854
+f 4817 4854 4683
+f 4683 4854 4724
+f 4683 4724 4551
+f 4551 4724 4522
+f 4551 4522 4481
+f 4481 4522 4419
+f 4481 4419 4313
+f 4313 4419 4343
+f 4313 4343 4191
+f 4191 4343 4129
+f 4191 4129 4043
+f 4043 4129 3984
+f 4043 3984 3903
+f 3903 3984 3951
+f 3903 3951 3755
+f 3755 3951 3770
+f 3755 3770 3633
+f 3633 3770 3573
+f 3633 3573 3457
+f 3457 3573 3498
+f 3457 3498 3361
+f 3361 3498 3370
+f 3361 3370 3255
+f 3255 3370 3217
+f 3255 3217 3137
+f 3137 3217 3074
+f 3137 3074 3015
+f 3015 3074 2993
+f 3015 2993 2864
+f 2864 2993 2856
+f 2864 2856 2683
+f 2683 2856 2719
+f 2683 2719 2559
+f 2559 2719 2596
+f 2559 2596 2397
+f 2397 2596 2437
+f 2397 2437 2305
+f 2305 2437 2261
+f 2305 2261 2109
+f 2109 2261 2146
+f 2109 2146 2039
+f 2039 2146 2015
+f 2039 2015 1955
+f 1955 2015 1858
+f 1955 1858 1789
+f 1789 1858 1790
+f 1789 1790 1683
+f 1683 1790 1674
+f 1683 1674 1517
+f 1517 1674 1495
+f 1517 1495 1381
+f 1381 1495 1407
+f 1381 1407 1309
+f 1309 1407 1266
+f 1309 1266 1171
+f 1171 1266 1168
+f 1171 1168 991
+f 991 1168 978
+f 991 978 817
+f 817 978 869
+f 817 869 762
+f 762 869 772
+f 762 772 572
+f 572 772 564
+f 572 564 465
+f 465 564 516
+f 465 516 399
+f 399 516 381
+f 399 381 197
+f 197 381 215
+f 197 215 103
+f 103 215 82
+f 103 82 28
+f 7269 7251 7273
+f 7273 7251 7385
+f 7273 7385 7393
+f 7757 7679 7762
+f 7762 7679 7807
+f 7762 7807 7877
+f 7679 7641 7575
+f 7575 7641 7638
+f 7575 7638 7521
+f 7870 7807 7753
+f 7753 7807 7679
+f 7753 7679 7564
+f 7564 7679 7575
+f 7564 7575 7449
+f 7449 7575 7515
+f 7449 7515 7299
+f 7299 7515 7311
+f 7299 7311 7197
+f 7197 7311 7155
+f 7197 7155 7055
+f 7055 7155 7041
+f 7055 7041 6891
+f 6891 7041 6879
+f 6891 6879 6780
+f 6780 6879 6841
+f 6780 6841 6701
+f 6701 6841 6715
+f 6701 6715 6487
+f 6487 6715 6493
+f 6487 6493 6393
+f 6393 6493 6359
+f 6393 6359 6271
+f 6271 6359 6303
+f 6271 6303 6121
+f 6121 6303 6178
+f 6121 6178 6031
+f 6031 6178 6040
+f 6031 6040 5885
+f 5885 6040 5921
+f 5885 5921 5735
+f 5735 5921 5705
+f 5735 5705 5639
+f 5639 5705 5649
+f 5639 5649 5459
+f 5459 5649 5489
+f 5459 5489 5391
+f 5391 5489 5289
+f 5391 5289 5253
+f 5253 5289 5219
+f 5253 5219 5081
+f 5081 5219 5053
+f 5081 5053 4969
+f 4969 5053 4907
+f 4969 4907 4822
+f 4822 4907 4797
+f 4822 4797 4663
+f 4663 4797 4727
+f 4663 4727 4549
+f 4549 4727 4565
+f 4549 4565 4477
+f 4477 4565 4385
+f 4477 4385 4353
+f 4353 4385 4289
+f 4353 4289 4125
+f 4125 4289 4192
+f 4125 4192 3985
+f 3985 4192 4083
+f 3985 4083 3906
+f 3906 4083 3917
+f 3906 3917 3777
+f 3777 3917 3805
+f 3777 3805 3673
+f 3673 3805 3599
+f 3673 3599 3553
+f 3553 3599 3477
+f 3553 3477 3337
+f 3337 3477 3417
+f 3337 3417 3247
+f 3247 3417 3277
+f 3247 3277 3071
+f 3071 3277 3063
+f 3071 3063 2938
+f 2938 3063 2949
+f 2938 2949 2845
+f 2845 2949 2813
+f 2845 2813 2647
+f 2647 2813 2641
+f 2647 2641 2583
+f 2583 2641 2567
+f 2583 2567 2399
+f 2399 2567 2406
+f 2399 2406 2248
+f 2248 2406 2299
+f 2248 2299 2138
+f 2138 2299 2195
+f 2138 2195 2016
+f 2016 2195 1957
+f 2016 1957 1875
+f 1875 1957 1873
+f 1875 1873 1774
+f 1774 1873 1799
+f 1774 1799 1605
+f 1605 1799 1579
+f 1605 1579 1487
+f 1487 1579 1463
+f 1487 1463 1433
+f 1433 1463 1441
+f 1433 1441 1203
+f 1203 1441 1305
+f 1203 1305 1160
+f 1160 1305 1172
+f 1160 1172 1011
+f 1011 1172 1037
+f 1011 1037 847
+f 847 1037 909
+f 847 909 681
+f 681 909 769
+f 681 769 558
+f 558 769 573
+f 558 573 462
+f 462 573 440
+f 462 440 366
+f 366 440 363
+f 366 363 274
+f 274 363 242
+f 274 242 128
+f 128 242 155
+f 128 155 32
+f 7765 7870 7672
+f 7672 7870 7753
+f 7672 7753 7601
+f 7601 7753 7564
+f 7601 7564 7409
+f 7409 7564 7449
+f 7409 7449 7343
+f 7343 7449 7299
+f 7343 7299 7201
+f 7201 7299 7197
+f 7201 7197 7065
+f 7065 7197 7055
+f 7065 7055 6943
+f 6943 7055 6891
+f 6943 6891 6839
+f 6839 6891 6780
+f 6839 6780 6615
+f 6615 6780 6701
+f 6615 6701 6541
+f 6541 6701 6487
+f 6541 6487 6437
+f 6437 6487 6393
+f 6437 6393 6269
+f 6269 6393 6271
+f 6269 6271 6113
+f 6113 6271 6121
+f 6113 6121 6013
+f 6013 6121 6031
+f 6013 6031 5880
+f 5880 6031 5885
+f 5880 5885 5773
+f 5773 5885 5735
+f 5773 5735 5644
+f 5644 5735 5639
+f 5644 5639 5539
+f 5539 5639 5459
+f 5539 5459 5292
+f 5292 5459 5391
+f 5292 5391 5220
+f 5220 5391 5253
+f 5220 5253 5071
+f 5071 5253 5081
+f 5071 5081 5002
+f 5002 5081 4969
+f 5002 4969 4825
+f 4825 4969 4822
+f 4825 4822 4717
+f 4717 4822 4663
+f 4717 4663 4585
+f 4585 4663 4549
+f 4585 4549 4397
+f 4397 4549 4477
+f 4397 4477 4263
+f 4263 4477 4353
+f 4263 4353 4168
+f 4168 4353 4125
+f 4168 4125 3979
+f 3979 4125 3985
+f 3979 3985 3901
+f 3901 3985 3906
+f 3901 3906 3821
+f 3821 3906 3777
+f 3821 3777 3615
+f 3615 3777 3673
+f 3615 3673 3481
+f 3481 3673 3553
+f 3481 3553 3412
+f 3412 3553 3337
+f 3412 3337 3171
+f 3171 3337 3247
+f 3171 3247 3053
+f 3053 3247 3071
+f 3053 3071 3001
+f 3001 3071 2938
+f 3001 2938 2809
+f 2809 2938 2845
+f 2809 2845 2643
+f 2643 2845 2647
+f 2643 2647 2589
+f 2589 2647 2583
+f 2589 2583 2419
+f 2419 2583 2399
+f 2419 2399 2284
+f 2284 2399 2248
+f 2284 2248 2177
+f 2177 2248 2138
+f 2177 2138 2083
+f 2083 2138 2016
+f 2083 2016 1932
+f 1932 2016 1875
+f 1932 1875 1714
+f 1714 1875 1774
+f 1714 1774 1652
+f 1652 1774 1605
+f 1652 1605 1447
+f 1447 1605 1487
+f 1447 1487 1352
+f 1352 1487 1433
+f 1352 1433 1277
+f 1277 1433 1203
+f 1277 1203 1119
+f 1119 1203 1160
+f 1119 1160 979
+f 979 1160 1011
+f 979 1011 857
+f 857 1011 847
+f 857 847 738
+f 738 847 681
+f 738 681 607
+f 607 681 558
+f 607 558 505
+f 505 558 462
+f 505 462 305
+f 305 462 366
+f 305 366 198
+f 198 366 274
+f 198 274 64
+f 64 274 128
+f 64 128 19
+f 7817 7765 7675
+f 7675 7765 7672
+f 7675 7672 7542
+f 7542 7672 7601
+f 7542 7601 7479
+f 7479 7601 7409
+f 7479 7409 7381
+f 7381 7409 7343
+f 7381 7343 7209
+f 7209 7343 7201
+f 7209 7201 7035
+f 7035 7201 7065
+f 7035 7065 6941
+f 6941 7065 6943
+f 6941 6943 6836
+f 6836 6943 6839
+f 6836 6839 6645
+f 6645 6839 6615
+f 6645 6615 6488
+f 6488 6615 6541
+f 6488 6541 6401
+f 6401 6541 6437
+f 6401 6437 6215
+f 6215 6437 6269
+f 6215 6269 6091
+f 6091 6269 6113
+f 6091 6113 6045
+f 6045 6113 6013
+f 6045 6013 5901
+f 5901 6013 5880
+f 5901 5880 5698
+f 5698 5880 5773
+f 5698 5773 5571
+f 5571 5773 5644
+f 5571 5644 5471
+f 5471 5644 5539
+f 5471 5539 5365
+f 5365 5539 5292
+f 5365 5292 5175
+f 5175 5292 5220
+f 5175 5220 5107
+f 5107 5220 5071
+f 5107 5071 4961
+f 4961 5071 5002
+f 4961 5002 4874
+f 4874 5002 4825
+f 4874 4825 4747
+f 4747 4825 4717
+f 4747 4717 4507
+f 4507 4717 4585
+f 4507 4585 4416
+f 4416 4585 4397
+f 4416 4397 4307
+f 4307 4397 4263
+f 4307 4263 4159
+f 4159 4263 4168
+f 4159 4168 4017
+f 4017 4168 3979
+f 4017 3979 3948
+f 3948 3979 3901
+f 3948 3901 3796
+f 3796 3901 3821
+f 3796 3821 3644
+f 3644 3821 3615
+f 3644 3615 3547
+f 3547 3615 3481
+f 3547 3481 3305
+f 3305 3481 3412
+f 3305 3412 3193
+f 3193 3412 3171
+f 3193 3171 3061
+f 3061 3171 3053
+f 3061 3053 2997
+f 2997 3053 3001
+f 2997 3001 2871
+f 2871 3001 2809
+f 2871 2809 2655
+f 2655 2809 2643
+f 2655 2643 2605
+f 2605 2643 2589
+f 2605 2589 2427
+f 2427 2589 2419
+f 2427 2419 2243
+f 2243 2419 2284
+f 2243 2284 2151
+f 2151 2284 2177
+f 2151 2177 2036
+f 2036 2177 2083
+f 2036 2083 1945
+f 1945 2083 1932
+f 1945 1932 1805
+f 1805 1932 1714
+f 1805 1714 1606
+f 1606 1714 1652
+f 1606 1652 1509
+f 1509 1652 1447
+f 1509 1447 1387
+f 1387 1447 1352
+f 1387 1352 1259
+f 1259 1352 1277
+f 1259 1277 1105
+f 1105 1277 1119
+f 1105 1119 1002
+f 1002 1119 979
+f 1002 979 919
+f 919 979 857
+f 919 857 783
+f 783 857 738
+f 783 738 551
+f 551 738 607
+f 551 607 474
+f 474 607 505
+f 474 505 419
+f 419 505 305
+f 419 305 253
+f 253 305 198
+f 253 198 44
+f 44 198 64
+f 44 64 19
+f 7867 7817 7682
+f 7682 7817 7675
+f 7682 7675 7631
+f 7631 7675 7542
+f 7631 7542 7432
+f 7432 7542 7479
+f 7432 7479 7275
+f 7275 7479 7381
+f 7275 7381 7213
+f 7213 7381 7209
+f 7213 7209 7047
+f 7047 7209 7035
+f 7047 7035 6914
+f 6914 7035 6941
+f 6914 6941 6797
+f 6797 6941 6836
+f 6797 6836 6703
+f 6703 6836 6645
+f 6703 6645 6550
+f 6550 6645 6488
+f 6550 6488 6396
+f 6396 6488 6401
+f 6396 6401 6281
+f 6281 6401 6215
+f 6281 6215 6095
+f 6095 6215 6091
+f 6095 6091 6037
+f 6037 6091 6045
+f 6037 6045 5877
+f 5877 6045 5901
+f 5877 5901 5695
+f 5695 5901 5698
+f 5695 5698 5611
+f 5611 5698 5571
+f 5611 5571 5544
+f 5544 5571 5471
+f 5544 5471 5341
+f 5341 5471 5365
+f 5341 5365 5273
+f 5273 5365 5175
+f 5273 5175 5078
+f 5078 5175 5107
+f 5078 5107 4911
+f 4911 5107 4961
+f 4911 4961 4779
+f 4779 4961 4874
+f 4779 4874 4694
+f 4694 4874 4747
+f 4694 4747 4517
+f 4517 4747 4507
+f 4517 4507 4445
+f 4445 4507 4416
+f 4445 4416 4355
+f 4355 4416 4307
+f 4355 4307 4225
+f 4225 4307 4159
+f 4225 4159 4073
+f 4073 4159 4017
+f 4073 4017 3929
+f 3929 4017 3948
+f 3929 3948 3745
+f 3745 3948 3796
+f 3745 3796 3624
+f 3624 3796 3644
+f 3624 3644 3560
+f 3560 3644 3547
+f 3560 3547 3323
+f 3323 3547 3305
+f 3323 3305 3176
+f 3176 3305 3193
+f 3176 3193 3079
+f 3079 3193 3061
+f 3079 3061 2945
+f 2945 3061 2997
+f 2945 2997 2787
+f 2787 2997 2871
+f 2787 2871 2720
+f 2720 2871 2655
+f 2720 2655 2513
+f 2513 2655 2605
+f 2513 2605 2410
+f 2410 2605 2427
+f 2410 2427 2280
+f 2280 2427 2243
+f 2280 2243 2103
+f 2103 2243 2151
+f 2103 2151 2065
+f 2065 2151 2036
+f 2065 2036 1853
+f 1853 2036 1945
+f 1853 1945 1817
+f 1817 1945 1805
+f 1817 1805 1663
+f 1663 1805 1606
+f 1663 1606 1551
+f 1551 1606 1509
+f 1551 1509 1363
+f 1363 1509 1387
+f 1363 1387 1211
+f 1211 1387 1259
+f 1211 1259 1146
+f 1146 1259 1105
+f 1146 1105 933
+f 933 1105 1002
+f 933 1002 897
+f 897 1002 919
+f 897 919 767
+f 767 919 783
+f 767 783 653
+f 653 783 551
+f 653 551 443
+f 443 551 474
+f 443 474 382
+f 382 474 419
+f 382 419 193
+f 193 419 253
+f 193 253 54
+f 54 253 44
+f 54 44 15
+f 7767 7867 7717
+f 7717 7867 7682
+f 7717 7682 7573
+f 7573 7682 7631
+f 7573 7631 7425
+f 7425 7631 7432
+f 7425 7432 7279
+f 7279 7432 7275
+f 7279 7275 7217
+f 7217 7275 7213
+f 7217 7213 7059
+f 7059 7213 7047
+f 7059 7047 6967
+f 6967 7047 6914
+f 6967 6914 6826
+f 6826 6914 6797
+f 6826 6797 6705
+f 6705 6797 6703
+f 6705 6703 6473
+f 6473 6703 6550
+f 6473 6550 6382
+f 6382 6550 6396
+f 6382 6396 6234
+f 6234 6396 6281
+f 6234 6281 6151
+f 6151 6281 6095
+f 6151 6095 6051
+f 6051 6095 6037
+f 6051 6037 5862
+f 5862 6037 5877
+f 5862 5877 5739
+f 5739 5877 5695
+f 5739 5695 5665
+f 5665 5695 5611
+f 5665 5611 5493
+f 5493 5611 5544
+f 5493 5544 5367
+f 5367 5544 5341
+f 5367 5341 5161
+f 5161 5341 5273
+f 5161 5273 5073
+f 5073 5273 5078
+f 5073 5078 4901
+f 4901 5078 4911
+f 4901 4911 4763
+f 4763 4911 4779
+f 4763 4779 4665
+f 4665 4779 4694
+f 4665 4694 4511
+f 4511 4694 4517
+f 4511 4517 4395
+f 4395 4517 4445
+f 4395 4445 4269
+f 4269 4445 4355
+f 4269 4355 4189
+f 4189 4355 4225
+f 4189 4225 4045
+f 4045 4225 4073
+f 4045 4073 3869
+f 3869 4073 3929
+f 3869 3929 3722
+f 3722 3929 3745
+f 3722 3745 3651
+f 3651 3745 3624
+f 3651 3624 3540
+f 3540 3624 3560
+f 3540 3560 3387
+f 3387 3560 3323
+f 3387 3323 3243
+f 3243 3323 3176
+f 3243 3176 3159
+f 3159 3176 3079
+f 3159 3079 3009
+f 3009 3079 2945
+f 3009 2945 2829
+f 2829 2945 2787
+f 2829 2787 2741
+f 2741 2787 2720
+f 2741 2720 2533
+f 2533 2720 2513
+f 2533 2513 2403
+f 2403 2513 2410
+f 2403 2410 2225
+f 2225 2410 2280
+f 2225 2280 2097
+f 2097 2280 2103
+f 2097 2103 2055
+f 2055 2103 2065
+f 2055 2065 1927
+f 1927 2065 1853
+f 1927 1853 1827
+f 1827 1853 1817
+f 1827 1817 1617
+f 1617 1817 1663
+f 1617 1663 1452
+f 1452 1663 1551
+f 1452 1551 1408
+f 1408 1551 1363
+f 1408 1363 1222
+f 1222 1363 1211
+f 1222 1211 1106
+f 1106 1211 1146
+f 1106 1146 960
+f 960 1146 933
+f 960 933 923
+f 923 933 897
+f 923 897 792
+f 792 897 767
+f 792 767 618
+f 618 767 653
+f 618 653 455
+f 455 653 443
+f 455 443 325
+f 325 443 382
+f 325 382 285
+f 285 382 193
+f 285 193 114
+f 114 193 54
+f 114 54 15
+f 7843 7767 7699
+f 7699 7767 7717
+f 7699 7717 7621
+f 7621 7717 7573
+f 7621 7573 7455
+f 7455 7573 7425
+f 7455 7425 7297
+f 7297 7425 7279
+f 7297 7279 7204
+f 7204 7279 7217
+f 7204 7217 7107
+f 7107 7217 7059
+f 7107 7059 6934
+f 6934 7059 6967
+f 6934 6967 6845
+f 6845 6967 6826
+f 6845 6826 6697
+f 6697 6826 6705
+f 6697 6705 6554
+f 6554 6705 6473
+f 6554 6473 6377
+f 6377 6473 6382
+f 6377 6382 6229
+f 6229 6382 6234
+f 6229 6234 6077
+f 6077 6234 6151
+f 6077 6151 5961
+f 5961 6151 6051
+f 5961 6051 5919
+f 5919 6051 5862
+f 5919 5862 5801
+f 5801 5862 5739
+f 5801 5739 5569
+f 5569 5739 5665
+f 5569 5665 5533
+f 5533 5665 5493
+f 5533 5493 5342
+f 5342 5493 5367
+f 5342 5367 5275
+f 5275 5367 5161
+f 5275 5161 5127
+f 5127 5161 5073
+f 5127 5073 4905
+f 4905 5073 4901
+f 4905 4901 4767
+f 4767 4901 4763
+f 4767 4763 4729
+f 4729 4763 4665
+f 4729 4665 4541
+f 4541 4665 4511
+f 4541 4511 4483
+f 4483 4511 4395
+f 4483 4395 4339
+f 4339 4395 4269
+f 4339 4269 4171
+f 4171 4269 4189
+f 4171 4189 4013
+f 4013 4189 4045
+f 4013 4045 3864
+f 3864 4045 3869
+f 3864 3869 3813
+f 3813 3869 3722
+f 3813 3722 3639
+f 3639 3722 3651
+f 3639 3651 3507
+f 3507 3651 3540
+f 3507 3540 3425
+f 3425 3540 3387
+f 3425 3387 3256
+f 3256 3387 3243
+f 3256 3243 3085
+f 3085 3243 3159
+f 3085 3159 2925
+f 2925 3159 3009
+f 2925 3009 2872
+f 2872 3009 2829
+f 2872 2829 2689
+f 2689 2829 2741
+f 2689 2741 2519
+f 2519 2741 2533
+f 2519 2533 2455
+f 2455 2533 2403
+f 2455 2403 2274
+f 2274 2403 2225
+f 2274 2225 2101
+f 2101 2225 2097
+f 2101 2097 2008
+f 2008 2097 2055
+f 2008 2055 1951
+f 1951 2055 1927
+f 1951 1927 1784
+f 1784 1927 1827
+f 1784 1827 1612
+f 1612 1827 1617
+f 1612 1617 1464
+f 1464 1617 1452
+f 1464 1452 1344
+f 1344 1452 1408
+f 1344 1408 1313
+f 1313 1408 1222
+f 1313 1222 1174
+f 1174 1222 1106
+f 1174 1106 1015
+f 1015 1106 960
+f 1015 960 925
+f 925 960 923
+f 925 923 689
+f 689 923 792
+f 689 792 673
+f 673 792 618
+f 673 618 475
+f 475 618 455
+f 475 455 326
+f 326 455 325
+f 326 325 186
+f 186 325 285
+f 186 285 83
+f 83 285 114
+f 83 114 3
+f 7833 7843 7723
+f 7723 7843 7699
+f 7723 7699 7527
+f 7527 7699 7621
+f 7527 7621 7493
+f 7493 7621 7455
+f 7493 7455 7283
+f 7283 7455 7297
+f 7283 7297 7241
+f 7241 7297 7204
+f 7241 7204 7033
+f 7033 7204 7107
+f 7033 7107 6977
+f 6977 7107 6934
+f 6977 6934 6851
+f 6851 6934 6845
+f 6851 6845 6671
+f 6671 6845 6697
+f 6671 6697 6507
+f 6507 6697 6554
+f 6507 6554 6405
+f 6405 6554 6377
+f 6405 6377 6300
+f 6300 6377 6229
+f 6300 6229 6109
+f 6109 6229 6077
+f 6109 6077 5997
+f 5997 6077 5961
+f 5997 5961 5897
+f 5897 5961 5919
+f 5897 5919 5771
+f 5771 5919 5801
+f 5771 5801 5633
+f 5633 5801 5569
+f 5633 5569 5436
+f 5436 5569 5533
+f 5436 5533 5385
+f 5385 5533 5342
+f 5385 5342 5251
+f 5251 5342 5275
+f 5251 5275 5049
+f 5049 5275 5127
+f 5049 5127 4989
+f 4989 5127 4905
+f 4989 4905 4813
+f 4813 4905 4767
+f 4813 4767 4711
+f 4711 4767 4729
+f 4711 4729 4559
+f 4559 4729 4541
+f 4559 4541 4443
+f 4443 4541 4483
+f 4443 4483 4233
+f 4233 4483 4339
+f 4233 4339 4181
+f 4181 4339 4171
+f 4181 4171 4048
+f 4048 4171 4013
+f 4048 4013 3858
+f 3858 4013 3864
+f 3858 3864 3705
+f 3705 3864 3813
+f 3705 3813 3669
+f 3669 3813 3639
+f 3669 3639 3461
+f 3461 3639 3507
+f 3461 3507 3313
+f 3313 3507 3425
+f 3313 3425 3202
+f 3202 3425 3256
+f 3202 3256 3095
+f 3095 3256 3085
+f 3095 3085 2911
+f 2911 3085 2925
+f 2911 2925 2853
+f 2853 2925 2872
+f 2853 2872 2761
+f 2761 2872 2689
+f 2761 2689 2617
+f 2617 2689 2519
+f 2617 2519 2475
+f 2475 2519 2455
+f 2475 2455 2241
+f 2241 2455 2274
+f 2241 2274 2121
+f 2121 2274 2101
+f 2121 2101 2005
+f 2005 2101 2008
+f 2005 2008 1885
+f 1885 2008 1951
+f 1885 1951 1820
+f 1820 1951 1784
+f 1820 1784 1671
+f 1671 1784 1612
+f 1671 1612 1471
+f 1471 1612 1464
+f 1471 1464 1388
+f 1388 1464 1344
+f 1388 1344 1256
+f 1256 1344 1313
+f 1256 1313 1147
+f 1147 1313 1174
+f 1147 1174 943
+f 943 1174 1015
+f 943 1015 876
+f 876 1015 925
+f 876 925 692
+f 692 925 689
+f 692 689 619
+f 619 689 673
+f 619 673 517
+f 517 673 475
+f 517 475 352
+f 352 475 326
+f 352 326 221
+f 221 326 186
+f 221 186 57
+f 57 186 83
+f 57 83 3
+f 7775 7833 7739
+f 7739 7833 7723
+f 7739 7723 7557
+f 7557 7723 7527
+f 7557 7527 7462
+f 7462 7527 7493
+f 7462 7493 7383
+f 7383 7493 7283
+f 7383 7283 7247
+f 7247 7283 7241
+f 7247 7241 7077
+f 7077 7241 7033
+f 7077 7033 6957
+f 6957 7033 6977
+f 6957 6977 6735
+f 6735 6977 6851
+f 6735 6851 6602
+f 6602 6851 6671
+f 6602 6671 6535
+f 6535 6671 6507
+f 6535 6507 6341
+f 6341 6507 6405
+f 6341 6405 6325
+f 6325 6405 6300
+f 6325 6300 6159
+f 6159 6300 6109
+f 6159 6109 6069
+f 6069 6109 5997
+f 6069 5997 5857
+f 5857 5997 5897
+f 5857 5897 5721
+f 5721 5897 5771
+f 5721 5771 5577
+f 5577 5771 5633
+f 5577 5633 5531
+f 5531 5633 5436
+f 5531 5436 5382
+f 5382 5436 5385
+f 5382 5385 5267
+f 5267 5385 5251
+f 5267 5251 5131
+f 5131 5251 5049
+f 5131 5049 4973
+f 4973 5049 4989
+f 4973 4989 4809
+f 4809 4989 4813
+f 4809 4813 4737
+f 4737 4813 4711
+f 4737 4711 4557
+f 4557 4711 4559
+f 4557 4559 4459
+f 4459 4559 4443
+f 4459 4443 4271
+f 4271 4443 4233
+f 4271 4233 4118
+f 4118 4233 4181
+f 4118 4181 4007
+f 4007 4181 4048
+f 4007 4048 3921
+f 3921 4048 3858
+f 3921 3858 3803
+f 3803 3858 3705
+f 3803 3705 3661
+f 3661 3705 3669
+f 3661 3669 3455
+f 3455 3669 3461
+f 3455 3461 3335
+f 3335 3461 3313
+f 3335 3313 3181
+f 3181 3313 3202
+f 3181 3202 3135
+f 3135 3202 3095
+f 3135 3095 2952
+f 2952 3095 2911
+f 2952 2911 2780
+f 2780 2911 2853
+f 2780 2853 2635
+f 2635 2853 2761
+f 2635 2761 2527
+f 2527 2761 2617
+f 2527 2617 2367
+f 2367 2617 2475
+f 2367 2475 2229
+f 2229 2475 2241
+f 2229 2241 2147
+f 2147 2241 2121
+f 2147 2121 2003
+f 2003 2121 2005
+f 2003 2005 1865
+f 1865 2005 1885
+f 1865 1885 1765
+f 1765 1885 1820
+f 1765 1820 1583
+f 1583 1820 1671
+f 1583 1671 1483
+f 1483 1671 1471
+f 1483 1471 1333
+f 1333 1471 1388
+f 1333 1388 1299
+f 1299 1388 1256
+f 1299 1256 1067
+f 1067 1256 1147
+f 1067 1147 1016
+f 1016 1147 943
+f 1016 943 885
+f 885 943 876
+f 885 876 731
+f 731 876 692
+f 731 692 657
+f 657 692 619
+f 657 619 513
+f 513 619 517
+f 513 517 342
+f 342 517 352
+f 342 352 203
+f 203 352 221
+f 203 221 73
+f 73 221 57
+f 73 57 35
+f 7809 7775 7725
+f 7725 7775 7739
+f 7725 7739 7583
+f 7583 7739 7557
+f 7583 7557 7491
+f 7491 7557 7462
+f 7491 7462 7345
+f 7345 7462 7383
+f 7345 7383 7159
+f 7159 7383 7247
+f 7159 7247 7105
+f 7105 7247 7077
+f 7105 7077 6973
+f 6973 7077 6957
+f 6973 6957 6785
+f 6785 6957 6735
+f 6785 6735 6605
+f 6605 6735 6602
+f 6605 6602 6499
+f 6499 6602 6535
+f 6499 6535 6353
+f 6353 6535 6341
+f 6353 6341 6285
+f 6285 6341 6325
+f 6285 6325 6153
+f 6153 6325 6159
+f 6153 6159 6005
+f 6005 6159 6069
+f 6005 6069 5886
+f 5886 6069 5857
+f 5886 5857 5722
+f 5722 5857 5721
+f 5722 5721 5673
+f 5673 5721 5577
+f 5673 5577 5519
+f 5519 5577 5531
+f 5519 5531 5305
+f 5305 5531 5382
+f 5305 5382 5165
+f 5165 5382 5267
+f 5165 5267 5075
+f 5075 5267 5131
+f 5075 5131 4903
+f 4903 5131 4973
+f 4903 4973 4783
+f 4783 4973 4809
+f 4783 4809 4709
+f 4709 4809 4737
+f 4709 4737 4613
+f 4613 4737 4557
+f 4613 4557 4472
+f 4472 4557 4459
+f 4472 4459 4331
+f 4331 4459 4271
+f 4331 4271 4160
+f 4160 4271 4118
+f 4160 4118 4089
+f 4089 4118 4007
+f 4089 4007 3925
+f 3925 4007 3921
+f 3925 3921 3829
+f 3829 3921 3803
+f 3829 3803 3681
+f 3681 3803 3661
+f 3681 3661 3545
+f 3545 3661 3455
+f 3545 3455 3377
+f 3377 3455 3335
+f 3377 3335 3173
+f 3173 3335 3181
+f 3173 3181 3081
+f 3081 3181 3135
+f 3081 3135 2955
+f 2955 3135 2952
+f 2955 2952 2791
+f 2791 2952 2780
+f 2791 2780 2671
+f 2671 2780 2635
+f 2671 2635 2537
+f 2537 2635 2527
+f 2537 2527 2481
+f 2481 2527 2367
+f 2481 2367 2277
+f 2277 2367 2229
+f 2277 2229 2199
+f 2199 2229 2147
+f 2199 2147 1981
+f 1981 2147 2003
+f 1981 2003 1899
+f 1899 2003 1865
+f 1899 1865 1725
+f 1725 1865 1765
+f 1725 1765 1641
+f 1641 1765 1583
+f 1641 1583 1480
+f 1480 1583 1483
+f 1480 1483 1417
+f 1417 1483 1333
+f 1417 1333 1245
+f 1245 1333 1299
+f 1245 1299 1133
+f 1133 1299 1067
+f 1133 1067 975
+f 975 1067 1016
+f 975 1016 890
+f 890 1016 885
+f 890 885 708
+f 708 885 731
+f 708 731 671
+f 671 731 657
+f 671 657 476
+f 476 657 513
+f 476 513 393
+f 393 513 342
+f 393 342 247
+f 247 342 203
+f 247 203 91
+f 91 203 73
+f 91 73 36
+f 7773 7809 7663
+f 7663 7809 7725
+f 7663 7725 7571
+f 7571 7725 7583
+f 7571 7583 7513
+f 7513 7583 7491
+f 7513 7491 7331
+f 7331 7491 7345
+f 7331 7345 7207
+f 7207 7345 7159
+f 7207 7159 7079
+f 7079 7159 7105
+f 7079 7105 6885
+f 6885 7105 6973
+f 6885 6973 6789
+f 6789 6973 6785
+f 6789 6785 6611
+f 6611 6785 6605
+f 6611 6605 6567
+f 6567 6605 6499
+f 6567 6499 6450
+f 6450 6499 6353
+f 6450 6353 6267
+f 6267 6353 6285
+f 6267 6285 6163
+f 6163 6285 6153
+f 6163 6153 5955
+f 5955 6153 6005
+f 5955 6005 5899
+f 5899 6005 5886
+f 5899 5886 5707
+f 5707 5886 5722
+f 5707 5722 5575
+f 5575 5722 5673
+f 5575 5673 5447
+f 5447 5673 5519
+f 5447 5519 5401
+f 5401 5519 5305
+f 5401 5305 5263
+f 5263 5305 5165
+f 5263 5165 5129
+f 5129 5165 5075
+f 5129 5075 4933
+f 4933 5075 4903
+f 4933 4903 4835
+f 4835 4903 4783
+f 4835 4783 4741
+f 4741 4783 4709
+f 4741 4709 4573
+f 4573 4709 4613
+f 4573 4613 4475
+f 4475 4613 4472
+f 4475 4472 4345
+f 4345 4472 4331
+f 4345 4331 4143
+f 4143 4331 4160
+f 4143 4160 4033
+f 4033 4160 4089
+f 4033 4089 3877
+f 3877 4089 3925
+f 3877 3925 3729
+f 3729 3925 3829
+f 3729 3829 3679
+f 3679 3829 3681
+f 3679 3681 3557
+f 3557 3681 3545
+f 3557 3545 3427
+f 3427 3545 3377
+f 3427 3377 3270
+f 3270 3377 3173
+f 3270 3173 3047
+f 3047 3173 3081
+f 3047 3081 2935
+f 2935 3081 2955
+f 2935 2955 2889
+f 2889 2955 2791
+f 2889 2791 2739
+f 2739 2791 2671
+f 2739 2671 2621
+f 2621 2671 2537
+f 2621 2537 2393
+f 2393 2537 2481
+f 2393 2481 2310
+f 2310 2481 2277
+f 2310 2277 2095
+f 2095 2277 2199
+f 2095 2199 2051
+f 2051 2199 1981
+f 2051 1981 1851
+f 1851 1981 1899
+f 1851 1899 1721
+f 1721 1899 1725
+f 1721 1725 1621
+f 1621 1725 1641
+f 1621 1641 1472
+f 1472 1641 1480
+f 1472 1480 1323
+f 1323 1480 1417
+f 1323 1417 1301
+f 1301 1417 1245
+f 1301 1245 1157
+f 1157 1245 1133
+f 1157 1133 965
+f 965 1133 975
+f 965 975 839
+f 839 975 890
+f 839 890 787
+f 787 890 708
+f 787 708 649
+f 649 708 671
+f 649 671 459
+f 459 671 476
+f 459 476 397
+f 397 476 393
+f 397 393 263
+f 263 393 247
+f 263 247 135
+f 135 247 91
+f 135 91 36
+f 7769 7773 7649
+f 7649 7773 7663
+f 7649 7663 7535
+f 7535 7663 7571
+f 7535 7571 7407
+f 7407 7571 7513
+f 7407 7513 7355
+f 7355 7513 7331
+f 7355 7331 7183
+f 7183 7331 7207
+f 7183 7207 7083
+f 7083 7207 7079
+f 7083 7079 6961
+f 6961 7079 6885
+f 6961 6885 6783
+f 6783 6885 6789
+f 6783 6789 6651
+f 6651 6789 6611
+f 6651 6611 6483
+f 6483 6611 6567
+f 6483 6567 6409
+f 6409 6567 6450
+f 6409 6450 6279
+f 6279 6450 6267
+f 6279 6267 6083
+f 6083 6267 6163
+f 6083 6163 6043
+f 6043 6163 5955
+f 6043 5955 5841
+f 5841 5955 5899
+f 5841 5899 5683
+f 5683 5899 5707
+f 5683 5707 5651
+f 5651 5707 5575
+f 5651 5575 5501
+f 5501 5575 5447
+f 5501 5447 5354
+f 5354 5447 5401
+f 5354 5401 5271
+f 5271 5401 5263
+f 5271 5263 5111
+f 5111 5263 5129
+f 5111 5129 4937
+f 4937 5129 4933
+f 4937 4933 4829
+f 4829 4933 4835
+f 4829 4835 4635
+f 4635 4835 4741
+f 4635 4741 4583
+f 4583 4741 4573
+f 4583 4573 4369
+f 4369 4573 4475
+f 4369 4475 4245
+f 4245 4475 4345
+f 4245 4345 4099
+f 4099 4345 4143
+f 4099 4143 4085
+f 4085 4143 4033
+f 4085 4033 3837
+f 3837 4033 3877
+f 3837 3877 3703
+f 3703 3877 3729
+f 3703 3729 3677
+f 3677 3729 3679
+f 3677 3679 3549
+f 3549 3679 3557
+f 3549 3557 3314
+f 3314 3557 3427
+f 3314 3427 3287
+f 3287 3427 3270
+f 3287 3270 3083
+f 3083 3270 3047
+f 3083 3047 2981
+f 2981 3047 2935
+f 2981 2935 2789
+f 2789 2935 2889
+f 2789 2889 2645
+f 2645 2889 2739
+f 2645 2739 2587
+f 2587 2739 2621
+f 2587 2621 2381
+f 2381 2621 2393
+f 2381 2393 2213
+f 2213 2393 2310
+f 2213 2310 2165
+f 2165 2310 2095
+f 2165 2095 1993
+f 1993 2095 2051
+f 1993 2051 1871
+f 1871 2051 1851
+f 1871 1851 1761
+f 1761 1851 1721
+f 1761 1721 1597
+f 1597 1721 1621
+f 1597 1621 1505
+f 1505 1621 1472
+f 1505 1472 1377
+f 1377 1472 1323
+f 1377 1323 1219
+f 1219 1323 1301
+f 1219 1301 1083
+f 1083 1301 1157
+f 1083 1157 947
+f 947 1157 965
+f 947 965 861
+f 861 965 839
+f 861 839 687
+f 687 839 787
+f 687 787 565
+f 565 787 649
+f 565 649 449
+f 449 649 459
+f 449 459 375
+f 375 459 397
+f 375 397 287
+f 287 397 263
+f 287 263 145
+f 145 263 135
+f 145 135 34
+f 7839 7769 7687
+f 7687 7769 7649
+f 7687 7649 7537
+f 7537 7649 7535
+f 7537 7535 7503
+f 7503 7535 7407
+f 7503 7407 7387
+f 7387 7407 7355
+f 7387 7355 7235
+f 7235 7355 7183
+f 7235 7183 7119
+f 7119 7183 7083
+f 7119 7083 6865
+f 6865 7083 6961
+f 6865 6961 6739
+f 6739 6961 6783
+f 6739 6783 6677
+f 6677 6783 6651
+f 6677 6651 6565
+f 6565 6651 6483
+f 6565 6483 6399
+f 6399 6483 6409
+f 6399 6409 6210
+f 6210 6409 6279
+f 6210 6279 6119
+f 6119 6279 6083
+f 6119 6083 5965
+f 5965 6083 6043
+f 5965 6043 5823
+f 5823 6043 5841
+f 5823 5841 5805
+f 5805 5841 5683
+f 5805 5683 5635
+f 5635 5683 5651
+f 5635 5651 5451
+f 5451 5651 5501
+f 5451 5501 5345
+f 5345 5501 5354
+f 5345 5354 5171
+f 5171 5354 5271
+f 5171 5271 5039
+f 5039 5271 5111
+f 5039 5111 4923
+f 4923 5111 4937
+f 4923 4937 4859
+f 4859 4937 4829
+f 4859 4829 4703
+f 4703 4829 4635
+f 4703 4635 4535
+f 4535 4635 4583
+f 4535 4583 4467
+f 4467 4583 4369
+f 4467 4369 4291
+f 4291 4369 4245
+f 4291 4245 4199
+f 4199 4245 4099
+f 4199 4099 4093
+f 4093 4099 4085
+f 4093 4085 3881
+f 3881 4085 3837
+f 3881 3837 3763
+f 3763 3837 3703
+f 3763 3703 3689
+f 3689 3703 3677
+f 3689 3677 3493
+f 3493 3677 3549
+f 3493 3549 3415
+f 3415 3549 3314
+f 3415 3314 3281
+f 3281 3314 3287
+f 3281 3287 3097
+f 3097 3287 3083
+f 3097 3083 2909
+f 2909 3083 2981
+f 2909 2981 2785
+f 2785 2981 2789
+f 2785 2789 2649
+f 2649 2789 2645
+f 2649 2645 2615
+f 2615 2645 2587
+f 2615 2587 2359
+f 2359 2587 2381
+f 2359 2381 2315
+f 2315 2381 2213
+f 2315 2213 2181
+f 2181 2213 2165
+f 2181 2165 2031
+f 2031 2165 1993
+f 2031 1993 1929
+f 1929 1993 1871
+f 1929 1871 1801
+f 1801 1871 1761
+f 1801 1761 1697
+f 1697 1761 1597
+f 1697 1597 1501
+f 1501 1597 1505
+f 1501 1505 1359
+f 1359 1505 1377
+f 1359 1377 1249
+f 1249 1377 1219
+f 1249 1219 1069
+f 1069 1219 1083
+f 1069 1083 1013
+f 1013 1083 947
+f 1013 947 863
+f 863 947 861
+f 863 861 677
+f 677 861 687
+f 677 687 675
+f 675 687 565
+f 675 565 543
+f 543 565 449
+f 543 449 407
+f 407 449 375
+f 407 375 211
+f 211 375 287
+f 211 287 139
+f 139 287 145
+f 139 145 34
+f 7797 7839 7651
+f 7651 7839 7687
+f 7651 7687 7613
+f 7613 7687 7537
+f 7613 7537 7435
+f 7435 7537 7503
+f 7435 7503 7293
+f 7293 7503 7387
+f 7293 7387 7189
+f 7189 7387 7235
+f 7189 7235 7103
+f 7103 7235 7119
+f 7103 7119 6959
+f 6959 7119 6865
+f 6959 6865 6759
+f 6759 6865 6739
+f 6759 6739 6673
+f 6673 6739 6677
+f 6673 6677 6537
+f 6537 6677 6565
+f 6537 6565 6345
+f 6345 6565 6399
+f 6345 6399 6283
+f 6283 6399 6210
+f 6283 6210 6131
+f 6131 6210 6119
+f 6131 6119 5949
+f 5949 6119 5965
+f 5949 5965 5867
+f 5867 5965 5823
+f 5867 5823 5751
+f 5751 5823 5805
+f 5751 5805 5637
+f 5637 5805 5635
+f 5637 5635 5419
+f 5419 5635 5451
+f 5419 5451 5327
+f 5327 5451 5345
+f 5327 5345 5177
+f 5177 5345 5171
+f 5177 5171 5083
+f 5083 5171 5039
+f 5083 5039 4897
+f 4897 5039 4923
+f 4897 4923 4827
+f 4827 4923 4859
+f 4827 4859 4745
+f 4745 4859 4703
+f 4745 4703 4533
+f 4533 4703 4535
+f 4533 4535 4455
+f 4455 4535 4467
+f 4455 4467 4277
+f 4277 4467 4291
+f 4277 4291 4145
+f 4145 4291 4199
+f 4145 4199 4055
+f 4055 4199 4093
+f 4055 4093 3895
+f 3895 4093 3881
+f 3895 3881 3793
+f 3793 3881 3763
+f 3793 3763 3687
+f 3687 3763 3689
+f 3687 3689 3495
+f 3495 3689 3493
+f 3495 3493 3399
+f 3399 3493 3415
+f 3399 3415 3197
+f 3197 3415 3281
+f 3197 3281 3131
+f 3131 3281 3097
+f 3131 3097 2905
+f 2905 3097 2909
+f 2905 2909 2885
+f 2885 2909 2785
+f 2885 2785 2759
+f 2759 2785 2649
+f 2759 2649 2619
+f 2619 2649 2615
+f 2619 2615 2363
+f 2363 2615 2359
+f 2363 2359 2321
+f 2321 2359 2315
+f 2321 2315 2122
+f 2122 2315 2181
+f 2122 2181 2023
+f 2023 2181 2031
+f 2023 2031 1925
+f 1925 2031 1929
+f 1925 1929 1711
+f 1711 1929 1801
+f 1711 1801 1633
+f 1633 1801 1697
+f 1633 1697 1531
+f 1531 1697 1501
+f 1531 1501 1367
+f 1367 1501 1359
+f 1367 1359 1291
+f 1291 1359 1249
+f 1291 1249 1061
+f 1061 1249 1069
+f 1061 1069 955
+f 955 1069 1013
+f 955 1013 805
+f 805 1013 863
+f 805 863 751
+f 751 863 677
+f 751 677 647
+f 647 677 675
+f 647 675 521
+f 521 675 543
+f 521 543 347
+f 347 543 407
+f 347 407 223
+f 223 407 211
+f 223 211 125
+f 125 211 139
+f 125 139 16
+f 7811 7797 7647
+f 7647 7797 7651
+f 7647 7651 7627
+f 7627 7651 7613
+f 7627 7613 7445
+f 7445 7613 7435
+f 7445 7435 7319
+f 7319 7435 7293
+f 7319 7293 7223
+f 7223 7293 7189
+f 7223 7189 7049
+f 7049 7189 7103
+f 7049 7103 6857
+f 6857 7103 6959
+f 6857 6959 6787
+f 6787 6959 6759
+f 6787 6759 6669
+f 6669 6759 6673
+f 6669 6673 6557
+f 6557 6673 6537
+f 6557 6537 6457
+f 6457 6537 6345
+f 6457 6345 6247
+f 6247 6345 6283
+f 6247 6283 6139
+f 6139 6283 6131
+f 6139 6131 5967
+f 5967 6131 5949
+f 5967 5949 5875
+f 5875 5949 5867
+f 5875 5867 5749
+f 5749 5867 5751
+f 5749 5751 5661
+f 5661 5751 5637
+f 5661 5637 5421
+f 5421 5637 5419
+f 5421 5419 5315
+f 5315 5419 5327
+f 5315 5327 5183
+f 5183 5327 5177
+f 5183 5177 5047
+f 5047 5177 5083
+f 5047 5083 4987
+f 4987 5083 4897
+f 4987 4897 4803
+f 4803 4897 4827
+f 4803 4827 4637
+f 4637 4827 4745
+f 4637 4745 4513
+f 4513 4745 4533
+f 4513 4533 4379
+f 4379 4533 4455
+f 4379 4455 4341
+f 4341 4455 4277
+f 4341 4277 4207
+f 4207 4277 4145
+f 4207 4145 4005
+f 4005 4145 4055
+f 4005 4055 3845
+f 3845 4055 3895
+f 3845 3895 3789
+f 3789 3895 3793
+f 3789 3793 3635
+f 3635 3793 3687
+f 3635 3687 3475
+f 3475 3687 3495
+f 3475 3495 3325
+f 3325 3495 3399
+f 3325 3399 3209
+f 3209 3399 3197
+f 3209 3197 3055
+f 3055 3197 3131
+f 3055 3131 3013
+f 3013 3131 2905
+f 3013 2905 2795
+f 2795 2905 2885
+f 2795 2885 2653
+f 2653 2885 2759
+f 2653 2759 2539
+f 2539 2759 2619
+f 2539 2619 2439
+f 2439 2619 2363
+f 2439 2363 2325
+f 2325 2363 2321
+f 2325 2321 2119
+f 2119 2321 2122
+f 2119 2122 1965
+f 1965 2122 2023
+f 1965 2023 1841
+f 1841 2023 1925
+f 1841 1925 1795
+f 1795 1925 1711
+f 1795 1711 1667
+f 1667 1711 1633
+f 1667 1633 1445
+f 1445 1633 1531
+f 1445 1531 1347
+f 1347 1531 1367
+f 1347 1367 1311
+f 1311 1367 1291
+f 1311 1291 1153
+f 1153 1291 1061
+f 1153 1061 935
+f 935 1061 955
+f 935 955 883
+f 883 955 805
+f 883 805 777
+f 777 805 751
+f 777 751 667
+f 667 751 647
+f 667 647 489
+f 489 647 521
+f 489 521 301
+f 301 521 347
+f 301 347 167
+f 167 347 223
+f 167 223 153
+f 153 223 125
+f 153 125 16
+f 7855 7811 7707
+f 7707 7811 7647
+f 7707 7647 7585
+f 7585 7647 7627
+f 7585 7627 7437
+f 7437 7627 7445
+f 7437 7445 7309
+f 7309 7445 7319
+f 7309 7319 7231
+f 7231 7319 7223
+f 7231 7223 7099
+f 7099 7223 7049
+f 7099 7049 6911
+f 6911 7049 6857
+f 6911 6857 6847
+f 6847 6857 6787
+f 6847 6787 6689
+f 6689 6787 6669
+f 6689 6669 6525
+f 6525 6669 6557
+f 6525 6557 6347
+f 6347 6557 6457
+f 6347 6457 6263
+f 6263 6457 6247
+f 6263 6247 6085
+f 6085 6247 6139
+f 6085 6139 5959
+f 5959 6139 5967
+f 5959 5967 5819
+f 5819 5967 5875
+f 5819 5875 5799
+f 5799 5875 5749
+f 5799 5749 5647
+f 5647 5749 5661
+f 5647 5661 5469
+f 5469 5661 5421
+f 5469 5421 5329
+f 5329 5421 5315
+f 5329 5315 5187
+f 5187 5315 5183
+f 5187 5183 5025
+f 5025 5183 5047
+f 5025 5047 4893
+f 4893 5047 4987
+f 4893 4987 4775
+f 4775 4987 4803
+f 4775 4803 4659
+f 4659 4803 4637
+f 4659 4637 4611
+f 4611 4637 4513
+f 4611 4513 4465
+f 4465 4513 4379
+f 4465 4379 4253
+f 4253 4379 4341
+f 4253 4341 4205
+f 4205 4341 4207
+f 4205 4207 4003
+f 4003 4207 4005
+f 4003 4005 3849
+f 3849 4005 3845
+f 3849 3845 3775
+f 3775 3845 3789
+f 3775 3789 3589
+f 3589 3789 3635
+f 3589 3635 3503
+f 3503 3635 3475
+f 3503 3475 3359
+f 3359 3475 3325
+f 3359 3325 3205
+f 3205 3325 3209
+f 3205 3209 3067
+f 3067 3209 3055
+f 3067 3055 2947
+f 2947 3055 3013
+f 2947 3013 2811
+f 2811 3013 2795
+f 2811 2795 2651
+f 2651 2795 2653
+f 2651 2653 2501
+f 2501 2653 2539
+f 2501 2539 2483
+f 2483 2539 2439
+f 2483 2439 2331
+f 2331 2439 2325
+f 2331 2325 2197
+f 2197 2325 2119
+f 2197 2119 2057
+f 2057 2119 1965
+f 2057 1965 1829
+f 1829 1965 1841
+f 1829 1841 1823
+f 1823 1841 1795
+f 1823 1795 1637
+f 1637 1795 1667
+f 1637 1667 1529
+f 1529 1667 1445
+f 1529 1445 1369
+f 1369 1445 1347
+f 1369 1347 1205
+f 1205 1347 1311
+f 1205 1311 1131
+f 1131 1311 1153
+f 1131 1153 989
+f 989 1153 935
+f 989 935 819
+f 819 935 883
+f 819 883 745
+f 745 883 777
+f 745 777 605
+f 605 777 667
+f 605 667 485
+f 485 667 489
+f 485 489 361
+f 361 489 301
+f 361 301 257
+f 257 301 167
+f 257 167 121
+f 121 167 153
+f 121 153 22
+f 7853 7855 7733
+f 7733 7855 7707
+f 7733 7707 7619
+f 7619 7707 7585
+f 7619 7585 7405
+f 7405 7585 7437
+f 7405 7437 7317
+f 7317 7437 7309
+f 7317 7309 7165
+f 7165 7309 7231
+f 7165 7231 7121
+f 7121 7231 7099
+f 7121 7099 6877
+f 6877 7099 6911
+f 6877 6911 6775
+f 6775 6911 6847
+f 6775 6847 6597
+f 6597 6847 6689
+f 6597 6689 6563
+f 6563 6689 6525
+f 6563 6525 6357
+f 6357 6525 6347
+f 6357 6347 6293
+f 6293 6347 6263
+f 6293 6263 6137
+f 6137 6263 6085
+f 6137 6085 6003
+f 6003 6085 5959
+f 6003 5959 5905
+f 5905 5959 5819
+f 5905 5819 5693
+f 5693 5819 5799
+f 5693 5799 5561
+f 5561 5799 5647
+f 5561 5647 5443
+f 5443 5647 5469
+f 5443 5469 5371
+f 5371 5469 5329
+f 5371 5329 5159
+f 5159 5329 5187
+f 5159 5187 5063
+f 5063 5187 5025
+f 5063 5025 5017
+f 5017 5025 4893
+f 5017 4893 4845
+f 4845 4893 4775
+f 4845 4775 4685
+f 4685 4775 4659
+f 4685 4659 4603
+f 4603 4659 4611
+f 4603 4611 4441
+f 4441 4611 4465
+f 4441 4465 4305
+f 4305 4465 4253
+f 4305 4253 4223
+f 4223 4253 4205
+f 4223 4205 3967
+f 3967 4205 4003
+f 3967 4003 3931
+f 3931 4003 3849
+f 3931 3849 3809
+f 3809 3849 3775
+f 3809 3775 3605
+f 3605 3775 3589
+f 3605 3589 3467
+f 3467 3589 3503
+f 3467 3503 3423
+f 3423 3503 3359
+f 3423 3359 3223
+f 3223 3359 3205
+f 3223 3205 3039
+f 3039 3205 3067
+f 3039 3067 3019
+f 3019 3067 2947
+f 3019 2947 2803
+f 2803 2947 2811
+f 2803 2811 2735
+f 2735 2811 2651
+f 2735 2651 2515
+f 2515 2651 2501
+f 2515 2501 2449
+f 2449 2501 2483
+f 2449 2483 2327
+f 2327 2483 2331
+f 2327 2331 2153
+f 2153 2331 2197
+f 2153 2197 2001
+f 2001 2197 2057
+f 2001 2057 1901
+f 1901 2057 1829
+f 1901 1829 1747
+f 1747 1829 1823
+f 1747 1823 1677
+f 1677 1823 1637
+f 1677 1637 1515
+f 1515 1637 1529
+f 1515 1529 1420
+f 1420 1529 1369
+f 1420 1369 1243
+f 1243 1369 1205
+f 1243 1205 1151
+f 1151 1205 1131
+f 1151 1131 957
+f 957 1131 989
+f 957 989 809
+f 809 989 819
+f 809 819 733
+f 733 819 745
+f 733 745 593
+f 593 745 605
+f 593 605 509
+f 509 605 485
+f 509 485 307
+f 307 485 361
+f 307 361 201
+f 201 361 257
+f 201 257 143
+f 143 257 121
+f 143 121 22
+f 7793 7853 7693
+f 7693 7853 7733
+f 7693 7733 7615
+f 7615 7733 7619
+f 7615 7619 7447
+f 7447 7619 7405
+f 7447 7405 7335
+f 7335 7405 7317
+f 7335 7317 7153
+f 7153 7317 7165
+f 7153 7165 7111
+f 7111 7165 7121
+f 7111 7121 6887
+f 6887 7121 6877
+f 6887 6877 6733
+f 6733 6877 6775
+f 6733 6775 6667
+f 6667 6775 6597
+f 6667 6597 6515
+f 6515 6597 6563
+f 6515 6563 6411
+f 6411 6563 6357
+f 6411 6357 6205
+f 6205 6357 6293
+f 6205 6293 6143
+f 6143 6293 6137
+f 6143 6137 6023
+f 6023 6137 6003
+f 6023 6003 5933
+f 5933 6003 5905
+f 5933 5905 5767
+f 5767 5905 5693
+f 5767 5693 5565
+f 5565 5693 5561
+f 5565 5561 5503
+f 5503 5561 5443
+f 5503 5443 5301
+f 5301 5443 5371
+f 5301 5371 5247
+f 5247 5371 5159
+f 5247 5159 5087
+f 5087 5159 5063
+f 5087 5063 4975
+f 4975 5063 5017
+f 4975 5017 4769
+f 4769 5017 4845
+f 4769 4845 4751
+f 4751 4845 4685
+f 4751 4685 4499
+f 4499 4685 4603
+f 4499 4603 4375
+f 4375 4603 4441
+f 4375 4441 4235
+f 4235 4441 4305
+f 4235 4305 4111
+f 4111 4305 4223
+f 4111 4223 4077
+f 4077 4223 3967
+f 4077 3967 3959
+f 3959 3967 3931
+f 3959 3931 3759
+f 3759 3931 3809
+f 3759 3809 3655
+f 3655 3809 3605
+f 3655 3605 3537
+f 3537 3605 3467
+f 3537 3467 3367
+f 3367 3467 3423
+f 3367 3423 3263
+f 3263 3423 3223
+f 3263 3223 3129
+f 3129 3223 3039
+f 3129 3039 2915
+f 2915 3039 3019
+f 2915 3019 2799
+f 2799 3019 2803
+f 2799 2803 2749
+f 2749 2803 2735
+f 2749 2735 2593
+f 2593 2735 2515
+f 2593 2515 2373
+f 2373 2515 2449
+f 2373 2449 2313
+f 2313 2449 2327
+f 2313 2327 2141
+f 2141 2327 2153
+f 2141 2153 2025
+f 2025 2153 2001
+f 2025 2001 1913
+f 1913 2001 1901
+f 1913 1901 1787
+f 1787 1901 1747
+f 1787 1747 1581
+f 1581 1747 1677
+f 1581 1677 1477
+f 1477 1677 1515
+f 1477 1515 1379
+f 1379 1515 1420
+f 1379 1420 1275
+f 1275 1420 1243
+f 1275 1243 1096
+f 1096 1243 1151
+f 1096 1151 1055
+f 1055 1151 957
+f 1055 957 901
+f 901 957 809
+f 901 809 713
+f 713 809 733
+f 713 733 639
+f 639 733 593
+f 639 593 421
+f 421 593 509
+f 421 509 349
+f 349 509 307
+f 349 307 267
+f 267 307 201
+f 267 201 119
+f 119 201 143
+f 119 143 18
+f 7815 7793 7749
+f 7749 7793 7693
+f 7749 7693 7611
+f 7611 7693 7615
+f 7611 7615 7507
+f 7507 7615 7447
+f 7507 7447 7369
+f 7369 7447 7335
+f 7369 7335 7199
+f 7199 7335 7153
+f 7199 7153 7097
+f 7097 7153 7111
+f 7097 7111 6859
+f 6859 7111 6887
+f 6859 6887 6743
+f 6743 6887 6733
+f 6743 6733 6639
+f 6639 6733 6667
+f 6639 6667 6579
+f 6579 6667 6515
+f 6579 6515 6361
+f 6361 6515 6411
+f 6361 6411 6323
+f 6323 6411 6205
+f 6323 6205 6125
+f 6125 6205 6143
+f 6125 6143 5943
+f 5943 6143 6023
+f 5943 6023 5873
+f 5873 6023 5933
+f 5873 5933 5713
+f 5713 5933 5767
+f 5713 5767 5559
+f 5559 5767 5565
+f 5559 5565 5513
+f 5513 5565 5503
+f 5513 5503 5299
+f 5299 5503 5301
+f 5299 5301 5235
+f 5235 5301 5247
+f 5235 5247 5095
+f 5095 5247 5087
+f 5095 5087 4935
+f 4935 5087 4975
+f 4935 4975 4861
+f 4861 4975 4769
+f 4861 4769 4715
+f 4715 4769 4751
+f 4715 4751 4539
+f 4539 4751 4499
+f 4539 4499 4391
+f 4391 4499 4375
+f 4391 4375 4287
+f 4287 4375 4235
+f 4287 4235 4105
+f 4105 4235 4111
+f 4105 4111 3969
+f 3969 4111 4077
+f 3969 4077 3915
+f 3915 4077 3959
+f 3915 3959 3753
+f 3753 3959 3759
+f 3753 3759 3607
+f 3607 3759 3655
+f 3607 3655 3485
+f 3485 3655 3537
+f 3485 3537 3321
+f 3321 3537 3367
+f 3321 3367 3185
+f 3185 3367 3263
+f 3185 3263 3142
+f 3142 3263 3129
+f 3142 3129 2959
+f 2959 3129 2915
+f 2959 2915 2771
+f 2771 2915 2799
+f 2771 2799 2747
+f 2747 2799 2749
+f 2747 2749 2551
+f 2551 2749 2593
+f 2551 2593 2485
+f 2485 2593 2373
+f 2485 2373 2303
+f 2303 2373 2313
+f 2303 2313 2117
+f 2117 2313 2141
+f 2117 2141 2081
+f 2081 2141 2025
+f 2081 2025 1863
+f 1863 2025 1913
+f 1863 1913 1781
+f 1781 1913 1787
+f 1781 1787 1643
+f 1643 1787 1581
+f 1643 1581 1545
+f 1545 1581 1477
+f 1545 1477 1371
+f 1371 1477 1379
+f 1371 1379 1225
+f 1225 1379 1275
+f 1225 1275 1063
+f 1063 1275 1096
+f 1063 1096 941
+f 941 1096 1055
+f 941 1055 887
+f 887 1055 901
+f 887 901 759
+f 759 901 713
+f 759 713 569
+f 569 713 639
+f 569 639 471
+f 471 639 421
+f 471 421 331
+f 331 421 349
+f 331 349 226
+f 226 349 267
+f 226 267 99
+f 99 267 119
+f 99 119 20
+f 7823 7815 7655
+f 7655 7815 7749
+f 7655 7749 7605
+f 7605 7749 7611
+f 7605 7611 7451
+f 7451 7611 7507
+f 7451 7507 7321
+f 7321 7507 7369
+f 7321 7369 7225
+f 7225 7369 7199
+f 7225 7199 7087
+f 7087 7199 7097
+f 7087 7097 6927
+f 6927 7097 6859
+f 6927 6859 6823
+f 6823 6859 6743
+f 6823 6743 6711
+f 6711 6743 6639
+f 6711 6639 6509
+f 6509 6639 6579
+f 6509 6579 6433
+f 6433 6579 6361
+f 6433 6361 6291
+f 6291 6361 6323
+f 6291 6323 6197
+f 6197 6323 6125
+f 6197 6125 6047
+f 6047 6125 5943
+f 6047 5943 5859
+f 5859 5943 5873
+f 5859 5873 5731
+f 5731 5873 5713
+f 5731 5713 5631
+f 5631 5713 5559
+f 5631 5559 5445
+f 5445 5559 5513
+f 5445 5513 5361
+f 5361 5513 5299
+f 5361 5299 5264
+f 5264 5299 5235
+f 5264 5235 5115
+f 5115 5235 5095
+f 5115 5095 5015
+f 5015 5095 4935
+f 5015 4935 4759
+f 4759 4935 4861
+f 4759 4861 4639
+f 4639 4861 4715
+f 4639 4715 4599
+f 4599 4715 4539
+f 4599 4539 4377
+f 4377 4539 4391
+f 4377 4391 4325
+f 4325 4391 4287
+f 4325 4287 4121
+f 4121 4287 4105
+f 4121 4105 4037
+f 4037 4105 3969
+f 4037 3969 3835
+f 3835 3969 3915
+f 3835 3915 3733
+f 3733 3915 3753
+f 3733 3753 3683
+f 3683 3753 3607
+f 3683 3607 3471
+f 3471 3607 3485
+f 3471 3485 3383
+f 3383 3485 3321
+f 3383 3321 3225
+f 3225 3321 3185
+f 3225 3185 3123
+f 3123 3185 3142
+f 3123 3142 2977
+f 2977 3142 2959
+f 2977 2959 2879
+f 2879 2959 2771
+f 2879 2771 2733
+f 2733 2771 2747
+f 2733 2747 2503
+f 2503 2747 2551
+f 2503 2551 2383
+f 2383 2551 2485
+f 2383 2485 2333
+f 2333 2485 2303
+f 2333 2303 2143
+f 2143 2303 2117
+f 2143 2117 2079
+f 2079 2117 2081
+f 2079 2081 1941
+f 1941 2081 1863
+f 1941 1863 1739
+f 1739 1863 1781
+f 1739 1781 1615
+f 1615 1781 1643
+f 1615 1643 1502
+f 1502 1643 1545
+f 1502 1545 1331
+f 1331 1545 1371
+f 1331 1371 1250
+f 1250 1371 1225
+f 1250 1225 1081
+f 1081 1225 1063
+f 1081 1063 973
+f 973 1063 941
+f 973 941 815
+f 815 941 887
+f 815 887 729
+f 729 887 759
+f 729 759 625
+f 625 759 569
+f 625 569 469
+f 469 569 471
+f 469 471 309
+f 309 471 331
+f 309 331 181
+f 181 331 226
+f 181 226 111
+f 111 226 99
+f 111 99 20
+f 7835 7823 7721
+f 7721 7823 7655
+f 7721 7655 7581
+f 7581 7655 7605
+f 7581 7605 7441
+f 7441 7605 7451
+f 7441 7451 7359
+f 7359 7451 7321
+f 7359 7321 7239
+f 7239 7321 7225
+f 7239 7225 7011
+f 7011 7225 7087
+f 7011 7087 6867
+f 6867 7087 6927
+f 6867 6927 6777
+f 6777 6927 6823
+f 6777 6823 6687
+f 6687 6823 6711
+f 6687 6711 6505
+f 6505 6711 6509
+f 6505 6509 6402
+f 6402 6509 6433
+f 6402 6433 6319
+f 6319 6433 6291
+f 6319 6291 6133
+f 6133 6291 6197
+f 6133 6197 6028
+f 6028 6197 6047
+f 6028 6047 5855
+f 5855 6047 5859
+f 5855 5859 5793
+f 5793 5859 5731
+f 5793 5731 5657
+f 5657 5731 5631
+f 5657 5631 5473
+f 5473 5631 5445
+f 5473 5445 5339
+f 5339 5445 5361
+f 5339 5361 5201
+f 5201 5361 5264
+f 5201 5264 5056
+f 5056 5264 5115
+f 5056 5115 4925
+f 4925 5115 5015
+f 4925 5015 4877
+f 4877 5015 4759
+f 4877 4759 4667
+f 4667 4759 4639
+f 4667 4639 4509
+f 4509 4639 4599
+f 4509 4599 4451
+f 4451 4599 4377
+f 4451 4377 4243
+f 4243 4377 4325
+f 4243 4325 4157
+f 4157 4325 4121
+f 4157 4121 3973
+f 3973 4121 4037
+f 3973 4037 3923
+f 3923 4037 3835
+f 3923 3835 3741
+f 3741 3835 3733
+f 3741 3733 3663
+f 3663 3733 3683
+f 3663 3683 3443
+f 3443 3683 3471
+f 3443 3471 3373
+f 3373 3471 3383
+f 3373 3383 3233
+f 3233 3383 3225
+f 3233 3225 3149
+f 3149 3225 3123
+f 3149 3123 2995
+f 2995 3123 2977
+f 2995 2977 2843
+f 2843 2977 2879
+f 2843 2879 2663
+f 2663 2879 2733
+f 2663 2733 2543
+f 2543 2733 2503
+f 2543 2503 2387
+f 2387 2503 2383
+f 2387 2383 2337
+f 2337 2383 2333
+f 2337 2333 2173
+f 2173 2333 2143
+f 2173 2143 1961
+f 1961 2143 2079
+f 1961 2079 1911
+f 1911 2079 1941
+f 1911 1941 1749
+f 1749 1941 1739
+f 1749 1739 1587
+f 1587 1739 1615
+f 1587 1615 1563
+f 1563 1615 1502
+f 1563 1502 1425
+f 1425 1502 1331
+f 1425 1331 1247
+f 1247 1331 1250
+f 1247 1250 1181
+f 1181 1250 1081
+f 1181 1081 1029
+f 1029 1081 973
+f 1029 973 829
+f 829 973 815
+f 829 815 685
+f 685 815 729
+f 685 729 615
+f 615 729 625
+f 615 625 493
+f 493 625 469
+f 493 469 373
+f 373 469 309
+f 373 309 237
+f 237 309 181
+f 237 181 109
+f 109 181 111
+f 109 111 31
+f 7831 7835 7657
+f 7657 7835 7721
+f 7657 7721 7624
+f 7624 7721 7581
+f 7624 7581 7495
+f 7495 7581 7441
+f 7495 7441 7371
+f 7371 7441 7359
+f 7371 7359 7261
+f 7261 7359 7239
+f 7261 7239 7051
+f 7051 7239 7011
+f 7051 7011 6870
+f 6870 7011 6867
+f 6870 6867 6792
+f 6792 6867 6777
+f 6792 6777 6613
+f 6613 6777 6687
+f 6613 6687 6519
+f 6519 6687 6505
+f 6519 6505 6367
+f 6367 6505 6402
+f 6367 6402 6241
+f 6241 6402 6319
+f 6241 6319 6185
+f 6185 6319 6133
+f 6185 6133 6065
+f 6065 6133 6028
+f 6065 6028 5848
+f 5848 6028 5855
+f 5848 5855 5687
+f 5687 5855 5793
+f 5687 5793 5671
+f 5671 5793 5657
+f 5671 5657 5499
+f 5499 5657 5473
+f 5499 5473 5313
+f 5313 5473 5339
+f 5313 5339 5269
+f 5269 5339 5201
+f 5269 5201 5121
+f 5121 5201 5056
+f 5121 5056 4993
+f 4993 5056 4925
+f 4993 4925 4867
+f 4867 4925 4877
+f 4867 4877 4677
+f 4677 4877 4667
+f 4677 4667 4563
+f 4563 4667 4509
+f 4563 4509 4399
+f 4399 4509 4451
+f 4399 4451 4265
+f 4265 4451 4243
+f 4265 4243 4187
+f 4187 4243 4157
+f 4187 4157 4069
+f 4069 4157 3973
+f 4069 3973 3893
+f 3893 3973 3923
+f 3893 3923 3749
+f 3749 3923 3741
+f 3749 3741 3575
+f 3575 3741 3663
+f 3575 3663 3555
+f 3555 3663 3443
+f 3555 3443 3390
+f 3390 3443 3373
+f 3390 3373 3279
+f 3279 3373 3233
+f 3279 3233 3077
+f 3077 3233 3149
+f 3077 3149 2957
+f 2957 3149 2995
+f 2957 2995 2801
+f 2801 2995 2843
+f 2801 2843 2661
+f 2661 2843 2663
+f 2661 2663 2507
+f 2507 2663 2543
+f 2507 2543 2473
+f 2473 2543 2387
+f 2473 2387 2217
+f 2217 2387 2337
+f 2217 2337 2179
+f 2179 2337 2173
+f 2179 2173 1971
+f 1971 2173 1961
+f 1971 1961 1867
+f 1867 1961 1911
+f 1867 1911 1793
+f 1793 1911 1749
+f 1793 1749 1595
+f 1595 1749 1587
+f 1595 1587 1513
+f 1513 1587 1563
+f 1513 1563 1335
+f 1335 1563 1425
+f 1335 1425 1201
+f 1201 1425 1247
+f 1201 1247 1163
+f 1163 1247 1181
+f 1163 1181 963
+f 963 1181 1029
+f 963 1029 835
+f 835 1029 829
+f 835 829 789
+f 789 829 685
+f 789 685 643
+f 643 685 615
+f 643 615 423
+f 423 615 493
+f 423 493 367
+f 367 493 373
+f 367 373 171
+f 171 373 237
+f 171 237 67
+f 67 237 109
+f 67 109 31
+f 7770 7831 7661
+f 7661 7831 7657
+f 7661 7657 7607
+f 7607 7657 7624
+f 7607 7624 7419
+f 7419 7624 7495
+f 7419 7495 7281
+f 7281 7495 7371
+f 7281 7371 7245
+f 7245 7371 7261
+f 7245 7261 7129
+f 7129 7261 7051
+f 7129 7051 6909
+f 6909 7051 6870
+f 6909 6870 6813
+f 6813 6870 6792
+f 6813 6792 6695
+f 6695 6792 6613
+f 6695 6613 6543
+f 6543 6613 6519
+f 6543 6519 6443
+f 6443 6519 6367
+f 6443 6367 6313
+f 6313 6367 6241
+f 6313 6241 6107
+f 6107 6241 6185
+f 6107 6185 5999
+f 5999 6185 6065
+f 5999 6065 5893
+f 5893 6065 5848
+f 5893 5848 5703
+f 5703 5848 5687
+f 5703 5687 5598
+f 5598 5687 5671
+f 5598 5671 5475
+f 5475 5671 5499
+f 5475 5499 5393
+f 5393 5499 5313
+f 5393 5313 5223
+f 5223 5313 5269
+f 5223 5269 5109
+f 5109 5269 5121
+f 5109 5121 4899
+f 4899 5121 4993
+f 4899 4993 4777
+f 4777 4993 4867
+f 4777 4867 4733
+f 4733 4867 4677
+f 4733 4677 4607
+f 4607 4677 4563
+f 4607 4563 4485
+f 4485 4563 4399
+f 4485 4399 4357
+f 4357 4399 4265
+f 4357 4265 4107
+f 4107 4265 4187
+f 4107 4187 4091
+f 4091 4187 4069
+f 4091 4069 3841
+f 3841 4069 3893
+f 3841 3893 3823
+f 3823 3893 3749
+f 3823 3749 3571
+f 3571 3749 3575
+f 3571 3575 3441
+f 3441 3575 3555
+f 3441 3555 3307
+f 3307 3555 3390
+f 3307 3390 3189
+f 3189 3390 3279
+f 3189 3279 3157
+f 3157 3279 3077
+f 3157 3077 3029
+f 3029 3077 2957
+f 3029 2957 2797
+f 2797 2957 2801
+f 2797 2801 2725
+f 2725 2801 2661
+f 2725 2661 2517
+f 2517 2661 2507
+f 2517 2507 2471
+f 2471 2507 2473
+f 2471 2473 2323
+f 2323 2473 2217
+f 2323 2217 2207
+f 2207 2217 2179
+f 2207 2179 1977
+f 1977 2179 1971
+f 1977 1971 1869
+f 1869 1971 1867
+f 1869 1867 1759
+f 1759 1867 1793
+f 1759 1793 1645
+f 1645 1793 1595
+f 1645 1595 1571
+f 1571 1595 1513
+f 1571 1513 1389
+f 1389 1513 1335
+f 1389 1335 1199
+f 1199 1335 1201
+f 1199 1201 1065
+f 1065 1201 1163
+f 1065 1163 997
+f 997 1163 963
+f 997 963 921
+f 921 963 835
+f 921 835 704
+f 704 835 789
+f 704 789 579
+f 579 789 643
+f 579 643 547
+f 547 643 423
+f 547 423 359
+f 359 423 367
+f 359 367 219
+f 219 367 171
+f 219 171 41
+f 41 171 67
+f 41 67 23
+f 7780 7770 7745
+f 7745 7770 7661
+f 7745 7661 7591
+f 7591 7661 7607
+f 7591 7607 7477
+f 7477 7607 7419
+f 7477 7419 7375
+f 7375 7419 7281
+f 7375 7281 7252
+f 7252 7281 7245
+f 7252 7245 7014
+f 7014 7245 7129
+f 7014 7129 6875
+f 6875 7129 6909
+f 6875 6909 6765
+f 6765 6909 6813
+f 6765 6813 6643
+f 6643 6813 6695
+f 6643 6695 6503
+f 6503 6695 6543
+f 6503 6543 6365
+f 6365 6543 6443
+f 6365 6443 6297
+f 6297 6443 6313
+f 6297 6313 6075
+f 6075 6313 6107
+f 6075 6107 6049
+f 6049 6107 5999
+f 6049 5999 5931
+f 5931 5999 5893
+f 5931 5893 5803
+f 5803 5893 5703
+f 5803 5703 5581
+f 5581 5703 5598
+f 5581 5598 5423
+f 5423 5598 5475
+f 5423 5475 5373
+f 5373 5475 5393
+f 5373 5393 5217
+f 5217 5393 5223
+f 5217 5223 5089
+f 5089 5223 5109
+f 5089 5109 4999
+f 4999 5109 4899
+f 4999 4899 4869
+f 4869 4899 4777
+f 4869 4777 4743
+f 4743 4777 4733
+f 4743 4733 4571
+f 4571 4733 4607
+f 4571 4607 4393
+f 4393 4607 4485
+f 4393 4485 4273
+f 4273 4485 4357
+f 4273 4357 4213
+f 4213 4357 4107
+f 4213 4107 4087
+f 4087 4107 4091
+f 4087 4091 3961
+f 3961 4091 3841
+f 3961 3841 3715
+f 3715 3841 3823
+f 3715 3823 3637
+f 3637 3823 3571
+f 3637 3571 3523
+f 3523 3571 3441
+f 3523 3441 3311
+f 3311 3441 3307
+f 3311 3307 3295
+f 3295 3307 3189
+f 3295 3189 3043
+f 3043 3189 3157
+f 3043 3157 2907
+f 2907 3157 3029
+f 2907 3029 2817
+f 2817 3029 2797
+f 2817 2797 2711
+f 2711 2797 2725
+f 2711 2725 2525
+f 2525 2725 2517
+f 2525 2517 2479
+f 2479 2517 2471
+f 2479 2471 2319
+f 2319 2471 2323
+f 2319 2323 2193
+f 2193 2323 2207
+f 2193 2207 1959
+f 1959 2207 1977
+f 1959 1977 1937
+f 1937 1977 1869
+f 1937 1869 1703
+f 1703 1869 1759
+f 1703 1759 1600
+f 1600 1759 1645
+f 1600 1645 1555
+f 1555 1645 1571
+f 1555 1571 1436
+f 1436 1571 1389
+f 1436 1389 1229
+f 1229 1389 1199
+f 1229 1199 1075
+f 1075 1199 1065
+f 1075 1065 1025
+f 1025 1065 997
+f 1025 997 870
+f 870 997 921
+f 870 921 743
+f 743 921 704
+f 743 704 645
+f 645 704 579
+f 645 579 429
+f 429 579 547
+f 429 547 299
+f 299 547 359
+f 299 359 165
+f 165 359 219
+f 165 219 161
+f 161 219 41
+f 161 41 23
+f 7790 7780 7709
+f 7709 7780 7745
+f 7709 7745 7595
+f 7595 7745 7591
+f 7595 7591 7480
+f 7480 7591 7477
+f 7480 7477 7351
+f 7351 7477 7375
+f 7351 7375 7211
+f 7211 7375 7252
+f 7211 7252 7101
+f 7101 7252 7014
+f 7101 7014 6883
+f 6883 7014 6875
+f 6883 6875 6821
+f 6821 6875 6765
+f 6821 6765 6625
+f 6625 6765 6643
+f 6625 6643 6575
+f 6575 6643 6503
+f 6575 6503 6415
+f 6415 6503 6365
+f 6415 6365 6213
+f 6213 6365 6297
+f 6213 6297 6123
+f 6123 6297 6075
+f 6123 6075 6007
+f 6007 6075 6049
+f 6007 6049 5917
+f 5917 6049 5931
+f 5917 5931 5775
+f 5775 5931 5803
+f 5775 5803 5627
+f 5627 5803 5581
+f 5627 5581 5525
+f 5525 5581 5423
+f 5525 5423 5307
+f 5307 5423 5373
+f 5307 5373 5230
+f 5230 5373 5217
+f 5230 5217 5037
+f 5037 5217 5089
+f 5037 5089 4949
+f 4949 5089 4999
+f 4949 4999 4815
+f 4815 4999 4869
+f 4815 4869 4699
+f 4699 4869 4743
+f 4699 4743 4597
+f 4597 4743 4571
+f 4597 4571 4407
+f 4407 4571 4393
+f 4407 4393 4317
+f 4317 4393 4273
+f 4317 4273 4141
+f 4141 4273 4213
+f 4141 4213 4039
+f 4039 4213 4087
+f 4039 4087 3887
+f 3887 4087 3961
+f 3887 3961 3765
+f 3765 3961 3715
+f 3765 3715 3597
+f 3597 3715 3637
+f 3597 3637 3518
+f 3518 3637 3523
+f 3518 3523 3318
+f 3318 3523 3311
+f 3318 3311 3230
+f 3230 3311 3295
+f 3230 3295 3121
+f 3121 3295 3043
+f 3121 3043 2991
+f 2991 3043 2907
+f 2991 2907 2882
+f 2882 2907 2817
+f 2882 2817 2667
+f 2667 2817 2711
+f 2667 2711 2611
+f 2611 2711 2525
+f 2611 2525 2377
+f 2377 2525 2479
+f 2377 2479 2232
+f 2232 2479 2319
+f 2232 2319 2125
+f 2125 2319 2193
+f 2125 2193 2049
+f 2049 2193 1959
+f 2049 1959 1886
+f 1886 1959 1937
+f 1886 1937 1726
+f 1726 1937 1703
+f 1726 1703 1577
+f 1577 1703 1600
+f 1577 1600 1561
+f 1561 1600 1555
+f 1561 1555 1415
+f 1415 1555 1436
+f 1415 1436 1197
+f 1197 1436 1229
+f 1197 1229 1087
+f 1087 1229 1075
+f 1087 1075 1043
+f 1043 1075 1025
+f 1043 1025 865
+f 865 1025 870
+f 865 870 683
+f 683 870 743
+f 683 743 613
+f 613 743 645
+f 613 645 545
+f 545 645 429
+f 545 429 334
+f 334 429 299
+f 334 299 283
+f 283 299 165
+f 283 165 104
+f 104 165 161
+f 104 161 24
+f 7841 7790 7751
+f 7751 7790 7709
+f 7751 7709 7589
+f 7589 7709 7595
+f 7589 7595 7501
+f 7501 7595 7480
+f 7501 7480 7295
+f 7295 7480 7351
+f 7295 7351 7214
+f 7214 7351 7211
+f 7214 7211 7073
+f 7073 7211 7101
+f 7073 7101 6925
+f 6925 7101 6883
+f 6925 6883 6811
+f 6811 6883 6821
+f 6811 6821 6707
+f 6707 6821 6625
+f 6707 6625 6531
+f 6531 6625 6575
+f 6531 6575 6387
+f 6387 6575 6415
+f 6387 6415 6321
+f 6321 6415 6213
+f 6321 6213 6111
+f 6111 6213 6123
+f 6111 6123 6035
+f 6035 6123 6007
+f 6035 6007 5902
+f 5902 6007 5917
+f 5902 5917 5736
+f 5736 5917 5775
+f 5736 5775 5557
+f 5557 5775 5627
+f 5557 5627 5467
+f 5467 5627 5525
+f 5467 5525 5337
+f 5337 5525 5307
+f 5337 5307 5195
+f 5195 5307 5230
+f 5195 5230 5066
+f 5066 5230 5037
+f 5066 5037 4963
+f 4963 5037 4949
+f 4963 4949 4879
+f 4879 4949 4815
+f 4879 4815 4721
+f 4721 4815 4699
+f 4721 4699 4577
+f 4577 4699 4597
+f 4577 4597 4389
+f 4389 4597 4407
+f 4389 4407 4259
+f 4259 4407 4317
+f 4259 4317 4153
+f 4153 4317 4141
+f 4153 4141 4059
+f 4059 4141 4039
+f 4059 4039 3865
+f 3865 4039 3887
+f 3865 3887 3747
+f 3747 3887 3765
+f 3747 3765 3648
+f 3648 3765 3597
+f 3648 3597 3525
+f 3525 3597 3518
+f 3525 3518 3303
+f 3303 3518 3318
+f 3303 3318 3190
+f 3190 3318 3230
+f 3190 3230 3165
+f 3165 3230 3121
+f 3165 3121 2929
+f 2929 3121 2991
+f 2929 2991 2869
+f 2869 2991 2882
+f 2869 2882 2697
+f 2697 2882 2667
+f 2697 2667 2569
+f 2569 2667 2611
+f 2569 2611 2391
+f 2391 2611 2377
+f 2391 2377 2295
+f 2295 2377 2232
+f 2295 2232 2183
+f 2183 2232 2125
+f 2183 2125 1985
+f 1985 2125 2049
+f 1985 2049 1837
+f 1837 2049 1886
+f 1837 1886 1705
+f 1705 1886 1726
+f 1705 1726 1584
+f 1584 1726 1577
+f 1584 1577 1543
+f 1543 1577 1561
+f 1543 1561 1353
+f 1353 1561 1415
+f 1353 1415 1191
+f 1191 1415 1197
+f 1191 1197 1185
+f 1185 1197 1087
+f 1185 1087 1052
+f 1052 1087 1043
+f 1052 1043 907
+f 907 1043 865
+f 907 865 795
+f 795 865 683
+f 795 683 561
+f 561 683 613
+f 561 613 524
+f 524 613 545
+f 524 545 356
+f 356 545 334
+f 356 334 183
+f 183 334 283
+f 183 283 37
+f 37 283 104
+f 37 104 24
+f 7850 7841 7653
+f 7653 7841 7751
+f 7653 7751 7577
+f 7577 7751 7589
+f 7577 7589 7469
+f 7469 7589 7501
+f 7469 7501 7373
+f 7373 7501 7295
+f 7373 7295 7175
+f 7175 7295 7214
+f 7175 7214 7017
+f 7017 7214 7073
+f 7017 7073 6969
+f 6969 7073 6925
+f 6969 6925 6731
+f 6731 6925 6811
+f 6731 6811 6619
+f 6619 6811 6707
+f 6619 6707 6529
+f 6529 6707 6531
+f 6529 6531 6349
+f 6349 6531 6387
+f 6349 6387 6295
+f 6295 6387 6321
+f 6295 6321 6177
+f 6177 6321 6111
+f 6177 6111 5991
+f 5991 6111 6035
+f 5991 6035 5907
+f 5907 6035 5902
+f 5907 5902 5779
+f 5779 5902 5736
+f 5779 5736 5595
+f 5595 5736 5557
+f 5595 5557 5431
+f 5431 5557 5467
+f 5431 5467 5377
+f 5377 5467 5337
+f 5377 5337 5193
+f 5193 5337 5195
+f 5193 5195 5123
+f 5123 5195 5066
+f 5123 5066 4943
+f 4943 5066 4963
+f 4943 4963 4873
+f 4873 4963 4879
+f 4873 4879 4693
+f 4693 4879 4721
+f 4693 4721 4595
+f 4595 4721 4577
+f 4595 4577 4383
+f 4383 4577 4389
+f 4383 4389 4329
+f 4329 4389 4259
+f 4329 4259 4221
+f 4221 4259 4153
+f 4221 4153 4053
+f 4053 4153 4059
+f 4053 4059 3857
+f 3857 4059 3865
+f 3857 3865 3811
+f 3811 3865 3747
+f 3811 3747 3691
+f 3691 3747 3648
+f 3691 3648 3497
+f 3497 3648 3525
+f 3497 3525 3393
+f 3393 3525 3303
+f 3393 3303 3213
+f 3213 3303 3190
+f 3213 3190 3141
+f 3141 3190 3165
+f 3141 3165 2937
+f 2937 3165 2929
+f 2937 2929 2894
+f 2894 2929 2869
+f 2894 2869 2665
+f 2665 2869 2697
+f 2665 2697 2505
+f 2505 2697 2569
+f 2505 2569 2435
+f 2435 2569 2391
+f 2435 2391 2219
+f 2219 2391 2295
+f 2219 2295 2205
+f 2205 2295 2183
+f 2205 2183 1989
+f 1989 2183 1985
+f 1989 1985 1843
+f 1843 1985 1837
+f 1843 1837 1769
+f 1769 1837 1705
+f 1769 1705 1693
+f 1693 1705 1584
+f 1693 1584 1455
+f 1455 1584 1543
+f 1455 1543 1327
+f 1327 1543 1353
+f 1327 1353 1279
+f 1279 1353 1191
+f 1279 1191 1145
+f 1145 1191 1185
+f 1145 1185 937
+f 937 1185 1052
+f 937 1052 855
+f 855 1052 907
+f 855 907 753
+f 753 907 795
+f 753 795 557
+f 557 795 561
+f 557 561 437
+f 437 561 524
+f 437 524 329
+f 329 524 356
+f 329 356 249
+f 249 356 183
+f 249 183 163
+f 163 183 37
+f 163 37 27
+f 5 27 164
+f 17 40 1
+f 7896 7861 7916
+f 7896 7878 7861
+f 7904 7808 7880
+f 7904 7919 7808
+f 7934 7866 7930
+f 7915 7858 7934
+f 62 14 1
+f 138 62 1
+f 138 1 40
+f 7932 7838 7915
+f 7903 7802 7932
+f 60 2 14
+f 98 60 14
+f 98 14 62
+f 7889 7791 7903
+f 7888 7788 7889
+f 94 7 2
+f 149 94 2
+f 149 2 60
+f 7928 7848 7888
+f 124 8 7
+f 124 7 94
+f 7882 7851 7928
+f 7921 7871 7882
+f 150 29 8
+f 150 8 142
+f 7922 7806 7921
+f 7933 7864 7922
+f 65 6 29
+f 48 65 29
+f 48 29 150
+f 7891 7862 7933
+f 7920 7800 7891
+f 84 30 6
+f 71 84 6
+f 71 6 65
+f 7909 7782 7920
+f 7892 7874 7909
+f 55 25 30
+f 160 55 30
+f 160 30 84
+f 7917 7821 7892
+f 105 11 25
+f 105 25 55
+f 7884 7828 7917
+f 7912 7822 7884
+f 96 21 11
+f 96 11 49
+f 7935 7796 7912
+f 7926 7764 7935
+f 116 4 21
+f 158 116 21
+f 158 21 96
+f 7902 7778 7926
+f 7908 7826 7902
+f 85 26 4
+f 117 85 4
+f 117 4 116
+f 7936 7814 7908
+f 7894 7846 7936
+f 86 33 26
+f 131 86 26
+f 131 26 85
+f 7916 7804 7894
+f 72 9 33
+f 72 33 86
+f 87 12 9
+f 87 9 132
+f 7138 7007 7031
+f 50 13 12
+f 6993 6989 6954
+f 6992 6922 6988
+f 106 28 13
+f 51 106 13
+f 51 13 50
+f 7133 7132 7005
+f 107 10 28
+f 7404 7386 7396
+f 133 32 10
+f 7808 7875 7880
+f 7900 7872 7919
+f 134 19 32
+f 134 32 156
+f 7906 7766 7900
+f 7898 7818 7906
+f 52 15 19
+f 66 52 19
+f 66 19 134
+f 7931 7868 7898
+f 7913 7768 7931
+f 118 3 15
+f 56 118 15
+f 56 15 52
+f 7927 7844 7913
+f 7883 7834 7927
+f 58 35 3
+f 88 58 3
+f 88 3 118
+f 7911 7776 7883
+f 75 36 35
+f 75 35 58
+f 7890 7810 7911
+f 7881 7774 7890
+f 136 34 36
+f 136 36 92
+f 7910 7771 7881
+f 7914 7840 7910
+f 140 16 34
+f 146 140 34
+f 146 34 136
+f 7893 7798 7914
+f 7923 7812 7893
+f 154 22 16
+f 126 154 16
+f 126 16 140
+f 7907 7856 7923
+f 7887 7854 7907
+f 144 18 22
+f 122 144 22
+f 122 22 154
+f 7895 7794 7887
+f 120 20 18
+f 120 18 144
+f 7925 7816 7895
+f 7886 7824 7925
+f 112 31 20
+f 112 20 100
+f 7924 7836 7886
+f 7929 7832 7924
+f 68 23 31
+f 110 68 31
+f 110 31 112
+f 7897 7772 7929
+f 7885 7783 7897
+f 162 24 23
+f 42 162 23
+f 42 23 68
+f 7905 7792 7885
+f 7918 7842 7905
+f 38 27 24
+f 108 38 24
+f 108 24 162
+f 164 27 38
+f 8 124 142
+f 11 105 49
+f 9 72 132
+f 7274 7358 7394
+f 7358 7402 7394
+f 6954 7003 6993
+f 6989 6985 6922
+f 6985 6984 6922
+f 6988 6922 6984
+f 7272 7392 7386
+f 7396 7386 7392
+f 32 133 156
+f 7516 7520 7576
+f 7759 7875 7808
+f 36 75 92
+f 20 120 100
+f 7124 7070 7195
+f 7124 7195 7266
+f 7124 7266 7146
+f 7124 7146 7142
+f 7124 7142 7138
+f 7124 7138 7031
+f 6901 6922 6992
+f 6901 6992 6995
+f 6901 6995 6997
+f 6901 6997 7005
+f 6901 7005 7132
+f 7091 7132 7133
+f 7091 7133 7135
+f 7091 7135 7140
+f 7091 7140 7143
+f 7091 7143 7147
+f 7091 7147 7253
+f 7091 7253 7071
+f 7901 7930 7784
+f 7784 7930 7830
+f 7784 7830 7702
+f 7702 7830 7698
+f 7702 7698 7543
+f 7543 7698 7604
+f 7543 7604 7512
+f 7512 7604 7506
+f 7512 7506 7307
+f 7307 7506 7380
+f 7307 7380 7158
+f 7158 7380 7222
+f 7158 7222 7015
+f 7015 7222 7022
+f 7015 7022 6982
+f 6982 7022 6952
+f 6982 6952 6850
+f 6850 6952 6800
+f 6850 6800 6637
+f 6637 6800 6596
+f 6637 6596 6481
+f 6481 6596 6572
+f 6481 6572 6446
+f 6446 6572 6460
+f 6446 6460 6289
+f 6289 6460 6232
+f 6289 6232 6200
+f 6200 6232 6106
+f 6200 6106 6041
+f 6041 6106 5972
+f 6041 5972 5912
+f 5912 5972 5866
+f 5912 5866 5796
+f 5796 5866 5730
+f 5796 5730 5574
+f 5574 5730 5622
+f 5574 5622 5487
+f 5487 5622 5466
+f 5487 5466 5311
+f 5311 5466 5404
+f 5311 5404 5164
+f 5164 5404 5170
+f 5164 5170 5024
+f 5024 5170 5140
+f 5024 5140 4921
+f 4921 5140 4972
+f 4921 4972 4842
+f 4842 4972 4772
+f 4842 4772 4754
+f 4754 4772 4652
+f 4754 4652 4523
+f 4523 4652 4502
+f 4523 4502 4473
+f 4473 4502 4488
+f 4473 4488 4335
+f 4335 4488 4232
+f 4335 4232 4104
+f 4104 4232 4128
+f 4104 4128 3982
+f 3982 4128 3990
+f 3982 3990 3946
+f 3946 3990 3944
+f 3946 3944 3826
+f 3826 3944 3786
+f 3826 3786 3594
+f 3594 3786 3696
+f 3594 3696 3446
+f 3446 3696 3566
+f 3446 3566 3382
+f 3382 3566 3410
+f 3382 3410 3298
+f 3298 3410 3252
+f 3298 3252 3088
+f 3088 3252 3156
+f 3088 3156 3012
+f 3012 3156 2924
+f 3012 2924 2775
+f 2775 2924 2898
+f 2775 2898 2757
+f 2757 2898 2738
+f 2757 2738 2610
+f 2610 2738 2624
+f 2610 2624 2411
+f 2411 2624 2464
+f 2411 2464 2340
+f 2340 2464 2224
+f 2340 2224 2160
+f 2160 2224 2212
+f 2160 2212 1969
+f 1969 2212 2068
+f 1969 2068 1832
+f 1832 2068 1908
+f 1832 1908 1775
+f 1775 1908 1724
+f 1775 1724 1627
+f 1627 1724 1620
+f 1627 1620 1469
+f 1469 1620 1534
+f 1469 1534 1442
+f 1442 1534 1340
+f 1442 1340 1267
+f 1267 1340 1234
+f 1267 1234 1120
+f 1120 1234 1180
+f 1120 1180 1023
+f 1023 1180 1040
+f 1023 1040 814
+f 814 1040 928
+f 814 928 719
+f 719 928 780
+f 719 780 584
+f 584 780 624
+f 584 624 444
+f 444 624 452
+f 444 452 294
+f 294 452 390
+f 294 390 254
+f 254 390 196
+f 254 196 89
+f 89 196 40
+f 89 40 17
+f 7402 7358 7518
+f 7518 7358 7429
+f 7518 7429 7522
+f 7522 7429 7580
+f 7522 7580 7637
+f 156 133 244
+f 244 133 245
+f 244 245 368
+f 368 245 383
+f 368 383 445
+f 445 383 456
+f 445 456 575
+f 575 456 663
+f 575 663 773
+f 773 663 728
+f 773 728 912
+f 912 728 871
+f 912 871 1038
+f 1038 871 952
+f 1038 952 1175
+f 1175 952 1184
+f 1175 1184 1307
+f 1307 1184 1228
+f 1307 1228 1443
+f 1443 1228 1444
+f 1443 1444 1465
+f 1465 1444 1510
+f 1465 1510 1580
+f 1580 1510 1653
+f 1580 1653 1800
+f 1800 1653 1709
+f 1800 1709 1876
+f 1876 1709 1883
+f 1876 1883 1958
+f 1958 1883 1964
+f 1958 1964 2196
+f 2196 1964 2187
+f 2196 2187 2300
+f 2300 2187 2239
+f 2300 2239 2412
+f 2412 2239 2396
+f 2412 2396 2568
+f 2568 2396 2592
+f 2568 2592 2642
+f 2642 2592 2718
+f 2642 2718 2814
+f 2814 2718 2865
+f 2814 2865 2950
+f 2950 2865 3023
+f 2950 3023 3065
+f 3065 3023 3110
+f 3065 3110 3278
+f 3278 3110 3284
+f 3278 3284 3419
+f 3419 3284 3330
+f 3419 3330 3479
+f 3479 3330 3544
+f 3479 3544 3600
+f 3600 3544 3613
+f 3600 3613 3806
+f 3806 3613 3752
+f 3806 3752 3919
+f 3919 3752 3866
+f 3919 3866 4084
+f 4084 3866 3996
+f 4084 3996 4194
+f 4194 3996 4216
+f 4194 4216 4290
+f 4290 4216 4240
+f 4290 4240 4387
+f 4387 4240 4437
+f 4387 4437 4567
+f 4567 4437 4516
+f 4567 4516 4728
+f 4728 4516 4690
+f 4728 4690 4798
+f 4798 4690 4858
+f 4798 4858 4909
+f 4909 4858 4942
+f 4909 4942 5054
+f 5054 4942 5118
+f 5054 5118 5221
+f 5221 5118 5231
+f 5221 5231 5290
+f 5290 5231 5332
+f 5290 5332 5490
+f 5490 5332 5456
+f 5490 5456 5650
+f 5650 5456 5584
+f 5650 5584 5706
+f 5706 5584 5792
+f 5706 5792 5924
+f 5924 5792 5844
+f 5924 5844 6042
+f 6042 5844 6058
+f 6042 6058 6181
+f 6181 6058 6116
+f 6181 6116 6304
+f 6304 6116 6204
+f 6304 6204 6360
+f 6360 6204 6375
+f 6360 6375 6496
+f 6496 6375 6532
+f 6496 6532 6716
+f 6716 6532 6718
+f 6716 6718 6843
+f 6843 6718 6803
+f 6843 6803 6881
+f 6881 6803 6862
+f 6881 6862 7042
+f 7042 6862 7071
+f 7042 7071 7156
+f 7156 7071 7253
+f 7156 7253 7312
+f 7312 7253 7386
+f 7312 7386 7516
+f 7516 7386 7404
+f 7516 7404 7520
+f 7918 7899 7852
+f 7852 7899 7786
+f 7852 7786 7654
+f 7654 7786 7736
+f 7654 7736 7578
+f 7578 7736 7568
+f 7578 7568 7471
+f 7471 7568 7490
+f 7471 7490 7374
+f 7374 7490 7340
+f 7374 7340 7178
+f 7178 7340 7152
+f 7178 7152 7019
+f 7019 7152 7094
+f 7019 7094 6970
+f 6970 7094 6915
+f 6970 6915 6732
+f 6732 6915 6749
+f 6732 6749 6620
+f 6620 6749 6609
+f 6620 6609 6533
+f 6533 6609 6574
+f 6533 6574 6350
+f 6350 6574 6416
+f 6350 6416 6296
+f 6296 6416 6239
+f 6296 6239 6182
+f 6182 6239 6082
+f 6182 6082 5992
+f 5992 6082 5964
+f 5992 5964 5913
+f 5913 5964 5814
+f 5913 5814 5780
+f 5780 5814 5699
+f 5780 5699 5596
+f 5596 5699 5555
+f 5596 5555 5432
+f 5432 5555 5516
+f 5432 5516 5379
+f 5379 5516 5410
+f 5379 5410 5194
+f 5194 5410 5245
+f 5194 5245 5124
+f 5124 5245 5036
+f 5124 5036 4944
+f 4944 5036 4998
+f 4944 4998 4875
+f 4875 4998 4834
+f 4875 4834 4695
+f 4695 4834 4642
+f 4695 4642 4596
+f 4596 4642 4592
+f 4596 4592 4384
+f 4384 4592 4425
+f 4384 4425 4330
+f 4330 4425 4302
+f 4330 4302 4222
+f 4222 4302 4176
+f 4222 4176 4054
+f 4054 4176 4029
+f 4054 4029 3859
+f 3859 4029 3913
+f 3859 3913 3812
+f 3812 3913 3784
+f 3812 3784 3692
+f 3692 3784 3645
+f 3692 3645 3499
+f 3499 3645 3535
+f 3499 3535 3394
+f 3394 3535 3328
+f 3394 3328 3214
+f 3214 3328 3177
+f 3214 3177 3143
+f 3143 3177 3134
+f 3143 3134 2939
+f 2939 3134 2932
+f 2939 2932 2895
+f 2895 2932 2896
+f 2895 2896 2666
+f 2666 2896 2706
+f 2666 2706 2506
+f 2506 2706 2522
+f 2506 2522 2436
+f 2436 2522 2420
+f 2436 2420 2220
+f 2220 2420 2285
+f 2220 2285 2206
+f 2206 2285 2188
+f 2206 2188 1990
+f 1990 2188 1970
+f 1990 1970 1847
+f 1847 1970 1884
+f 1847 1884 1770
+f 1770 1884 1766
+f 1770 1766 1695
+f 1695 1766 1601
+f 1695 1601 1456
+f 1456 1601 1552
+f 1456 1552 1328
+f 1328 1552 1354
+f 1328 1354 1280
+f 1280 1354 1287
+f 1280 1287 1148
+f 1148 1287 1078
+f 1148 1078 938
+f 938 1078 1009
+f 938 1009 858
+f 858 1009 877
+f 858 877 756
+f 756 877 764
+f 756 764 559
+f 559 764 576
+f 559 576 438
+f 438 576 528
+f 438 528 330
+f 330 528 338
+f 330 338 250
+f 250 338 292
+f 250 292 164
+f 164 292 76
+f 164 76 5
+f 138 40 240
+f 240 40 196
+f 240 196 388
+f 388 196 390
+f 388 390 500
+f 500 390 452
+f 500 452 556
+f 556 452 624
+f 556 624 724
+f 724 624 780
+f 724 780 930
+f 930 780 928
+f 930 928 1058
+f 1058 928 1040
+f 1058 1040 1102
+f 1102 1040 1180
+f 1102 1180 1304
+f 1304 1180 1234
+f 1304 1234 1402
+f 1402 1234 1340
+f 1402 1340 1476
+f 1476 1340 1534
+f 1476 1534 1690
+f 1690 1534 1620
+f 1690 1620 1798
+f 1798 1620 1724
+f 1798 1724 1880
+f 1880 1724 1908
+f 1880 1908 2054
+f 2054 1908 2068
+f 2054 2068 2106
+f 2106 2068 2212
+f 2106 2212 2270
+f 2270 2212 2224
+f 2270 2224 2386
+f 2386 2224 2464
+f 2386 2464 2532
+f 2532 2464 2624
+f 2532 2624 2754
+f 2754 2624 2738
+f 2754 2738 2828
+f 2828 2738 2898
+f 2828 2898 2934
+f 2934 2898 2924
+f 2934 2924 3116
+f 3116 2924 3156
+f 3116 3156 3294
+f 3294 3156 3252
+f 3294 3252 3376
+f 3376 3252 3410
+f 3376 3410 3564
+f 3564 3410 3566
+f 3564 3566 3658
+f 3658 3566 3696
+f 3658 3696 3740
+f 3740 3696 3786
+f 3740 3786 3936
+f 3936 3786 3944
+f 3936 3944 4036
+f 4036 3944 3990
+f 4036 3990 4210
+f 4210 3990 4128
+f 4210 4128 4320
+f 4320 4128 4232
+f 4320 4232 4382
+f 4382 4232 4488
+f 4382 4488 4556
+f 4556 4488 4502
+f 4556 4502 4672
+f 4672 4502 4652
+f 4672 4652 4850
+f 4850 4652 4772
+f 4850 4772 5014
+f 5014 4772 4972
+f 5014 4972 5126
+f 5126 4972 5140
+f 5126 5140 5200
+f 5200 5140 5170
+f 5200 5170 5288
+f 5288 5170 5404
+f 5288 5404 5528
+f 5528 5404 5466
+f 5528 5466 5668
+f 5668 5466 5622
+f 5668 5622 5754
+f 5754 5622 5730
+f 5754 5730 5812
+f 5812 5730 5866
+f 5812 5866 6018
+f 6018 5866 5972
+f 6018 5972 6174
+f 6174 5972 6106
+f 6174 6106 6260
+f 6260 6106 6232
+f 6260 6232 6420
+f 6420 6232 6460
+f 6420 6460 6548
+f 6548 6460 6572
+f 6548 6572 6618
+f 6618 6572 6596
+f 6618 6596 6818
+f 6818 6596 6800
+f 6818 6800 6874
+f 6874 6800 6952
+f 6874 6952 7028
+f 7028 6952 7022
+f 7028 7022 7182
+f 7182 7022 7222
+f 7182 7222 7364
+f 7364 7222 7380
+f 7364 7380 7416
+f 7416 7380 7506
+f 7416 7506 7530
+f 7530 7506 7604
+f 7530 7604 7666
+f 7666 7604 7698
+f 7666 7698 7866
+f 7866 7698 7830
+f 7866 7830 7930
+f 62 138 206
+f 206 138 240
+f 206 240 318
+f 318 240 388
+f 318 388 525
+f 525 388 500
+f 525 500 630
+f 630 500 556
+f 630 556 702
+f 702 556 724
+f 702 724 859
+f 859 724 930
+f 859 930 1028
+f 1028 930 1058
+f 1028 1058 1100
+f 1100 1058 1102
+f 1100 1102 1282
+f 1282 1102 1304
+f 1282 1304 1318
+f 1318 1304 1402
+f 1318 1402 1538
+f 1538 1402 1476
+f 1538 1476 1660
+f 1660 1476 1690
+f 1660 1690 1730
+f 1730 1690 1798
+f 1730 1798 1936
+f 1936 1798 1880
+f 1936 1880 2028
+f 2028 1880 2054
+f 2028 2054 2190
+f 2190 2054 2106
+f 2190 2106 2330
+f 2330 2106 2270
+f 2330 2270 2442
+f 2442 2270 2386
+f 2442 2386 2626
+f 2626 2386 2532
+f 2626 2532 2752
+f 2752 2532 2754
+f 2752 2754 2892
+f 2892 2754 2828
+f 2892 2828 2928
+f 2928 2828 2934
+f 2928 2934 3162
+f 3162 2934 3116
+f 3162 3116 3220
+f 3220 3116 3294
+f 3220 3294 3354
+f 3354 3294 3376
+f 3354 3376 3484
+f 3484 3376 3564
+f 3484 3564 3628
+f 3628 3564 3658
+f 3628 3658 3720
+f 3720 3658 3740
+f 3720 3740 3958
+f 3958 3740 3936
+f 3958 3936 4016
+f 4016 3936 4036
+f 4016 4036 4110
+f 4110 4036 4210
+f 4110 4210 4348
+f 4348 4210 4320
+f 4348 4320 4490
+f 4490 4320 4382
+f 4490 4382 4594
+f 4594 4382 4556
+f 4594 4556 4740
+f 4740 4556 4672
+f 4740 4672 4800
+f 4800 4672 4850
+f 4800 4850 5012
+f 5012 4850 5014
+f 5012 5014 5057
+f 5057 5014 5126
+f 5057 5126 5190
+f 5190 5126 5200
+f 5190 5200 5304
+f 5304 5200 5288
+f 5304 5288 5518
+f 5518 5288 5528
+f 5518 5528 5614
+f 5614 5528 5668
+f 5614 5668 5712
+f 5712 5668 5754
+f 5712 5754 5828
+f 5828 5754 5812
+f 5828 5812 5984
+f 5984 5812 6018
+f 5984 6018 6118
+f 6118 6018 6174
+f 6118 6174 6258
+f 6258 6174 6260
+f 6258 6260 6451
+f 6451 6260 6420
+f 6451 6420 6486
+f 6486 6420 6548
+f 6486 6548 6710
+f 6710 6548 6618
+f 6710 6618 6752
+f 6752 6618 6818
+f 6752 6818 6906
+f 6906 6818 6874
+f 6906 6874 7046
+f 7046 6874 7028
+f 7046 7028 7260
+f 7260 7028 7182
+f 7260 7182 7290
+f 7290 7182 7364
+f 7290 7364 7424
+f 7424 7364 7416
+f 7424 7416 7570
+f 7570 7416 7530
+f 7570 7530 7730
+f 7730 7530 7666
+f 7730 7666 7858
+f 7858 7666 7866
+f 7858 7866 7934
+f 98 62 261
+f 261 62 206
+f 261 206 378
+f 378 206 318
+f 378 318 428
+f 428 318 525
+f 428 525 589
+f 589 525 630
+f 589 630 802
+f 802 630 702
+f 802 702 824
+f 824 702 859
+f 824 859 946
+f 946 859 1028
+f 946 1028 1166
+f 1166 1028 1100
+f 1166 1100 1223
+f 1223 1100 1282
+f 1223 1282 1400
+f 1400 1282 1318
+f 1400 1318 1570
+f 1570 1318 1538
+f 1570 1538 1680
+f 1680 1538 1660
+f 1680 1660 1810
+f 1810 1660 1730
+f 1810 1730 1910
+f 1910 1730 1936
+f 1910 1936 2048
+f 2048 1936 2028
+f 2048 2028 2136
+f 2136 2028 2190
+f 2136 2190 2216
+f 2216 2190 2330
+f 2216 2330 2478
+f 2478 2330 2442
+f 2478 2442 2510
+f 2510 2442 2626
+f 2510 2626 2658
+f 2658 2626 2752
+f 2658 2752 2888
+f 2888 2752 2892
+f 2888 2892 3000
+f 3000 2892 2928
+f 3000 2928 3070
+f 3070 2928 3162
+f 3070 3162 3188
+f 3188 3162 3220
+f 3188 3220 3348
+f 3348 3220 3354
+f 3348 3354 3440
+f 3440 3354 3484
+f 3440 3484 3588
+f 3588 3484 3628
+f 3588 3628 3828
+f 3828 3628 3720
+f 3828 3720 3876
+f 3876 3720 3958
+f 3876 3958 3998
+f 3998 3958 4016
+f 3998 4016 4140
+f 4140 4016 4110
+f 4140 4110 4250
+f 4250 4110 4348
+f 4250 4348 4402
+f 4402 4348 4490
+f 4402 4490 4610
+f 4610 4490 4594
+f 4610 4594 4650
+f 4650 4594 4740
+f 4650 4740 4762
+f 4762 4740 4800
+f 4762 4800 4996
+f 4996 4800 5012
+f 4996 5012 5092
+f 5092 5012 5057
+f 5092 5057 5168
+f 5168 5057 5190
+f 5168 5190 5334
+f 5334 5190 5304
+f 5334 5304 5484
+f 5484 5304 5518
+f 5484 5518 5588
+f 5588 5518 5614
+f 5588 5614 5770
+f 5770 5614 5712
+f 5770 5712 5836
+f 5836 5712 5828
+f 5836 5828 5953
+f 5953 5828 5984
+f 5953 5984 6170
+f 6170 5984 6118
+f 6170 6118 6254
+f 6254 6118 6258
+f 6254 6258 6344
+f 6344 6258 6451
+f 6344 6451 6594
+f 6594 6451 6486
+f 6594 6486 6656
+f 6656 6486 6710
+f 6656 6710 6827
+f 6827 6710 6752
+f 6827 6752 6918
+f 6918 6752 6906
+f 6918 6906 7118
+f 7118 6906 7046
+f 7118 7046 7174
+f 7174 7046 7260
+f 7174 7260 7378
+f 7378 7260 7290
+f 7378 7290 7488
+f 7488 7290 7424
+f 7488 7424 7610
+f 7610 7424 7570
+f 7610 7570 7678
+f 7678 7570 7730
+f 7678 7730 7838
+f 7838 7730 7858
+f 7838 7858 7915
+f 60 98 278
+f 278 98 261
+f 278 261 298
+f 298 261 378
+f 298 378 488
+f 488 378 428
+f 488 428 610
+f 610 428 589
+f 610 589 712
+f 712 589 802
+f 712 802 822
+f 822 802 824
+f 822 824 1060
+f 1060 824 946
+f 1060 946 1140
+f 1140 946 1166
+f 1140 1166 1232
+f 1232 1166 1223
+f 1232 1223 1320
+f 1320 1223 1400
+f 1320 1400 1488
+f 1488 1400 1570
+f 1488 1570 1700
+f 1700 1570 1680
+f 1700 1680 1780
+f 1780 1680 1810
+f 1780 1810 1836
+f 1836 1810 1910
+f 1836 1910 1988
+f 1988 1910 2048
+f 1988 2048 2168
+f 2168 2048 2136
+f 2168 2136 2294
+f 2294 2136 2216
+f 2294 2216 2366
+f 2366 2216 2478
+f 2366 2478 2512
+f 2512 2478 2510
+f 2512 2510 2728
+f 2728 2510 2658
+f 2728 2658 2876
+f 2876 2658 2888
+f 2876 2888 3008
+f 3008 2888 3000
+f 3008 3000 3042
+f 3042 3000 3070
+f 3042 3070 3216
+f 3216 3070 3188
+f 3216 3188 3380
+f 3380 3188 3348
+f 3380 3348 3466
+f 3466 3348 3440
+f 3466 3440 3686
+f 3686 3440 3588
+f 3686 3588 3744
+f 3744 3588 3828
+f 3744 3828 3954
+f 3954 3828 3876
+f 3954 3876 4042
+f 4042 3876 3998
+f 4042 3998 4116
+f 4116 3998 4140
+f 4116 4140 4310
+f 4310 4140 4250
+f 4310 4250 4414
+f 4414 4250 4402
+f 4414 4402 4620
+f 4620 4402 4610
+f 4620 4610 4654
+f 4654 4610 4650
+f 4654 4650 4832
+f 4832 4650 4762
+f 4832 4762 4982
+f 4982 4762 4996
+f 4982 4996 5134
+f 5134 4996 5092
+f 5134 5092 5280
+f 5280 5092 5168
+f 5280 5168 5358
+f 5358 5168 5334
+f 5358 5334 5512
+f 5512 5334 5484
+f 5512 5484 5568
+f 5568 5484 5588
+f 5568 5588 5718
+f 5718 5588 5770
+f 5718 5770 5870
+f 5870 5770 5836
+f 5870 5836 5980
+f 5980 5836 5953
+f 5980 5953 6156
+f 6156 5953 6170
+f 6156 6170 6208
+f 6208 6170 6254
+f 6208 6254 6442
+f 6442 6254 6344
+f 6442 6344 6546
+f 6546 6344 6594
+f 6546 6594 6648
+f 6648 6594 6656
+f 6648 6656 6770
+f 6770 6656 6827
+f 6770 6827 6956
+f 6956 6827 6918
+f 6956 6918 7114
+f 7114 6918 7118
+f 7114 7118 7234
+f 7234 7118 7174
+f 7234 7174 7292
+f 7292 7174 7378
+f 7292 7378 7454
+f 7454 7378 7488
+f 7454 7488 7552
+f 7552 7488 7610
+f 7552 7610 7744
+f 7744 7610 7678
+f 7744 7678 7802
+f 7802 7678 7838
+f 7802 7838 7932
+f 149 60 190
+f 190 60 278
+f 190 278 304
+f 304 278 298
+f 304 298 538
+f 538 298 488
+f 538 488 592
+f 592 488 610
+f 592 610 705
+f 705 610 712
+f 705 712 894
+f 894 712 822
+f 894 822 1020
+f 1020 822 1060
+f 1020 1060 1080
+f 1080 1060 1140
+f 1080 1140 1268
+f 1268 1140 1232
+f 1268 1232 1355
+f 1355 1232 1320
+f 1355 1320 1496
+f 1496 1320 1488
+f 1496 1488 1632
+f 1632 1488 1700
+f 1632 1700 1826
+f 1826 1700 1780
+f 1826 1780 1905
+f 1905 1780 1836
+f 1905 1836 2060
+f 2060 1836 1988
+f 2060 1988 2108
+f 2108 1988 2168
+f 2108 2168 2336
+f 2336 2168 2294
+f 2336 2294 2376
+f 2376 2294 2366
+f 2376 2366 2614
+f 2614 2366 2512
+f 2614 2512 2730
+f 2730 2512 2728
+f 2730 2728 2784
+f 2784 2728 2876
+f 2784 2876 2914
+f 2914 2876 3008
+f 2914 3008 3060
+f 3060 3008 3042
+f 3060 3042 3180
+f 3180 3042 3216
+f 3180 3216 3398
+f 3398 3216 3380
+f 3398 3380 3492
+f 3492 3380 3466
+f 3492 3466 3580
+f 3580 3466 3686
+f 3580 3686 3816
+f 3816 3686 3744
+f 3816 3744 3928
+f 3928 3744 3954
+f 3928 3954 4065
+f 4065 3954 4042
+f 4065 4042 4152
+f 4152 4042 4116
+f 4152 4116 4276
+f 4276 4116 4310
+f 4276 4310 4470
+f 4470 4310 4414
+f 4470 4414 4544
+f 4544 4414 4620
+f 4544 4620 4674
+f 4674 4620 4654
+f 4674 4654 4766
+f 4766 4654 4832
+f 4766 4832 4940
+f 4940 4832 4982
+f 4940 4982 5052
+f 5052 4982 5134
+f 5052 5134 5234
+f 5234 5134 5280
+f 5234 5280 5364
+f 5364 5280 5358
+f 5364 5358 5434
+f 5434 5358 5512
+f 5434 5512 5594
+f 5594 5512 5568
+f 5594 5568 5790
+f 5790 5568 5718
+f 5790 5718 5849
+f 5849 5718 5870
+f 5849 5870 5970
+f 5970 5870 5980
+f 5970 5980 6188
+f 6188 5980 6156
+f 6188 6156 6266
+f 6266 6156 6208
+f 6266 6208 6448
+f 6448 6208 6442
+f 6448 6442 6528
+f 6528 6442 6546
+f 6528 6546 6634
+f 6634 6546 6648
+f 6634 6648 6796
+f 6796 6648 6770
+f 6796 6770 6940
+f 6940 6770 6956
+f 6940 6956 7084
+f 7084 6956 7114
+f 7084 7114 7179
+f 7179 7114 7234
+f 7179 7234 7316
+f 7316 7234 7292
+f 7316 7292 7476
+f 7476 7292 7454
+f 7476 7454 7524
+f 7524 7454 7552
+f 7524 7552 7705
+f 7705 7552 7744
+f 7705 7744 7791
+f 7791 7744 7802
+f 7791 7802 7903
+f 94 149 187
+f 187 149 190
+f 187 190 412
+f 412 190 304
+f 412 304 426
+f 426 304 538
+f 426 538 642
+f 642 538 592
+f 642 592 709
+f 709 592 705
+f 709 705 891
+f 891 705 894
+f 891 894 1050
+f 1050 894 1020
+f 1050 1020 1130
+f 1130 1020 1080
+f 1130 1080 1296
+f 1296 1080 1268
+f 1296 1268 1322
+f 1322 1268 1355
+f 1322 1355 1450
+f 1450 1355 1496
+f 1450 1496 1692
+f 1692 1496 1632
+f 1692 1632 1702
+f 1702 1632 1826
+f 1702 1826 1950
+f 1950 1826 1905
+f 1950 1905 1998
+f 1998 1905 2060
+f 1998 2060 2204
+f 2204 2060 2108
+f 2204 2108 2275
+f 2275 2108 2336
+f 2275 2336 2362
+f 2362 2336 2376
+f 2362 2376 2536
+f 2536 2376 2614
+f 2536 2614 2640
+f 2640 2614 2730
+f 2640 2730 2820
+f 2820 2730 2784
+f 2820 2784 3006
+f 3006 2784 2914
+f 3006 2914 3058
+f 3058 2914 3060
+f 3058 3060 3212
+f 3212 3060 3180
+f 3212 3180 3430
+f 3430 3180 3398
+f 3430 3398 3512
+f 3512 3398 3492
+f 3512 3492 3592
+f 3592 3492 3580
+f 3592 3580 3780
+f 3780 3580 3816
+f 3780 3816 3848
+f 3848 3816 3928
+f 3848 3928 4012
+f 4012 3928 4065
+f 4012 4065 4198
+f 4198 4065 4152
+f 4198 4152 4268
+f 4268 4152 4276
+f 4268 4276 4364
+f 4364 4276 4470
+f 4364 4470 4532
+f 4532 4470 4544
+f 4532 4544 4646
+f 4646 4544 4674
+f 4646 4674 4796
+f 4796 4674 4766
+f 4796 4766 4980
+f 4980 4766 4940
+f 4980 4940 5150
+f 5150 4940 5052
+f 5150 5052 5186
+f 5186 5052 5234
+f 5186 5234 5324
+f 5324 5234 5364
+f 5324 5364 5464
+f 5464 5364 5434
+f 5464 5434 5670
+f 5670 5434 5594
+f 5670 5594 5686
+f 5686 5594 5790
+f 5686 5790 5830
+f 5830 5790 5849
+f 5830 5849 6064
+f 6064 5849 5970
+f 6064 5970 6094
+f 6094 5970 6188
+f 6094 6188 6235
+f 6235 6188 6266
+f 6235 6266 6432
+f 6432 6266 6448
+f 6432 6448 6512
+f 6512 6448 6528
+f 6512 6528 6650
+f 6650 6528 6634
+f 6650 6634 6816
+f 6816 6634 6796
+f 6816 6796 6938
+f 6938 6796 6940
+f 6938 6940 7085
+f 7085 6940 7084
+f 7085 7084 7205
+f 7205 7084 7179
+f 7205 7179 7328
+f 7328 7179 7316
+f 7328 7316 7484
+f 7484 7316 7476
+f 7484 7476 7555
+f 7555 7476 7524
+f 7555 7524 7712
+f 7712 7524 7705
+f 7712 7705 7788
+f 7788 7705 7791
+f 7788 7791 7889
+f 124 94 290
+f 290 94 187
+f 290 187 314
+f 314 187 412
+f 314 412 536
+f 536 412 426
+f 536 426 599
+f 599 426 642
+f 599 642 720
+f 720 642 709
+f 720 709 808
+f 808 709 891
+f 808 891 996
+f 996 891 1050
+f 996 1050 1188
+f 1188 1050 1130
+f 1188 1130 1254
+f 1254 1130 1296
+f 1254 1296 1342
+f 1342 1296 1322
+f 1342 1322 1523
+f 1523 1322 1450
+f 1523 1450 1636
+f 1636 1450 1692
+f 1636 1692 1816
+f 1816 1692 1702
+f 1816 1702 1940
+f 1940 1702 1950
+f 1940 1950 1974
+f 1974 1950 1998
+f 1974 1998 2192
+f 2192 1998 2204
+f 2192 2204 2318
+f 2318 2204 2275
+f 2318 2275 2370
+f 2370 2275 2362
+f 2370 2362 2530
+f 2530 2362 2536
+f 2530 2536 2724
+f 2724 2536 2640
+f 2724 2640 2806
+f 2806 2640 2820
+f 2806 2820 2942
+f 2942 2820 3006
+f 2942 3006 3148
+f 3148 3006 3058
+f 3148 3058 3292
+f 3292 3058 3212
+f 3292 3212 3396
+f 3396 3212 3430
+f 3396 3430 3532
+f 3532 3430 3512
+f 3532 3512 3602
+f 3602 3512 3592
+f 3602 3592 3792
+f 3792 3592 3780
+f 3792 3780 3884
+f 3884 3780 3848
+f 3884 3848 4080
+f 4080 3848 4012
+f 4080 4012 4132
+f 4132 4012 4198
+f 4132 4198 4328
+f 4328 4198 4268
+f 4328 4268 4438
+f 4438 4268 4364
+f 4438 4364 4548
+f 4548 4364 4532
+f 4548 4532 4644
+f 4644 4532 4646
+f 4644 4646 4790
+f 4790 4646 4796
+f 4790 4796 4984
+f 4984 4796 4980
+f 4984 4980 5114
+f 5114 4980 5150
+f 5114 5150 5228
+f 5228 5150 5186
+f 5228 5186 5414
+f 5414 5186 5324
+f 5414 5324 5427
+f 5427 5324 5464
+f 5427 5464 5609
+f 5609 5464 5670
+f 5609 5670 5743
+f 5743 5670 5686
+f 5743 5686 5846
+f 5846 5686 5830
+f 5846 5830 6060
+f 6060 5830 6064
+f 6060 6064 6130
+f 6130 6064 6094
+f 6130 6094 6274
+f 6274 6094 6235
+f 6274 6235 6454
+f 6454 6235 6432
+f 6454 6432 6502
+f 6502 6432 6512
+f 6502 6512 6666
+f 6666 6512 6650
+f 6666 6650 6820
+f 6820 6650 6816
+f 6820 6816 6871
+f 6871 6816 6938
+f 6871 6938 7040
+f 7040 6938 7085
+f 7040 7085 7228
+f 7228 7085 7205
+f 7228 7205 7302
+f 7302 7205 7328
+f 7302 7328 7472
+f 7472 7328 7484
+f 7472 7484 7556
+f 7556 7484 7555
+f 7556 7555 7644
+f 7644 7555 7712
+f 7644 7712 7848
+f 7848 7712 7788
+f 7848 7788 7888
+f 142 124 266
+f 266 124 290
+f 266 290 335
+f 335 290 314
+f 335 314 432
+f 432 314 536
+f 432 536 604
+f 604 536 599
+f 604 599 726
+f 726 599 720
+f 726 720 830
+f 830 720 808
+f 830 808 1042
+f 1042 808 996
+f 1042 996 1107
+f 1107 996 1188
+f 1107 1188 1190
+f 1190 1188 1254
+f 1190 1254 1437
+f 1437 1254 1342
+f 1437 1342 1553
+f 1553 1342 1523
+f 1553 1523 1662
+f 1662 1523 1636
+f 1662 1636 1776
+f 1776 1636 1816
+f 1776 1816 1859
+f 1859 1816 1940
+f 1859 1940 1992
+f 1992 1940 1974
+f 1992 1974 2113
+f 2113 1974 2192
+f 2113 2192 2249
+f 2249 2192 2318
+f 2249 2318 2380
+f 2380 2318 2370
+f 2380 2370 2608
+f 2608 2370 2530
+f 2608 2530 2758
+f 2758 2530 2724
+f 2758 2724 2816
+f 2816 2724 2806
+f 2816 2806 2904
+f 2904 2806 2942
+f 2904 2942 3093
+f 3093 2942 3148
+f 3093 3148 3275
+f 3275 3148 3292
+f 3275 3292 3358
+f 3358 3292 3396
+f 3358 3396 3454
+f 3454 3396 3532
+f 3454 3532 3666
+f 3666 3532 3602
+f 3666 3602 3820
+f 3820 3602 3792
+f 3820 3792 3910
+f 3910 3792 3884
+f 3910 3884 4049
+f 4049 3884 4080
+f 4049 4080 4134
+f 4134 4080 4132
+f 4134 4132 4312
+f 4312 4132 4328
+f 4312 4328 4372
+f 4372 4328 4438
+f 4372 4438 4570
+f 4570 4438 4548
+f 4570 4548 4681
+f 4681 4548 4644
+f 4681 4644 4864
+f 4864 4644 4790
+f 4864 4790 4916
+f 4916 4790 4984
+f 4916 4984 5146
+f 5146 4984 5114
+f 5146 5114 5198
+f 5198 5114 5228
+f 5198 5228 5352
+f 5352 5228 5414
+f 5352 5414 5542
+f 5542 5414 5427
+f 5542 5427 5624
+f 5624 5427 5609
+f 5624 5609 5760
+f 5760 5609 5743
+f 5760 5743 5832
+f 5832 5743 5846
+f 5832 5846 6016
+f 6016 5846 6060
+f 6016 6060 6168
+f 6168 6060 6130
+f 6168 6130 6318
+f 6318 6130 6274
+f 6318 6274 6383
+f 6383 6274 6454
+f 6383 6454 6478
+f 6478 6454 6502
+f 6478 6502 6603
+f 6603 6502 6666
+f 6603 6666 6738
+f 6738 6666 6820
+f 6738 6820 6980
+f 6980 6820 6871
+f 6980 6871 7026
+f 7026 6871 7040
+f 7026 7040 7164
+f 7164 7040 7228
+f 7164 7228 7349
+f 7349 7228 7302
+f 7349 7302 7510
+f 7510 7302 7472
+f 7510 7472 7561
+f 7561 7472 7556
+f 7561 7556 7683
+f 7683 7556 7644
+f 7683 7644 7851
+f 7851 7644 7848
+f 7851 7848 7928
+f 150 142 227
+f 227 142 266
+f 227 266 316
+f 316 266 335
+f 316 335 512
+f 512 335 432
+f 512 432 600
+f 600 432 604
+f 600 604 804
+f 804 604 726
+f 804 726 881
+f 881 726 830
+f 881 830 1010
+f 1010 830 1042
+f 1010 1042 1073
+f 1073 1042 1107
+f 1073 1107 1214
+f 1214 1107 1190
+f 1214 1190 1345
+f 1345 1190 1437
+f 1345 1437 1536
+f 1536 1437 1553
+f 1536 1553 1613
+f 1613 1553 1662
+f 1613 1662 1785
+f 1785 1662 1776
+f 1785 1776 1906
+f 1906 1776 1859
+f 1906 1859 2017
+f 2017 1859 1992
+f 2017 1992 2176
+f 2176 1992 2113
+f 2176 2113 2254
+f 2254 2113 2249
+f 2254 2249 2372
+f 2372 2249 2380
+f 2372 2380 2500
+f 2500 2380 2608
+f 2500 2608 2638
+f 2638 2608 2758
+f 2638 2758 2781
+f 2781 2758 2816
+f 2781 2816 2918
+f 2918 2816 2904
+f 2918 2904 3152
+f 3152 2904 3093
+f 3152 3093 3260
+f 3260 3093 3275
+f 3260 3275 3420
+f 3420 3275 3358
+f 3420 3358 3490
+f 3490 3358 3454
+f 3490 3454 3698
+f 3698 3454 3666
+f 3698 3666 3797
+f 3797 3666 3820
+f 3797 3820 3872
+f 3872 3820 3910
+f 3872 3910 4062
+f 4062 3910 4049
+f 4062 4049 4137
+f 4137 4049 4134
+f 4137 4134 4242
+f 4242 4134 4312
+f 4242 4312 4458
+f 4458 4312 4372
+f 4458 4372 4504
+f 4504 4372 4570
+f 4504 4570 4682
+f 4682 4570 4681
+f 4682 4681 4782
+f 4782 4681 4864
+f 4782 4864 5003
+f 5003 4864 4916
+f 5003 4916 5029
+f 5029 4916 5146
+f 5029 5146 5278
+f 5278 5146 5198
+f 5278 5198 5296
+f 5296 5198 5352
+f 5296 5352 5530
+f 5530 5352 5542
+f 5530 5542 5602
+f 5602 5542 5624
+f 5602 5624 5778
+f 5778 5624 5760
+f 5778 5760 5840
+f 5840 5760 5832
+f 5840 5832 6010
+f 6010 5832 6016
+f 6010 6016 6088
+f 6088 6016 6168
+f 6088 6168 6307
+f 6307 6168 6318
+f 6307 6318 6376
+f 6376 6318 6383
+f 6376 6383 6497
+f 6497 6383 6478
+f 6497 6478 6654
+f 6654 6478 6603
+f 6654 6603 6746
+f 6746 6603 6738
+f 6746 6738 6976
+f 6976 6738 6980
+f 6976 6980 7020
+f 7020 6980 7026
+f 7020 7026 7238
+f 7238 7026 7164
+f 7238 7164 7334
+f 7334 7164 7349
+f 7334 7349 7412
+f 7412 7349 7510
+f 7412 7510 7594
+f 7594 7510 7561
+f 7594 7561 7728
+f 7728 7561 7683
+f 7728 7683 7871
+f 7871 7683 7851
+f 7871 7851 7882
+f 48 150 233
+f 233 150 227
+f 233 227 394
+f 394 227 316
+f 394 316 463
+f 463 316 512
+f 463 512 590
+f 590 512 600
+f 590 600 757
+f 757 600 804
+f 757 804 917
+f 917 804 881
+f 917 881 1035
+f 1035 881 1010
+f 1035 1010 1086
+f 1086 1010 1073
+f 1086 1073 1288
+f 1288 1073 1214
+f 1288 1214 1375
+f 1375 1214 1345
+f 1375 1345 1470
+f 1470 1345 1536
+f 1470 1536 1670
+f 1670 1536 1613
+f 1670 1613 1812
+f 1812 1613 1785
+f 1812 1785 1877
+f 1877 1785 1906
+f 1877 1906 2009
+f 2009 1906 2017
+f 2009 2017 2094
+f 2094 2017 2176
+f 2094 2176 2236
+f 2236 2176 2254
+f 2236 2254 2425
+f 2425 2254 2372
+f 2425 2372 2524
+f 2524 2372 2500
+f 2524 2500 2746
+f 2746 2500 2638
+f 2746 2638 2776
+f 2776 2638 2781
+f 2776 2781 3028
+f 3028 2781 2918
+f 3028 2918 3051
+f 3051 2918 3152
+f 3051 3152 3184
+f 3184 3152 3260
+f 3184 3260 3332
+f 3332 3260 3420
+f 3332 3420 3464
+f 3464 3420 3490
+f 3464 3490 3694
+f 3694 3490 3698
+f 3694 3698 3762
+f 3762 3698 3797
+f 3762 3797 3886
+f 3886 3797 3872
+f 3886 3872 4082
+f 4082 3872 4062
+f 4082 4062 4184
+f 4184 4062 4137
+f 4184 4137 4283
+f 4283 4137 4242
+f 4283 4242 4368
+f 4368 4242 4458
+f 4368 4458 4606
+f 4606 4458 4504
+f 4606 4504 4750
+f 4750 4504 4682
+f 4750 4682 4774
+f 4774 4682 4782
+f 4774 4782 4930
+f 4930 4782 5003
+f 4930 5003 5042
+f 5042 5003 5029
+f 5042 5029 5206
+f 5206 5029 5278
+f 5206 5278 5298
+f 5298 5278 5296
+f 5298 5296 5442
+f 5442 5296 5530
+f 5442 5530 5626
+f 5626 5530 5602
+f 5626 5602 5748
+f 5748 5602 5778
+f 5748 5778 5881
+f 5881 5778 5840
+f 5881 5840 6026
+f 6026 5840 6010
+f 6026 6010 6128
+f 6128 6010 6088
+f 6128 6088 6221
+f 6221 6088 6307
+f 6221 6307 6422
+f 6422 6307 6376
+f 6422 6376 6582
+f 6582 6376 6497
+f 6582 6497 6676
+f 6676 6497 6654
+f 6676 6654 6837
+f 6837 6654 6746
+f 6837 6746 6972
+f 6972 6746 6976
+f 6972 6976 7126
+f 7126 6976 7020
+f 7126 7020 7192
+f 7192 7020 7238
+f 7192 7238 7304
+f 7304 7238 7334
+f 7304 7334 7463
+f 7463 7334 7412
+f 7463 7412 7526
+f 7526 7412 7594
+f 7526 7594 7732
+f 7732 7594 7728
+f 7732 7728 7806
+f 7806 7728 7871
+f 7806 7871 7921
+f 65 48 280
+f 280 48 233
+f 280 233 343
+f 343 233 394
+f 343 394 540
+f 540 394 463
+f 540 463 628
+f 628 463 590
+f 628 590 758
+f 758 590 757
+f 758 757 812
+f 812 757 917
+f 812 917 1036
+f 1036 917 1035
+f 1036 1035 1097
+f 1097 1035 1086
+f 1097 1086 1274
+f 1274 1086 1288
+f 1274 1288 1398
+f 1398 1288 1375
+f 1398 1375 1461
+f 1461 1375 1470
+f 1461 1470 1696
+f 1696 1470 1670
+f 1696 1670 1744
+f 1744 1670 1812
+f 1744 1812 1944
+f 1944 1812 1877
+f 1944 1877 2018
+f 2018 1877 2009
+f 2018 2009 2090
+f 2090 2009 2094
+f 2090 2094 2272
+f 2272 2094 2236
+f 2272 2236 2468
+f 2468 2236 2425
+f 2468 2425 2578
+f 2578 2425 2524
+f 2578 2524 2660
+f 2660 2524 2746
+f 2660 2746 2778
+f 2778 2746 2776
+f 2778 2776 3018
+f 3018 2776 3028
+f 3018 3028 3090
+f 3090 3028 3051
+f 3090 3051 3290
+f 3290 3051 3184
+f 3290 3184 3406
+f 3406 3184 3332
+f 3406 3332 3541
+f 3541 3332 3464
+f 3541 3464 3604
+f 3604 3464 3694
+f 3604 3694 3768
+f 3768 3694 3762
+f 3768 3762 3949
+f 3949 3762 3886
+f 3949 3886 4002
+f 4002 3886 4082
+f 4002 4082 4169
+f 4169 4082 4184
+f 4169 4184 4336
+f 4336 4184 4283
+f 4336 4283 4422
+f 4422 4283 4368
+f 4422 4368 4526
+f 4526 4368 4606
+f 4526 4606 4658
+f 4658 4606 4750
+f 4658 4750 4852
+f 4852 4750 4774
+f 4852 4774 4932
+f 4932 4774 4930
+f 4932 4930 5034
+f 5034 4930 5042
+f 5034 5042 5262
+f 5262 5042 5206
+f 5262 5206 5380
+f 5380 5206 5298
+f 5380 5298 5462
+f 5462 5298 5442
+f 5462 5442 5580
+f 5580 5442 5626
+f 5580 5626 5787
+f 5787 5626 5748
+f 5787 5748 5914
+f 5914 5748 5881
+f 5914 5881 6012
+f 6012 5881 6026
+f 6012 6026 6090
+f 6090 6026 6128
+f 6090 6128 6301
+f 6301 6128 6221
+f 6301 6221 6456
+f 6456 6221 6422
+f 6456 6422 6578
+f 6578 6422 6582
+f 6578 6582 6661
+f 6661 6582 6676
+f 6661 6676 6742
+f 6742 6676 6837
+f 6742 6837 6864
+f 6864 6837 6972
+f 6864 6972 7062
+f 7062 6972 7126
+f 7062 7126 7187
+f 7187 7126 7192
+f 7187 7192 7368
+f 7368 7192 7304
+f 7368 7304 7430
+f 7430 7304 7463
+f 7430 7463 7598
+f 7598 7463 7526
+f 7598 7526 7742
+f 7742 7526 7732
+f 7742 7732 7864
+f 7864 7732 7806
+f 7864 7806 7922
+f 71 65 179
+f 179 65 280
+f 179 280 344
+f 344 280 343
+f 344 343 477
+f 477 343 540
+f 477 540 550
+f 550 540 628
+f 550 628 765
+f 765 628 758
+f 765 758 848
+f 848 758 812
+f 848 812 953
+f 953 812 1036
+f 953 1036 1074
+f 1074 1036 1097
+f 1074 1097 1297
+f 1297 1097 1274
+f 1297 1274 1421
+f 1421 1274 1398
+f 1421 1398 1481
+f 1481 1398 1461
+f 1481 1461 1686
+f 1686 1461 1696
+f 1686 1696 1755
+f 1755 1696 1744
+f 1755 1744 1860
+f 1860 1744 1944
+f 1860 1944 1999
+f 1999 1944 2018
+f 1999 2018 2161
+f 2161 2018 2090
+f 2161 2090 2262
+f 2262 2090 2272
+f 2262 2272 2470
+f 2470 2272 2468
+f 2470 2468 2586
+f 2586 2468 2578
+f 2586 2578 2682
+f 2682 2578 2660
+f 2682 2660 2878
+f 2878 2660 2778
+f 2878 2778 2922
+f 2922 2778 3018
+f 2922 3018 3094
+f 3094 3018 3090
+f 3094 3090 3254
+f 3254 3090 3290
+f 3254 3290 3403
+f 3403 3290 3406
+f 3403 3406 3519
+f 3519 3406 3541
+f 3519 3541 3619
+f 3619 3541 3604
+f 3619 3604 3800
+f 3800 3604 3768
+f 3800 3768 3862
+f 3862 3768 3949
+f 3862 3949 4010
+f 4010 3949 4002
+f 4010 4002 4202
+f 4202 4002 4169
+f 4202 4169 4284
+f 4284 4169 4336
+f 4284 4336 4388
+f 4388 4336 4422
+f 4388 4422 4578
+f 4578 4422 4526
+f 4578 4526 4632
+f 4632 4526 4658
+f 4632 4658 4793
+f 4793 4658 4852
+f 4793 4852 4960
+f 4960 4852 4932
+f 4960 4932 5144
+f 5144 4932 5034
+f 5144 5034 5182
+f 5182 5034 5262
+f 5182 5262 5322
+f 5322 5262 5380
+f 5322 5380 5522
+f 5522 5380 5462
+f 5522 5462 5645
+f 5645 5462 5580
+f 5645 5580 5757
+f 5757 5580 5787
+f 5757 5787 5822
+f 5822 5787 5914
+f 5822 5914 5958
+f 5958 5914 6012
+f 5958 6012 6148
+f 6148 6012 6090
+f 6148 6090 6250
+f 6250 6090 6301
+f 6250 6301 6408
+f 6408 6301 6456
+f 6408 6456 6588
+f 6588 6456 6578
+f 6588 6578 6700
+f 6700 6578 6661
+f 6700 6661 6854
+f 6854 6661 6742
+f 6854 6742 6932
+f 6932 6742 6864
+f 6932 6864 7116
+f 7116 6864 7062
+f 7116 7062 7168
+f 7168 7062 7187
+f 7168 7187 7287
+f 7287 7187 7368
+f 7287 7368 7474
+f 7474 7368 7430
+f 7474 7430 7618
+f 7618 7430 7598
+f 7618 7598 7646
+f 7646 7598 7742
+f 7646 7742 7862
+f 7862 7742 7864
+f 7862 7864 7933
+f 84 71 246
+f 246 71 179
+f 246 179 395
+f 395 179 344
+f 395 344 502
+f 502 344 477
+f 502 477 620
+f 620 477 550
+f 620 550 749
+f 749 550 765
+f 749 765 905
+f 905 765 848
+f 905 848 984
+f 984 848 953
+f 984 953 1156
+f 1156 953 1074
+f 1156 1074 1308
+f 1308 1074 1297
+f 1308 1297 1364
+f 1364 1297 1421
+f 1364 1421 1548
+f 1548 1421 1481
+f 1548 1481 1574
+f 1574 1481 1686
+f 1574 1686 1777
+f 1777 1686 1755
+f 1777 1755 1948
+f 1948 1755 1860
+f 1948 1860 1982
+f 1982 1860 1999
+f 1982 1999 2148
+f 2148 1999 2161
+f 2148 2161 2311
+f 2311 2161 2262
+f 2311 2262 2421
+f 2421 2262 2470
+f 2421 2470 2548
+f 2548 2470 2586
+f 2548 2586 2732
+f 2732 2586 2682
+f 2732 2682 2883
+f 2883 2682 2878
+f 2883 2878 2944
+f 2944 2878 2922
+f 2944 2922 3075
+f 3075 2922 3094
+f 3075 3094 3267
+f 3267 3094 3254
+f 3267 3254 3351
+f 3351 3254 3403
+f 3351 3403 3510
+f 3510 3403 3519
+f 3510 3519 3620
+f 3620 3519 3619
+f 3620 3619 3738
+f 3738 3619 3800
+f 3738 3800 3840
+f 3840 3800 3862
+f 3840 3862 3986
+f 3986 3862 4010
+f 3986 4010 4102
+f 4102 4010 4202
+f 4102 4202 4323
+f 4323 4202 4284
+f 4323 4284 4450
+f 4450 4284 4388
+f 4450 4388 4568
+f 4568 4388 4578
+f 4568 4578 4692
+f 4692 4578 4632
+f 4692 4632 4866
+f 4866 4632 4793
+f 4866 4793 4992
+f 4992 4793 4960
+f 4992 4960 5070
+f 5070 4960 5144
+f 5070 5144 5226
+f 5226 5144 5182
+f 5226 5182 5348
+f 5348 5182 5322
+f 5348 5322 5510
+f 5510 5322 5522
+f 5510 5522 5664
+f 5664 5522 5645
+f 5664 5645 5726
+f 5726 5645 5757
+f 5726 5757 5896
+f 5896 5757 5822
+f 5896 5822 5986
+f 5986 5822 5958
+f 5986 5958 6190
+f 6190 5958 6148
+f 6190 6148 6222
+f 6222 6148 6250
+f 6222 6250 6438
+f 6438 6250 6408
+f 6438 6408 6518
+f 6518 6408 6588
+f 6518 6588 6681
+f 6681 6588 6700
+f 6681 6700 6830
+f 6830 6700 6854
+f 6830 6854 6882
+f 6882 6854 6932
+f 6882 6932 7076
+f 7076 6932 7116
+f 7076 7116 7258
+f 7258 7116 7168
+f 7258 7168 7288
+f 7288 7168 7287
+f 7288 7287 7499
+f 7499 7287 7474
+f 7499 7474 7547
+f 7547 7474 7618
+f 7547 7618 7715
+f 7715 7618 7646
+f 7715 7646 7800
+f 7800 7646 7862
+f 7800 7862 7891
+f 160 84 216
+f 216 84 246
+f 216 246 357
+f 357 246 395
+f 357 395 492
+f 492 395 502
+f 492 502 664
+f 664 502 620
+f 664 620 698
+f 698 620 749
+f 698 749 838
+f 838 749 905
+f 838 905 1024
+f 1024 905 984
+f 1024 984 1121
+f 1121 984 1156
+f 1121 1156 1239
+f 1239 1156 1308
+f 1239 1308 1365
+f 1365 1308 1364
+f 1365 1364 1511
+f 1511 1364 1548
+f 1511 1548 1640
+f 1640 1548 1574
+f 1640 1574 1767
+f 1767 1574 1777
+f 1767 1777 1834
+f 1834 1777 1948
+f 1834 1948 2032
+f 2032 1948 1982
+f 2032 1982 2139
+f 2139 1982 2148
+f 2139 2148 2298
+f 2298 2148 2311
+f 2298 2311 2462
+f 2462 2311 2421
+f 2462 2421 2564
+f 2564 2421 2548
+f 2564 2548 2744
+f 2744 2548 2732
+f 2744 2732 2822
+f 2822 2732 2883
+f 2822 2883 3004
+f 3004 2883 2944
+f 3004 2944 3046
+f 3046 2944 3075
+f 3046 3075 3286
+f 3286 3075 3267
+f 3286 3267 3391
+f 3391 3267 3351
+f 3391 3351 3480
+f 3480 3351 3510
+f 3480 3510 3654
+f 3654 3510 3620
+f 3654 3620 3757
+f 3757 3620 3738
+f 3757 3738 3898
+f 3898 3738 3840
+f 3898 3840 4030
+f 4030 3840 3986
+f 4030 3986 4124
+f 4124 3986 4102
+f 4124 4102 4258
+f 4258 4102 4323
+f 4258 4323 4411
+f 4411 4323 4450
+f 4411 4450 4618
+f 4618 4450 4568
+f 4618 4568 4736
+f 4736 4568 4692
+f 4736 4692 4843
+f 4843 4692 4866
+f 4843 4866 5008
+f 5008 4866 4992
+f 5008 4992 5079
+f 5079 4992 5070
+f 5079 5070 5259
+f 5259 5070 5226
+f 5259 5226 5396
+f 5396 5226 5348
+f 5396 5348 5437
+f 5437 5348 5510
+f 5437 5510 5656
+f 5656 5510 5664
+f 5656 5664 5710
+f 5710 5664 5726
+f 5710 5726 5817
+f 5817 5726 5896
+f 5817 5896 5947
+f 5947 5896 5986
+f 5947 5986 6103
+f 6103 5986 6190
+f 6103 6190 6262
+f 6262 6190 6222
+f 6262 6222 6372
+f 6372 6222 6438
+f 6372 6438 6523
+f 6523 6438 6518
+f 6523 6518 6622
+f 6622 6518 6681
+f 6622 6681 6808
+f 6808 6681 6830
+f 6808 6830 6935
+f 6935 6830 6882
+f 6935 6882 7038
+f 7038 6882 7076
+f 7038 7076 7250
+f 7250 7076 7258
+f 7250 7258 7278
+f 7278 7258 7288
+f 7278 7288 7440
+f 7440 7288 7499
+f 7440 7499 7588
+f 7588 7499 7547
+f 7588 7547 7668
+f 7668 7547 7715
+f 7668 7715 7782
+f 7782 7715 7800
+f 7782 7800 7920
+f 55 160 234
+f 234 160 216
+f 234 216 416
+f 416 216 357
+f 416 357 542
+f 542 357 492
+f 542 492 585
+f 585 492 664
+f 585 664 799
+f 799 664 698
+f 799 698 906
+f 906 698 838
+f 906 838 954
+f 954 838 1024
+f 954 1024 1108
+f 1108 1024 1121
+f 1108 1121 1316
+f 1316 1121 1239
+f 1316 1239 1376
+f 1376 1239 1365
+f 1376 1365 1524
+f 1524 1365 1511
+f 1524 1511 1682
+f 1682 1511 1640
+f 1682 1640 1745
+f 1745 1640 1767
+f 1745 1767 1840
+f 1840 1767 1834
+f 1840 1834 2037
+f 2037 1834 2032
+f 2037 2032 2088
+f 2088 2032 2139
+f 2088 2139 2263
+f 2263 2139 2298
+f 2263 2298 2400
+f 2400 2298 2462
+f 2400 2462 2574
+f 2574 2462 2564
+f 2574 2564 2715
+f 2715 2564 2744
+f 2715 2744 2794
+f 2794 2744 2822
+f 2794 2822 3026
+f 3026 2822 3004
+f 3026 3004 3140
+f 3140 3004 3046
+f 3140 3046 3262
+f 3262 3046 3286
+f 3262 3286 3404
+f 3404 3286 3391
+f 3404 3391 3506
+f 3506 3391 3480
+f 3506 3480 3586
+f 3586 3480 3654
+f 3586 3654 3723
+f 3723 3654 3757
+f 3723 3757 3900
+f 3900 3757 3898
+f 3900 3898 4066
+f 4066 3898 4030
+f 4066 4030 4219
+f 4219 4030 4124
+f 4219 4124 4351
+f 4351 4124 4258
+f 4351 4258 4428
+f 4428 4258 4411
+f 4428 4411 4528
+f 4528 4411 4618
+f 4528 4618 4714
+f 4714 4618 4736
+f 4714 4736 4820
+f 4820 4736 4843
+f 4820 4843 4910
+f 4910 4843 5008
+f 4910 5008 5030
+f 5030 5008 5079
+f 5030 5079 5192
+f 5192 5079 5259
+f 5192 5259 5350
+f 5350 5259 5396
+f 5350 5396 5480
+f 5480 5396 5437
+f 5480 5437 5660
+f 5660 5437 5656
+f 5660 5656 5702
+f 5702 5656 5710
+f 5702 5710 5925
+f 5925 5710 5817
+f 5925 5817 6056
+f 6056 5817 5947
+f 6056 5947 6080
+f 6080 5947 6103
+f 6080 6103 6225
+f 6225 6103 6262
+f 6225 6262 6439
+f 6439 6262 6372
+f 6439 6372 6468
+f 6468 6372 6523
+f 6468 6523 6682
+f 6682 6523 6622
+f 6682 6622 6804
+f 6804 6622 6808
+f 6804 6808 6965
+f 6965 6808 6935
+f 6965 6935 7096
+f 7096 6935 7038
+f 7096 7038 7256
+f 7256 7038 7250
+f 7256 7250 7362
+f 7362 7250 7278
+f 7362 7278 7422
+f 7422 7278 7440
+f 7422 7440 7625
+f 7625 7440 7588
+f 7625 7588 7720
+f 7720 7588 7668
+f 7720 7668 7874
+f 7874 7668 7782
+f 7874 7782 7909
+f 105 55 175
+f 175 55 234
+f 175 234 296
+f 296 234 416
+f 296 416 506
+f 506 416 542
+f 506 542 635
+f 635 542 585
+f 635 585 800
+f 800 585 799
+f 800 799 918
+f 918 799 906
+f 918 906 1032
+f 1032 906 954
+f 1032 954 1092
+f 1092 954 1108
+f 1092 1108 1195
+f 1195 1108 1316
+f 1195 1316 1428
+f 1428 1316 1376
+f 1428 1376 1458
+f 1458 1376 1524
+f 1458 1524 1628
+f 1628 1524 1682
+f 1628 1682 1746
+f 1746 1682 1745
+f 1746 1745 1861
+f 1861 1745 1840
+f 1861 1840 2043
+f 2043 1840 2037
+f 2043 2037 2162
+f 2162 2037 2088
+f 2162 2088 2281
+f 2281 2088 2263
+f 2281 2263 2432
+f 2432 2263 2400
+f 2432 2400 2581
+f 2581 2400 2574
+f 2581 2574 2694
+f 2694 2574 2715
+f 2694 2715 2808
+f 2808 2715 2794
+f 2808 2794 2963
+f 2963 2794 3026
+f 2963 3026 3066
+f 3066 3026 3140
+f 3066 3140 3246
+f 3246 3140 3262
+f 3246 3262 3386
+f 3386 3262 3404
+f 3386 3404 3529
+f 3529 3404 3506
+f 3529 3506 3578
+f 3578 3506 3586
+f 3578 3586 3802
+f 3802 3586 3723
+f 3802 3723 3880
+f 3880 3723 3900
+f 3880 3900 4026
+f 4026 3900 4066
+f 4026 4066 4204
+f 4204 4066 4219
+f 4204 4219 4300
+f 4300 4219 4351
+f 4300 4351 4374
+f 4374 4351 4428
+f 4374 4428 4579
+f 4579 4428 4528
+f 4579 4528 4630
+f 4630 4528 4714
+f 4630 4714 4794
+f 4794 4714 4820
+f 4794 4820 4918
+f 4918 4820 4910
+f 4918 4910 5067
+f 5067 4910 5030
+f 5067 5030 5246
+f 5246 5030 5192
+f 5246 5192 5355
+f 5355 5192 5350
+f 5355 5350 5536
+f 5536 5350 5480
+f 5536 5480 5592
+f 5592 5480 5660
+f 5592 5660 5788
+f 5788 5660 5702
+f 5788 5702 5852
+f 5852 5702 5925
+f 5852 5925 5975
+f 5975 5925 6056
+f 5975 6056 6160
+f 6160 6056 6080
+f 6160 6080 6218
+f 6218 6080 6225
+f 6218 6225 6462
+f 6462 6225 6439
+f 6462 6439 6592
+f 6592 6439 6468
+f 6592 6468 6714
+f 6714 6468 6682
+f 6714 6682 6762
+f 6762 6682 6804
+f 6762 6804 6966
+f 6966 6804 6965
+f 6966 6965 7056
+f 7056 6965 7096
+f 7056 7096 7180
+f 7180 7096 7256
+f 7180 7256 7324
+f 7324 7256 7362
+f 7324 7362 7500
+f 7500 7362 7422
+f 7500 7422 7630
+f 7630 7422 7625
+f 7630 7625 7673
+f 7673 7625 7720
+f 7673 7720 7821
+f 7821 7720 7874
+f 7821 7874 7892
+f 49 105 282
+f 282 105 175
+f 282 175 384
+f 384 175 296
+f 384 296 497
+f 497 296 506
+f 497 506 665
+f 665 506 635
+f 665 635 774
+f 774 635 800
+f 774 800 932
+f 932 800 918
+f 932 918 993
+f 993 918 1032
+f 993 1032 1176
+f 1176 1032 1092
+f 1176 1092 1257
+f 1257 1092 1195
+f 1257 1195 1409
+f 1409 1195 1428
+f 1409 1428 1489
+f 1489 1428 1458
+f 1489 1458 1629
+f 1629 1458 1628
+f 1629 1628 1756
+f 1756 1628 1746
+f 1756 1746 1920
+f 1920 1746 1861
+f 1920 1861 1976
+f 1976 1861 2043
+f 1976 2043 2131
+f 2131 2043 2162
+f 2131 2162 2233
+f 2233 2162 2281
+f 2233 2281 2453
+f 2453 2281 2432
+f 2453 2432 2604
+f 2604 2432 2581
+f 2604 2581 2716
+f 2716 2581 2694
+f 2716 2694 2826
+f 2826 2694 2808
+f 2826 2808 3024
+f 3024 2808 2963
+f 3024 2963 3154
+f 3154 2963 3066
+f 3154 3066 3196
+f 3196 3066 3246
+f 3196 3246 3371
+f 3371 3246 3386
+f 3371 3386 3451
+f 3451 3386 3529
+f 3451 3529 3582
+f 3582 3529 3578
+f 3582 3578 3788
+f 3788 3578 3802
+f 3788 3802 3907
+f 3907 3802 3880
+f 3907 3880 4068
+f 4068 3880 4026
+f 4068 4026 4180
+f 4180 4026 4204
+f 4180 4204 4286
+f 4286 4204 4300
+f 4286 4300 4406
+f 4406 4300 4374
+f 4406 4374 4582
+f 4582 4374 4579
+f 4582 4579 4662
+f 4662 4579 4630
+f 4662 4630 4812
+f 4812 4630 4794
+f 4812 4794 4947
+f 4947 4794 4918
+f 4947 4918 5061
+f 5061 4918 5067
+f 5061 5067 5240
+f 5240 5067 5246
+f 5240 5246 5389
+f 5389 5246 5355
+f 5389 5355 5507
+f 5507 5355 5536
+f 5507 5536 5590
+f 5590 5536 5592
+f 5590 5592 5720
+f 5720 5592 5788
+f 5720 5788 5884
+f 5884 5788 5852
+f 5884 5852 5954
+f 5954 5852 5975
+f 5954 5975 6176
+f 6176 5975 6160
+f 6176 6160 6245
+f 6245 6160 6218
+f 6245 6218 6338
+f 6338 6218 6462
+f 6338 6462 6498
+f 6498 6462 6592
+f 6498 6592 6624
+f 6624 6592 6714
+f 6624 6714 6730
+f 6730 6714 6762
+f 6730 6762 6908
+f 6908 6762 6966
+f 6908 6966 7024
+f 7024 6966 7056
+f 7024 7056 7171
+f 7171 7056 7180
+f 7171 7180 7350
+f 7350 7180 7324
+f 7350 7324 7459
+f 7459 7324 7500
+f 7459 7500 7540
+f 7540 7500 7630
+f 7540 7630 7684
+f 7684 7630 7673
+f 7684 7673 7828
+f 7828 7673 7821
+f 7828 7821 7917
+f 96 49 170
+f 170 49 282
+f 170 282 417
+f 417 282 384
+f 417 384 483
+f 483 384 497
+f 483 497 612
+f 612 497 665
+f 612 665 750
+f 750 665 774
+f 750 774 849
+f 849 774 932
+f 849 932 961
+f 961 932 993
+f 961 993 1169
+f 1169 993 1176
+f 1169 1176 1269
+f 1269 1176 1257
+f 1269 1257 1330
+f 1330 1257 1409
+f 1330 1409 1497
+f 1497 1409 1489
+f 1497 1489 1592
+f 1592 1489 1629
+f 1592 1629 1757
+f 1757 1629 1756
+f 1757 1756 1848
+f 1848 1756 1920
+f 1848 1920 2019
+f 2019 1920 1976
+f 2019 1976 2114
+f 2114 1976 2131
+f 2114 2131 2250
+f 2250 2131 2233
+f 2250 2233 2426
+f 2426 2233 2453
+f 2426 2453 2582
+f 2582 2453 2604
+f 2582 2604 2700
+f 2700 2604 2716
+f 2700 2716 2857
+f 2857 2716 2826
+f 2857 2826 2920
+f 2920 2826 3024
+f 2920 3024 3146
+f 3146 3024 3154
+f 3146 3154 3203
+f 3203 3154 3196
+f 3203 3196 3334
+f 3334 3196 3371
+f 3334 3371 3514
+f 3514 3371 3451
+f 3514 3451 3614
+f 3614 3451 3582
+f 3614 3582 3728
+f 3728 3582 3788
+f 3728 3788 3956
+f 3956 3788 3907
+f 3956 3907 3993
+f 3993 3907 4068
+f 3993 4068 4212
+f 4212 4068 4180
+f 4212 4180 4324
+f 4324 4180 4286
+f 4324 4286 4454
+f 4454 4286 4406
+f 4454 4406 4602
+f 4602 4406 4582
+f 4602 4582 4634
+f 4634 4582 4662
+f 4634 4662 4807
+f 4807 4662 4812
+f 4807 4812 4896
+f 4896 4812 4947
+f 4896 4947 5137
+f 5137 4947 5061
+f 5137 5061 5282
+f 5282 5061 5240
+f 5282 5240 5406
+f 5406 5240 5389
+f 5406 5389 5545
+f 5545 5389 5507
+f 5545 5507 5564
+f 5564 5507 5590
+f 5564 5590 5691
+f 5691 5590 5720
+f 5691 5720 5915
+f 5915 5720 5884
+f 5915 5884 6034
+f 6034 5884 5954
+f 6034 5954 6166
+f 6166 5954 6176
+f 6166 6176 6228
+f 6228 6176 6245
+f 6228 6245 6392
+f 6392 6245 6338
+f 6392 6338 6492
+f 6492 6338 6498
+f 6492 6498 6629
+f 6629 6498 6624
+f 6629 6624 6833
+f 6833 6624 6730
+f 6833 6730 6902
+f 6902 6730 6908
+f 6902 6908 7128
+f 7128 6908 7024
+f 7128 7024 7150
+f 7150 7024 7171
+f 7150 7171 7390
+f 7390 7171 7350
+f 7390 7350 7467
+f 7467 7350 7459
+f 7467 7459 7634
+f 7634 7459 7540
+f 7634 7540 7691
+f 7691 7540 7684
+f 7691 7684 7822
+f 7822 7684 7828
+f 7822 7828 7884
+f 158 96 262
+f 262 96 170
+f 262 170 369
+f 369 170 417
+f 369 417 518
+f 518 417 483
+f 518 483 601
+f 601 483 612
+f 601 612 775
+f 775 612 750
+f 775 750 850
+f 850 750 849
+f 850 849 980
+f 980 849 961
+f 980 961 1093
+f 1093 961 1169
+f 1093 1169 1289
+f 1289 1169 1269
+f 1289 1269 1424
+f 1424 1269 1330
+f 1424 1330 1541
+f 1541 1330 1497
+f 1541 1497 1607
+f 1607 1497 1592
+f 1607 1592 1735
+f 1735 1592 1757
+f 1735 1757 1894
+f 1894 1757 1848
+f 1894 1848 1983
+f 1983 1848 2019
+f 1983 2019 2171
+f 2171 2019 2114
+f 2171 2114 2222
+f 2222 2114 2250
+f 2222 2250 2433
+f 2433 2250 2426
+f 2433 2426 2549
+f 2549 2426 2582
+f 2549 2582 2707
+f 2707 2582 2700
+f 2707 2700 2861
+f 2861 2700 2857
+f 2861 2857 2990
+f 2990 2857 2920
+f 2990 2920 3100
+f 3100 2920 3146
+f 3100 3146 3200
+f 3200 3146 3203
+f 3200 3203 3310
+f 3310 3203 3334
+f 3310 3334 3474
+f 3474 3334 3514
+f 3474 3514 3649
+f 3649 3514 3614
+f 3649 3614 3771
+f 3771 3614 3728
+f 3771 3728 3891
+f 3891 3728 3956
+f 3891 3956 4023
+f 4023 3956 3993
+f 4023 3993 4114
+f 4114 3993 4212
+f 4114 4212 4252
+f 4252 4212 4324
+f 4252 4324 4430
+f 4430 4324 4454
+f 4430 4454 4562
+f 4562 4454 4602
+f 4562 4602 4702
+f 4702 4602 4634
+f 4702 4634 4823
+f 4823 4634 4807
+f 4823 4807 4952
+f 4952 4807 4896
+f 4952 4896 5100
+f 5100 4896 5137
+f 5100 5137 5215
+f 5215 5137 5282
+f 5215 5282 5326
+f 5326 5282 5406
+f 5326 5406 5430
+f 5430 5406 5545
+f 5430 5545 5616
+f 5616 5545 5564
+f 5616 5564 5716
+f 5716 5564 5691
+f 5716 5691 5926
+f 5926 5691 5915
+f 5926 5915 5976
+f 5976 5915 6034
+f 5976 6034 6172
+f 6172 6034 6166
+f 6172 6166 6246
+f 6246 6166 6228
+f 6246 6228 6364
+f 6364 6228 6392
+f 6364 6392 6524
+f 6524 6392 6492
+f 6524 6492 6693
+f 6693 6492 6629
+f 6693 6629 6768
+f 6768 6629 6833
+f 6768 6833 6949
+f 6949 6833 6902
+f 6949 6902 7044
+f 7044 6902 7128
+f 7044 7128 7196
+f 7196 7128 7150
+f 7196 7150 7341
+f 7341 7150 7390
+f 7341 7390 7433
+f 7433 7390 7467
+f 7433 7467 7565
+f 7565 7467 7634
+f 7565 7634 7748
+f 7748 7634 7691
+f 7748 7691 7796
+f 7796 7691 7822
+f 7796 7822 7912
+f 116 158 192
+f 192 158 262
+f 192 262 312
+f 312 262 369
+f 312 369 457
+f 457 369 518
+f 457 518 577
+f 577 518 601
+f 577 601 699
+f 699 601 775
+f 699 775 913
+f 913 775 850
+f 913 850 970
+f 970 850 980
+f 970 980 1122
+f 1122 980 1093
+f 1122 1093 1209
+f 1209 1093 1289
+f 1209 1289 1338
+f 1338 1289 1424
+f 1338 1424 1525
+f 1525 1424 1541
+f 1525 1541 1687
+f 1687 1541 1607
+f 1687 1607 1736
+f 1736 1607 1735
+f 1736 1735 1921
+f 1921 1735 1894
+f 1921 1894 2044
+f 2044 1894 1983
+f 2044 1983 2132
+f 2132 1983 2171
+f 2132 2171 2290
+f 2290 2171 2222
+f 2290 2222 2454
+f 2454 2222 2433
+f 2454 2433 2575
+f 2575 2433 2549
+f 2575 2549 2677
+f 2677 2549 2707
+f 2677 2707 2835
+f 2835 2707 2861
+f 2835 2861 2978
+f 2978 2861 2990
+f 2978 2990 3111
+f 3111 2990 3100
+f 3111 3100 3208
+f 3208 3100 3200
+f 3208 3200 3422
+f 3422 3200 3310
+f 3422 3310 3561
+f 3561 3310 3474
+f 3561 3474 3672
+f 3672 3474 3649
+f 3672 3649 3713
+f 3713 3649 3771
+f 3713 3771 3856
+f 3856 3771 3891
+f 3856 3891 4020
+f 4020 3891 4023
+f 4020 4023 4138
+f 4138 4023 4114
+f 4138 4114 4315
+f 4315 4114 4252
+f 4315 4252 4432
+f 4432 4252 4430
+f 4432 4430 4546
+f 4546 4430 4562
+f 4546 4562 4707
+f 4707 4562 4702
+f 4707 4702 4787
+f 4787 4702 4823
+f 4787 4823 5010
+f 5010 4823 4952
+f 5010 4952 5062
+f 5062 4952 5100
+f 5062 5100 5174
+f 5174 5100 5215
+f 5174 5215 5390
+f 5390 5215 5326
+f 5390 5326 5497
+f 5497 5326 5430
+f 5497 5430 5556
+f 5556 5430 5616
+f 5556 5616 5680
+f 5680 5616 5716
+f 5680 5716 5818
+f 5818 5716 5926
+f 5818 5926 6029
+f 6029 5926 5976
+f 6029 5976 6136
+f 6136 5976 6172
+f 6136 6172 6226
+f 6226 6172 6246
+f 6226 6246 6384
+f 6384 6246 6364
+f 6384 6364 6482
+f 6482 6364 6524
+f 6482 6524 6720
+f 6720 6524 6693
+f 6720 6693 6773
+f 6773 6693 6768
+f 6773 6768 6892
+f 6892 6768 6949
+f 6892 6949 7092
+f 7092 6949 7044
+f 7092 7044 7230
+f 7230 7044 7196
+f 7230 7196 7314
+f 7314 7196 7341
+f 7314 7341 7414
+f 7414 7341 7433
+f 7414 7433 7550
+f 7550 7433 7565
+f 7550 7565 7692
+f 7692 7565 7748
+f 7692 7748 7764
+f 7764 7748 7796
+f 7764 7796 7935
+f 117 116 255
+f 255 116 192
+f 255 192 353
+f 353 192 312
+f 353 312 467
+f 467 312 457
+f 467 457 554
+f 554 457 577
+f 554 577 693
+f 693 577 699
+f 693 699 851
+f 851 699 913
+f 851 913 1047
+f 1047 913 970
+f 1047 970 1094
+f 1094 970 1122
+f 1094 1122 1240
+f 1240 1122 1209
+f 1240 1209 1356
+f 1356 1209 1338
+f 1356 1338 1568
+f 1568 1338 1525
+f 1568 1525 1654
+f 1654 1525 1687
+f 1654 1687 1821
+f 1821 1687 1736
+f 1821 1736 1849
+f 1849 1736 1921
+f 1849 1921 2020
+f 2020 1921 2044
+f 2020 2044 2115
+f 2115 2044 2132
+f 2115 2132 2302
+f 2302 2132 2290
+f 2302 2290 2459
+f 2459 2290 2454
+f 2459 2454 2556
+f 2556 2454 2575
+f 2556 2575 2678
+f 2678 2575 2677
+f 2678 2677 2836
+f 2836 2677 2835
+f 2836 2835 2970
+f 2970 2835 2978
+f 2970 2978 3127
+f 3127 2978 3111
+f 3127 3111 3271
+f 3271 3111 3208
+f 3271 3208 3341
+f 3341 3208 3422
+f 3341 3422 3448
+f 3448 3422 3561
+f 3448 3561 3668
+f 3668 3561 3672
+f 3668 3672 3818
+f 3818 3672 3713
+f 3818 3713 3940
+f 3940 3713 3856
+f 3940 3856 4072
+f 4072 3856 4020
+f 4072 4020 4195
+f 4195 4020 4138
+f 4195 4138 4256
+f 4256 4138 4315
+f 4256 4315 4448
+f 4448 4315 4432
+f 4448 4432 4520
+f 4520 4432 4546
+f 4520 4546 4688
+f 4688 4546 4707
+f 4688 4707 4886
+f 4886 4707 4787
+f 4886 4787 4892
+f 4892 4787 5010
+f 4892 5010 5094
+f 5094 5010 5062
+f 5094 5062 5180
+f 5180 5062 5174
+f 5180 5174 5408
+f 5408 5174 5390
+f 5408 5390 5498
+f 5498 5390 5497
+f 5498 5497 5642
+f 5642 5497 5556
+f 5642 5556 5763
+f 5763 5556 5680
+f 5763 5680 5928
+f 5928 5680 5818
+f 5928 5818 6054
+f 6054 5818 6029
+f 6054 6029 6195
+f 6195 6029 6136
+f 6195 6136 6308
+f 6308 6136 6226
+f 6308 6226 6427
+f 6427 6226 6384
+f 6427 6384 6562
+f 6562 6384 6482
+f 6562 6482 6662
+f 6662 6482 6720
+f 6662 6720 6756
+f 6756 6720 6773
+f 6756 6773 6903
+f 6903 6773 6892
+f 6903 6892 7110
+f 7110 6892 7092
+f 7110 7092 7162
+f 7162 7092 7230
+f 7162 7230 7329
+f 7329 7230 7314
+f 7329 7314 7418
+f 7418 7314 7414
+f 7418 7414 7533
+f 7533 7414 7550
+f 7533 7550 7706
+f 7706 7550 7692
+f 7706 7692 7778
+f 7778 7692 7764
+f 7778 7764 7926
+f 85 117 271
+f 271 117 255
+f 271 255 370
+f 370 255 353
+f 370 353 484
+f 484 353 467
+f 484 467 636
+f 636 467 554
+f 636 554 784
+f 784 554 693
+f 784 693 852
+f 852 693 851
+f 852 851 1003
+f 1003 851 1047
+f 1003 1047 1123
+f 1123 1047 1094
+f 1123 1094 1196
+f 1196 1094 1240
+f 1196 1240 1390
+f 1390 1240 1356
+f 1390 1356 1526
+f 1526 1356 1568
+f 1526 1568 1593
+f 1593 1568 1654
+f 1593 1654 1715
+f 1715 1654 1821
+f 1715 1821 1895
+f 1895 1821 1849
+f 1895 1849 2063
+f 2063 1849 2020
+f 2063 2020 2092
+f 2092 2020 2115
+f 2092 2115 2264
+f 2264 2115 2302
+f 2264 2302 2413
+f 2413 2302 2459
+f 2413 2459 2576
+f 2576 2459 2556
+f 2576 2556 2670
+f 2670 2556 2678
+f 2670 2678 2824
+f 2824 2678 2836
+f 2824 2836 2971
+f 2971 2836 2970
+f 2971 2970 3112
+f 3112 2970 3127
+f 3112 3127 3228
+f 3228 3127 3271
+f 3228 3271 3356
+f 3356 3271 3341
+f 3356 3341 3470
+f 3470 3341 3448
+f 3470 3448 3596
+f 3596 3448 3668
+f 3596 3668 3732
+f 3732 3668 3818
+f 3732 3818 3941
+f 3941 3818 3940
+f 3941 3940 4076
+f 4076 3940 4072
+f 4076 4072 4177
+f 4177 4072 4195
+f 4177 4195 4297
+f 4297 4195 4256
+f 4297 4256 4464
+f 4464 4256 4448
+f 4464 4448 4538
+f 4538 4448 4520
+f 4538 4520 4708
+f 4708 4520 4688
+f 4708 4688 4882
+f 4882 4688 4886
+f 4882 4886 5006
+f 5006 4886 4892
+f 5006 4892 5045
+f 5045 4892 5094
+f 5045 5094 5210
+f 5210 5094 5180
+f 5210 5180 5370
+f 5370 5180 5408
+f 5370 5408 5428
+f 5428 5408 5498
+f 5428 5498 5586
+f 5586 5498 5642
+f 5586 5642 5734
+f 5734 5642 5763
+f 5734 5763 5930
+f 5930 5763 5928
+f 5930 5928 5982
+f 5982 5928 6054
+f 5982 6054 6202
+f 6202 6054 6195
+f 6202 6195 6316
+f 6316 6195 6308
+f 6316 6308 6340
+f 6340 6308 6427
+f 6340 6427 6589
+f 6589 6427 6562
+f 6589 6562 6685
+f 6685 6562 6662
+f 6685 6662 6750
+f 6750 6662 6756
+f 6750 6756 6930
+f 6930 6756 6903
+f 6930 6903 7072
+f 7072 6903 7110
+f 7072 7110 7220
+f 7220 7110 7162
+f 7220 7162 7330
+f 7330 7162 7329
+f 7330 7329 7444
+f 7444 7329 7418
+f 7444 7418 7600
+f 7600 7418 7533
+f 7600 7533 7716
+f 7716 7533 7706
+f 7716 7706 7826
+f 7826 7706 7778
+f 7826 7778 7902
+f 131 85 180
+f 180 85 271
+f 180 271 322
+f 322 271 370
+f 322 370 435
+f 435 370 484
+f 435 484 654
+f 654 484 636
+f 654 636 680
+f 680 636 784
+f 680 784 831
+f 831 784 852
+f 831 852 1053
+f 1053 852 1003
+f 1053 1003 1141
+f 1141 1003 1123
+f 1141 1123 1270
+f 1270 1123 1196
+f 1270 1196 1326
+f 1326 1196 1390
+f 1326 1390 1527
+f 1527 1390 1526
+f 1527 1526 1576
+f 1576 1526 1593
+f 1576 1593 1719
+f 1719 1593 1715
+f 1719 1715 1922
+f 1922 1715 1895
+f 1922 1895 2072
+f 2072 1895 2063
+f 2072 2063 2202
+f 2202 2063 2092
+f 2202 2092 2265
+f 2265 2092 2264
+f 2265 2264 2414
+f 2414 2264 2413
+f 2414 2413 2601
+f 2601 2413 2576
+f 2601 2576 2708
+f 2708 2576 2670
+f 2708 2670 2850
+f 2850 2670 2824
+f 2850 2824 2979
+f 2979 2824 2971
+f 2979 2971 3128
+f 3128 2971 3112
+f 3128 3112 3238
+f 3238 3112 3228
+f 3238 3228 3352
+f 3352 3228 3356
+f 3352 3356 3452
+f 3452 3356 3470
+f 3452 3470 3632
+f 3632 3470 3596
+f 3632 3596 3709
+f 3709 3596 3732
+f 3709 3732 3942
+f 3942 3732 3941
+f 3942 3941 3977
+f 3977 3941 4076
+f 3977 4076 4220
+f 4220 4076 4177
+f 4220 4177 4304
+f 4304 4177 4297
+f 4304 4297 4439
+f 4439 4297 4464
+f 4439 4464 4506
+f 4506 4464 4538
+f 4506 4538 4670
+f 4670 4538 4708
+f 4670 4708 4848
+f 4848 4708 4882
+f 4848 4882 4978
+f 4978 4882 5006
+f 4978 5006 5142
+f 5142 5006 5045
+f 5142 5045 5157
+f 5157 5045 5210
+f 5157 5210 5293
+f 5293 5210 5370
+f 5293 5370 5481
+f 5481 5370 5428
+f 5481 5428 5630
+f 5630 5428 5586
+f 5630 5586 5682
+f 5682 5586 5734
+f 5682 5734 5916
+f 5916 5734 5930
+f 5916 5930 6062
+f 6062 5930 5982
+f 6062 5982 6161
+f 6161 5982 6202
+f 6161 6202 6290
+f 6290 6202 6316
+f 6290 6316 6428
+f 6428 6316 6340
+f 6428 6340 6514
+f 6514 6340 6589
+f 6514 6589 6694
+f 6694 6589 6685
+f 6694 6685 6809
+f 6809 6685 6750
+f 6809 6750 6950
+f 6950 6750 6930
+f 6950 6930 7064
+f 7064 6930 7072
+f 7064 7072 7172
+f 7172 7072 7220
+f 7172 7220 7366
+f 7366 7220 7330
+f 7366 7330 7468
+f 7468 7330 7444
+f 7468 7444 7534
+f 7534 7444 7600
+f 7534 7600 7660
+f 7660 7600 7716
+f 7660 7716 7814
+f 7814 7716 7826
+f 7814 7826 7908
+f 86 131 235
+f 235 131 180
+f 235 180 418
+f 418 180 322
+f 418 322 532
+f 532 322 435
+f 532 435 655
+f 655 435 654
+f 655 654 721
+f 721 654 680
+f 721 680 872
+f 872 680 831
+f 872 831 940
+f 940 831 1053
+f 940 1053 1142
+f 1142 1053 1141
+f 1142 1141 1217
+f 1217 1141 1270
+f 1217 1270 1391
+f 1391 1270 1326
+f 1391 1326 1542
+f 1542 1326 1527
+f 1542 1527 1655
+f 1655 1527 1576
+f 1655 1576 1806
+f 1806 1576 1719
+f 1806 1719 1896
+f 1896 1719 1922
+f 1896 1922 2045
+f 2045 1922 2072
+f 2045 2072 2086
+f 2086 2072 2202
+f 2086 2202 2240
+f 2240 2202 2265
+f 2240 2265 2460
+f 2460 2265 2414
+f 2460 2414 2557
+f 2557 2414 2601
+f 2557 2601 2686
+f 2686 2601 2708
+f 2686 2708 2851
+f 2851 2708 2850
+f 2851 2850 2986
+f 2986 2850 2979
+f 2986 2979 3113
+f 3113 2979 3128
+f 3113 3128 3239
+f 3239 3128 3238
+f 3239 3238 3364
+f 3364 3238 3352
+f 3364 3352 3488
+f 3488 3352 3452
+f 3488 3452 3610
+f 3610 3452 3632
+f 3610 3632 3726
+f 3726 3632 3709
+f 3726 3709 3920
+f 3920 3709 3942
+f 3920 3942 3978
+f 3978 3942 3977
+f 3978 3977 4149
+f 4149 3977 4220
+f 4149 4220 4294
+f 4294 4220 4304
+f 4294 4304 4426
+f 4426 4304 4439
+f 4426 4439 4622
+f 4622 4439 4506
+f 4622 4506 4656
+f 4656 4506 4670
+f 4656 4670 4872
+f 4872 4670 4848
+f 4872 4848 4968
+f 4968 4848 4978
+f 4968 4978 5032
+f 5032 4978 5142
+f 5032 5142 5241
+f 5241 5142 5157
+f 5241 5157 5336
+f 5336 5157 5293
+f 5336 5293 5524
+f 5524 5293 5481
+f 5524 5481 5619
+f 5619 5481 5630
+f 5619 5630 5764
+f 5764 5630 5682
+f 5764 5682 5936
+f 5936 5682 5916
+f 5936 5916 6068
+f 6068 5916 6062
+f 6068 6062 6183
+f 6183 6062 6161
+f 6183 6161 6311
+f 6311 6161 6290
+f 6311 6290 6417
+f 6417 6290 6428
+f 6417 6428 6471
+f 6471 6428 6514
+f 6471 6514 6610
+f 6610 6514 6694
+f 6610 6694 6757
+f 6757 6694 6809
+f 6757 6809 6923
+f 6923 6809 6950
+f 6923 6950 7032
+f 7032 6950 7064
+f 7032 7064 7264
+f 7264 7064 7172
+f 7264 7172 7342
+f 7342 7172 7366
+f 7342 7366 7460
+f 7460 7366 7468
+f 7460 7468 7562
+f 7562 7468 7534
+f 7562 7534 7738
+f 7738 7534 7660
+f 7738 7660 7846
+f 7846 7660 7814
+f 7846 7814 7936
+f 72 86 209
+f 209 86 235
+f 209 235 323
+f 323 235 418
+f 323 418 533
+f 533 418 532
+f 533 532 670
+f 670 532 655
+f 670 655 739
+f 739 655 721
+f 739 721 832
+f 832 721 872
+f 832 872 987
+f 987 872 940
+f 987 940 1124
+f 1124 940 1142
+f 1124 1142 1241
+f 1241 1142 1217
+f 1241 1217 1392
+f 1392 1217 1391
+f 1392 1391 1559
+f 1559 1391 1542
+f 1559 1542 1594
+f 1594 1542 1655
+f 1594 1655 1807
+f 1807 1655 1806
+f 1807 1806 1933
+f 1933 1806 1896
+f 1933 1896 2077
+f 2077 1896 2045
+f 2077 2045 2133
+f 2133 2045 2086
+f 2133 2086 2291
+f 2291 2086 2240
+f 2291 2240 2415
+f 2415 2240 2460
+f 2415 2460 2602
+f 2602 2460 2557
+f 2602 2557 2687
+f 2687 2557 2686
+f 2687 2686 2841
+f 2841 2686 2851
+f 2841 2851 2964
+f 2964 2851 2986
+f 2964 2986 3114
+f 3114 2986 3113
+f 3114 3113 3222
+f 3222 3113 3239
+f 3222 3239 3345
+f 3345 3239 3364
+f 3345 3364 3536
+f 3536 3364 3488
+f 3536 3488 3625
+f 3625 3488 3610
+f 3625 3610 3710
+f 3710 3610 3726
+f 3710 3726 3934
+f 3934 3726 3920
+f 3934 3920 4024
+f 4024 3920 3978
+f 4024 3978 4119
+f 4119 3978 4149
+f 4119 4149 4298
+f 4298 4149 4294
+f 4298 4294 4366
+f 4366 4294 4426
+f 4366 4426 4616
+f 4616 4426 4622
+f 4616 4622 4725
+f 4725 4622 4656
+f 4725 4656 4838
+f 4838 4656 4872
+f 4838 4872 4956
+f 4956 4872 4968
+f 4956 4968 5046
+f 5046 4968 5032
+f 5046 5032 5250
+f 5250 5032 5241
+f 5250 5241 5360
+f 5360 5241 5336
+f 5360 5336 5482
+f 5482 5336 5524
+f 5482 5524 5678
+f 5678 5524 5619
+f 5678 5619 5783
+f 5783 5619 5764
+f 5783 5764 5854
+f 5854 5764 5936
+f 5854 5936 6021
+f 6021 5936 6068
+f 6021 6068 6149
+f 6149 6068 6183
+f 6149 6183 6211
+f 6211 6183 6311
+f 6211 6311 6429
+f 6429 6311 6417
+f 6429 6417 6570
+f 6570 6417 6471
+f 6570 6471 6642
+f 6642 6471 6610
+f 6642 6610 6728
+f 6728 6610 6757
+f 6728 6757 6856
+f 6856 6757 6923
+f 6856 6923 7010
+f 7010 6923 7032
+f 7010 7032 7244
+f 7244 7032 7264
+f 7244 7264 7308
+f 7308 7264 7342
+f 7308 7342 7486
+f 7486 7342 7460
+f 7486 7460 7548
+f 7548 7460 7562
+f 7548 7562 7696
+f 7696 7562 7738
+f 7696 7738 7804
+f 7804 7738 7846
+f 7804 7846 7894
+f 132 72 210
+f 210 72 209
+f 210 209 324
+f 324 209 323
+f 324 323 436
+f 436 323 533
+f 436 533 586
+f 586 533 670
+f 586 670 740
+f 740 670 739
+f 740 739 898
+f 898 739 832
+f 898 832 971
+f 971 832 987
+f 971 987 1161
+f 1161 987 1124
+f 1161 1124 1218
+f 1218 1124 1241
+f 1218 1241 1393
+f 1393 1241 1392
+f 1393 1392 1498
+f 1498 1392 1559
+f 1498 1559 1630
+f 1630 1559 1594
+f 1630 1594 1737
+f 1737 1594 1807
+f 1737 1807 1897
+f 1897 1807 1933
+f 1897 1933 2078
+f 2078 1933 2077
+f 2078 2077 2163
+f 2163 2077 2133
+f 2163 2133 2266
+f 2266 2133 2291
+f 2266 2291 2390
+f 2390 2291 2415
+f 2390 2415 2597
+f 2597 2415 2602
+f 2597 2602 2695
+f 2695 2602 2687
+f 2695 2687 2837
+f 2837 2687 2841
+f 2837 2841 2974
+f 2974 2841 2964
+f 2974 2964 3103
+f 3103 2964 3114
+f 3103 3114 3231
+f 3231 3114 3222
+f 3231 3222 3365
+f 3365 3222 3345
+f 3365 3345 3522
+f 3522 3345 3536
+f 3522 3536 3676
+f 3676 3536 3625
+f 3676 3625 3774
+f 3774 3625 3710
+f 3774 3710 3914
+f 3914 3710 3934
+f 3914 3934 4032
+f 4032 3934 4024
+f 4032 4024 4178
+f 4178 4024 4119
+f 4178 4119 4352
+f 4352 4119 4298
+f 4352 4298 4412
+f 4412 4298 4366
+f 4412 4366 4530
+f 4530 4366 4616
+f 4530 4616 4732
+f 4732 4616 4725
+f 4732 4725 4884
+f 4884 4725 4838
+f 4884 4838 4986
+f 4986 4838 4956
+f 4986 4956 5098
+f 5098 4956 5046
+f 5098 5046 5216
+f 5216 5046 5250
+f 5216 5250 5412
+f 5412 5250 5360
+f 5412 5360 5488
+f 5488 5360 5482
+f 5488 5482 5610
+f 5610 5482 5678
+f 5610 5678 5692
+f 5692 5678 5783
+f 5692 5783 5891
+f 5891 5783 5854
+f 5891 5854 5995
+f 5995 5854 6021
+f 5995 6021 6184
+f 6184 6021 6149
+f 6184 6149 6277
+f 6277 6149 6211
+f 6277 6211 6352
+f 6352 6211 6429
+f 6352 6429 6590
+f 6590 6429 6570
+f 6590 6570 6686
+f 6686 6570 6642
+f 6686 6642 6810
+f 6810 6642 6728
+f 6810 6728 6893
+f 6893 6728 6856
+f 6893 6856 7057
+f 7057 6856 7010
+f 7057 7010 7188
+f 7188 7010 7244
+f 7188 7244 7354
+f 7354 7244 7308
+f 7354 7308 7429
+f 7429 7308 7486
+f 7429 7486 7580
+f 7580 7486 7548
+f 7580 7548 7670
+f 7670 7548 7696
+f 7670 7696 7861
+f 7861 7696 7804
+f 7861 7804 7916
+f 87 132 236
+f 236 132 210
+f 236 210 403
+f 403 210 324
+f 403 324 446
+f 446 324 436
+f 446 436 566
+f 566 436 586
+f 566 586 785
+f 785 586 740
+f 785 740 853
+f 853 740 898
+f 853 898 1004
+f 1004 898 971
+f 1004 971 1143
+f 1143 971 1161
+f 1143 1161 1210
+f 1210 1161 1218
+f 1210 1218 1410
+f 1410 1218 1393
+f 1410 1393 1560
+f 1560 1393 1498
+f 1560 1498 1608
+f 1608 1498 1630
+f 1608 1630 1710
+f 1710 1630 1737
+f 1710 1737 1850
+f 1850 1737 1897
+f 1850 1897 2064
+f 2064 1897 2078
+f 2064 2078 2134
+f 2134 2078 2163
+f 2134 2163 2267
+f 2267 2163 2266
+f 2267 2266 2446
+f 2446 2266 2390
+f 2446 2390 2550
+f 2550 2390 2597
+f 2550 2597 2679
+f 2679 2597 2695
+f 2679 2695 2838
+f 2838 2695 2837
+f 2838 2837 2987
+f 2987 2837 2974
+f 2987 2974 3104
+f 3104 2974 3103
+f 3104 3103 3242
+f 3242 3103 3231
+f 3242 3231 3342
+f 3342 3231 3365
+f 3342 3365 3552
+f 3552 3365 3522
+f 3552 3522 3642
+f 3642 3522 3676
+f 3642 3676 3718
+f 3718 3676 3774
+f 3718 3774 3874
+f 3874 3774 3914
+f 3874 3914 4000
+f 4000 3914 4032
+f 4000 4032 4156
+f 4156 4032 4178
+f 4156 4178 4338
+f 4338 4178 4352
+f 4338 4352 4440
+f 4440 4352 4412
+f 4440 4412 4589
+f 4589 4412 4530
+f 4589 4530 4628
+f 4628 4530 4732
+f 4628 4732 4808
+f 4808 4732 4884
+f 4808 4884 4914
+f 4914 4884 4986
+f 4914 4986 5104
+f 5104 4986 5098
+f 5104 5098 5256
+f 5256 5098 5216
+f 5256 5216 5319
+f 5319 5216 5412
+f 5319 5412 5538
+f 5538 5412 5488
+f 5538 5488 5599
+f 5599 5488 5610
+f 5599 5610 5784
+f 5784 5610 5692
+f 5784 5692 5826
+f 5826 5692 5891
+f 5826 5891 5988
+f 5988 5891 5995
+f 5988 5995 6142
+f 6142 5995 6184
+f 6142 6184 6312
+f 6312 6184 6277
+f 6312 6277 6397
+f 6397 6277 6352
+f 6397 6352 6555
+f 6555 6352 6590
+f 6555 6590 6630
+f 6630 6590 6686
+f 6630 6686 6764
+f 6764 6686 6810
+f 6764 6810 6924
+f 6924 6810 6893
+f 6924 6893 7070
+f 7070 6893 7057
+f 7070 7057 7195
+f 7195 7057 7188
+f 7195 7188 7358
+f 7358 7188 7354
+f 7358 7354 7429
+f 7637 7580 7642
+f 7642 7580 7670
+f 7642 7670 7758
+f 7758 7670 7761
+f 7761 7670 7861
+f 7761 7861 7878
+f 7070 7124 6924
+f 6924 7124 6904
+f 6924 6904 6764
+f 6764 6904 6793
+f 6764 6793 6630
+f 6630 6793 6722
+f 6630 6722 6555
+f 6555 6722 6472
+f 6555 6472 6397
+f 6397 6472 6385
+f 6397 6385 6312
+f 6312 6385 6330
+f 6312 6330 6142
+f 6142 6330 6150
+f 6142 6150 5988
+f 5988 6150 5996
+f 5988 5996 5826
+f 5826 5996 5938
+f 5826 5938 5784
+f 5784 5938 5758
+f 5784 5758 5599
+f 5599 5758 5606
+f 5599 5606 5538
+f 5538 5606 5450
+f 5538 5450 5319
+f 5319 5450 5383
+f 5319 5383 5256
+f 5256 5383 5211
+f 5256 5211 5104
+f 5104 5211 5138
+f 5104 5138 4914
+f 4914 5138 4966
+f 4914 4966 4808
+f 4808 4966 4855
+f 4808 4855 4628
+f 4628 4855 4648
+f 4628 4648 4589
+f 4589 4648 4496
+f 4589 4496 4440
+f 4440 4496 4480
+f 4440 4480 4338
+f 4338 4480 4238
+f 4338 4238 4156
+f 4156 4238 4150
+f 4156 4150 4000
+f 4000 4150 3994
+f 4000 3994 3874
+f 3874 3994 3853
+f 3874 3853 3718
+f 3718 3853 3808
+f 3718 3808 3642
+f 3642 3808 3584
+f 3642 3584 3552
+f 3552 3584 3530
+f 3552 3530 3342
+f 3342 3530 3319
+f 3342 3319 3242
+f 3242 3319 3240
+f 3242 3240 3104
+f 3104 3240 3119
+f 3104 3119 2987
+f 2987 3119 2966
+f 2987 2966 2838
+f 2838 2966 2862
+f 2838 2862 2679
+f 2679 2862 2709
+f 2679 2709 2550
+f 2550 2709 2565
+f 2550 2565 2446
+f 2446 2565 2434
+f 2446 2434 2267
+f 2267 2434 2292
+f 2267 2292 2134
+f 2134 2292 2210
+f 2134 2210 2064
+f 2064 2210 2073
+f 2064 2073 1850
+f 1850 2073 1923
+f 1850 1923 1710
+f 1710 1923 1758
+f 1710 1758 1608
+f 1608 1758 1656
+f 1608 1656 1560
+f 1560 1656 1566
+f 1560 1566 1410
+f 1410 1566 1411
+f 1410 1411 1210
+f 1210 1411 1271
+f 1210 1271 1143
+f 1143 1271 1144
+f 1143 1144 1004
+f 1004 1144 972
+f 1004 972 853
+f 853 972 899
+f 853 899 785
+f 785 899 741
+f 785 741 566
+f 566 741 637
+f 566 637 446
+f 446 637 507
+f 446 507 403
+f 403 507 345
+f 403 345 236
+f 236 345 217
+f 236 217 87
+f 87 217 152
+f 87 152 12
+f 7266 7195 7270
+f 7270 7195 7358
+f 7270 7358 7274
+f 7124 7031 6904
+f 6904 7031 6896
+f 6904 6896 6793
+f 6793 6896 6774
+f 6793 6774 6722
+f 6722 6774 6600
+f 6722 6600 6472
+f 6472 6600 6551
+f 6472 6551 6385
+f 6385 6551 6430
+f 6385 6430 6330
+f 6330 6430 6240
+f 6330 6240 6150
+f 6150 6240 6104
+f 6150 6104 5996
+f 5996 6104 6002
+f 5996 6002 5938
+f 5938 6002 5872
+f 5938 5872 5758
+f 5758 5872 5728
+f 5758 5728 5606
+f 5606 5728 5676
+f 5606 5676 5450
+f 5450 5676 5457
+f 5450 5457 5383
+f 5383 5457 5400
+f 5383 5400 5211
+f 5211 5400 5212
+f 5211 5212 5138
+f 5138 5212 5148
+f 5138 5148 4966
+f 4966 5148 4957
+f 4966 4957 4855
+f 4855 4957 4788
+f 4855 4788 4648
+f 4648 4788 4720
+f 4648 4720 4496
+f 4496 4720 4498
+f 4496 4498 4480
+f 4480 4498 4404
+f 4480 4404 4238
+f 4238 4404 4280
+f 4238 4280 4150
+f 4150 4280 4166
+f 4150 4166 3994
+f 3994 4166 4058
+f 3994 4058 3853
+f 3853 4058 3844
+f 3853 3844 3808
+f 3808 3844 3714
+f 3808 3714 3584
+f 3584 3714 3630
+f 3584 3630 3530
+f 3530 3630 3459
+f 3530 3459 3319
+f 3319 3459 3346
+f 3319 3346 3240
+f 3240 3346 3276
+f 3240 3276 3119
+f 3119 3276 3120
+f 3119 3120 2966
+f 2966 3120 2972
+f 2966 2972 2862
+f 2862 2972 2852
+f 2862 2852 2709
+f 2709 2852 2710
+f 2709 2710 2565
+f 2565 2710 2558
+f 2565 2558 2434
+f 2434 2558 2447
+f 2434 2447 2292
+f 2292 2447 2251
+f 2292 2251 2210
+f 2210 2251 2164
+f 2210 2164 2073
+f 2073 2164 2000
+f 2073 2000 1923
+f 1923 2000 1924
+f 1923 1924 1758
+f 1758 1924 1720
+f 1758 1720 1656
+f 1656 1720 1675
+f 1656 1675 1566
+f 1566 1675 1499
+f 1566 1499 1411
+f 1411 1499 1431
+f 1411 1431 1271
+f 1271 1431 1290
+f 1271 1290 1144
+f 1144 1290 1125
+f 1144 1125 972
+f 972 1125 988
+f 972 988 899
+f 899 988 914
+f 899 914 741
+f 741 914 793
+f 741 793 637
+f 637 793 666
+f 637 666 507
+f 507 666 447
+f 507 447 345
+f 345 447 404
+f 345 404 217
+f 217 404 272
+f 217 272 152
+f 152 272 50
+f 152 50 12
+f 51 50 176
+f 176 50 272
+f 176 272 410
+f 410 272 404
+f 410 404 534
+f 534 404 447
+f 534 447 602
+f 602 447 666
+f 602 666 700
+f 700 666 793
+f 700 793 882
+f 882 793 914
+f 882 914 1005
+f 1005 914 988
+f 1005 988 1126
+f 1126 988 1125
+f 1126 1125 1242
+f 1242 1125 1290
+f 1242 1290 1432
+f 1432 1290 1431
+f 1432 1431 1453
+f 1453 1431 1499
+f 1453 1499 1657
+f 1657 1499 1675
+f 1657 1675 1814
+f 1814 1675 1720
+f 1814 1720 1954
+f 1954 1720 1924
+f 1954 1924 2074
+f 2074 1924 2000
+f 2074 2000 2172
+f 2172 2000 2164
+f 2172 2164 2307
+f 2307 2164 2251
+f 2307 2251 2466
+f 2466 2251 2447
+f 2466 2447 2542
+f 2542 2447 2558
+f 2542 2558 2680
+f 2680 2558 2710
+f 2680 2710 2868
+f 2868 2710 2852
+f 2868 2852 2953
+f 2953 2852 2972
+f 2953 2972 3164
+f 3164 2972 3120
+f 3164 3120 3250
+f 3250 3120 3276
+f 3250 3276 3408
+f 3408 3276 3346
+f 3408 3346 3502
+f 3502 3346 3459
+f 3502 3459 3660
+f 3660 3459 3630
+f 3660 3630 3736
+f 3736 3630 3714
+f 3736 3714 3854
+f 3854 3714 3844
+f 3854 3844 4052
+f 4052 3844 4058
+f 4052 4058 4164
+f 4164 4058 4166
+f 4164 4166 4262
+f 4262 4166 4280
+f 4262 4280 4417
+f 4417 4280 4404
+f 4417 4404 4590
+f 4590 4404 4498
+f 4590 4498 4676
+f 4676 4498 4720
+f 4676 4720 4844
+f 4844 4720 4788
+f 4844 4788 4928
+f 4928 4788 4957
+f 4928 4957 5105
+f 5105 4957 5148
+f 5105 5148 5242
+f 5242 5148 5212
+f 5242 5212 5312
+f 5312 5212 5400
+f 5312 5400 5458
+f 5458 5400 5457
+f 5458 5457 5604
+f 5604 5457 5676
+f 5604 5676 5798
+f 5798 5676 5728
+f 5798 5728 5863
+f 5863 5728 5872
+f 5863 5872 5978
+f 5978 5872 6002
+f 5978 6002 6099
+f 6099 6002 6104
+f 6099 6104 6328
+f 6328 6104 6240
+f 6328 6240 6356
+f 6356 6240 6430
+f 6356 6430 6584
+f 6584 6430 6551
+f 6584 6551 6663
+f 6663 6551 6600
+f 6663 6600 6834
+f 6834 6600 6774
+f 6834 6774 6954
+f 6954 6774 6896
+f 6954 6896 7003
+f 7003 6896 7031
+f 7003 7031 7007
+f 106 51 275
+f 275 51 176
+f 275 176 405
+f 405 176 410
+f 405 410 498
+f 498 410 534
+f 498 534 638
+f 638 534 602
+f 638 602 722
+f 722 602 700
+f 722 700 833
+f 833 700 882
+f 833 882 1048
+f 1048 882 1005
+f 1048 1005 1127
+f 1127 1005 1126
+f 1127 1126 1298
+f 1298 1126 1242
+f 1298 1242 1412
+f 1412 1242 1432
+f 1412 1432 1462
+f 1462 1432 1453
+f 1462 1453 1666
+f 1666 1453 1657
+f 1666 1657 1738
+f 1738 1657 1814
+f 1738 1814 1898
+f 1898 1814 1954
+f 1898 1954 2033
+f 2033 1954 2074
+f 2033 2074 2100
+f 2100 2074 2172
+f 2100 2172 2228
+f 2228 2172 2307
+f 2228 2307 2448
+f 2448 2307 2466
+f 2448 2466 2566
+f 2566 2466 2542
+f 2566 2542 2696
+f 2696 2542 2680
+f 2696 2680 2842
+f 2842 2680 2868
+f 2842 2868 2988
+f 2988 2868 2953
+f 2988 2953 3052
+f 3052 2953 3164
+f 3052 3164 3268
+f 3268 3164 3250
+f 3268 3250 3413
+f 3413 3250 3408
+f 3413 3408 3516
+f 3516 3408 3502
+f 3516 3502 3622
+f 3622 3502 3660
+f 3622 3660 3782
+f 3782 3660 3736
+f 3782 3736 3892
+f 3892 3736 3854
+f 3892 3854 3972
+f 3972 3854 4052
+f 3972 4052 4186
+f 4186 4052 4164
+f 4186 4164 4248
+f 4248 4164 4262
+f 4248 4262 4462
+f 4462 4262 4417
+f 4462 4417 4553
+f 4553 4417 4590
+f 4553 4590 4698
+f 4698 4590 4676
+f 4698 4676 4802
+f 4802 4676 4844
+f 4802 4844 4958
+f 4958 4844 4928
+f 4958 4928 5086
+f 5086 4928 5105
+f 5086 5105 5204
+f 5204 5105 5242
+f 5204 5242 5320
+f 5320 5242 5312
+f 5320 5312 5492
+f 5492 5312 5458
+f 5492 5458 5552
+f 5552 5458 5604
+f 5552 5604 5746
+f 5746 5604 5798
+f 5746 5798 5834
+f 5834 5798 5863
+f 5834 5863 6022
+f 6022 5863 5978
+f 6022 5978 6192
+f 6192 5978 6099
+f 6192 6099 6256
+f 6256 6099 6328
+f 6256 6328 6390
+f 6390 6328 6356
+f 6390 6356 6540
+f 6540 6356 6584
+f 6540 6584 6664
+f 6664 6584 6663
+f 6664 6663 6844
+f 6844 6663 6834
+f 6844 6834 6922
+f 6922 6834 6954
+f 6922 6954 6989
+f 6922 6901 6844
+f 6844 6901 6781
+f 6844 6781 6664
+f 6664 6781 6632
+f 6664 6632 6540
+f 6540 6632 6560
+f 6540 6560 6390
+f 6390 6560 6370
+f 6390 6370 6256
+f 6256 6370 6252
+f 6256 6252 6192
+f 6192 6252 6100
+f 6192 6100 6022
+f 6022 6100 5990
+f 6022 5990 5834
+f 5834 5990 5838
+f 5834 5838 5746
+f 5746 5838 5766
+f 5746 5766 5552
+f 5552 5766 5654
+f 5552 5654 5492
+f 5492 5654 5440
+f 5492 5440 5320
+f 5320 5440 5376
+f 5320 5376 5204
+f 5204 5376 5158
+f 5204 5158 5086
+f 5086 5158 5120
+f 5086 5120 4958
+f 4958 5120 4948
+f 4958 4948 4802
+f 4802 4948 4856
+f 4802 4856 4698
+f 4698 4856 4726
+f 4698 4726 4553
+f 4553 4726 4524
+f 4553 4524 4462
+f 4462 4524 4420
+f 4462 4420 4248
+f 4248 4420 4344
+f 4248 4344 4186
+f 4186 4344 4130
+f 4186 4130 3972
+f 3972 4130 3987
+f 3972 3987 3892
+f 3892 3987 3952
+f 3892 3952 3782
+f 3782 3952 3772
+f 3782 3772 3622
+f 3622 3772 3574
+f 3622 3574 3516
+f 3516 3574 3500
+f 3516 3500 3413
+f 3413 3500 3372
+f 3413 3372 3268
+f 3268 3372 3218
+f 3268 3218 3052
+f 3052 3218 3076
+f 3052 3076 2988
+f 2988 3076 2994
+f 2988 2994 2842
+f 2842 2994 2858
+f 2842 2858 2696
+f 2696 2858 2721
+f 2696 2721 2566
+f 2566 2721 2598
+f 2566 2598 2448
+f 2448 2598 2438
+f 2448 2438 2228
+f 2228 2438 2268
+f 2228 2268 2100
+f 2100 2268 2149
+f 2100 2149 2033
+f 2033 2149 2021
+f 2033 2021 1898
+f 1898 2021 1862
+f 1898 1862 1738
+f 1738 1862 1791
+f 1738 1791 1666
+f 1666 1791 1676
+f 1666 1676 1462
+f 1462 1676 1500
+f 1462 1500 1412
+f 1412 1500 1413
+f 1412 1413 1298
+f 1298 1413 1272
+f 1298 1272 1127
+f 1127 1272 1170
+f 1127 1170 1048
+f 1048 1170 981
+f 1048 981 833
+f 833 981 873
+f 833 873 722
+f 722 873 776
+f 722 776 638
+f 638 776 567
+f 638 567 498
+f 498 567 519
+f 498 519 405
+f 405 519 385
+f 405 385 275
+f 275 385 218
+f 275 218 106
+f 106 218 90
+f 106 90 28
+f 7132 7091 6901
+f 6901 7091 6946
+f 6901 6946 6781
+f 6781 6946 6758
+f 6781 6758 6632
+f 6632 6758 6638
+f 6632 6638 6560
+f 6560 6638 6476
+f 6560 6476 6370
+f 6370 6476 6336
+f 6370 6336 6252
+f 6252 6336 6278
+f 6252 6278 6100
+f 6100 6278 6196
+f 6100 6196 5990
+f 5990 6196 5948
+f 5990 5948 5838
+f 5838 5948 5892
+f 5838 5892 5766
+f 5766 5892 5744
+f 5766 5744 5654
+f 5654 5744 5620
+f 5654 5620 5440
+f 5440 5620 5508
+f 5440 5508 5376
+f 5376 5508 5398
+f 5376 5398 5158
+f 5158 5398 5260
+f 5158 5260 5120
+f 5120 5260 5106
+f 5120 5106 4948
+f 4948 5106 4922
+f 4948 4922 4856
+f 4856 4922 4818
+f 4856 4818 4726
+f 4726 4818 4684
+f 4726 4684 4524
+f 4524 4684 4554
+f 4524 4554 4420
+f 4420 4554 4482
+f 4420 4482 4344
+f 4344 4482 4316
+f 4344 4316 4130
+f 4130 4316 4196
+f 4130 4196 3987
+f 3987 4196 4044
+f 3987 4044 3952
+f 3952 4044 3904
+f 3952 3904 3772
+f 3772 3904 3758
+f 3772 3758 3574
+f 3574 3758 3634
+f 3574 3634 3500
+f 3500 3634 3460
+f 3500 3460 3372
+f 3372 3460 3366
+f 3372 3366 3218
+f 3218 3366 3257
+f 3218 3257 3076
+f 3076 3257 3138
+f 3076 3138 2994
+f 2994 3138 3016
+f 2994 3016 2858
+f 2858 3016 2866
+f 2858 2866 2721
+f 2721 2866 2688
+f 2721 2688 2598
+f 2598 2688 2560
+f 2598 2560 2438
+f 2438 2560 2401
+f 2438 2401 2268
+f 2268 2401 2308
+f 2268 2308 2149
+f 2149 2308 2116
+f 2149 2116 2021
+f 2021 2116 2046
+f 2021 2046 1862
+f 1862 2046 1956
+f 1862 1956 1791
+f 1791 1956 1792
+f 1791 1792 1676
+f 1676 1792 1688
+f 1676 1688 1500
+f 1500 1688 1528
+f 1500 1528 1413
+f 1413 1528 1382
+f 1413 1382 1272
+f 1272 1382 1310
+f 1272 1310 1170
+f 1170 1310 1177
+f 1170 1177 981
+f 981 1177 994
+f 981 994 873
+f 873 994 818
+f 873 818 776
+f 776 818 766
+f 776 766 567
+f 567 766 578
+f 567 578 519
+f 519 578 468
+f 519 468 385
+f 385 468 406
+f 385 406 218
+f 218 406 199
+f 218 199 90
+f 90 199 107
+f 90 107 28
+f 7091 7071 6946
+f 6946 7071 6862
+f 6946 6862 6758
+f 6758 6862 6803
+f 6758 6803 6638
+f 6638 6803 6718
+f 6638 6718 6476
+f 6476 6718 6532
+f 6476 6532 6336
+f 6336 6532 6375
+f 6336 6375 6278
+f 6278 6375 6204
+f 6278 6204 6196
+f 6196 6204 6116
+f 6196 6116 5948
+f 5948 6116 6058
+f 5948 6058 5892
+f 5892 6058 5844
+f 5892 5844 5744
+f 5744 5844 5792
+f 5744 5792 5620
+f 5620 5792 5584
+f 5620 5584 5508
+f 5508 5584 5456
+f 5508 5456 5398
+f 5398 5456 5332
+f 5398 5332 5260
+f 5260 5332 5231
+f 5260 5231 5106
+f 5106 5231 5118
+f 5106 5118 4922
+f 4922 5118 4942
+f 4922 4942 4818
+f 4818 4942 4858
+f 4818 4858 4684
+f 4684 4858 4690
+f 4684 4690 4554
+f 4554 4690 4516
+f 4554 4516 4482
+f 4482 4516 4437
+f 4482 4437 4316
+f 4316 4437 4240
+f 4316 4240 4196
+f 4196 4240 4216
+f 4196 4216 4044
+f 4044 4216 3996
+f 4044 3996 3904
+f 3904 3996 3866
+f 3904 3866 3758
+f 3758 3866 3752
+f 3758 3752 3634
+f 3634 3752 3613
+f 3634 3613 3460
+f 3460 3613 3544
+f 3460 3544 3366
+f 3366 3544 3330
+f 3366 3330 3257
+f 3257 3330 3284
+f 3257 3284 3138
+f 3138 3284 3110
+f 3138 3110 3016
+f 3016 3110 3023
+f 3016 3023 2866
+f 2866 3023 2865
+f 2866 2865 2688
+f 2688 2865 2718
+f 2688 2718 2560
+f 2560 2718 2592
+f 2560 2592 2401
+f 2401 2592 2396
+f 2401 2396 2308
+f 2308 2396 2239
+f 2308 2239 2116
+f 2116 2239 2187
+f 2116 2187 2046
+f 2046 2187 1964
+f 2046 1964 1956
+f 1956 1964 1883
+f 1956 1883 1792
+f 1792 1883 1709
+f 1792 1709 1688
+f 1688 1709 1653
+f 1688 1653 1528
+f 1528 1653 1510
+f 1528 1510 1382
+f 1382 1510 1444
+f 1382 1444 1310
+f 1310 1444 1228
+f 1310 1228 1177
+f 1177 1228 1184
+f 1177 1184 994
+f 994 1184 952
+f 994 952 818
+f 818 952 871
+f 818 871 766
+f 766 871 728
+f 766 728 578
+f 578 728 663
+f 578 663 468
+f 468 663 456
+f 468 456 406
+f 406 456 383
+f 406 383 199
+f 199 383 245
+f 199 245 107
+f 107 245 133
+f 107 133 10
+f 7272 7386 7267
+f 7267 7386 7253
+f 7267 7253 7147
+f 7640 7685 7635
+f 7635 7685 7576
+f 7635 7576 7520
+f 7759 7808 7755
+f 7755 7808 7685
+f 7755 7685 7640
+f 134 156 276
+f 276 156 244
+f 276 244 371
+f 371 244 368
+f 371 368 464
+f 464 368 445
+f 464 445 560
+f 560 445 575
+f 560 575 682
+f 682 575 773
+f 682 773 854
+f 854 773 912
+f 854 912 1012
+f 1012 912 1038
+f 1012 1038 1162
+f 1162 1038 1175
+f 1162 1175 1204
+f 1204 1175 1307
+f 1204 1307 1434
+f 1434 1307 1443
+f 1434 1443 1490
+f 1490 1443 1465
+f 1490 1465 1609
+f 1609 1465 1580
+f 1609 1580 1778
+f 1778 1580 1800
+f 1778 1800 1878
+f 1878 1800 1876
+f 1878 1876 2022
+f 2022 1876 1958
+f 2022 1958 2140
+f 2140 1958 2196
+f 2140 2196 2252
+f 2252 2196 2300
+f 2252 2300 2402
+f 2402 2300 2412
+f 2402 2412 2584
+f 2584 2412 2568
+f 2584 2568 2648
+f 2648 2568 2642
+f 2648 2642 2846
+f 2846 2642 2814
+f 2846 2814 2940
+f 2940 2814 2950
+f 2940 2950 3072
+f 3072 2950 3065
+f 3072 3065 3248
+f 3248 3065 3278
+f 3248 3278 3338
+f 3338 3278 3419
+f 3338 3419 3554
+f 3554 3419 3479
+f 3554 3479 3674
+f 3674 3479 3600
+f 3674 3600 3778
+f 3778 3600 3806
+f 3778 3806 3908
+f 3908 3806 3919
+f 3908 3919 3988
+f 3988 3919 4084
+f 3988 4084 4126
+f 4126 4084 4194
+f 4126 4194 4354
+f 4354 4194 4290
+f 4354 4290 4478
+f 4478 4290 4387
+f 4478 4387 4550
+f 4550 4387 4567
+f 4550 4567 4664
+f 4664 4567 4728
+f 4664 4728 4824
+f 4824 4728 4798
+f 4824 4798 4970
+f 4970 4798 4909
+f 4970 4909 5082
+f 5082 4909 5054
+f 5082 5054 5254
+f 5254 5054 5221
+f 5254 5221 5392
+f 5392 5221 5290
+f 5392 5290 5460
+f 5460 5290 5490
+f 5460 5490 5640
+f 5640 5490 5650
+f 5640 5650 5737
+f 5737 5650 5706
+f 5737 5706 5887
+f 5887 5706 5924
+f 5887 5924 6032
+f 6032 5924 6042
+f 6032 6042 6122
+f 6122 6042 6181
+f 6122 6181 6272
+f 6272 6181 6304
+f 6272 6304 6394
+f 6394 6304 6360
+f 6394 6360 6489
+f 6489 6360 6496
+f 6489 6496 6702
+f 6702 6496 6716
+f 6702 6716 6782
+f 6782 6716 6843
+f 6782 6843 6894
+f 6894 6843 6881
+f 6894 6881 7058
+f 7058 6881 7042
+f 7058 7042 7198
+f 7198 7042 7156
+f 7198 7156 7300
+f 7300 7156 7312
+f 7300 7312 7450
+f 7450 7312 7516
+f 7450 7516 7566
+f 7566 7516 7576
+f 7566 7576 7754
+f 7754 7576 7685
+f 7754 7685 7872
+f 7872 7685 7808
+f 7872 7808 7919
+f 66 134 200
+f 200 134 276
+f 200 276 306
+f 306 276 371
+f 306 371 508
+f 508 371 464
+f 508 464 608
+f 608 464 560
+f 608 560 742
+f 742 560 682
+f 742 682 860
+f 860 682 854
+f 860 854 982
+f 982 854 1012
+f 982 1012 1128
+f 1128 1012 1162
+f 1128 1162 1278
+f 1278 1162 1204
+f 1278 1204 1357
+f 1357 1204 1434
+f 1357 1434 1448
+f 1448 1434 1490
+f 1448 1490 1658
+f 1658 1490 1609
+f 1658 1609 1716
+f 1716 1609 1778
+f 1716 1778 1934
+f 1934 1778 1878
+f 1934 1878 2084
+f 2084 1878 2022
+f 2084 2022 2178
+f 2178 2022 2140
+f 2178 2140 2286
+f 2286 2140 2252
+f 2286 2252 2422
+f 2422 2252 2402
+f 2422 2402 2590
+f 2590 2402 2584
+f 2590 2584 2644
+f 2644 2584 2648
+f 2644 2648 2810
+f 2810 2648 2846
+f 2810 2846 3002
+f 3002 2846 2940
+f 3002 2940 3054
+f 3054 2940 3072
+f 3054 3072 3172
+f 3172 3072 3248
+f 3172 3248 3414
+f 3414 3248 3338
+f 3414 3338 3482
+f 3482 3338 3554
+f 3482 3554 3616
+f 3616 3554 3674
+f 3616 3674 3822
+f 3822 3674 3778
+f 3822 3778 3902
+f 3902 3778 3908
+f 3902 3908 3980
+f 3980 3908 3988
+f 3980 3988 4170
+f 4170 3988 4126
+f 4170 4126 4264
+f 4264 4126 4354
+f 4264 4354 4398
+f 4398 4354 4478
+f 4398 4478 4586
+f 4586 4478 4550
+f 4586 4550 4718
+f 4718 4550 4664
+f 4718 4664 4826
+f 4826 4664 4824
+f 4826 4824 5004
+f 5004 4824 4970
+f 5004 4970 5072
+f 5072 4970 5082
+f 5072 5082 5222
+f 5222 5082 5254
+f 5222 5254 5294
+f 5294 5254 5392
+f 5294 5392 5540
+f 5540 5392 5460
+f 5540 5460 5646
+f 5646 5460 5640
+f 5646 5640 5774
+f 5774 5640 5737
+f 5774 5737 5882
+f 5882 5737 5887
+f 5882 5887 6014
+f 6014 5887 6032
+f 6014 6032 6114
+f 6114 6032 6122
+f 6114 6122 6270
+f 6270 6122 6272
+f 6270 6272 6440
+f 6440 6272 6394
+f 6440 6394 6542
+f 6542 6394 6489
+f 6542 6489 6616
+f 6616 6489 6702
+f 6616 6702 6840
+f 6840 6702 6782
+f 6840 6782 6944
+f 6944 6782 6894
+f 6944 6894 7066
+f 7066 6894 7058
+f 7066 7058 7202
+f 7202 7058 7198
+f 7202 7198 7344
+f 7344 7198 7300
+f 7344 7300 7410
+f 7410 7300 7450
+f 7410 7450 7602
+f 7602 7450 7566
+f 7602 7566 7674
+f 7674 7566 7754
+f 7674 7754 7766
+f 7766 7754 7872
+f 7766 7872 7900
+f 52 66 256
+f 256 66 200
+f 256 200 420
+f 420 200 306
+f 420 306 478
+f 478 306 508
+f 478 508 552
+f 552 508 608
+f 552 608 786
+f 786 608 742
+f 786 742 920
+f 920 742 860
+f 920 860 1006
+f 1006 860 982
+f 1006 982 1109
+f 1109 982 1128
+f 1109 1128 1260
+f 1260 1128 1278
+f 1260 1278 1394
+f 1394 1278 1357
+f 1394 1357 1512
+f 1512 1357 1448
+f 1512 1448 1610
+f 1610 1448 1658
+f 1610 1658 1808
+f 1808 1658 1716
+f 1808 1716 1946
+f 1946 1716 1934
+f 1946 1934 2038
+f 2038 1934 2084
+f 2038 2084 2152
+f 2152 2084 2178
+f 2152 2178 2244
+f 2244 2178 2286
+f 2244 2286 2428
+f 2428 2286 2422
+f 2428 2422 2606
+f 2606 2422 2590
+f 2606 2590 2656
+f 2656 2590 2644
+f 2656 2644 2873
+f 2873 2644 2810
+f 2873 2810 2998
+f 2998 2810 3002
+f 2998 3002 3062
+f 3062 3002 3054
+f 3062 3054 3194
+f 3194 3054 3172
+f 3194 3172 3306
+f 3306 3172 3414
+f 3306 3414 3548
+f 3548 3414 3482
+f 3548 3482 3646
+f 3646 3482 3616
+f 3646 3616 3798
+f 3798 3616 3822
+f 3798 3822 3950
+f 3950 3822 3902
+f 3950 3902 4018
+f 4018 3902 3980
+f 4018 3980 4161
+f 4161 3980 4170
+f 4161 4170 4308
+f 4308 4170 4264
+f 4308 4264 4418
+f 4418 4264 4398
+f 4418 4398 4508
+f 4508 4398 4586
+f 4508 4586 4748
+f 4748 4586 4718
+f 4748 4718 4876
+f 4876 4718 4826
+f 4876 4826 4962
+f 4962 4826 5004
+f 4962 5004 5108
+f 5108 5004 5072
+f 5108 5072 5176
+f 5176 5072 5222
+f 5176 5222 5366
+f 5366 5222 5294
+f 5366 5294 5472
+f 5472 5294 5540
+f 5472 5540 5572
+f 5572 5540 5646
+f 5572 5646 5700
+f 5700 5646 5774
+f 5700 5774 5903
+f 5903 5774 5882
+f 5903 5882 6046
+f 6046 5882 6014
+f 6046 6014 6092
+f 6092 6014 6114
+f 6092 6114 6216
+f 6216 6114 6270
+f 6216 6270 6403
+f 6403 6270 6440
+f 6403 6440 6490
+f 6490 6440 6542
+f 6490 6542 6646
+f 6646 6542 6616
+f 6646 6616 6838
+f 6838 6616 6840
+f 6838 6840 6942
+f 6942 6840 6944
+f 6942 6944 7036
+f 7036 6944 7066
+f 7036 7066 7210
+f 7210 7066 7202
+f 7210 7202 7382
+f 7382 7202 7344
+f 7382 7344 7481
+f 7481 7344 7410
+f 7481 7410 7544
+f 7544 7410 7602
+f 7544 7602 7676
+f 7676 7602 7674
+f 7676 7674 7818
+f 7818 7674 7766
+f 7818 7766 7906
+f 56 52 194
+f 194 52 256
+f 194 256 386
+f 386 256 420
+f 386 420 448
+f 448 420 478
+f 448 478 656
+f 656 478 552
+f 656 552 768
+f 768 552 786
+f 768 786 900
+f 900 786 920
+f 900 920 934
+f 934 920 1006
+f 934 1006 1149
+f 1149 1006 1109
+f 1149 1109 1212
+f 1212 1109 1260
+f 1212 1260 1366
+f 1366 1260 1394
+f 1366 1394 1554
+f 1554 1394 1512
+f 1554 1512 1664
+f 1664 1512 1610
+f 1664 1610 1818
+f 1818 1610 1808
+f 1818 1808 1854
+f 1854 1808 1946
+f 1854 1946 2066
+f 2066 1946 2038
+f 2066 2038 2104
+f 2104 2038 2152
+f 2104 2152 2282
+f 2282 2152 2244
+f 2282 2244 2416
+f 2416 2244 2428
+f 2416 2428 2514
+f 2514 2428 2606
+f 2514 2606 2722
+f 2722 2606 2656
+f 2722 2656 2788
+f 2788 2656 2873
+f 2788 2873 2946
+f 2946 2873 2998
+f 2946 2998 3080
+f 3080 2998 3062
+f 3080 3062 3178
+f 3178 3062 3194
+f 3178 3194 3324
+f 3324 3194 3306
+f 3324 3306 3562
+f 3562 3306 3548
+f 3562 3548 3626
+f 3626 3548 3646
+f 3626 3646 3746
+f 3746 3646 3798
+f 3746 3798 3930
+f 3930 3798 3950
+f 3930 3950 4074
+f 4074 3950 4018
+f 4074 4018 4226
+f 4226 4018 4161
+f 4226 4161 4356
+f 4356 4161 4308
+f 4356 4308 4446
+f 4446 4308 4418
+f 4446 4418 4518
+f 4518 4418 4508
+f 4518 4508 4696
+f 4696 4508 4748
+f 4696 4748 4780
+f 4780 4748 4876
+f 4780 4876 4912
+f 4912 4876 4962
+f 4912 4962 5080
+f 5080 4962 5108
+f 5080 5108 5274
+f 5274 5108 5176
+f 5274 5176 5343
+f 5343 5176 5366
+f 5343 5366 5546
+f 5546 5366 5472
+f 5546 5472 5612
+f 5612 5472 5572
+f 5612 5572 5696
+f 5696 5572 5700
+f 5696 5700 5878
+f 5878 5700 5903
+f 5878 5903 6038
+f 6038 5903 6046
+f 6038 6046 6096
+f 6096 6046 6092
+f 6096 6092 6282
+f 6282 6092 6216
+f 6282 6216 6398
+f 6398 6216 6403
+f 6398 6403 6552
+f 6552 6403 6490
+f 6552 6490 6704
+f 6704 6490 6646
+f 6704 6646 6798
+f 6798 6646 6838
+f 6798 6838 6916
+f 6916 6838 6942
+f 6916 6942 7048
+f 7048 6942 7036
+f 7048 7036 7215
+f 7215 7036 7210
+f 7215 7210 7276
+f 7276 7210 7382
+f 7276 7382 7434
+f 7434 7382 7481
+f 7434 7481 7632
+f 7632 7481 7544
+f 7632 7544 7686
+f 7686 7544 7676
+f 7686 7676 7868
+f 7868 7676 7818
+f 7868 7818 7898
+f 118 56 286
+f 286 56 194
+f 286 194 327
+f 327 194 386
+f 327 386 458
+f 458 386 448
+f 458 448 621
+f 621 448 656
+f 621 656 794
+f 794 656 768
+f 794 768 924
+f 924 768 900
+f 924 900 962
+f 962 900 934
+f 962 934 1110
+f 1110 934 1149
+f 1110 1149 1224
+f 1224 1149 1212
+f 1224 1212 1414
+f 1414 1212 1366
+f 1414 1366 1454
+f 1454 1366 1554
+f 1454 1554 1618
+f 1618 1554 1664
+f 1618 1664 1828
+f 1828 1664 1818
+f 1828 1818 1928
+f 1928 1818 1854
+f 1928 1854 2056
+f 2056 1854 2066
+f 2056 2066 2098
+f 2098 2066 2104
+f 2098 2104 2226
+f 2226 2104 2282
+f 2226 2282 2404
+f 2404 2282 2416
+f 2404 2416 2534
+f 2534 2416 2514
+f 2534 2514 2742
+f 2742 2514 2722
+f 2742 2722 2830
+f 2830 2722 2788
+f 2830 2788 3010
+f 3010 2788 2946
+f 3010 2946 3160
+f 3160 2946 3080
+f 3160 3080 3244
+f 3244 3080 3178
+f 3244 3178 3388
+f 3388 3178 3324
+f 3388 3324 3542
+f 3542 3324 3562
+f 3542 3562 3652
+f 3652 3562 3626
+f 3652 3626 3724
+f 3724 3626 3746
+f 3724 3746 3870
+f 3870 3746 3930
+f 3870 3930 4046
+f 4046 3930 4074
+f 4046 4074 4190
+f 4190 4074 4226
+f 4190 4226 4270
+f 4270 4226 4356
+f 4270 4356 4396
+f 4396 4356 4446
+f 4396 4446 4512
+f 4512 4446 4518
+f 4512 4518 4666
+f 4666 4518 4696
+f 4666 4696 4764
+f 4764 4696 4780
+f 4764 4780 4902
+f 4902 4780 4912
+f 4902 4912 5074
+f 5074 4912 5080
+f 5074 5080 5162
+f 5162 5080 5274
+f 5162 5274 5368
+f 5368 5274 5343
+f 5368 5343 5494
+f 5494 5343 5546
+f 5494 5546 5666
+f 5666 5546 5612
+f 5666 5612 5740
+f 5740 5612 5696
+f 5740 5696 5864
+f 5864 5696 5878
+f 5864 5878 6052
+f 6052 5878 6038
+f 6052 6038 6152
+f 6152 6038 6096
+f 6152 6096 6236
+f 6236 6096 6282
+f 6236 6282 6386
+f 6386 6282 6398
+f 6386 6398 6474
+f 6474 6398 6552
+f 6474 6552 6706
+f 6706 6552 6704
+f 6706 6704 6828
+f 6828 6704 6798
+f 6828 6798 6968
+f 6968 6798 6916
+f 6968 6916 7060
+f 7060 6916 7048
+f 7060 7048 7218
+f 7218 7048 7215
+f 7218 7215 7280
+f 7280 7215 7276
+f 7280 7276 7426
+f 7426 7276 7434
+f 7426 7434 7574
+f 7574 7434 7632
+f 7574 7632 7718
+f 7718 7632 7686
+f 7718 7686 7768
+f 7768 7686 7868
+f 7768 7868 7931
+f 88 118 188
+f 188 118 286
+f 188 286 328
+f 328 286 327
+f 328 327 479
+f 479 327 458
+f 479 458 674
+f 674 458 621
+f 674 621 690
+f 690 621 794
+f 690 794 926
+f 926 794 924
+f 926 924 1017
+f 1017 924 962
+f 1017 962 1178
+f 1178 962 1110
+f 1178 1110 1314
+f 1314 1110 1224
+f 1314 1224 1346
+f 1346 1224 1414
+f 1346 1414 1466
+f 1466 1414 1454
+f 1466 1454 1614
+f 1614 1454 1618
+f 1614 1618 1786
+f 1786 1618 1828
+f 1786 1828 1952
+f 1952 1828 1928
+f 1952 1928 2010
+f 2010 1928 2056
+f 2010 2056 2102
+f 2102 2056 2098
+f 2102 2098 2276
+f 2276 2098 2226
+f 2276 2226 2456
+f 2456 2226 2404
+f 2456 2404 2520
+f 2520 2404 2534
+f 2520 2534 2690
+f 2690 2534 2742
+f 2690 2742 2874
+f 2874 2742 2830
+f 2874 2830 2926
+f 2926 2830 3010
+f 2926 3010 3086
+f 3086 3010 3160
+f 3086 3160 3258
+f 3258 3160 3244
+f 3258 3244 3426
+f 3426 3244 3388
+f 3426 3388 3508
+f 3508 3388 3542
+f 3508 3542 3640
+f 3640 3542 3652
+f 3640 3652 3814
+f 3814 3652 3724
+f 3814 3724 3867
+f 3867 3724 3870
+f 3867 3870 4014
+f 4014 3870 4046
+f 4014 4046 4172
+f 4172 4046 4190
+f 4172 4190 4340
+f 4340 4190 4270
+f 4340 4270 4484
+f 4484 4270 4396
+f 4484 4396 4542
+f 4542 4396 4512
+f 4542 4512 4730
+f 4730 4512 4666
+f 4730 4666 4768
+f 4768 4666 4764
+f 4768 4764 4906
+f 4906 4764 4902
+f 4906 4902 5128
+f 5128 4902 5074
+f 5128 5074 5276
+f 5276 5074 5162
+f 5276 5162 5344
+f 5344 5162 5368
+f 5344 5368 5534
+f 5534 5368 5494
+f 5534 5494 5570
+f 5570 5494 5666
+f 5570 5666 5802
+f 5802 5666 5740
+f 5802 5740 5920
+f 5920 5740 5864
+f 5920 5864 5962
+f 5962 5864 6052
+f 5962 6052 6078
+f 6078 6052 6152
+f 6078 6152 6230
+f 6230 6152 6236
+f 6230 6236 6378
+f 6378 6236 6386
+f 6378 6386 6556
+f 6556 6386 6474
+f 6556 6474 6698
+f 6698 6474 6706
+f 6698 6706 6846
+f 6846 6706 6828
+f 6846 6828 6936
+f 6936 6828 6968
+f 6936 6968 7108
+f 7108 6968 7060
+f 7108 7060 7206
+f 7206 7060 7218
+f 7206 7218 7298
+f 7298 7218 7280
+f 7298 7280 7456
+f 7456 7280 7426
+f 7456 7426 7622
+f 7622 7426 7574
+f 7622 7574 7700
+f 7700 7574 7718
+f 7700 7718 7844
+f 7844 7718 7768
+f 7844 7768 7913
+f 58 88 222
+f 222 88 188
+f 222 188 354
+f 354 188 328
+f 354 328 520
+f 520 328 479
+f 520 479 622
+f 622 479 674
+f 622 674 694
+f 694 674 690
+f 694 690 878
+f 878 690 926
+f 878 926 944
+f 944 926 1017
+f 944 1017 1150
+f 1150 1017 1178
+f 1150 1178 1258
+f 1258 1178 1314
+f 1258 1314 1395
+f 1395 1314 1346
+f 1395 1346 1473
+f 1473 1346 1466
+f 1473 1466 1672
+f 1672 1466 1614
+f 1672 1614 1822
+f 1822 1614 1786
+f 1822 1786 1887
+f 1887 1786 1952
+f 1887 1952 2006
+f 2006 1952 2010
+f 2006 2010 2123
+f 2123 2010 2102
+f 2123 2102 2242
+f 2242 2102 2276
+f 2242 2276 2476
+f 2476 2276 2456
+f 2476 2456 2618
+f 2618 2456 2520
+f 2618 2520 2762
+f 2762 2520 2690
+f 2762 2690 2854
+f 2854 2690 2874
+f 2854 2874 2912
+f 2912 2874 2926
+f 2912 2926 3096
+f 3096 2926 3086
+f 3096 3086 3204
+f 3204 3086 3258
+f 3204 3258 3315
+f 3315 3258 3426
+f 3315 3426 3462
+f 3462 3426 3508
+f 3462 3508 3670
+f 3670 3508 3640
+f 3670 3640 3706
+f 3706 3640 3814
+f 3706 3814 3860
+f 3860 3814 3867
+f 3860 3867 4050
+f 4050 3867 4014
+f 4050 4014 4182
+f 4182 4014 4172
+f 4182 4172 4234
+f 4234 4172 4340
+f 4234 4340 4444
+f 4444 4340 4484
+f 4444 4484 4560
+f 4560 4484 4542
+f 4560 4542 4712
+f 4712 4542 4730
+f 4712 4730 4814
+f 4814 4730 4768
+f 4814 4768 4990
+f 4990 4768 4906
+f 4990 4906 5050
+f 5050 4906 5128
+f 5050 5128 5252
+f 5252 5128 5276
+f 5252 5276 5386
+f 5386 5276 5344
+f 5386 5344 5438
+f 5438 5344 5534
+f 5438 5534 5634
+f 5634 5534 5570
+f 5634 5570 5772
+f 5772 5570 5802
+f 5772 5802 5898
+f 5898 5802 5920
+f 5898 5920 5998
+f 5998 5920 5962
+f 5998 5962 6110
+f 6110 5962 6078
+f 6110 6078 6302
+f 6302 6078 6230
+f 6302 6230 6406
+f 6406 6230 6378
+f 6406 6378 6508
+f 6508 6378 6556
+f 6508 6556 6672
+f 6672 6556 6698
+f 6672 6698 6852
+f 6852 6698 6846
+f 6852 6846 6978
+f 6978 6846 6936
+f 6978 6936 7034
+f 7034 6936 7108
+f 7034 7108 7242
+f 7242 7108 7206
+f 7242 7206 7284
+f 7284 7206 7298
+f 7284 7298 7494
+f 7494 7298 7456
+f 7494 7456 7528
+f 7528 7456 7622
+f 7528 7622 7724
+f 7724 7622 7700
+f 7724 7700 7834
+f 7834 7700 7844
+f 7834 7844 7927
+f 75 58 204
+f 204 58 222
+f 204 222 346
+f 346 222 354
+f 346 354 514
+f 514 354 520
+f 514 520 658
+f 658 520 622
+f 658 622 732
+f 732 622 694
+f 732 694 886
+f 886 694 878
+f 886 878 1018
+f 1018 878 944
+f 1018 944 1068
+f 1068 944 1150
+f 1068 1150 1300
+f 1300 1150 1258
+f 1300 1258 1334
+f 1334 1258 1395
+f 1334 1395 1484
+f 1484 1395 1473
+f 1484 1473 1585
+f 1585 1473 1672
+f 1585 1672 1768
+f 1768 1672 1822
+f 1768 1822 1866
+f 1866 1822 1887
+f 1866 1887 2004
+f 2004 1887 2006
+f 2004 2006 2150
+f 2150 2006 2123
+f 2150 2123 2230
+f 2230 2123 2242
+f 2230 2242 2368
+f 2368 2242 2476
+f 2368 2476 2528
+f 2528 2476 2618
+f 2528 2618 2636
+f 2636 2618 2762
+f 2636 2762 2782
+f 2782 2762 2854
+f 2782 2854 2954
+f 2954 2854 2912
+f 2954 2912 3136
+f 3136 2912 3096
+f 3136 3096 3182
+f 3182 3096 3204
+f 3182 3204 3336
+f 3336 3204 3315
+f 3336 3315 3456
+f 3456 3315 3462
+f 3456 3462 3662
+f 3662 3462 3670
+f 3662 3670 3804
+f 3804 3670 3706
+f 3804 3706 3922
+f 3922 3706 3860
+f 3922 3860 4008
+f 4008 3860 4050
+f 4008 4050 4120
+f 4120 4050 4182
+f 4120 4182 4272
+f 4272 4182 4234
+f 4272 4234 4460
+f 4460 4234 4444
+f 4460 4444 4558
+f 4558 4444 4560
+f 4558 4560 4738
+f 4738 4560 4712
+f 4738 4712 4810
+f 4810 4712 4814
+f 4810 4814 4974
+f 4974 4814 4990
+f 4974 4990 5132
+f 5132 4990 5050
+f 5132 5050 5268
+f 5268 5050 5252
+f 5268 5252 5384
+f 5384 5252 5386
+f 5384 5386 5532
+f 5532 5386 5438
+f 5532 5438 5578
+f 5578 5438 5634
+f 5578 5634 5723
+f 5723 5634 5772
+f 5723 5772 5858
+f 5858 5772 5898
+f 5858 5898 6070
+f 6070 5898 5998
+f 6070 5998 6162
+f 6162 5998 6110
+f 6162 6110 6326
+f 6326 6110 6302
+f 6326 6302 6342
+f 6342 6302 6406
+f 6342 6406 6536
+f 6536 6406 6508
+f 6536 6508 6604
+f 6604 6508 6672
+f 6604 6672 6736
+f 6736 6672 6852
+f 6736 6852 6958
+f 6958 6852 6978
+f 6958 6978 7078
+f 7078 6978 7034
+f 7078 7034 7248
+f 7248 7034 7242
+f 7248 7242 7384
+f 7384 7242 7284
+f 7384 7284 7464
+f 7464 7284 7494
+f 7464 7494 7558
+f 7558 7494 7528
+f 7558 7528 7740
+f 7740 7528 7724
+f 7740 7724 7776
+f 7776 7724 7834
+f 7776 7834 7883
+f 92 75 248
+f 248 75 204
+f 248 204 396
+f 396 204 346
+f 396 346 480
+f 480 346 514
+f 480 514 672
+f 672 514 658
+f 672 658 710
+f 710 658 732
+f 710 732 892
+f 892 732 886
+f 892 886 976
+f 976 886 1018
+f 976 1018 1134
+f 1134 1018 1068
+f 1134 1068 1246
+f 1246 1068 1300
+f 1246 1300 1418
+f 1418 1300 1334
+f 1418 1334 1482
+f 1482 1334 1484
+f 1482 1484 1642
+f 1642 1484 1585
+f 1642 1585 1727
+f 1727 1585 1768
+f 1727 1768 1900
+f 1900 1768 1866
+f 1900 1866 1984
+f 1984 1866 2004
+f 1984 2004 2200
+f 2200 2004 2150
+f 2200 2150 2278
+f 2278 2150 2230
+f 2278 2230 2482
+f 2482 2230 2368
+f 2482 2368 2538
+f 2538 2368 2528
+f 2538 2528 2672
+f 2672 2528 2636
+f 2672 2636 2792
+f 2792 2636 2782
+f 2792 2782 2956
+f 2956 2782 2954
+f 2956 2954 3082
+f 3082 2954 3136
+f 3082 3136 3174
+f 3174 3136 3182
+f 3174 3182 3378
+f 3378 3182 3336
+f 3378 3336 3546
+f 3546 3336 3456
+f 3546 3456 3682
+f 3682 3456 3662
+f 3682 3662 3830
+f 3830 3662 3804
+f 3830 3804 3926
+f 3926 3804 3922
+f 3926 3922 4090
+f 4090 3922 4008
+f 4090 4008 4162
+f 4162 4008 4120
+f 4162 4120 4332
+f 4332 4120 4272
+f 4332 4272 4474
+f 4474 4272 4460
+f 4474 4460 4614
+f 4614 4460 4558
+f 4614 4558 4710
+f 4710 4558 4738
+f 4710 4738 4784
+f 4784 4738 4810
+f 4784 4810 4904
+f 4904 4810 4974
+f 4904 4974 5076
+f 5076 4974 5132
+f 5076 5132 5166
+f 5166 5132 5268
+f 5166 5268 5306
+f 5306 5268 5384
+f 5306 5384 5520
+f 5520 5384 5532
+f 5520 5532 5674
+f 5674 5532 5578
+f 5674 5578 5724
+f 5724 5578 5723
+f 5724 5723 5888
+f 5888 5723 5858
+f 5888 5858 6006
+f 6006 5858 6070
+f 6006 6070 6154
+f 6154 6070 6162
+f 6154 6162 6286
+f 6286 6162 6326
+f 6286 6326 6354
+f 6354 6326 6342
+f 6354 6342 6500
+f 6500 6342 6536
+f 6500 6536 6606
+f 6606 6536 6604
+f 6606 6604 6786
+f 6786 6604 6736
+f 6786 6736 6974
+f 6974 6736 6958
+f 6974 6958 7106
+f 7106 6958 7078
+f 7106 7078 7160
+f 7160 7078 7248
+f 7160 7248 7346
+f 7346 7248 7384
+f 7346 7384 7492
+f 7492 7384 7464
+f 7492 7464 7584
+f 7584 7464 7558
+f 7584 7558 7726
+f 7726 7558 7740
+f 7726 7740 7810
+f 7810 7740 7776
+f 7810 7776 7911
+f 136 92 264
+f 264 92 248
+f 264 248 398
+f 398 248 396
+f 398 396 460
+f 460 396 480
+f 460 480 650
+f 650 480 672
+f 650 672 788
+f 788 672 710
+f 788 710 840
+f 840 710 892
+f 840 892 966
+f 966 892 976
+f 966 976 1158
+f 1158 976 1134
+f 1158 1134 1302
+f 1302 1134 1246
+f 1302 1246 1324
+f 1324 1246 1418
+f 1324 1418 1474
+f 1474 1418 1482
+f 1474 1482 1622
+f 1622 1482 1642
+f 1622 1642 1722
+f 1722 1642 1727
+f 1722 1727 1852
+f 1852 1727 1900
+f 1852 1900 2052
+f 2052 1900 1984
+f 2052 1984 2096
+f 2096 1984 2200
+f 2096 2200 2312
+f 2312 2200 2278
+f 2312 2278 2394
+f 2394 2278 2482
+f 2394 2482 2622
+f 2622 2482 2538
+f 2622 2538 2740
+f 2740 2538 2672
+f 2740 2672 2890
+f 2890 2672 2792
+f 2890 2792 2936
+f 2936 2792 2956
+f 2936 2956 3048
+f 3048 2956 3082
+f 3048 3082 3272
+f 3272 3082 3174
+f 3272 3174 3428
+f 3428 3174 3378
+f 3428 3378 3558
+f 3558 3378 3546
+f 3558 3546 3680
+f 3680 3546 3682
+f 3680 3682 3730
+f 3730 3682 3830
+f 3730 3830 3878
+f 3878 3830 3926
+f 3878 3926 4034
+f 4034 3926 4090
+f 4034 4090 4144
+f 4144 4090 4162
+f 4144 4162 4346
+f 4346 4162 4332
+f 4346 4332 4476
+f 4476 4332 4474
+f 4476 4474 4574
+f 4574 4474 4614
+f 4574 4614 4742
+f 4742 4614 4710
+f 4742 4710 4836
+f 4836 4710 4784
+f 4836 4784 4934
+f 4934 4784 4904
+f 4934 4904 5130
+f 5130 4904 5076
+f 5130 5076 5265
+f 5265 5076 5166
+f 5265 5166 5402
+f 5402 5166 5306
+f 5402 5306 5448
+f 5448 5306 5520
+f 5448 5520 5576
+f 5576 5520 5674
+f 5576 5674 5708
+f 5708 5674 5724
+f 5708 5724 5900
+f 5900 5724 5888
+f 5900 5888 5956
+f 5956 5888 6006
+f 5956 6006 6164
+f 6164 6006 6154
+f 6164 6154 6268
+f 6268 6154 6286
+f 6268 6286 6452
+f 6452 6286 6354
+f 6452 6354 6568
+f 6568 6354 6500
+f 6568 6500 6612
+f 6612 6500 6606
+f 6612 6606 6790
+f 6790 6606 6786
+f 6790 6786 6886
+f 6886 6786 6974
+f 6886 6974 7080
+f 7080 6974 7106
+f 7080 7106 7208
+f 7208 7106 7160
+f 7208 7160 7332
+f 7332 7160 7346
+f 7332 7346 7514
+f 7514 7346 7492
+f 7514 7492 7572
+f 7572 7492 7584
+f 7572 7584 7664
+f 7664 7584 7726
+f 7664 7726 7774
+f 7774 7726 7810
+f 7774 7810 7890
+f 146 136 288
+f 288 136 264
+f 288 264 376
+f 376 264 398
+f 376 398 450
+f 450 398 460
+f 450 460 568
+f 568 460 650
+f 568 650 688
+f 688 650 788
+f 688 788 862
+f 862 788 840
+f 862 840 948
+f 948 840 966
+f 948 966 1084
+f 1084 966 1158
+f 1084 1158 1220
+f 1220 1158 1302
+f 1220 1302 1378
+f 1378 1302 1324
+f 1378 1324 1506
+f 1506 1324 1474
+f 1506 1474 1598
+f 1598 1474 1622
+f 1598 1622 1762
+f 1762 1622 1722
+f 1762 1722 1872
+f 1872 1722 1852
+f 1872 1852 1994
+f 1994 1852 2052
+f 1994 2052 2166
+f 2166 2052 2096
+f 2166 2096 2214
+f 2214 2096 2312
+f 2214 2312 2382
+f 2382 2312 2394
+f 2382 2394 2588
+f 2588 2394 2622
+f 2588 2622 2646
+f 2646 2622 2740
+f 2646 2740 2790
+f 2790 2740 2890
+f 2790 2890 2982
+f 2982 2890 2936
+f 2982 2936 3084
+f 3084 2936 3048
+f 3084 3048 3288
+f 3288 3048 3272
+f 3288 3272 3316
+f 3316 3272 3428
+f 3316 3428 3550
+f 3550 3428 3558
+f 3550 3558 3678
+f 3678 3558 3680
+f 3678 3680 3704
+f 3704 3680 3730
+f 3704 3730 3838
+f 3838 3730 3878
+f 3838 3878 4086
+f 4086 3878 4034
+f 4086 4034 4100
+f 4100 4034 4144
+f 4100 4144 4246
+f 4246 4144 4346
+f 4246 4346 4370
+f 4370 4346 4476
+f 4370 4476 4584
+f 4584 4476 4574
+f 4584 4574 4636
+f 4636 4574 4742
+f 4636 4742 4830
+f 4830 4742 4836
+f 4830 4836 4938
+f 4938 4836 4934
+f 4938 4934 5112
+f 5112 4934 5130
+f 5112 5130 5272
+f 5272 5130 5265
+f 5272 5265 5356
+f 5356 5265 5402
+f 5356 5402 5502
+f 5502 5402 5448
+f 5502 5448 5652
+f 5652 5448 5576
+f 5652 5576 5684
+f 5684 5576 5708
+f 5684 5708 5842
+f 5842 5708 5900
+f 5842 5900 6044
+f 6044 5900 5956
+f 6044 5956 6084
+f 6084 5956 6164
+f 6084 6164 6280
+f 6280 6164 6268
+f 6280 6268 6410
+f 6410 6268 6452
+f 6410 6452 6484
+f 6484 6452 6568
+f 6484 6568 6652
+f 6652 6568 6612
+f 6652 6612 6784
+f 6784 6612 6790
+f 6784 6790 6962
+f 6962 6790 6886
+f 6962 6886 7086
+f 7086 6886 7080
+f 7086 7080 7184
+f 7184 7080 7208
+f 7184 7208 7356
+f 7356 7208 7332
+f 7356 7332 7408
+f 7408 7332 7514
+f 7408 7514 7536
+f 7536 7514 7572
+f 7536 7572 7650
+f 7650 7572 7664
+f 7650 7664 7771
+f 7771 7664 7774
+f 7771 7774 7881
+f 140 146 212
+f 212 146 288
+f 212 288 408
+f 408 288 376
+f 408 376 544
+f 544 376 450
+f 544 450 676
+f 676 450 568
+f 676 568 678
+f 678 568 688
+f 678 688 864
+f 864 688 862
+f 864 862 1014
+f 1014 862 948
+f 1014 948 1070
+f 1070 948 1084
+f 1070 1084 1251
+f 1251 1084 1220
+f 1251 1220 1360
+f 1360 1220 1378
+f 1360 1378 1503
+f 1503 1378 1506
+f 1503 1506 1698
+f 1698 1506 1598
+f 1698 1598 1802
+f 1802 1598 1762
+f 1802 1762 1930
+f 1930 1762 1872
+f 1930 1872 2034
+f 2034 1872 1994
+f 2034 1994 2182
+f 2182 1994 2166
+f 2182 2166 2316
+f 2316 2166 2214
+f 2316 2214 2360
+f 2360 2214 2382
+f 2360 2382 2616
+f 2616 2382 2588
+f 2616 2588 2650
+f 2650 2588 2646
+f 2650 2646 2786
+f 2786 2646 2790
+f 2786 2790 2910
+f 2910 2790 2982
+f 2910 2982 3098
+f 3098 2982 3084
+f 3098 3084 3282
+f 3282 3084 3288
+f 3282 3288 3416
+f 3416 3288 3316
+f 3416 3316 3494
+f 3494 3316 3550
+f 3494 3550 3690
+f 3690 3550 3678
+f 3690 3678 3764
+f 3764 3678 3704
+f 3764 3704 3882
+f 3882 3704 3838
+f 3882 3838 4094
+f 4094 3838 4086
+f 4094 4086 4200
+f 4200 4086 4100
+f 4200 4100 4292
+f 4292 4100 4246
+f 4292 4246 4468
+f 4468 4246 4370
+f 4468 4370 4536
+f 4536 4370 4584
+f 4536 4584 4704
+f 4704 4584 4636
+f 4704 4636 4860
+f 4860 4636 4830
+f 4860 4830 4924
+f 4924 4830 4938
+f 4924 4938 5040
+f 5040 4938 5112
+f 5040 5112 5172
+f 5172 5112 5272
+f 5172 5272 5346
+f 5346 5272 5356
+f 5346 5356 5452
+f 5452 5356 5502
+f 5452 5502 5636
+f 5636 5502 5652
+f 5636 5652 5806
+f 5806 5652 5684
+f 5806 5684 5824
+f 5824 5684 5842
+f 5824 5842 5966
+f 5966 5842 6044
+f 5966 6044 6120
+f 6120 6044 6084
+f 6120 6084 6212
+f 6212 6084 6280
+f 6212 6280 6400
+f 6400 6280 6410
+f 6400 6410 6566
+f 6566 6410 6484
+f 6566 6484 6678
+f 6678 6484 6652
+f 6678 6652 6740
+f 6740 6652 6784
+f 6740 6784 6866
+f 6866 6784 6962
+f 6866 6962 7120
+f 7120 6962 7086
+f 7120 7086 7236
+f 7236 7086 7184
+f 7236 7184 7388
+f 7388 7184 7356
+f 7388 7356 7504
+f 7504 7356 7408
+f 7504 7408 7538
+f 7538 7408 7536
+f 7538 7536 7688
+f 7688 7536 7650
+f 7688 7650 7840
+f 7840 7650 7771
+f 7840 7771 7910
+f 126 140 224
+f 224 140 212
+f 224 212 348
+f 348 212 408
+f 348 408 522
+f 522 408 544
+f 522 544 648
+f 648 544 676
+f 648 676 752
+f 752 676 678
+f 752 678 806
+f 806 678 864
+f 806 864 956
+f 956 864 1014
+f 956 1014 1062
+f 1062 1014 1070
+f 1062 1070 1292
+f 1292 1070 1251
+f 1292 1251 1368
+f 1368 1251 1360
+f 1368 1360 1532
+f 1532 1360 1503
+f 1532 1503 1634
+f 1634 1503 1698
+f 1634 1698 1712
+f 1712 1698 1802
+f 1712 1802 1926
+f 1926 1802 1930
+f 1926 1930 2024
+f 2024 1930 2034
+f 2024 2034 2124
+f 2124 2034 2182
+f 2124 2182 2322
+f 2322 2182 2316
+f 2322 2316 2364
+f 2364 2316 2360
+f 2364 2360 2620
+f 2620 2360 2616
+f 2620 2616 2760
+f 2760 2616 2650
+f 2760 2650 2886
+f 2886 2650 2786
+f 2886 2786 2906
+f 2906 2786 2910
+f 2906 2910 3132
+f 3132 2910 3098
+f 3132 3098 3198
+f 3198 3098 3282
+f 3198 3282 3400
+f 3400 3282 3416
+f 3400 3416 3496
+f 3496 3416 3494
+f 3496 3494 3688
+f 3688 3494 3690
+f 3688 3690 3794
+f 3794 3690 3764
+f 3794 3764 3896
+f 3896 3764 3882
+f 3896 3882 4056
+f 4056 3882 4094
+f 4056 4094 4146
+f 4146 4094 4200
+f 4146 4200 4278
+f 4278 4200 4292
+f 4278 4292 4456
+f 4456 4292 4468
+f 4456 4468 4534
+f 4534 4468 4536
+f 4534 4536 4746
+f 4746 4536 4704
+f 4746 4704 4828
+f 4828 4704 4860
+f 4828 4860 4898
+f 4898 4860 4924
+f 4898 4924 5084
+f 5084 4924 5040
+f 5084 5040 5178
+f 5178 5040 5172
+f 5178 5172 5328
+f 5328 5172 5346
+f 5328 5346 5420
+f 5420 5346 5452
+f 5420 5452 5638
+f 5638 5452 5636
+f 5638 5636 5752
+f 5752 5636 5806
+f 5752 5806 5868
+f 5868 5806 5824
+f 5868 5824 5950
+f 5950 5824 5966
+f 5950 5966 6132
+f 6132 5966 6120
+f 6132 6120 6284
+f 6284 6120 6212
+f 6284 6212 6346
+f 6346 6212 6400
+f 6346 6400 6538
+f 6538 6400 6566
+f 6538 6566 6674
+f 6674 6566 6678
+f 6674 6678 6760
+f 6760 6678 6740
+f 6760 6740 6960
+f 6960 6740 6866
+f 6960 6866 7104
+f 7104 6866 7120
+f 7104 7120 7190
+f 7190 7120 7236
+f 7190 7236 7294
+f 7294 7236 7388
+f 7294 7388 7436
+f 7436 7388 7504
+f 7436 7504 7614
+f 7614 7504 7538
+f 7614 7538 7652
+f 7652 7538 7688
+f 7652 7688 7798
+f 7798 7688 7840
+f 7798 7840 7914
+f 154 126 168
+f 168 126 224
+f 168 224 302
+f 302 224 348
+f 302 348 490
+f 490 348 522
+f 490 522 668
+f 668 522 648
+f 668 648 778
+f 778 648 752
+f 778 752 884
+f 884 752 806
+f 884 806 936
+f 936 806 956
+f 936 956 1154
+f 1154 956 1062
+f 1154 1062 1312
+f 1312 1062 1292
+f 1312 1292 1348
+f 1348 1292 1368
+f 1348 1368 1446
+f 1446 1368 1532
+f 1446 1532 1668
+f 1668 1532 1634
+f 1668 1634 1796
+f 1796 1634 1712
+f 1796 1712 1842
+f 1842 1712 1926
+f 1842 1926 1966
+f 1966 1926 2024
+f 1966 2024 2120
+f 2120 2024 2124
+f 2120 2124 2326
+f 2326 2124 2322
+f 2326 2322 2440
+f 2440 2322 2364
+f 2440 2364 2540
+f 2540 2364 2620
+f 2540 2620 2654
+f 2654 2620 2760
+f 2654 2760 2796
+f 2796 2760 2886
+f 2796 2886 3014
+f 3014 2886 2906
+f 3014 2906 3056
+f 3056 2906 3132
+f 3056 3132 3210
+f 3210 3132 3198
+f 3210 3198 3326
+f 3326 3198 3400
+f 3326 3400 3476
+f 3476 3400 3496
+f 3476 3496 3636
+f 3636 3496 3688
+f 3636 3688 3790
+f 3790 3688 3794
+f 3790 3794 3846
+f 3846 3794 3896
+f 3846 3896 4006
+f 4006 3896 4056
+f 4006 4056 4208
+f 4208 4056 4146
+f 4208 4146 4342
+f 4342 4146 4278
+f 4342 4278 4380
+f 4380 4278 4456
+f 4380 4456 4514
+f 4514 4456 4534
+f 4514 4534 4638
+f 4638 4534 4746
+f 4638 4746 4804
+f 4804 4746 4828
+f 4804 4828 4988
+f 4988 4828 4898
+f 4988 4898 5048
+f 5048 4898 5084
+f 5048 5084 5184
+f 5184 5084 5178
+f 5184 5178 5316
+f 5316 5178 5328
+f 5316 5328 5422
+f 5422 5328 5420
+f 5422 5420 5662
+f 5662 5420 5638
+f 5662 5638 5750
+f 5750 5638 5752
+f 5750 5752 5876
+f 5876 5752 5868
+f 5876 5868 5968
+f 5968 5868 5950
+f 5968 5950 6140
+f 6140 5950 6132
+f 6140 6132 6248
+f 6248 6132 6284
+f 6248 6284 6458
+f 6458 6284 6346
+f 6458 6346 6558
+f 6558 6346 6538
+f 6558 6538 6670
+f 6670 6538 6674
+f 6670 6674 6788
+f 6788 6674 6760
+f 6788 6760 6858
+f 6858 6760 6960
+f 6858 6960 7050
+f 7050 6960 7104
+f 7050 7104 7224
+f 7224 7104 7190
+f 7224 7190 7320
+f 7320 7190 7294
+f 7320 7294 7446
+f 7446 7294 7436
+f 7446 7436 7628
+f 7628 7436 7614
+f 7628 7614 7648
+f 7648 7614 7652
+f 7648 7652 7812
+f 7812 7652 7798
+f 7812 7798 7893
+f 122 154 258
+f 258 154 168
+f 258 168 362
+f 362 168 302
+f 362 302 486
+f 486 302 490
+f 486 490 606
+f 606 490 668
+f 606 668 746
+f 746 668 778
+f 746 778 820
+f 820 778 884
+f 820 884 990
+f 990 884 936
+f 990 936 1132
+f 1132 936 1154
+f 1132 1154 1206
+f 1206 1154 1312
+f 1206 1312 1370
+f 1370 1312 1348
+f 1370 1348 1530
+f 1530 1348 1446
+f 1530 1446 1638
+f 1638 1446 1668
+f 1638 1668 1824
+f 1824 1668 1796
+f 1824 1796 1830
+f 1830 1796 1842
+f 1830 1842 2058
+f 2058 1842 1966
+f 2058 1966 2198
+f 2198 1966 2120
+f 2198 2120 2332
+f 2332 2120 2326
+f 2332 2326 2484
+f 2484 2326 2440
+f 2484 2440 2502
+f 2502 2440 2540
+f 2502 2540 2652
+f 2652 2540 2654
+f 2652 2654 2812
+f 2812 2654 2796
+f 2812 2796 2948
+f 2948 2796 3014
+f 2948 3014 3068
+f 3068 3014 3056
+f 3068 3056 3206
+f 3206 3056 3210
+f 3206 3210 3360
+f 3360 3210 3326
+f 3360 3326 3504
+f 3504 3326 3476
+f 3504 3476 3590
+f 3590 3476 3636
+f 3590 3636 3776
+f 3776 3636 3790
+f 3776 3790 3850
+f 3850 3790 3846
+f 3850 3846 4004
+f 4004 3846 4006
+f 4004 4006 4206
+f 4206 4006 4208
+f 4206 4208 4254
+f 4254 4208 4342
+f 4254 4342 4466
+f 4466 4342 4380
+f 4466 4380 4612
+f 4612 4380 4514
+f 4612 4514 4660
+f 4660 4514 4638
+f 4660 4638 4776
+f 4776 4638 4804
+f 4776 4804 4894
+f 4894 4804 4988
+f 4894 4988 5026
+f 5026 4988 5048
+f 5026 5048 5188
+f 5188 5048 5184
+f 5188 5184 5330
+f 5330 5184 5316
+f 5330 5316 5470
+f 5470 5316 5422
+f 5470 5422 5648
+f 5648 5422 5662
+f 5648 5662 5800
+f 5800 5662 5750
+f 5800 5750 5820
+f 5820 5750 5876
+f 5820 5876 5960
+f 5960 5876 5968
+f 5960 5968 6086
+f 6086 5968 6140
+f 6086 6140 6264
+f 6264 6140 6248
+f 6264 6248 6348
+f 6348 6248 6458
+f 6348 6458 6526
+f 6526 6458 6558
+f 6526 6558 6690
+f 6690 6558 6670
+f 6690 6670 6848
+f 6848 6670 6788
+f 6848 6788 6912
+f 6912 6788 6858
+f 6912 6858 7100
+f 7100 6858 7050
+f 7100 7050 7232
+f 7232 7050 7224
+f 7232 7224 7310
+f 7310 7224 7320
+f 7310 7320 7438
+f 7438 7320 7446
+f 7438 7446 7586
+f 7586 7446 7628
+f 7586 7628 7708
+f 7708 7628 7648
+f 7708 7648 7856
+f 7856 7648 7812
+f 7856 7812 7923
+f 144 122 202
+f 202 122 258
+f 202 258 308
+f 308 258 362
+f 308 362 510
+f 510 362 486
+f 510 486 594
+f 594 486 606
+f 594 606 734
+f 734 606 746
+f 734 746 810
+f 810 746 820
+f 810 820 958
+f 958 820 990
+f 958 990 1152
+f 1152 990 1132
+f 1152 1132 1244
+f 1244 1132 1206
+f 1244 1206 1422
+f 1422 1206 1370
+f 1422 1370 1516
+f 1516 1370 1530
+f 1516 1530 1678
+f 1678 1530 1638
+f 1678 1638 1748
+f 1748 1638 1824
+f 1748 1824 1902
+f 1902 1824 1830
+f 1902 1830 2002
+f 2002 1830 2058
+f 2002 2058 2154
+f 2154 2058 2198
+f 2154 2198 2328
+f 2328 2198 2332
+f 2328 2332 2450
+f 2450 2332 2484
+f 2450 2484 2516
+f 2516 2484 2502
+f 2516 2502 2736
+f 2736 2502 2652
+f 2736 2652 2804
+f 2804 2652 2812
+f 2804 2812 3020
+f 3020 2812 2948
+f 3020 2948 3040
+f 3040 2948 3068
+f 3040 3068 3224
+f 3224 3068 3206
+f 3224 3206 3424
+f 3424 3206 3360
+f 3424 3360 3468
+f 3468 3360 3504
+f 3468 3504 3606
+f 3606 3504 3590
+f 3606 3590 3810
+f 3810 3590 3776
+f 3810 3776 3932
+f 3932 3776 3850
+f 3932 3850 3968
+f 3968 3850 4004
+f 3968 4004 4224
+f 4224 4004 4206
+f 4224 4206 4306
+f 4306 4206 4254
+f 4306 4254 4442
+f 4442 4254 4466
+f 4442 4466 4604
+f 4604 4466 4612
+f 4604 4612 4686
+f 4686 4612 4660
+f 4686 4660 4846
+f 4846 4660 4776
+f 4846 4776 5018
+f 5018 4776 4894
+f 5018 4894 5064
+f 5064 4894 5026
+f 5064 5026 5160
+f 5160 5026 5188
+f 5160 5188 5372
+f 5372 5188 5330
+f 5372 5330 5444
+f 5444 5330 5470
+f 5444 5470 5562
+f 5562 5470 5648
+f 5562 5648 5694
+f 5694 5648 5800
+f 5694 5800 5906
+f 5906 5800 5820
+f 5906 5820 6004
+f 6004 5820 5960
+f 6004 5960 6138
+f 6138 5960 6086
+f 6138 6086 6294
+f 6294 6086 6264
+f 6294 6264 6358
+f 6358 6264 6348
+f 6358 6348 6564
+f 6564 6348 6526
+f 6564 6526 6598
+f 6598 6526 6690
+f 6598 6690 6776
+f 6776 6690 6848
+f 6776 6848 6878
+f 6878 6848 6912
+f 6878 6912 7122
+f 7122 6912 7100
+f 7122 7100 7166
+f 7166 7100 7232
+f 7166 7232 7318
+f 7318 7232 7310
+f 7318 7310 7406
+f 7406 7310 7438
+f 7406 7438 7620
+f 7620 7438 7586
+f 7620 7586 7734
+f 7734 7586 7708
+f 7734 7708 7854
+f 7854 7708 7856
+f 7854 7856 7907
+f 120 144 268
+f 268 144 202
+f 268 202 350
+f 350 202 308
+f 350 308 422
+f 422 308 510
+f 422 510 640
+f 640 510 594
+f 640 594 714
+f 714 594 734
+f 714 734 902
+f 902 734 810
+f 902 810 1056
+f 1056 810 958
+f 1056 958 1098
+f 1098 958 1152
+f 1098 1152 1276
+f 1276 1152 1244
+f 1276 1244 1380
+f 1380 1244 1422
+f 1380 1422 1478
+f 1478 1422 1516
+f 1478 1516 1582
+f 1582 1516 1678
+f 1582 1678 1788
+f 1788 1678 1748
+f 1788 1748 1914
+f 1914 1748 1902
+f 1914 1902 2026
+f 2026 1902 2002
+f 2026 2002 2142
+f 2142 2002 2154
+f 2142 2154 2314
+f 2314 2154 2328
+f 2314 2328 2374
+f 2374 2328 2450
+f 2374 2450 2594
+f 2594 2450 2516
+f 2594 2516 2750
+f 2750 2516 2736
+f 2750 2736 2800
+f 2800 2736 2804
+f 2800 2804 2916
+f 2916 2804 3020
+f 2916 3020 3130
+f 3130 3020 3040
+f 3130 3040 3264
+f 3264 3040 3224
+f 3264 3224 3368
+f 3368 3224 3424
+f 3368 3424 3538
+f 3538 3424 3468
+f 3538 3468 3656
+f 3656 3468 3606
+f 3656 3606 3760
+f 3760 3606 3810
+f 3760 3810 3960
+f 3960 3810 3932
+f 3960 3932 4078
+f 4078 3932 3968
+f 4078 3968 4112
+f 4112 3968 4224
+f 4112 4224 4236
+f 4236 4224 4306
+f 4236 4306 4376
+f 4376 4306 4442
+f 4376 4442 4500
+f 4500 4442 4604
+f 4500 4604 4752
+f 4752 4604 4686
+f 4752 4686 4770
+f 4770 4686 4846
+f 4770 4846 4976
+f 4976 4846 5018
+f 4976 5018 5088
+f 5088 5018 5064
+f 5088 5064 5248
+f 5248 5064 5160
+f 5248 5160 5302
+f 5302 5160 5372
+f 5302 5372 5504
+f 5504 5372 5444
+f 5504 5444 5566
+f 5566 5444 5562
+f 5566 5562 5768
+f 5768 5562 5694
+f 5768 5694 5934
+f 5934 5694 5906
+f 5934 5906 6024
+f 6024 5906 6004
+f 6024 6004 6144
+f 6144 6004 6138
+f 6144 6138 6206
+f 6206 6138 6294
+f 6206 6294 6412
+f 6412 6294 6358
+f 6412 6358 6516
+f 6516 6358 6564
+f 6516 6564 6668
+f 6668 6564 6598
+f 6668 6598 6734
+f 6734 6598 6776
+f 6734 6776 6888
+f 6888 6776 6878
+f 6888 6878 7112
+f 7112 6878 7122
+f 7112 7122 7154
+f 7154 7122 7166
+f 7154 7166 7336
+f 7336 7166 7318
+f 7336 7318 7448
+f 7448 7318 7406
+f 7448 7406 7616
+f 7616 7406 7620
+f 7616 7620 7694
+f 7694 7620 7734
+f 7694 7734 7794
+f 7794 7734 7854
+f 7794 7854 7887
+f 100 120 228
+f 228 120 268
+f 228 268 332
+f 332 268 350
+f 332 350 472
+f 472 350 422
+f 472 422 570
+f 570 422 640
+f 570 640 760
+f 760 640 714
+f 760 714 888
+f 888 714 902
+f 888 902 942
+f 942 902 1056
+f 942 1056 1064
+f 1064 1056 1098
+f 1064 1098 1226
+f 1226 1098 1276
+f 1226 1276 1372
+f 1372 1276 1380
+f 1372 1380 1546
+f 1546 1380 1478
+f 1546 1478 1644
+f 1644 1478 1582
+f 1644 1582 1782
+f 1782 1582 1788
+f 1782 1788 1864
+f 1864 1788 1914
+f 1864 1914 2082
+f 2082 1914 2026
+f 2082 2026 2118
+f 2118 2026 2142
+f 2118 2142 2304
+f 2304 2142 2314
+f 2304 2314 2486
+f 2486 2314 2374
+f 2486 2374 2552
+f 2552 2374 2594
+f 2552 2594 2748
+f 2748 2594 2750
+f 2748 2750 2772
+f 2772 2750 2800
+f 2772 2800 2960
+f 2960 2800 2916
+f 2960 2916 3144
+f 3144 2916 3130
+f 3144 3130 3186
+f 3186 3130 3264
+f 3186 3264 3322
+f 3322 3264 3368
+f 3322 3368 3486
+f 3486 3368 3538
+f 3486 3538 3608
+f 3608 3538 3656
+f 3608 3656 3754
+f 3754 3656 3760
+f 3754 3760 3916
+f 3916 3760 3960
+f 3916 3960 3970
+f 3970 3960 4078
+f 3970 4078 4106
+f 4106 4078 4112
+f 4106 4112 4288
+f 4288 4112 4236
+f 4288 4236 4392
+f 4392 4236 4376
+f 4392 4376 4540
+f 4540 4376 4500
+f 4540 4500 4716
+f 4716 4500 4752
+f 4716 4752 4862
+f 4862 4752 4770
+f 4862 4770 4936
+f 4936 4770 4976
+f 4936 4976 5096
+f 5096 4976 5088
+f 5096 5088 5236
+f 5236 5088 5248
+f 5236 5248 5300
+f 5300 5248 5302
+f 5300 5302 5514
+f 5514 5302 5504
+f 5514 5504 5560
+f 5560 5504 5566
+f 5560 5566 5714
+f 5714 5566 5768
+f 5714 5768 5874
+f 5874 5768 5934
+f 5874 5934 5944
+f 5944 5934 6024
+f 5944 6024 6126
+f 6126 6024 6144
+f 6126 6144 6324
+f 6324 6144 6206
+f 6324 6206 6362
+f 6362 6206 6412
+f 6362 6412 6580
+f 6580 6412 6516
+f 6580 6516 6640
+f 6640 6516 6668
+f 6640 6668 6744
+f 6744 6668 6734
+f 6744 6734 6860
+f 6860 6734 6888
+f 6860 6888 7098
+f 7098 6888 7112
+f 7098 7112 7200
+f 7200 7112 7154
+f 7200 7154 7370
+f 7370 7154 7336
+f 7370 7336 7508
+f 7508 7336 7448
+f 7508 7448 7612
+f 7612 7448 7616
+f 7612 7616 7750
+f 7750 7616 7694
+f 7750 7694 7816
+f 7816 7694 7794
+f 7816 7794 7895
+f 112 100 182
+f 182 100 228
+f 182 228 310
+f 310 228 332
+f 310 332 470
+f 470 332 472
+f 470 472 626
+f 626 472 570
+f 626 570 730
+f 730 570 760
+f 730 760 816
+f 816 760 888
+f 816 888 974
+f 974 888 942
+f 974 942 1082
+f 1082 942 1064
+f 1082 1064 1252
+f 1252 1064 1226
+f 1252 1226 1332
+f 1332 1226 1372
+f 1332 1372 1504
+f 1504 1372 1546
+f 1504 1546 1616
+f 1616 1546 1644
+f 1616 1644 1740
+f 1740 1644 1782
+f 1740 1782 1942
+f 1942 1782 1864
+f 1942 1864 2080
+f 2080 1864 2082
+f 2080 2082 2144
+f 2144 2082 2118
+f 2144 2118 2334
+f 2334 2118 2304
+f 2334 2304 2384
+f 2384 2304 2486
+f 2384 2486 2504
+f 2504 2486 2552
+f 2504 2552 2734
+f 2734 2552 2748
+f 2734 2748 2880
+f 2880 2748 2772
+f 2880 2772 2980
+f 2980 2772 2960
+f 2980 2960 3124
+f 3124 2960 3144
+f 3124 3144 3226
+f 3226 3144 3186
+f 3226 3186 3384
+f 3384 3186 3322
+f 3384 3322 3472
+f 3472 3322 3486
+f 3472 3486 3684
+f 3684 3486 3608
+f 3684 3608 3734
+f 3734 3608 3754
+f 3734 3754 3836
+f 3836 3754 3916
+f 3836 3916 4038
+f 4038 3916 3970
+f 4038 3970 4122
+f 4122 3970 4106
+f 4122 4106 4326
+f 4326 4106 4288
+f 4326 4288 4378
+f 4378 4288 4392
+f 4378 4392 4600
+f 4600 4392 4540
+f 4600 4540 4640
+f 4640 4540 4716
+f 4640 4716 4760
+f 4760 4716 4862
+f 4760 4862 5016
+f 5016 4862 4936
+f 5016 4936 5116
+f 5116 4936 5096
+f 5116 5096 5266
+f 5266 5096 5236
+f 5266 5236 5362
+f 5362 5236 5300
+f 5362 5300 5446
+f 5446 5300 5514
+f 5446 5514 5632
+f 5632 5514 5560
+f 5632 5560 5732
+f 5732 5560 5714
+f 5732 5714 5860
+f 5860 5714 5874
+f 5860 5874 6048
+f 6048 5874 5944
+f 6048 5944 6198
+f 6198 5944 6126
+f 6198 6126 6292
+f 6292 6126 6324
+f 6292 6324 6434
+f 6434 6324 6362
+f 6434 6362 6510
+f 6510 6362 6580
+f 6510 6580 6712
+f 6712 6580 6640
+f 6712 6640 6824
+f 6824 6640 6744
+f 6824 6744 6928
+f 6928 6744 6860
+f 6928 6860 7088
+f 7088 6860 7098
+f 7088 7098 7226
+f 7226 7098 7200
+f 7226 7200 7322
+f 7322 7200 7370
+f 7322 7370 7452
+f 7452 7370 7508
+f 7452 7508 7606
+f 7606 7508 7612
+f 7606 7612 7656
+f 7656 7612 7750
+f 7656 7750 7824
+f 7824 7750 7816
+f 7824 7816 7925
+f 110 112 238
+f 238 112 182
+f 238 182 374
+f 374 182 310
+f 374 310 494
+f 494 310 470
+f 494 470 616
+f 616 470 626
+f 616 626 686
+f 686 626 730
+f 686 730 834
+f 834 730 816
+f 834 816 1030
+f 1030 816 974
+f 1030 974 1182
+f 1182 974 1082
+f 1182 1082 1248
+f 1248 1082 1252
+f 1248 1252 1426
+f 1426 1252 1332
+f 1426 1332 1564
+f 1564 1332 1504
+f 1564 1504 1588
+f 1588 1504 1616
+f 1588 1616 1750
+f 1750 1616 1740
+f 1750 1740 1912
+f 1912 1740 1942
+f 1912 1942 1962
+f 1962 1942 2080
+f 1962 2080 2174
+f 2174 2080 2144
+f 2174 2144 2338
+f 2338 2144 2334
+f 2338 2334 2388
+f 2388 2334 2384
+f 2388 2384 2544
+f 2544 2384 2504
+f 2544 2504 2664
+f 2664 2504 2734
+f 2664 2734 2844
+f 2844 2734 2880
+f 2844 2880 2996
+f 2996 2880 2980
+f 2996 2980 3150
+f 3150 2980 3124
+f 3150 3124 3234
+f 3234 3124 3226
+f 3234 3226 3374
+f 3374 3226 3384
+f 3374 3384 3444
+f 3444 3384 3472
+f 3444 3472 3664
+f 3664 3472 3684
+f 3664 3684 3742
+f 3742 3684 3734
+f 3742 3734 3924
+f 3924 3734 3836
+f 3924 3836 3974
+f 3974 3836 4038
+f 3974 4038 4158
+f 4158 4038 4122
+f 4158 4122 4244
+f 4244 4122 4326
+f 4244 4326 4452
+f 4452 4326 4378
+f 4452 4378 4510
+f 4510 4378 4600
+f 4510 4600 4668
+f 4668 4600 4640
+f 4668 4640 4878
+f 4878 4640 4760
+f 4878 4760 4926
+f 4926 4760 5016
+f 4926 5016 5058
+f 5058 5016 5116
+f 5058 5116 5202
+f 5202 5116 5266
+f 5202 5266 5340
+f 5340 5266 5362
+f 5340 5362 5474
+f 5474 5362 5446
+f 5474 5446 5658
+f 5658 5446 5632
+f 5658 5632 5794
+f 5794 5632 5732
+f 5794 5732 5856
+f 5856 5732 5860
+f 5856 5860 6030
+f 6030 5860 6048
+f 6030 6048 6134
+f 6134 6048 6198
+f 6134 6198 6320
+f 6320 6198 6292
+f 6320 6292 6404
+f 6404 6292 6434
+f 6404 6434 6506
+f 6506 6434 6510
+f 6506 6510 6688
+f 6688 6510 6712
+f 6688 6712 6778
+f 6778 6712 6824
+f 6778 6824 6868
+f 6868 6824 6928
+f 6868 6928 7012
+f 7012 6928 7088
+f 7012 7088 7240
+f 7240 7088 7226
+f 7240 7226 7360
+f 7360 7226 7322
+f 7360 7322 7442
+f 7442 7322 7452
+f 7442 7452 7582
+f 7582 7452 7606
+f 7582 7606 7722
+f 7722 7606 7656
+f 7722 7656 7836
+f 7836 7656 7824
+f 7836 7824 7886
+f 68 110 172
+f 172 110 238
+f 172 238 372
+f 372 238 374
+f 372 374 424
+f 424 374 494
+f 424 494 644
+f 644 494 616
+f 644 616 790
+f 790 616 686
+f 790 686 836
+f 836 686 834
+f 836 834 964
+f 964 834 1030
+f 964 1030 1164
+f 1164 1030 1182
+f 1164 1182 1202
+f 1202 1182 1248
+f 1202 1248 1336
+f 1336 1248 1426
+f 1336 1426 1514
+f 1514 1426 1564
+f 1514 1564 1596
+f 1596 1564 1588
+f 1596 1588 1794
+f 1794 1588 1750
+f 1794 1750 1868
+f 1868 1750 1912
+f 1868 1912 1972
+f 1972 1912 1962
+f 1972 1962 2180
+f 2180 1962 2174
+f 2180 2174 2218
+f 2218 2174 2338
+f 2218 2338 2474
+f 2474 2338 2388
+f 2474 2388 2508
+f 2508 2388 2544
+f 2508 2544 2662
+f 2662 2544 2664
+f 2662 2664 2802
+f 2802 2664 2844
+f 2802 2844 2958
+f 2958 2844 2996
+f 2958 2996 3078
+f 3078 2996 3150
+f 3078 3150 3280
+f 3280 3150 3234
+f 3280 3234 3392
+f 3392 3234 3374
+f 3392 3374 3556
+f 3556 3374 3444
+f 3556 3444 3576
+f 3576 3444 3664
+f 3576 3664 3750
+f 3750 3664 3742
+f 3750 3742 3894
+f 3894 3742 3924
+f 3894 3924 4070
+f 4070 3924 3974
+f 4070 3974 4188
+f 4188 3974 4158
+f 4188 4158 4266
+f 4266 4158 4244
+f 4266 4244 4400
+f 4400 4244 4452
+f 4400 4452 4564
+f 4564 4452 4510
+f 4564 4510 4678
+f 4678 4510 4668
+f 4678 4668 4868
+f 4868 4668 4878
+f 4868 4878 4994
+f 4994 4878 4926
+f 4994 4926 5122
+f 5122 4926 5058
+f 5122 5058 5270
+f 5270 5058 5202
+f 5270 5202 5314
+f 5314 5202 5340
+f 5314 5340 5500
+f 5500 5340 5474
+f 5500 5474 5672
+f 5672 5474 5658
+f 5672 5658 5688
+f 5688 5658 5794
+f 5688 5794 5850
+f 5850 5794 5856
+f 5850 5856 6066
+f 6066 5856 6030
+f 6066 6030 6186
+f 6186 6030 6134
+f 6186 6134 6242
+f 6242 6134 6320
+f 6242 6320 6368
+f 6368 6320 6404
+f 6368 6404 6520
+f 6520 6404 6506
+f 6520 6506 6614
+f 6614 6506 6688
+f 6614 6688 6794
+f 6794 6688 6778
+f 6794 6778 6872
+f 6872 6778 6868
+f 6872 6868 7052
+f 7052 6868 7012
+f 7052 7012 7262
+f 7262 7012 7240
+f 7262 7240 7372
+f 7372 7240 7360
+f 7372 7360 7496
+f 7496 7360 7442
+f 7496 7442 7626
+f 7626 7442 7582
+f 7626 7582 7658
+f 7658 7582 7722
+f 7658 7722 7832
+f 7832 7722 7836
+f 7832 7836 7924
+f 42 68 220
+f 220 68 172
+f 220 172 360
+f 360 172 372
+f 360 372 548
+f 548 372 424
+f 548 424 580
+f 580 424 644
+f 580 644 706
+f 706 644 790
+f 706 790 922
+f 922 790 836
+f 922 836 998
+f 998 836 964
+f 998 964 1066
+f 1066 964 1164
+f 1066 1164 1200
+f 1200 1164 1202
+f 1200 1202 1396
+f 1396 1202 1336
+f 1396 1336 1572
+f 1572 1336 1514
+f 1572 1514 1646
+f 1646 1514 1596
+f 1646 1596 1760
+f 1760 1596 1794
+f 1760 1794 1870
+f 1870 1794 1868
+f 1870 1868 1978
+f 1978 1868 1972
+f 1978 1972 2208
+f 2208 1972 2180
+f 2208 2180 2324
+f 2324 2180 2218
+f 2324 2218 2472
+f 2472 2218 2474
+f 2472 2474 2518
+f 2518 2474 2508
+f 2518 2508 2726
+f 2726 2508 2662
+f 2726 2662 2798
+f 2798 2662 2802
+f 2798 2802 3030
+f 3030 2802 2958
+f 3030 2958 3158
+f 3158 2958 3078
+f 3158 3078 3191
+f 3191 3078 3280
+f 3191 3280 3308
+f 3308 3280 3392
+f 3308 3392 3442
+f 3442 3392 3556
+f 3442 3556 3572
+f 3572 3556 3576
+f 3572 3576 3824
+f 3824 3576 3750
+f 3824 3750 3842
+f 3842 3750 3894
+f 3842 3894 4092
+f 4092 3894 4070
+f 4092 4070 4108
+f 4108 4070 4188
+f 4108 4188 4358
+f 4358 4188 4266
+f 4358 4266 4486
+f 4486 4266 4400
+f 4486 4400 4608
+f 4608 4400 4564
+f 4608 4564 4734
+f 4734 4564 4678
+f 4734 4678 4778
+f 4778 4678 4868
+f 4778 4868 4900
+f 4900 4868 4994
+f 4900 4994 5110
+f 5110 4994 5122
+f 5110 5122 5224
+f 5224 5122 5270
+f 5224 5270 5394
+f 5394 5270 5314
+f 5394 5314 5476
+f 5476 5314 5500
+f 5476 5500 5600
+f 5600 5500 5672
+f 5600 5672 5704
+f 5704 5672 5688
+f 5704 5688 5894
+f 5894 5688 5850
+f 5894 5850 6000
+f 6000 5850 6066
+f 6000 6066 6108
+f 6108 6066 6186
+f 6108 6186 6314
+f 6314 6186 6242
+f 6314 6242 6444
+f 6444 6242 6368
+f 6444 6368 6544
+f 6544 6368 6520
+f 6544 6520 6696
+f 6696 6520 6614
+f 6696 6614 6814
+f 6814 6614 6794
+f 6814 6794 6910
+f 6910 6794 6872
+f 6910 6872 7130
+f 7130 6872 7052
+f 7130 7052 7246
+f 7246 7052 7262
+f 7246 7262 7282
+f 7282 7262 7372
+f 7282 7372 7420
+f 7420 7372 7496
+f 7420 7496 7608
+f 7608 7496 7626
+f 7608 7626 7662
+f 7662 7626 7658
+f 7662 7658 7772
+f 7772 7658 7832
+f 7772 7832 7929
+f 162 42 166
+f 166 42 220
+f 166 220 300
+f 300 220 360
+f 300 360 430
+f 430 360 548
+f 430 548 646
+f 646 548 580
+f 646 580 744
+f 744 580 706
+f 744 706 874
+f 874 706 922
+f 874 922 1026
+f 1026 922 998
+f 1026 998 1076
+f 1076 998 1066
+f 1076 1066 1230
+f 1230 1066 1200
+f 1230 1200 1438
+f 1438 1200 1396
+f 1438 1396 1556
+f 1556 1396 1572
+f 1556 1572 1602
+f 1602 1572 1646
+f 1602 1646 1704
+f 1704 1646 1760
+f 1704 1760 1938
+f 1938 1760 1870
+f 1938 1870 1960
+f 1960 1870 1978
+f 1960 1978 2194
+f 2194 1978 2208
+f 2194 2208 2320
+f 2320 2208 2324
+f 2320 2324 2480
+f 2480 2324 2472
+f 2480 2472 2526
+f 2526 2472 2518
+f 2526 2518 2712
+f 2712 2518 2726
+f 2712 2726 2818
+f 2818 2726 2798
+f 2818 2798 2908
+f 2908 2798 3030
+f 2908 3030 3044
+f 3044 3030 3158
+f 3044 3158 3296
+f 3296 3158 3191
+f 3296 3191 3312
+f 3312 3191 3308
+f 3312 3308 3524
+f 3524 3308 3442
+f 3524 3442 3638
+f 3638 3442 3572
+f 3638 3572 3716
+f 3716 3572 3824
+f 3716 3824 3962
+f 3962 3824 3842
+f 3962 3842 4088
+f 4088 3842 4092
+f 4088 4092 4214
+f 4214 4092 4108
+f 4214 4108 4274
+f 4274 4108 4358
+f 4274 4358 4394
+f 4394 4358 4486
+f 4394 4486 4572
+f 4572 4486 4608
+f 4572 4608 4744
+f 4744 4608 4734
+f 4744 4734 4870
+f 4870 4734 4778
+f 4870 4778 5000
+f 5000 4778 4900
+f 5000 4900 5090
+f 5090 4900 5110
+f 5090 5110 5218
+f 5218 5110 5224
+f 5218 5224 5374
+f 5374 5224 5394
+f 5374 5394 5424
+f 5424 5394 5476
+f 5424 5476 5582
+f 5582 5476 5600
+f 5582 5600 5804
+f 5804 5600 5704
+f 5804 5704 5932
+f 5932 5704 5894
+f 5932 5894 6050
+f 6050 5894 6000
+f 6050 6000 6076
+f 6076 6000 6108
+f 6076 6108 6298
+f 6298 6108 6314
+f 6298 6314 6366
+f 6366 6314 6444
+f 6366 6444 6504
+f 6504 6444 6544
+f 6504 6544 6644
+f 6644 6544 6696
+f 6644 6696 6766
+f 6766 6696 6814
+f 6766 6814 6876
+f 6876 6814 6910
+f 6876 6910 7016
+f 7016 6910 7130
+f 7016 7130 7254
+f 7254 7130 7246
+f 7254 7246 7376
+f 7376 7246 7282
+f 7376 7282 7478
+f 7478 7282 7420
+f 7478 7420 7592
+f 7592 7420 7608
+f 7592 7608 7746
+f 7746 7608 7662
+f 7746 7662 7783
+f 7783 7662 7772
+f 7783 7772 7897
+f 108 162 284
+f 284 162 166
+f 284 166 336
+f 336 166 300
+f 336 300 546
+f 546 300 430
+f 546 430 614
+f 614 430 646
+f 614 646 684
+f 684 646 744
+f 684 744 866
+f 866 744 874
+f 866 874 1044
+f 1044 874 1026
+f 1044 1026 1088
+f 1088 1026 1076
+f 1088 1076 1198
+f 1198 1076 1230
+f 1198 1230 1416
+f 1416 1230 1438
+f 1416 1438 1562
+f 1562 1438 1556
+f 1562 1556 1578
+f 1578 1556 1602
+f 1578 1602 1728
+f 1728 1602 1704
+f 1728 1704 1888
+f 1888 1704 1938
+f 1888 1938 2050
+f 2050 1938 1960
+f 2050 1960 2126
+f 2126 1960 2194
+f 2126 2194 2234
+f 2234 2194 2320
+f 2234 2320 2378
+f 2378 2320 2480
+f 2378 2480 2612
+f 2612 2480 2526
+f 2612 2526 2668
+f 2668 2526 2712
+f 2668 2712 2884
+f 2884 2712 2818
+f 2884 2818 2992
+f 2992 2818 2908
+f 2992 2908 3122
+f 3122 2908 3044
+f 3122 3044 3232
+f 3232 3044 3296
+f 3232 3296 3320
+f 3320 3296 3312
+f 3320 3312 3520
+f 3520 3312 3524
+f 3520 3524 3598
+f 3598 3524 3638
+f 3598 3638 3766
+f 3766 3638 3716
+f 3766 3716 3888
+f 3888 3716 3962
+f 3888 3962 4040
+f 4040 3962 4088
+f 4040 4088 4142
+f 4142 4088 4214
+f 4142 4214 4318
+f 4318 4214 4274
+f 4318 4274 4408
+f 4408 4274 4394
+f 4408 4394 4598
+f 4598 4394 4572
+f 4598 4572 4700
+f 4700 4572 4744
+f 4700 4744 4816
+f 4816 4744 4870
+f 4816 4870 4950
+f 4950 4870 5000
+f 4950 5000 5038
+f 5038 5000 5090
+f 5038 5090 5232
+f 5232 5090 5218
+f 5232 5218 5308
+f 5308 5218 5374
+f 5308 5374 5526
+f 5526 5374 5424
+f 5526 5424 5628
+f 5628 5424 5582
+f 5628 5582 5776
+f 5776 5582 5804
+f 5776 5804 5918
+f 5918 5804 5932
+f 5918 5932 6008
+f 6008 5932 6050
+f 6008 6050 6124
+f 6124 6050 6076
+f 6124 6076 6214
+f 6214 6076 6298
+f 6214 6298 6418
+f 6418 6298 6366
+f 6418 6366 6576
+f 6576 6366 6504
+f 6576 6504 6626
+f 6626 6504 6644
+f 6626 6644 6822
+f 6822 6644 6766
+f 6822 6766 6884
+f 6884 6766 6876
+f 6884 6876 7102
+f 7102 6876 7016
+f 7102 7016 7212
+f 7212 7016 7254
+f 7212 7254 7352
+f 7352 7254 7376
+f 7352 7376 7482
+f 7482 7376 7478
+f 7482 7478 7596
+f 7596 7478 7592
+f 7596 7592 7710
+f 7710 7592 7746
+f 7710 7746 7792
+f 7792 7746 7783
+f 7792 7783 7885
+f 38 108 184
+f 184 108 284
+f 184 284 358
+f 358 284 336
+f 358 336 526
+f 526 336 546
+f 526 546 562
+f 562 546 614
+f 562 614 796
+f 796 614 684
+f 796 684 908
+f 908 684 866
+f 908 866 1054
+f 1054 866 1044
+f 1054 1044 1186
+f 1186 1044 1088
+f 1186 1088 1192
+f 1192 1088 1198
+f 1192 1198 1358
+f 1358 1198 1416
+f 1358 1416 1544
+f 1544 1416 1562
+f 1544 1562 1586
+f 1586 1562 1578
+f 1586 1578 1706
+f 1706 1578 1728
+f 1706 1728 1838
+f 1838 1728 1888
+f 1838 1888 1986
+f 1986 1888 2050
+f 1986 2050 2184
+f 2184 2050 2126
+f 2184 2126 2296
+f 2296 2126 2234
+f 2296 2234 2392
+f 2392 2234 2378
+f 2392 2378 2570
+f 2570 2378 2612
+f 2570 2612 2698
+f 2698 2612 2668
+f 2698 2668 2870
+f 2870 2668 2884
+f 2870 2884 2930
+f 2930 2884 2992
+f 2930 2992 3166
+f 3166 2992 3122
+f 3166 3122 3192
+f 3192 3122 3232
+f 3192 3232 3304
+f 3304 3232 3320
+f 3304 3320 3526
+f 3526 3320 3520
+f 3526 3520 3650
+f 3650 3520 3598
+f 3650 3598 3748
+f 3748 3598 3766
+f 3748 3766 3868
+f 3868 3766 3888
+f 3868 3888 4060
+f 4060 3888 4040
+f 4060 4040 4154
+f 4154 4040 4142
+f 4154 4142 4260
+f 4260 4142 4318
+f 4260 4318 4390
+f 4390 4318 4408
+f 4390 4408 4580
+f 4580 4408 4598
+f 4580 4598 4722
+f 4722 4598 4700
+f 4722 4700 4880
+f 4880 4700 4816
+f 4880 4816 4964
+f 4964 4816 4950
+f 4964 4950 5068
+f 5068 4950 5038
+f 5068 5038 5196
+f 5196 5038 5232
+f 5196 5232 5338
+f 5338 5232 5308
+f 5338 5308 5468
+f 5468 5308 5526
+f 5468 5526 5558
+f 5558 5526 5628
+f 5558 5628 5738
+f 5738 5628 5776
+f 5738 5776 5904
+f 5904 5776 5918
+f 5904 5918 6036
+f 6036 5918 6008
+f 6036 6008 6112
+f 6112 6008 6124
+f 6112 6124 6322
+f 6322 6124 6214
+f 6322 6214 6388
+f 6388 6214 6418
+f 6388 6418 6534
+f 6534 6418 6576
+f 6534 6576 6708
+f 6708 6576 6626
+f 6708 6626 6812
+f 6812 6626 6822
+f 6812 6822 6926
+f 6926 6822 6884
+f 6926 6884 7074
+f 7074 6884 7102
+f 7074 7102 7216
+f 7216 7102 7212
+f 7216 7212 7296
+f 7296 7212 7352
+f 7296 7352 7502
+f 7502 7352 7482
+f 7502 7482 7590
+f 7590 7482 7596
+f 7590 7596 7752
+f 7752 7596 7710
+f 7752 7710 7842
+f 7842 7710 7792
+f 7842 7792 7905
+f 164 38 250
+f 250 38 184
+f 250 184 330
+f 330 184 358
+f 330 358 438
+f 438 358 526
+f 438 526 559
+f 559 526 562
+f 559 562 756
+f 756 562 796
+f 756 796 858
+f 858 796 908
+f 858 908 938
+f 938 908 1054
+f 938 1054 1148
+f 1148 1054 1186
+f 1148 1186 1280
+f 1280 1186 1192
+f 1280 1192 1328
+f 1328 1192 1358
+f 1328 1358 1456
+f 1456 1358 1544
+f 1456 1544 1695
+f 1695 1544 1586
+f 1695 1586 1770
+f 1770 1586 1706
+f 1770 1706 1847
+f 1847 1706 1838
+f 1847 1838 1990
+f 1990 1838 1986
+f 1990 1986 2206
+f 2206 1986 2184
+f 2206 2184 2220
+f 2220 2184 2296
+f 2220 2296 2436
+f 2436 2296 2392
+f 2436 2392 2506
+f 2506 2392 2570
+f 2506 2570 2666
+f 2666 2570 2698
+f 2666 2698 2895
+f 2895 2698 2870
+f 2895 2870 2939
+f 2939 2870 2930
+f 2939 2930 3143
+f 3143 2930 3166
+f 3143 3166 3214
+f 3214 3166 3192
+f 3214 3192 3394
+f 3394 3192 3304
+f 3394 3304 3499
+f 3499 3304 3526
+f 3499 3526 3692
+f 3692 3526 3650
+f 3692 3650 3812
+f 3812 3650 3748
+f 3812 3748 3859
+f 3859 3748 3868
+f 3859 3868 4054
+f 4054 3868 4060
+f 4054 4060 4222
+f 4222 4060 4154
+f 4222 4154 4330
+f 4330 4154 4260
+f 4330 4260 4384
+f 4384 4260 4390
+f 4384 4390 4596
+f 4596 4390 4580
+f 4596 4580 4695
+f 4695 4580 4722
+f 4695 4722 4875
+f 4875 4722 4880
+f 4875 4880 4944
+f 4944 4880 4964
+f 4944 4964 5124
+f 5124 4964 5068
+f 5124 5068 5194
+f 5194 5068 5196
+f 5194 5196 5379
+f 5379 5196 5338
+f 5379 5338 5432
+f 5432 5338 5468
+f 5432 5468 5596
+f 5596 5468 5558
+f 5596 5558 5780
+f 5780 5558 5738
+f 5780 5738 5913
+f 5913 5738 5904
+f 5913 5904 5992
+f 5992 5904 6036
+f 5992 6036 6182
+f 6182 6036 6112
+f 6182 6112 6296
+f 6296 6112 6322
+f 6296 6322 6350
+f 6350 6322 6388
+f 6350 6388 6533
+f 6533 6388 6534
+f 6533 6534 6620
+f 6620 6534 6708
+f 6620 6708 6732
+f 6732 6708 6812
+f 6732 6812 6970
+f 6970 6812 6926
+f 6970 6926 7019
+f 7019 6926 7074
+f 7019 7074 7178
+f 7178 7074 7216
+f 7178 7216 7374
+f 7374 7216 7296
+f 7374 7296 7471
+f 7471 7296 7502
+f 7471 7502 7578
+f 7578 7502 7590
+f 7578 7590 7654
+f 7654 7590 7752
+f 7654 7752 7852
+f 7852 7752 7842
+f 7852 7842 7918
+f 7899 8010 7786
+f 7786 8010 8005
+f 7786 8005 7736
+f 7736 8005 8003
+f 7736 8003 7568
+f 7568 8003 7999
+f 7568 7999 7490
+f 7490 7999 7995
+f 7490 7995 7340
+f 7340 7995 7991
+f 7340 7991 7152
+f 7152 7991 7985
+f 7152 7985 7094
+f 7094 7985 7983
+f 7094 7983 6915
+f 6915 7983 7977
+f 6915 7977 6749
+f 6749 7977 7973
+f 6749 7973 6609
+f 6609 7973 7971
+f 6609 7971 6574
+f 6574 7971 7967
+f 6574 7967 6416
+f 6416 7967 7963
+f 6416 7963 6239
+f 6239 7963 7957
+f 6239 7957 6082
+f 6082 7957 7953
+f 6082 7953 5964
+f 5964 7953 7949
+f 5964 7949 5814
+f 5814 7949 7945
+f 5814 7945 5699
+f 5699 7945 7941
+f 5699 7941 5555
+f 5555 7941 7937
+f 5555 7937 5516
+f 5516 7937 7397
+f 5516 7397 5410
+f 5410 7397 6999
+f 5410 6999 5245
+f 5245 6999 6725
+f 5245 6725 5036
+f 5036 6725 6465
+f 5036 6465 4998
+f 4998 6465 6333
+f 4998 6333 4834
+f 4834 6333 6071
+f 4834 6071 4642
+f 4642 6071 5939
+f 4642 5939 4592
+f 4592 5939 5807
+f 4592 5807 4425
+f 4425 5807 5547
+f 4425 5547 4302
+f 4302 5547 5417
+f 4302 5417 4176
+f 4176 5417 5285
+f 4176 5285 4029
+f 4029 5285 5153
+f 4029 5153 3913
+f 3913 5153 5021
+f 3913 5021 3784
+f 3784 5021 4887
+f 3784 4887 3645
+f 3645 4887 4757
+f 3645 4757 3535
+f 3535 4757 4625
+f 3535 4625 3328
+f 3328 4625 4493
+f 3328 4493 3177
+f 3177 4493 4359
+f 3177 4359 3134
+f 3134 4359 4227
+f 3134 4227 2932
+f 2932 4227 4095
+f 2932 4095 2896
+f 2896 4095 3965
+f 2896 3965 2706
+f 2706 3965 3831
+f 2706 3831 2522
+f 2522 3831 3699
+f 2522 3699 2420
+f 2420 3699 3567
+f 2420 3567 2285
+f 2285 3567 3437
+f 2285 3437 2188
+f 2188 3437 3431
+f 2188 3431 1970
+f 1970 3431 3301
+f 1970 3301 1884
+f 1884 3301 3167
+f 1884 3167 1766
+f 1766 3167 3035
+f 1766 3035 1601
+f 1601 3035 3031
+f 1601 3031 1552
+f 1552 3031 2901
+f 1552 2901 1354
+f 1354 2901 2767
+f 1354 2767 1287
+f 1287 2767 2765
+f 1287 2765 1078
+f 1078 2765 2633
+f 1078 2633 1009
+f 1009 2633 2629
+f 1009 2629 877
+f 877 2629 2497
+f 877 2497 764
+f 764 2497 2491
+f 764 2491 576
+f 576 2491 2487
+f 576 2487 528
+f 528 2487 2355
+f 528 2355 338
+f 338 2355 2353
+f 338 2353 292
+f 292 2353 2349
+f 292 2349 76
+f 76 2349 2345
+f 76 2345 5
+f 5 2345 2342
+f 5 2342 74
+f 74 2342 2346
+f 74 2346 291
+f 291 2346 2350
+f 291 2350 337
+f 337 2350 2354
+f 337 2354 527
+f 527 2354 2356
+f 527 2356 571
+f 571 2356 2488
+f 571 2488 761
+f 761 2488 2492
+f 761 2492 875
+f 875 2492 2498
+f 875 2498 1007
+f 1007 2498 2630
+f 1007 2630 1077
+f 1077 2630 2634
+f 1077 2634 1283
+f 1283 2634 2766
+f 1283 2766 1349
+f 1349 2766 2768
+f 1349 2768 1549
+f 1549 2768 2902
+f 1549 2902 1599
+f 1599 2902 3032
+f 1599 3032 1763
+f 1763 3032 3036
+f 1763 3036 1881
+f 1881 3036 3168
+f 1881 3168 1967
+f 1967 3168 3302
+f 1967 3302 2185
+f 2185 3302 3432
+f 2185 3432 2283
+f 2283 3432 3438
+f 2283 3438 2417
+f 2417 3438 3568
+f 2417 3568 2521
+f 2521 3568 3700
+f 2521 3700 2701
+f 2701 3700 3832
+f 2701 3832 2893
+f 2893 3832 3966
+f 2893 3966 2931
+f 2931 3966 4096
+f 2931 4096 3133
+f 3133 4096 4228
+f 3133 4228 3175
+f 3175 4228 4360
+f 3175 4360 3327
+f 3327 4360 4494
+f 3327 4494 3533
+f 3533 4494 4626
+f 3533 4626 3643
+f 3643 4626 4758
+f 3643 4758 3783
+f 3783 4758 4888
+f 3783 4888 3911
+f 3911 4888 5022
+f 3911 5022 4027
+f 4027 5022 5154
+f 4027 5154 4173
+f 4173 5154 5286
+f 4173 5286 4301
+f 4301 5286 5418
+f 4301 5418 4423
+f 4423 5418 5548
+f 4423 5548 4591
+f 4591 5548 5808
+f 4591 5808 4641
+f 4641 5808 5940
+f 4641 5940 4833
+f 4833 5940 6072
+f 4833 6072 4997
+f 4997 6072 6334
+f 4997 6334 5035
+f 5035 6334 6466
+f 5035 6466 5243
+f 5243 6466 6726
+f 5243 6726 5409
+f 5409 6726 7000
+f 5409 7000 5515
+f 5515 7000 7398
+f 5515 7398 5553
+f 5553 7398 7938
+f 5553 7938 5697
+f 5697 7938 7942
+f 5697 7942 5813
+f 5813 7942 7946
+f 5813 7946 5963
+f 5963 7946 7950
+f 5963 7950 6081
+f 6081 7950 7954
+f 6081 7954 6237
+f 6237 7954 7958
+f 6237 7958 6413
+f 6413 7958 7964
+f 6413 7964 6573
+f 6573 7964 7968
+f 6573 7968 6607
+f 6607 7968 7972
+f 6607 7972 6747
+f 6747 7972 7974
+f 6747 7974 6913
+f 6913 7974 7978
+f 6913 7978 7093
+f 7093 7978 7984
+f 7093 7984 7151
+f 7151 7984 7986
+f 7151 7986 7337
+f 7337 7986 7992
+f 7337 7992 7489
+f 7489 7992 7996
+f 7489 7996 7567
+f 7567 7996 8000
+f 7567 8000 7735
+f 7735 8000 8004
+f 7735 8004 7785
+f 7785 8004 8006
+f 7785 8006 7899
+f 7899 8006 8010
+f 8009 7901 8007
+f 8007 7901 7784
+f 8007 7784 8001
+f 8001 7784 7702
+f 8001 7702 7997
+f 7997 7702 7543
+f 7997 7543 7993
+f 7993 7543 7512
+f 7993 7512 7989
+f 7989 7512 7307
+f 7989 7307 7987
+f 7987 7307 7158
+f 7987 7158 7981
+f 7981 7158 7015
+f 7981 7015 7979
+f 7979 7015 6982
+f 7979 6982 7975
+f 7975 6982 6850
+f 7975 6850 7969
+f 7969 6850 6637
+f 7969 6637 7965
+f 7965 6637 6481
+f 7965 6481 7961
+f 7961 6481 6446
+f 7961 6446 7959
+f 7959 6446 6289
+f 7959 6289 7955
+f 7955 6289 6200
+f 7955 6200 7951
+f 7951 6200 6041
+f 7951 6041 7947
+f 7947 6041 5912
+f 7947 5912 7943
+f 7943 5912 5796
+f 7943 5796 7939
+f 7939 5796 5574
+f 7939 5574 7399
+f 7399 5574 5487
+f 7399 5487 7001
+f 7001 5487 5311
+f 7001 5311 6723
+f 6723 5311 5164
+f 6723 5164 6463
+f 6463 5164 5024
+f 6463 5024 6331
+f 6331 5024 4921
+f 6331 4921 6073
+f 6073 4921 4842
+f 6073 4842 5941
+f 5941 4842 4754
+f 5941 4754 5809
+f 5809 4754 4523
+f 5809 4523 5549
+f 5549 4523 4473
+f 5549 4473 5415
+f 5415 4473 4335
+f 5415 4335 5283
+f 5283 4335 4104
+f 5283 4104 5151
+f 5151 4104 3982
+f 5151 3982 5019
+f 5019 3982 3946
+f 5019 3946 4889
+f 4889 3946 3826
+f 4889 3826 4755
+f 4755 3826 3594
+f 4755 3594 4623
+f 4623 3594 3446
+f 4623 3446 4491
+f 4491 3446 3382
+f 4491 3382 4361
+f 4361 3382 3298
+f 4361 3298 4229
+f 4229 3298 3088
+f 4229 3088 4097
+f 4097 3088 3012
+f 4097 3012 3963
+f 3963 3012 2775
+f 3963 2775 3833
+f 3833 2775 2757
+f 3833 2757 3701
+f 3701 2757 2610
+f 3701 2610 3569
+f 3569 2610 2411
+f 3569 2411 3435
+f 3435 2411 2340
+f 3435 2340 3433
+f 3433 2340 2160
+f 3433 2160 3299
+f 3299 2160 1969
+f 3299 1969 3169
+f 3169 1969 1832
+f 3169 1832 3037
+f 3037 1832 1775
+f 3037 1775 3033
+f 3033 1775 1627
+f 3033 1627 2899
+f 2899 1627 1469
+f 2899 1469 2769
+f 2769 1469 1442
+f 2769 1442 2763
+f 2763 1442 1267
+f 2763 1267 2631
+f 2631 1267 1120
+f 2631 1120 2627
+f 2627 1120 1023
+f 2627 1023 2495
+f 2495 1023 814
+f 2495 814 2493
+f 2493 814 719
+f 2493 719 2489
+f 2489 719 584
+f 2489 584 2357
+f 2357 584 444
+f 2357 444 2351
+f 2351 444 294
+f 2351 294 2347
+f 2347 294 254
+f 2347 254 2343
+f 2343 254 89
+f 2343 89 2341
+f 2341 89 17
+f 2341 17 2344
+f 2344 17 81
+f 2344 81 2348
+f 2348 81 251
+f 2348 251 2352
+f 2352 251 293
+f 2352 293 2358
+f 2358 293 439
+f 2358 439 2490
+f 2490 439 581
+f 2490 581 2494
+f 2494 581 715
+f 2494 715 2496
+f 2496 715 813
+f 2496 813 2628
+f 2628 813 1021
+f 2628 1021 2632
+f 2632 1021 1111
+f 2632 1111 2764
+f 2764 1111 1261
+f 2764 1261 2770
+f 2770 1261 1439
+f 2770 1439 2900
+f 2900 1439 1467
+f 2900 1467 3034
+f 3034 1467 1623
+f 3034 1623 3038
+f 3038 1623 1771
+f 3038 1771 3170
+f 3170 1771 1831
+f 3170 1831 3300
+f 3300 1831 1968
+f 3300 1968 3434
+f 3434 1968 2155
+f 3434 2155 3436
+f 3436 2155 2339
+f 3436 2339 3570
+f 3570 2339 2405
+f 3570 2405 3702
+f 3702 2405 2609
+f 3702 2609 3834
+f 3834 2609 2755
+f 3834 2755 3964
+f 3964 2755 2773
+f 3964 2773 4098
+f 4098 2773 3011
+f 4098 3011 4230
+f 4230 3011 3087
+f 4230 3087 4362
+f 4362 3087 3297
+f 4362 3297 4492
+f 4492 3297 3381
+f 4492 3381 4624
+f 4624 3381 3445
+f 4624 3445 4756
+f 4756 3445 3593
+f 4756 3593 4890
+f 4890 3593 3825
+f 4890 3825 5020
+f 5020 3825 3945
+f 5020 3945 5152
+f 5152 3945 3981
+f 5152 3981 5284
+f 5284 3981 4103
+f 5284 4103 5416
+f 5416 4103 4333
+f 5416 4333 5550
+f 5550 4333 4471
+f 5550 4471 5810
+f 5810 4471 4521
+f 5810 4521 5942
+f 5942 4521 4753
+f 5942 4753 6074
+f 6074 4753 4839
+f 6074 4839 6332
+f 6332 4839 4919
+f 6332 4919 6464
+f 6464 4919 5023
+f 6464 5023 6724
+f 6724 5023 5163
+f 6724 5163 7002
+f 7002 5163 5309
+f 7002 5309 7400
+f 7400 5309 5485
+f 7400 5485 7940
+f 7940 5485 5573
+f 7940 5573 7944
+f 7944 5573 5795
+f 7944 5795 7948
+f 7948 5795 5908
+f 7948 5908 7952
+f 7952 5908 6039
+f 7952 6039 7956
+f 7956 6039 6199
+f 7956 6199 7960
+f 7960 6199 6287
+f 7960 6287 7962
+f 7962 6287 6445
+f 7962 6445 7966
+f 7966 6445 6479
+f 7966 6479 7970
+f 7970 6479 6635
+f 7970 6635 7976
+f 7976 6635 6849
+f 7976 6849 7980
+f 7980 6849 6981
+f 7980 6981 7982
+f 7982 6981 7013
+f 7982 7013 7988
+f 7988 7013 7157
+f 7988 7157 7990
+f 7990 7157 7305
+f 7990 7305 7994
+f 7994 7305 7511
+f 7994 7511 7998
+f 7998 7511 7541
+f 7998 7541 8002
+f 8002 7541 7701
+f 8002 7701 8008
+f 8008 7701 7781
+f 8008 7781 8009
+f 8009 7781 7901
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Inlet.obj b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Inlet.obj
new file mode 100644
index 0000000000000000000000000000000000000000..aa3fbb7ccefb306e1000298945a69d7f5bf2af2a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Inlet.obj
@@ -0,0 +1,382 @@
+# Wavefront OBJ file
+# Regions:
+#     0    CATIASTL
+#
+# points    : 188
+# triangles : 186
+#
+v -117.911 9.79717e-15 31.5765
+v -117.926 2.6732 31.6185
+v -117.926 -2.6732 31.6185
+v -117.972 5.34341 31.7443
+v -117.972 -5.34341 31.7443
+v -118.048 8.00766 31.954
+v -118.048 -8.00766 31.954
+v -118.155 10.663 32.2472
+v -118.155 -10.663 32.2472
+v -118.292 13.3063 32.6236
+v -118.292 -13.3063 32.6236
+v -118.459 15.9349 33.0829
+v -118.459 -15.9349 33.0829
+v -118.656 18.5456 33.6244
+v -118.656 -18.5456 33.6244
+v -118.883 21.1356 34.2475
+v -118.883 -21.1356 34.2475
+v -119.139 23.702 34.9517
+v -119.139 -23.702 34.9517
+v -119.425 26.242 35.736
+v -119.425 -26.242 35.736
+v -119.739 28.7526 36.5996
+v -119.739 -28.7526 36.5996
+v -120.082 31.2311 37.5416
+v -120.082 -31.2311 37.5416
+v -120.453 33.6748 38.561
+v -120.453 -33.6748 38.561
+v -120.852 36.0808 39.6564
+v -120.852 -36.0808 39.6564
+v -121.277 38.4465 40.8268
+v -121.277 -38.4465 40.8268
+v -121.73 40.7693 42.0708
+v -121.73 -40.7693 42.0708
+v -122.209 43.0466 43.3871
+v -122.209 -43.0466 43.3871
+v -122.714 45.2758 44.7742
+v -122.714 -45.2758 44.7742
+v -123.244 47.4544 46.2304
+v -123.244 -47.4544 46.2304
+v -123.799 49.58 47.7543
+v -123.799 -49.58 47.7543
+v -124.378 51.6502 49.344
+v -124.378 -51.6502 49.344
+v -124.979 53.6628 50.9979
+v -124.979 -53.6628 50.9979
+v -125.604 55.6154 52.714
+v -125.604 -55.6154 52.714
+v -126.251 57.5059 54.4905
+v -126.251 -57.5059 54.4905
+v -126.919 59.3322 56.3254
+v -126.919 -59.3322 56.3254
+v -127.607 61.0922 58.2165
+v -127.607 -61.0922 58.2165
+v -128.315 62.784 60.1619
+v -128.315 -62.784 60.1619
+v -129.042 64.4056 62.1594
+v -129.042 -64.4056 62.1594
+v -129.787 65.9553 64.2066
+v -129.787 -65.9553 64.2066
+v -130.549 67.4314 66.3013
+v -130.549 -67.4314 66.3013
+v -131.328 68.8321 68.4412
+v -131.328 -68.8321 68.4412
+v -132.123 70.156 70.6239
+v -132.123 -70.156 70.6239
+v -132.932 71.4015 72.847
+v -132.932 -71.4015 72.847
+v -133.755 72.5673 75.1079
+v -133.755 -72.5673 75.1079
+v -134.591 73.652 77.4042
+v -134.591 -73.652 77.4042
+v -135.438 74.6544 79.7333
+v -135.438 -74.6544 79.7333
+v -136.297 75.5735 82.0925
+v -136.297 -75.5735 82.0925
+v -137.166 76.4082 84.4792
+v -137.166 -76.4082 84.4792
+v -138.044 77.1575 86.8909
+v -138.044 -77.1575 86.8909
+v -138.929 77.8207 89.3247
+v -138.929 -77.8207 89.3247
+v -139.822 78.3969 91.778
+v -139.822 -78.3969 91.778
+v -140.721 78.8856 94.248
+v -140.721 -78.8856 94.248
+v -141.625 79.2862 96.732
+v -141.625 -79.2862 96.732
+v -142.533 79.5982 99.2271
+v -142.533 -79.5982 99.2271
+v -143.445 79.8214 101.731
+v -143.445 -79.8214 101.731
+v -144.358 79.9553 104.24
+v -144.358 -79.9553 104.24
+v -145.272 80 106.752
+v -145.272 -80 106.752
+v -146.187 79.9553 109.264
+v -146.187 -79.9553 109.264
+v -147.1 79.8214 111.773
+v -147.1 -79.8214 111.773
+v -148.011 79.5982 114.277
+v -148.011 -79.5982 114.277
+v -148.919 79.2862 116.772
+v -148.919 -79.2862 116.772
+v -149.823 78.8856 119.256
+v -149.823 -78.8856 119.256
+v -150.722 78.3969 121.726
+v -150.722 -78.3969 121.726
+v -151.615 77.8207 124.179
+v -151.615 -77.8207 124.179
+v -152.501 77.1575 126.613
+v -152.501 -77.1575 126.613
+v -153.379 76.4082 129.025
+v -153.379 -76.4082 129.025
+v -154.248 75.5735 131.411
+v -154.248 -75.5735 131.411
+v -155.106 74.6544 133.77
+v -155.106 -74.6544 133.77
+v -155.954 73.652 136.1
+v -155.954 -73.652 136.1
+v -156.79 72.5673 138.396
+v -156.79 -72.5673 138.396
+v -157.613 71.4015 140.657
+v -157.613 -71.4015 140.657
+v -158.422 70.156 142.88
+v -158.422 -70.156 142.88
+v -159.216 68.8321 145.062
+v -159.216 -68.8321 145.062
+v -159.995 67.4314 147.202
+v -159.995 -67.4314 147.202
+v -160.758 65.9553 149.297
+v -160.758 -65.9553 149.297
+v -161.503 64.4056 151.344
+v -161.503 -64.4056 151.344
+v -162.23 62.784 153.342
+v -162.23 -62.784 153.342
+v -162.938 61.0922 155.287
+v -162.938 -61.0922 155.287
+v -163.626 59.3322 157.178
+v -163.626 -59.3322 157.178
+v -164.294 57.5059 159.013
+v -164.294 -57.5059 159.013
+v -164.941 55.6154 160.79
+v -164.941 -55.6154 160.79
+v -165.565 53.6628 162.506
+v -165.565 -53.6628 162.506
+v -166.167 51.6502 164.16
+v -166.167 -51.6502 164.16
+v -166.746 49.58 165.749
+v -166.746 -49.58 165.749
+v -167.3 47.4544 167.273
+v -167.3 -47.4544 167.273
+v -167.83 45.2758 168.73
+v -167.83 -45.2758 168.73
+v -168.335 43.0466 170.117
+v -168.335 -43.0466 170.117
+v -168.814 40.7693 171.433
+v -168.814 -40.7693 171.433
+v -169.267 38.4465 172.677
+v -169.267 -38.4465 172.677
+v -169.693 36.0808 173.847
+v -169.693 -36.0808 173.847
+v -170.092 33.6748 174.943
+v -170.092 -33.6748 174.943
+v -170.463 31.2311 175.962
+v -170.463 -31.2311 175.962
+v -170.806 28.7526 176.904
+v -170.806 -28.7526 176.904
+v -171.12 26.242 177.768
+v -171.12 -26.242 177.768
+v -171.405 23.702 178.552
+v -171.405 -23.702 178.552
+v -171.662 21.1356 179.256
+v -171.662 -21.1356 179.256
+v -171.889 18.5456 179.879
+v -171.889 -18.5456 179.879
+v -172.086 15.9349 180.421
+v -172.086 -15.9349 180.421
+v -172.253 13.3063 180.88
+v -172.253 -13.3063 180.88
+v -172.39 10.663 181.257
+v -172.39 -10.663 181.257
+v -172.497 8.00766 181.55
+v -172.497 -8.00766 181.55
+v -172.573 5.34341 181.759
+v -172.573 -5.34341 181.759
+v -172.619 2.6732 181.885
+v -172.619 -2.6732 181.885
+v -172.634 0 181.927
+g CATIASTL
+f 92 96 94
+f 96 92 98
+f 98 92 90
+f 98 90 100
+f 100 90 88
+f 100 88 102
+f 102 88 86
+f 102 86 104
+f 104 86 84
+f 104 84 106
+f 106 84 82
+f 106 82 108
+f 108 82 80
+f 108 80 110
+f 110 80 78
+f 110 78 112
+f 112 78 76
+f 112 76 114
+f 114 76 74
+f 114 74 116
+f 116 74 72
+f 116 72 118
+f 118 72 70
+f 118 70 120
+f 120 70 68
+f 120 68 122
+f 122 68 66
+f 122 66 124
+f 124 66 64
+f 124 64 126
+f 126 64 62
+f 126 62 128
+f 128 62 60
+f 128 60 130
+f 130 60 58
+f 130 58 132
+f 132 58 56
+f 132 56 134
+f 134 56 54
+f 134 54 136
+f 136 54 52
+f 136 52 138
+f 138 52 50
+f 138 50 140
+f 140 50 48
+f 140 48 142
+f 142 48 46
+f 142 46 144
+f 144 46 44
+f 144 44 146
+f 146 44 42
+f 146 42 148
+f 148 42 40
+f 148 40 150
+f 150 40 38
+f 150 38 152
+f 152 38 36
+f 152 36 154
+f 154 36 34
+f 154 34 156
+f 156 34 32
+f 156 32 158
+f 158 32 30
+f 158 30 160
+f 160 30 28
+f 160 28 162
+f 162 28 26
+f 162 26 164
+f 164 26 24
+f 164 24 166
+f 166 24 22
+f 166 22 168
+f 168 22 20
+f 168 20 170
+f 170 20 18
+f 170 18 172
+f 172 18 16
+f 172 16 174
+f 174 16 14
+f 174 14 176
+f 176 14 12
+f 176 12 178
+f 178 12 10
+f 178 10 180
+f 180 10 8
+f 180 8 182
+f 182 8 6
+f 182 6 184
+f 184 6 4
+f 184 4 186
+f 186 4 2
+f 186 2 188
+f 188 2 1
+f 188 1 187
+f 187 1 3
+f 187 3 185
+f 185 3 5
+f 185 5 183
+f 183 5 7
+f 183 7 181
+f 181 7 9
+f 181 9 179
+f 179 9 11
+f 179 11 177
+f 177 11 13
+f 177 13 175
+f 175 13 15
+f 175 15 173
+f 173 15 17
+f 173 17 171
+f 171 17 19
+f 171 19 169
+f 169 19 21
+f 169 21 167
+f 167 21 23
+f 167 23 165
+f 165 23 25
+f 165 25 163
+f 163 25 27
+f 163 27 161
+f 161 27 29
+f 161 29 159
+f 159 29 31
+f 159 31 157
+f 157 31 33
+f 157 33 155
+f 155 33 35
+f 155 35 153
+f 153 35 37
+f 153 37 151
+f 151 37 39
+f 151 39 149
+f 149 39 41
+f 149 41 147
+f 147 41 43
+f 147 43 145
+f 145 43 45
+f 145 45 143
+f 143 45 47
+f 143 47 141
+f 141 47 49
+f 141 49 139
+f 139 49 51
+f 139 51 137
+f 137 51 53
+f 137 53 135
+f 135 53 55
+f 135 55 133
+f 133 55 57
+f 133 57 131
+f 131 57 59
+f 131 59 129
+f 129 59 61
+f 129 61 127
+f 127 61 63
+f 127 63 125
+f 125 63 65
+f 125 65 123
+f 123 65 67
+f 123 67 121
+f 121 67 69
+f 121 69 119
+f 119 69 71
+f 119 71 117
+f 117 71 73
+f 117 73 115
+f 115 73 75
+f 115 75 113
+f 113 75 77
+f 113 77 111
+f 111 77 79
+f 111 79 109
+f 109 79 81
+f 109 81 107
+f 107 81 83
+f 107 83 105
+f 105 83 85
+f 105 85 103
+f 103 85 87
+f 103 87 101
+f 101 87 89
+f 101 89 99
+f 99 89 91
+f 99 91 97
+f 97 91 93
+f 97 93 95
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/InletSmall.obj b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/InletSmall.obj
new file mode 100644
index 0000000000000000000000000000000000000000..6c661397fc9204a1786d7274d1fe56ce3cefc62e
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/InletSmall.obj
@@ -0,0 +1,250 @@
+# Wavefront OBJ file
+# Regions:
+#     0    CATIASTL
+#
+# points    : 122
+# triangles : 120
+#
+v 174.966 29.7913 243.719
+v 149.662 -12.308 261.438
+v 175.49 -29.7086 243.353
+v 170.439 -29.9337 246.889
+v 150.21 -13.7001 261.054
+v 181.086 27.9095 239.435
+v 186.01 -24.7091 235.987
+v 196.6 1.86591 228.572
+v 148.377 -7.95114 262.337
+v 187.612 23.2414 234.865
+v 180.395 -28.2272 239.918
+v 149.975 13.124 261.219
+v 192.949 -15.8282 231.128
+v 177.46 29.2702 241.973
+v 184.497 25.8838 237.046
+v 193.329 15.0559 230.862
+v 159.649 -25.8838 254.445
+v 194.171 -13.124 230.272
+v 196.072 6.45146 228.941
+v 148.073 -6.45146 262.55
+v 193.589 -14.4953 230.68
+v 148.243 7.32825 262.432
+v 150.817 -15.0559 260.629
+v 189.487 21.1678 233.552
+v 157.535 -24.1871 255.925
+v 164.249 -28.4389 251.224
+v 147.546 -1.86591 262.92
+v 174.232 -29.8839 244.234
+v 151.48 -16.3717 260.165
+v 166.686 -29.2702 249.518
+v 193.935 13.7001 230.437
+v 182.251 27.306 238.619
+v 157.113 23.8005 256.221
+v 195.16 -10.2806 229.58
+v 195.903 -7.32825 229.06
+v 188.017 -22.8288 234.581
+v 179.194 -28.7128 240.759
+v 195.562 -8.81611 229.298
+v 167.927 -29.57 248.649
+v 147.833 -4.93468 262.719
+v 147.603 2.7641 262.88
+v 158.136 24.7091 255.504
+v 173.706 29.9337 244.602
+v 149.451 11.7178 261.586
+v 196.18 -5.82096 228.865
+v 161.417 27.033 253.207
+v 151.197 15.8282 260.363
+v 160.757 -26.6302 253.669
+v 156.534 -23.2414 256.626
+v 147.519 1.22264 262.939
+v 196.489 3.40481 228.65
+v 191.505 -18.3647 232.139
+v 171.704 -29.9966 246.004
+v 150.557 14.4953 260.811
+v 163.75 28.2272 251.573
+v 160.291 26.3275 253.995
+v 163.06 -27.9095 252.057
+v 147.5 -0.322061 262.952
+v 191.948 17.6441 231.829
+v 167.408 29.4545 249.012
+v 183.855 -26.3275 237.496
+v 155.575 -22.2341 257.298
+v 168.656 29.7086 248.138
+v 147.965 5.82096 262.626
+v 171.176 29.98 246.373
+v 195.402 9.42973 229.411
+v 154.659 -21.1678 257.939
+v 188.571 22.2341 234.193
+v 162.571 27.6668 252.399
+v 187.033 -23.8005 235.27
+v 196.627 -1.22264 228.553
+v 190.356 20.0453 232.943
+v 176.738 -29.4545 242.479
+v 169.179 -29.7913 247.772
+v 155.187 21.7965 257.569
+v 166.172 29.1223 249.878
+v 148.583 8.81611 262.193
+v 181.575 -27.6668 239.092
+v 152.198 -17.6441 259.662
+v 194.695 -11.7178 229.905
+v 147.657 -3.40481 262.842
+v 177.974 -29.1223 241.614
+v 172.969 -29.98 245.118
+v 183.389 26.6302 237.822
+v 196.543 -2.7641 228.611
+v 147.752 4.29823 262.775
+v 182.729 -27.033 238.284
+v 161.895 -27.306 252.872
+v 196.646 0.322061 228.539
+v 188.958 -21.7965 233.922
+v 164.952 28.7128 250.732
+v 156.129 22.8288 256.91
+v 186.611 24.1871 235.566
+v 179.897 28.4389 240.267
+v 148.986 10.2806 261.911
+v 149.173 -10.8833 261.781
+v 158.574 -25.0687 255.198
+v 176.219 29.57 242.843
+v 148.744 -9.42973 262.081
+v 154.291 20.7065 258.197
+v 153.789 -20.0453 258.548
+v 196.313 4.93468 228.773
+v 169.913 29.8839 247.258
+v 172.442 29.9966 245.487
+v 192.666 16.3717 231.327
+v 152.641 18.3647 259.352
+v 192.254 -17.1191 231.615
+v 184.949 -25.5522 236.73
+v 165.458 -28.8929 250.377
+v 152.968 -18.8697 259.123
+v 195.769 7.95114 229.154
+v 153.441 19.5615 258.792
+v 190.705 -19.5615 232.699
+v 191.178 18.8697 232.368
+v 159.197 25.5522 254.762
+v 194.484 12.308 230.053
+v 178.688 28.8929 241.114
+v 189.855 -20.7065 233.294
+v 185.572 25.0687 236.294
+v 151.892 17.1191 259.876
+v 194.973 10.8833 229.711
+v 196.394 -4.29823 228.716
+g CATIASTL
+f 104 65 43
+f 43 65 103
+f 43 103 1
+f 1 103 63
+f 1 63 98
+f 98 63 60
+f 98 60 14
+f 14 60 76
+f 14 76 117
+f 117 76 91
+f 117 91 94
+f 94 91 55
+f 94 55 6
+f 6 55 69
+f 6 69 32
+f 32 69 46
+f 32 46 84
+f 84 46 56
+f 84 56 15
+f 15 56 115
+f 15 115 119
+f 119 115 42
+f 119 42 93
+f 93 42 33
+f 93 33 10
+f 10 33 92
+f 10 92 68
+f 68 92 75
+f 68 75 24
+f 24 75 100
+f 24 100 72
+f 72 100 112
+f 72 112 114
+f 114 112 106
+f 114 106 59
+f 59 106 120
+f 59 120 105
+f 105 120 47
+f 105 47 16
+f 16 47 54
+f 16 54 31
+f 31 54 12
+f 31 12 116
+f 116 12 44
+f 116 44 121
+f 121 44 95
+f 121 95 66
+f 66 95 77
+f 66 77 111
+f 111 77 22
+f 111 22 19
+f 19 22 64
+f 19 64 102
+f 102 64 86
+f 102 86 51
+f 51 86 41
+f 51 41 8
+f 8 41 50
+f 8 50 89
+f 89 50 58
+f 89 58 71
+f 71 58 27
+f 71 27 85
+f 85 27 81
+f 85 81 122
+f 122 81 40
+f 122 40 45
+f 45 40 20
+f 45 20 35
+f 35 20 9
+f 35 9 38
+f 38 9 99
+f 38 99 34
+f 34 99 96
+f 34 96 80
+f 80 96 2
+f 80 2 18
+f 18 2 5
+f 18 5 21
+f 21 5 23
+f 21 23 13
+f 13 23 29
+f 13 29 107
+f 107 29 79
+f 107 79 52
+f 52 79 110
+f 52 110 113
+f 113 110 101
+f 113 101 118
+f 118 101 67
+f 118 67 90
+f 90 67 62
+f 90 62 36
+f 36 62 49
+f 36 49 70
+f 70 49 25
+f 70 25 7
+f 7 25 97
+f 7 97 108
+f 108 97 17
+f 108 17 61
+f 61 17 48
+f 61 48 87
+f 87 48 88
+f 87 88 78
+f 78 88 57
+f 78 57 11
+f 11 57 26
+f 11 26 37
+f 37 26 109
+f 37 109 82
+f 82 109 30
+f 82 30 73
+f 73 30 39
+f 73 39 3
+f 3 39 74
+f 3 74 28
+f 28 74 4
+f 28 4 83
+f 83 4 53
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Outlet.obj b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Outlet.obj
new file mode 100644
index 0000000000000000000000000000000000000000..ce035e4315f6a70e461689abbb6aa11de7e743d6
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/Outlet.obj
@@ -0,0 +1,382 @@
+# Wavefront OBJ file
+# Regions:
+#     0    CATIASTL
+#
+# points    : 188
+# triangles : 186
+#
+v 70 9.79717e-15 -100
+v 70.0447 -2.6732 -100
+v 70.0447 2.6732 -100
+v 70.1786 -5.34341 -100
+v 70.1786 5.34341 -100
+v 70.4018 -8.00766 -100
+v 70.4018 8.00766 -100
+v 70.7138 -10.663 -100
+v 70.7138 10.663 -100
+v 71.1144 -13.3063 -100
+v 71.1144 13.3063 -100
+v 71.6031 -15.9349 -100
+v 71.6031 15.9349 -100
+v 72.1793 -18.5456 -100
+v 72.1793 18.5456 -100
+v 72.8425 -21.1356 -100
+v 72.8425 21.1356 -100
+v 73.5918 -23.702 -100
+v 73.5918 23.702 -100
+v 74.4265 -26.242 -100
+v 74.4265 26.242 -100
+v 75.3456 -28.7526 -100
+v 75.3456 28.7526 -100
+v 76.348 -31.2311 -100
+v 76.348 31.2311 -100
+v 77.4327 -33.6748 -100
+v 77.4327 33.6748 -100
+v 78.5985 -36.0808 -100
+v 78.5985 36.0808 -100
+v 79.844 -38.4465 -100
+v 79.844 38.4465 -100
+v 81.1679 -40.7693 -100
+v 81.1679 40.7693 -100
+v 82.5686 -43.0466 -100
+v 82.5686 43.0466 -100
+v 84.0447 -45.2758 -100
+v 84.0447 45.2758 -100
+v 85.5944 -47.4544 -100
+v 85.5944 47.4544 -100
+v 87.216 -49.58 -100
+v 87.216 49.58 -100
+v 88.9078 -51.6502 -100
+v 88.9078 51.6502 -100
+v 90.6678 -53.6628 -100
+v 90.6678 53.6628 -100
+v 92.4941 -55.6154 -100
+v 92.4941 55.6154 -100
+v 94.3846 -57.5059 -100
+v 94.3846 57.5059 -100
+v 96.3372 -59.3322 -100
+v 96.3372 59.3322 -100
+v 98.3498 -61.0922 -100
+v 98.3498 61.0922 -100
+v 100.42 -62.784 -100
+v 100.42 62.784 -100
+v 102.546 -64.4056 -100
+v 102.546 64.4056 -100
+v 104.724 -65.9553 -100
+v 104.724 65.9553 -100
+v 106.953 -67.4314 -100
+v 106.953 67.4314 -100
+v 109.231 -68.8321 -100
+v 109.231 68.8321 -100
+v 111.553 -70.156 -100
+v 111.553 70.156 -100
+v 113.919 -71.4015 -100
+v 113.919 71.4015 -100
+v 116.325 -72.5673 -100
+v 116.325 72.5673 -100
+v 118.769 -73.652 -100
+v 118.769 73.652 -100
+v 121.247 -74.6544 -100
+v 121.247 74.6544 -100
+v 123.758 -75.5735 -100
+v 123.758 75.5735 -100
+v 126.298 -76.4082 -100
+v 126.298 76.4082 -100
+v 128.864 -77.1575 -100
+v 128.864 77.1575 -100
+v 131.454 -77.8207 -100
+v 131.454 77.8207 -100
+v 134.065 -78.3969 -100
+v 134.065 78.3969 -100
+v 136.694 -78.8856 -100
+v 136.694 78.8856 -100
+v 139.337 -79.2862 -100
+v 139.337 79.2862 -100
+v 141.992 -79.5982 -100
+v 141.992 79.5982 -100
+v 144.657 -79.8214 -100
+v 144.657 79.8214 -100
+v 147.327 79.9553 -100
+v 147.327 -79.9553 -100
+v 150 80 -100
+v 150 -80 -100
+v 152.673 79.9553 -100
+v 152.673 -79.9553 -100
+v 155.343 -79.8214 -100
+v 155.343 79.8214 -100
+v 158.008 -79.5982 -100
+v 158.008 79.5982 -100
+v 160.663 -79.2862 -100
+v 160.663 79.2862 -100
+v 163.306 -78.8856 -100
+v 163.306 78.8856 -100
+v 165.935 -78.3969 -100
+v 165.935 78.3969 -100
+v 168.546 -77.8207 -100
+v 168.546 77.8207 -100
+v 171.136 -77.1575 -100
+v 171.136 77.1575 -100
+v 173.702 -76.4082 -100
+v 173.702 76.4082 -100
+v 176.242 -75.5735 -100
+v 176.242 75.5735 -100
+v 178.753 -74.6544 -100
+v 178.753 74.6544 -100
+v 181.231 -73.652 -100
+v 181.231 73.652 -100
+v 183.675 -72.5673 -100
+v 183.675 72.5673 -100
+v 186.081 -71.4015 -100
+v 186.081 71.4015 -100
+v 188.447 -70.156 -100
+v 188.447 70.156 -100
+v 190.769 -68.8321 -100
+v 190.769 68.8321 -100
+v 193.047 -67.4314 -100
+v 193.047 67.4314 -100
+v 195.276 -65.9553 -100
+v 195.276 65.9553 -100
+v 197.454 -64.4056 -100
+v 197.454 64.4056 -100
+v 199.58 -62.784 -100
+v 199.58 62.784 -100
+v 201.65 -61.0922 -100
+v 201.65 61.0922 -100
+v 203.663 -59.3322 -100
+v 203.663 59.3322 -100
+v 205.615 -57.5059 -100
+v 205.615 57.5059 -100
+v 207.506 -55.6154 -100
+v 207.506 55.6154 -100
+v 209.332 -53.6628 -100
+v 209.332 53.6628 -100
+v 211.092 -51.6502 -100
+v 211.092 51.6502 -100
+v 212.784 -49.58 -100
+v 212.784 49.58 -100
+v 214.406 -47.4544 -100
+v 214.406 47.4544 -100
+v 215.955 -45.2758 -100
+v 215.955 45.2758 -100
+v 217.431 -43.0466 -100
+v 217.431 43.0466 -100
+v 218.832 -40.7693 -100
+v 218.832 40.7693 -100
+v 220.156 -38.4465 -100
+v 220.156 38.4465 -100
+v 221.402 -36.0808 -100
+v 221.402 36.0808 -100
+v 222.567 -33.6748 -100
+v 222.567 33.6748 -100
+v 223.652 -31.2311 -100
+v 223.652 31.2311 -100
+v 224.654 -28.7526 -100
+v 224.654 28.7526 -100
+v 225.574 -26.242 -100
+v 225.574 26.242 -100
+v 226.408 -23.702 -100
+v 226.408 23.702 -100
+v 227.158 -21.1356 -100
+v 227.158 21.1356 -100
+v 227.821 -18.5456 -100
+v 227.821 18.5456 -100
+v 228.397 -15.9349 -100
+v 228.397 15.9349 -100
+v 228.886 -13.3063 -100
+v 228.886 13.3063 -100
+v 229.286 -10.663 -100
+v 229.286 10.663 -100
+v 229.598 -8.00766 -100
+v 229.598 8.00766 -100
+v 229.821 -5.34341 -100
+v 229.821 5.34341 -100
+v 229.955 -2.6732 -100
+v 229.955 2.6732 -100
+v 230 0 -100
+g CATIASTL
+f 94 96 92
+f 95 93 97
+f 97 93 90
+f 97 90 98
+f 98 90 88
+f 98 88 100
+f 100 88 86
+f 100 86 102
+f 102 86 84
+f 102 84 104
+f 104 84 82
+f 104 82 106
+f 106 82 80
+f 106 80 108
+f 108 80 78
+f 108 78 110
+f 110 78 76
+f 110 76 112
+f 112 76 74
+f 112 74 114
+f 114 74 72
+f 114 72 116
+f 116 72 70
+f 116 70 118
+f 118 70 68
+f 118 68 120
+f 120 68 66
+f 120 66 122
+f 122 66 64
+f 122 64 124
+f 124 64 62
+f 124 62 126
+f 126 62 60
+f 126 60 128
+f 128 60 58
+f 128 58 130
+f 130 58 56
+f 130 56 132
+f 132 56 54
+f 132 54 134
+f 134 54 52
+f 134 52 136
+f 136 52 50
+f 136 50 138
+f 138 50 48
+f 138 48 140
+f 140 48 46
+f 140 46 142
+f 142 46 44
+f 142 44 144
+f 144 44 42
+f 144 42 146
+f 146 42 40
+f 146 40 148
+f 148 40 38
+f 148 38 150
+f 150 38 36
+f 150 36 152
+f 152 36 34
+f 152 34 154
+f 154 34 32
+f 154 32 156
+f 156 32 30
+f 156 30 158
+f 158 30 28
+f 158 28 160
+f 160 28 26
+f 160 26 162
+f 162 26 24
+f 162 24 164
+f 164 24 22
+f 164 22 166
+f 166 22 20
+f 166 20 168
+f 168 20 18
+f 168 18 170
+f 170 18 16
+f 170 16 172
+f 172 16 14
+f 172 14 174
+f 174 14 12
+f 174 12 176
+f 176 12 10
+f 176 10 178
+f 178 10 8
+f 178 8 180
+f 180 8 6
+f 180 6 182
+f 182 6 4
+f 182 4 184
+f 184 4 2
+f 184 2 186
+f 186 2 1
+f 186 1 188
+f 188 1 3
+f 188 3 187
+f 187 3 5
+f 187 5 185
+f 185 5 7
+f 185 7 183
+f 183 7 9
+f 183 9 181
+f 181 9 11
+f 181 11 179
+f 179 11 13
+f 179 13 177
+f 177 13 15
+f 177 15 175
+f 175 15 17
+f 175 17 173
+f 173 17 19
+f 173 19 171
+f 171 19 21
+f 171 21 169
+f 169 21 23
+f 169 23 167
+f 167 23 25
+f 167 25 165
+f 165 25 27
+f 165 27 163
+f 163 27 29
+f 163 29 161
+f 161 29 31
+f 161 31 159
+f 159 31 33
+f 159 33 157
+f 157 33 35
+f 157 35 155
+f 155 35 37
+f 155 37 153
+f 153 37 39
+f 153 39 151
+f 151 39 41
+f 151 41 149
+f 149 41 43
+f 149 43 147
+f 147 43 45
+f 147 45 145
+f 145 45 47
+f 145 47 143
+f 143 47 49
+f 143 49 141
+f 141 49 51
+f 141 51 139
+f 139 51 53
+f 139 53 137
+f 137 53 55
+f 137 55 135
+f 135 55 57
+f 135 57 133
+f 133 57 59
+f 133 59 131
+f 131 59 61
+f 131 61 129
+f 129 61 63
+f 129 63 127
+f 127 63 65
+f 127 65 125
+f 125 65 67
+f 125 67 123
+f 123 67 69
+f 123 69 121
+f 121 69 71
+f 121 71 119
+f 119 71 73
+f 119 73 117
+f 117 73 75
+f 117 75 115
+f 115 75 77
+f 115 77 113
+f 113 77 79
+f 113 79 111
+f 111 79 81
+f 111 81 109
+f 109 81 83
+f 109 83 107
+f 107 83 85
+f 107 85 105
+f 105 85 87
+f 105 87 103
+f 103 87 89
+f 103 89 101
+f 101 89 91
+f 101 91 99
+f 99 91 92
+f 99 92 96
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/SmallPipe.obj b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/SmallPipe.obj
new file mode 100644
index 0000000000000000000000000000000000000000..9956423edb8494e0a9a47261dfc4580bb00ee43d
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/constant/triSurface/SmallPipe.obj
@@ -0,0 +1,536 @@
+# Wavefront OBJ file
+# Regions:
+#     0    CATIASTL
+#
+# points    : 264
+# triangles : 264
+#
+v 129.002 -29.9955 183.325
+v 128.148 29.9955 183.923
+v 129.334 29.9857 183.096
+v 127.819 -29.9857 184.156
+v 130.194 -29.9355 182.51
+v 126.974 29.9355 184.764
+v 130.287 29.9279 182.447
+v 126.883 -29.9279 184.831
+v 125.958 -29.826 185.512
+v 131.244 29.826 181.811
+v 131.391 -29.8064 181.714
+v 125.816 29.8064 185.617
+v 125.045 -29.6803 186.199
+v 132.202 29.6803 181.188
+v 124.679 29.6089 186.478
+v 132.59 -29.6089 180.939
+v 133.158 29.4915 180.58
+v 124.147 -29.4915 186.889
+v 123.565 29.3443 187.344
+v 133.784 -29.3443 180.188
+v 133.793 29.3421 180.183
+v 123.556 -29.3421 187.351
+v 134.427 29.1741 179.793
+v 122.974 -29.1741 187.813
+v 134.972 -29.0143 179.462
+v 122.477 29.0143 188.212
+v 121.832 -28.7837 188.736
+v 135.685 28.7837 179.036
+v 121.374 28.6035 189.113
+v 136.195 -28.6035 178.735
+v 120.948 -28.423 189.467
+v 136.674 28.423 178.456
+v 120.306 28.1266 190.008
+v 137.402 -28.1266 178.037
+v 120.088 -28.0192 190.194
+v 137.651 28.0192 177.896
+v 119.273 27.5863 190.895
+v 138.588 -27.5863 177.37
+v 138.614 27.5739 177.356
+v 119.252 -27.5739 190.914
+v 118.44 -27.0887 191.626
+v 139.561 27.0887 176.837
+v 139.751 -26.9856 176.734
+v 118.278 26.9856 191.769
+v 117.914 -26.7451 192.094
+v 140.18 26.7451 176.503
+v 140.791 26.385 176.179
+v 117.401 -26.385 192.557
+v 117.322 26.3275 192.628
+v 140.885 -26.3275 176.129
+v 141.397 26.0063 175.861
+v 116.895 -26.0063 193.018
+v 116.411 25.6208 193.463
+v 141.98 -25.6208 175.559
+v 116.401 -25.6118 193.473
+v 141.994 25.6118 175.553
+v 143.043 -24.8634 175.02
+v 115.541 24.8634 194.277
+v 115.517 -24.8419 194.299
+v 143.072 24.8419 175.005
+v 114.71 24.0583 195.069
+v 144.072 -24.0583 174.51
+v 144.115 24.0228 174.488
+v 114.675 -24.0228 195.102
+v 113.919 23.2083 195.836
+v 145.063 -23.2083 174.029
+v 113.874 -23.1575 195.88
+v 145.12 23.1575 174.002
+v 113.168 22.3161 196.576
+v 146.016 -22.3161 173.576
+v 146.084 22.2488 173.544
+v 113.114 -22.2488 196.63
+v 112.457 21.3845 197.288
+v 146.928 -21.3845 173.152
+v 112.396 -21.2997 197.35
+v 147.007 21.2997 173.115
+v 147.887 20.3127 172.714
+v 111.718 -20.3127 198.04
+v 111.695 20.2771 198.064
+v 147.917 -20.2771 172.701
+v 148.368 19.7356 172.499
+v 111.351 -19.7356 198.418
+v 110.997 -19.1474 198.785
+v 148.834 19.1474 172.292
+v 148.851 -19.1253 172.284
+v 110.984 19.1253 198.798
+v 149.289 18.5427 172.091
+v 110.653 -18.5427 199.145
+v 110.324 17.9325 199.49
+v 149.726 -17.9325 171.9
+v 110.322 -17.9277 199.493
+v 149.73 17.9277 171.899
+v 150.542 -16.7021 171.549
+v 109.715 16.7021 200.137
+v 109.702 -16.675 200.15
+v 150.56 16.675 171.542
+v 109.156 15.4374 200.738
+v 151.298 -15.4374 171.229
+v 109.135 -15.3868 200.76
+v 151.327 15.3868 171.217
+v 151.992 -14.1415 170.94
+v 108.646 14.1415 201.291
+v 152.03 14.0664 170.924
+v 108.619 -14.0664 201.321
+v 108.186 12.8177 201.795
+v 152.624 -12.8177 170.68
+v 108.154 -12.7171 201.831
+v 152.669 12.7171 170.662
+v 153.191 -11.4687 170.449
+v 107.775 11.4687 202.25
+v 107.74 -11.3421 202.29
+v 153.241 11.3421 170.429
+v 153.699 -10.0842 170.245
+v 107.41 10.0842 202.657
+v 153.746 9.94438 170.226
+v 107.376 -9.94438 202.695
+v 154.141 -8.67993 170.069
+v 107.094 8.67993 203.012
+v 154.176 8.55855 170.056
+v 107.069 -8.55855 203.04
+v 154.515 -7.25883 169.921
+v 106.827 7.25883 203.314
+v 106.809 -7.15661 203.333
+v 154.54 7.15661 169.912
+v 154.822 -5.82374 169.801
+v 106.608 5.82374 203.561
+v 154.838 5.74127 169.795
+v 106.597 -5.74127 203.574
+v 106.439 4.37752 203.754
+v 155.062 -4.37752 169.708
+v 155.071 4.31526 169.704
+v 106.433 -4.31526 203.761
+v 106.318 2.92296 203.892
+v 155.233 -2.92296 169.641
+v 155.237 2.88126 169.64
+v 106.315 -2.88126 203.895
+v 155.336 -1.46286 169.601
+v 106.245 1.46286 203.975
+v 106.244 -1.44195 203.976
+v 155.337 1.44195 169.601
+v 155.37 1.95944e-14 169.588
+v 106.221 1.95944e-14 204.003
+v 174.966 29.7913 243.719
+v 149.662 -12.308 261.438
+v 175.49 -29.7086 243.353
+v 170.439 -29.9337 246.889
+v 150.21 -13.7001 261.054
+v 181.086 27.9095 239.435
+v 186.01 -24.7091 235.987
+v 196.6 1.86591 228.572
+v 148.377 -7.95114 262.337
+v 187.612 23.2414 234.865
+v 180.395 -28.2272 239.918
+v 149.975 13.124 261.219
+v 192.949 -15.8282 231.128
+v 177.46 29.2702 241.973
+v 159.649 -25.8838 254.445
+v 184.497 25.8838 237.046
+v 193.329 15.0559 230.862
+v 194.171 -13.124 230.272
+v 148.073 -6.45146 262.55
+v 196.072 6.45146 228.941
+v 193.589 -14.4953 230.68
+v 148.243 7.32825 262.432
+v 150.817 -15.0559 260.629
+v 189.487 21.1678 233.552
+v 157.535 -24.1871 255.925
+v 164.249 -28.4389 251.224
+v 147.546 -1.86591 262.92
+v 174.232 -29.8839 244.234
+v 151.48 -16.3717 260.165
+v 166.686 -29.2702 249.518
+v 193.935 13.7001 230.437
+v 182.251 27.306 238.619
+v 157.113 23.8005 256.221
+v 195.16 -10.2806 229.58
+v 195.903 -7.32825 229.06
+v 179.194 -28.7128 240.759
+v 188.017 -22.8288 234.581
+v 195.562 -8.81611 229.298
+v 167.927 -29.57 248.649
+v 147.833 -4.93468 262.719
+v 147.603 2.7641 262.88
+v 158.136 24.7091 255.504
+v 173.706 29.9337 244.602
+v 149.451 11.7178 261.586
+v 196.18 -5.82096 228.865
+v 161.417 27.033 253.207
+v 151.197 15.8282 260.363
+v 160.757 -26.6302 253.669
+v 156.534 -23.2414 256.626
+v 147.519 1.22264 262.939
+v 196.489 3.40481 228.65
+v 191.505 -18.3647 232.139
+v 171.704 -29.9966 246.004
+v 150.557 14.4953 260.811
+v 163.75 28.2272 251.573
+v 160.291 26.3275 253.995
+v 163.06 -27.9095 252.057
+v 147.5 -0.322061 262.952
+v 191.948 17.6441 231.829
+v 167.408 29.4545 249.012
+v 183.855 -26.3275 237.496
+v 155.575 -22.2341 257.298
+v 168.656 29.7086 248.138
+v 147.965 5.82096 262.626
+v 171.176 29.98 246.373
+v 195.402 9.42973 229.411
+v 154.659 -21.1678 257.939
+v 188.571 22.2341 234.193
+v 162.571 27.6668 252.399
+v 187.033 -23.8005 235.27
+v 196.627 -1.22264 228.553
+v 190.356 20.0453 232.943
+v 176.738 -29.4545 242.479
+v 169.179 -29.7913 247.772
+v 155.187 21.7965 257.569
+v 166.172 29.1223 249.878
+v 148.583 8.81611 262.193
+v 181.575 -27.6668 239.092
+v 152.198 -17.6441 259.662
+v 194.695 -11.7178 229.905
+v 147.657 -3.40481 262.842
+v 177.974 -29.1223 241.614
+v 172.969 -29.98 245.118
+v 183.389 26.6302 237.822
+v 196.543 -2.7641 228.611
+v 147.752 4.29823 262.775
+v 182.729 -27.033 238.284
+v 161.895 -27.306 252.872
+v 196.646 0.322061 228.539
+v 188.958 -21.7965 233.922
+v 156.129 22.8288 256.91
+v 164.952 28.7128 250.732
+v 186.611 24.1871 235.566
+v 179.897 28.4389 240.267
+v 148.986 10.2806 261.911
+v 149.173 -10.8833 261.781
+v 158.574 -25.0687 255.198
+v 176.219 29.57 242.843
+v 148.744 -9.42973 262.081
+v 154.291 20.7065 258.197
+v 153.789 -20.0453 258.548
+v 196.313 4.93468 228.773
+v 169.913 29.8839 247.258
+v 172.442 29.9966 245.487
+v 192.666 16.3717 231.327
+v 152.641 18.3647 259.352
+v 192.254 -17.1191 231.615
+v 184.949 -25.5522 236.73
+v 165.458 -28.8929 250.377
+v 152.968 -18.8697 259.123
+v 195.769 7.95114 229.154
+v 153.441 19.5615 258.792
+v 190.705 -19.5615 232.699
+v 191.178 18.8697 232.368
+v 159.197 25.5522 254.762
+v 194.484 12.308 230.053
+v 178.688 28.8929 241.114
+v 189.855 -20.7065 233.294
+v 185.572 25.0687 236.294
+v 151.892 17.1191 259.876
+v 194.973 10.8833 229.711
+v 196.394 -4.29823 228.716
+g CATIASTL
+f 229 220 38
+f 34 38 220
+f 220 153 34
+f 30 34 153
+f 153 178 30
+f 25 30 178
+f 178 224 25
+f 20 25 224
+f 224 215 20
+f 16 20 215
+f 215 145 16
+f 11 16 145
+f 145 170 11
+f 11 170 5
+f 5 170 225
+f 5 225 1
+f 1 225 195
+f 1 195 4
+f 4 195 146
+f 13 9 216
+f 216 181 13
+f 24 22 172
+f 172 251 24
+f 24 251 27
+f 27 251 168
+f 40 35 199
+f 199 230 40
+f 55 52 157
+f 157 239 55
+f 55 239 59
+f 59 239 167
+f 59 167 64
+f 64 167 191
+f 75 72 204
+f 204 209 75
+f 78 75 209
+f 209 243 78
+f 95 91 221
+f 221 171 95
+f 99 95 171
+f 171 165 99
+f 104 99 165
+f 165 147 104
+f 107 104 147
+f 147 144 107
+f 111 107 144
+f 144 238 111
+f 116 111 238
+f 238 241 116
+f 120 116 241
+f 241 151 120
+f 123 120 151
+f 151 161 123
+f 128 123 161
+f 161 182 128
+f 128 182 132
+f 132 182 223
+f 132 223 136
+f 136 223 169
+f 136 169 139
+f 139 169 200
+f 138 192 183
+f 138 183 133
+f 133 183 228
+f 133 228 129
+f 164 219 118
+f 114 118 219
+f 219 237 114
+f 110 114 237
+f 237 186 110
+f 105 110 186
+f 186 154 105
+f 102 105 154
+f 154 196 102
+f 97 102 196
+f 196 189 97
+f 94 97 189
+f 189 262 94
+f 89 94 262
+f 262 248 89
+f 86 89 248
+f 248 254 86
+f 79 86 254
+f 254 242 79
+f 73 79 242
+f 242 217 73
+f 69 73 217
+f 217 233 69
+f 69 233 65
+f 65 233 175
+f 65 175 61
+f 61 175 184
+f 61 184 58
+f 58 184 257
+f 142 139 200
+f 142 200 192
+f 142 192 138
+f 50 203 43
+f 43 203 229
+f 43 229 38
+f 216 9 146
+f 146 9 8
+f 146 8 4
+f 172 22 181
+f 181 22 18
+f 181 18 13
+f 199 35 168
+f 168 35 31
+f 168 31 27
+f 190 45 230
+f 230 45 41
+f 230 41 40
+f 157 52 190
+f 190 52 48
+f 190 48 45
+f 204 72 191
+f 191 72 67
+f 191 67 64
+f 252 83 243
+f 243 83 82
+f 243 82 78
+f 221 91 252
+f 252 91 88
+f 252 88 83
+f 129 228 126
+f 126 228 206
+f 126 206 122
+f 122 206 164
+f 122 164 118
+f 198 49 257
+f 257 49 53
+f 257 53 58
+f 188 211 37
+f 33 37 211
+f 211 197 33
+f 29 33 197
+f 197 234 29
+f 26 29 234
+f 234 218 26
+f 19 26 218
+f 218 202 19
+f 15 19 202
+f 202 205 15
+f 12 15 205
+f 205 245 12
+f 12 245 6
+f 6 245 207
+f 6 207 2
+f 2 207 246
+f 2 246 3
+f 3 246 185
+f 14 10 143
+f 143 240 14
+f 23 21 156
+f 156 259 23
+f 23 259 28
+f 28 259 236
+f 39 36 148
+f 148 174 39
+f 56 51 158
+f 158 261 56
+f 56 261 60
+f 60 261 235
+f 60 235 63
+f 63 235 152
+f 76 71 210
+f 210 166 76
+f 77 76 166
+f 166 214 77
+f 96 92 201
+f 201 247 96
+f 100 96 247
+f 247 159 100
+f 103 100 159
+f 159 173 103
+f 108 103 173
+f 173 258 108
+f 112 108 258
+f 258 263 112
+f 115 112 263
+f 263 208 115
+f 119 115 208
+f 208 253 119
+f 124 119 253
+f 253 162 124
+f 127 124 162
+f 162 244 127
+f 127 244 131
+f 131 244 193
+f 131 193 135
+f 135 193 150
+f 135 150 140
+f 140 150 231
+f 137 213 227
+f 137 227 134
+f 134 227 264
+f 134 264 130
+f 177 180 117
+f 113 117 180
+f 180 176 113
+f 109 113 176
+f 176 222 109
+f 106 109 222
+f 222 160 106
+f 101 106 160
+f 160 163 101
+f 98 101 163
+f 163 155 98
+f 93 98 155
+f 155 249 93
+f 90 93 249
+f 249 194 90
+f 85 90 194
+f 194 255 85
+f 80 85 255
+f 255 260 80
+f 74 80 260
+f 260 232 74
+f 70 74 232
+f 232 179 70
+f 70 179 66
+f 66 179 212
+f 66 212 62
+f 62 212 149
+f 62 149 57
+f 57 149 250
+f 141 140 231
+f 141 231 213
+f 141 213 137
+f 49 198 44
+f 44 198 188
+f 44 188 37
+f 143 10 185
+f 185 10 7
+f 185 7 3
+f 156 21 240
+f 240 21 17
+f 240 17 14
+f 148 36 236
+f 236 36 32
+f 236 32 28
+f 226 46 174
+f 174 46 42
+f 174 42 39
+f 158 51 226
+f 226 51 47
+f 226 47 46
+f 210 71 152
+f 152 71 68
+f 152 68 63
+f 256 84 214
+f 214 84 81
+f 214 81 77
+f 201 92 256
+f 256 92 87
+f 256 87 84
+f 130 264 125
+f 125 264 187
+f 125 187 121
+f 121 187 177
+f 121 177 117
+f 203 50 250
+f 250 50 54
+f 250 54 57
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/blockMeshDict b/tutorials/mesh/moveDynamicMesh/bendJunction/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..8e0ce196b4078e775beb782db64e3b532dc8cb72
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/blockMeshDict
@@ -0,0 +1,346 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2006                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale  1;
+
+// Nb of cells
+/*
+// 2260
+d0	5;
+d1	1;
+d2	2;
+d3	10;
+d4	3;
+d5	10;
+d6	2;
+d7	2;
+d8	2;
+d9	5;
+*/
+
+// 100000
+d0	17;
+d1	3;
+d2	5;
+d3	30;
+d4	8;
+d5	30;
+d6	7;
+d7	5;
+d8	5;
+d9	17;
+
+#inputMode merge
+
+vertices
+(
+    (       163.03320099       -11.03547257      252.075300317) //      0
+    (       163.03320099        11.03547257      252.075300317) //      1
+    (      181.112660821        11.03547257      239.415926257) //      2
+    (      181.112660821       -11.03547257      239.415926257) //      3
+    (      186.820645067                -25      235.419152659) //      4
+    (      157.325216744                -25      256.072073914) //      5
+    (      157.325216744                 25      256.072073914) //      6
+    (      186.820645067                 25      235.419152659) //      7
+    (      121.715728415      28.2842709103               -100) //      8
+    (       178.28427091      28.2842709103               -100) //      9
+    (       178.28427091      13.2842713871               -100) //     10
+    (       178.28427091     -28.2842715846               -100) //     11
+    (      121.715728415     -28.2842715846               -100) //     12
+    (      121.715728415     -13.2842713871               -100) //     13
+    (       206.56854183      -56.568543179               -100) //     14
+    (      93.4314568307     -56.5685431693               -100) //     15
+    (      93.4314568307      56.5685418206               -100) //     16
+    (      206.568541821      56.5685418206               -100) //     17
+    (      206.568541821                 25               -100) //     18
+    (      121.715728415      13.2842713871               -100) //     19
+    (      93.4314568307                 30               -100) //     20
+    (      206.568541821                -25               -100) //     21
+    (       178.28427091     -13.2842713871               -100) //     22
+    (      93.4314568307                -30               -100) //     23
+    (       144.25122796                 25      174.623724471) //     24
+    (      114.755799637                 25      195.276645725) //     25
+    (      114.755799637                -25      195.276645725) //     26
+    (       144.25122796                -25      174.623724471) //     27
+    (     -135.598492956      28.2842709103      80.1733574929) //     28
+    (     -154.946073968      28.2842709103      133.330399444) //     29
+    (     -154.946073968      13.2842713871      133.330399444) //     30
+    (     -154.946073968     -28.2842715846      133.330399444) //     31
+    (     -135.598492956     -28.2842715846      80.1733574929) //     32
+    (     -135.598492956     -13.2842713871      80.1733574929) //     33
+    (     -164.619864362      -56.568543179      159.908920112) //     34
+    (     -125.924702335     -56.5685431693      53.5948362005) //     35
+    (     -125.924702335      56.5685418206      53.5948362005) //     36
+    (     -164.619864359      56.5685418206      159.908920103) //     37
+    (     -164.619864359                 25      159.908920103) //     38
+    (     -135.598492956      13.2842713871      80.1733574929) //     39
+    (     -125.924702335                 30      53.5948362005) //     40
+    (     -164.619864359                -25      159.908920103) //     41
+    (     -154.946073968     -13.2842713871      133.330399444) //     42
+    (     -125.924702335                -30      53.5948362005) //     43
+    (       126.07044907      13.2842713871      152.956715912) //     44
+    (      100.613664182      13.2842713871      170.781748589) //     45
+    (      89.7088908564      13.2842713871      109.622698279) //     46
+    (      72.3293929347      13.2842713871      121.791953734) //     47
+    (       126.07044907      28.2842715846      152.956715912) //     48
+    (      100.613664182      28.2842715846      170.781748589) //     49
+    (      89.7088908564      28.2842715846      109.622698279) //     50
+    (      72.3293929347      28.2842715846      121.791953734) //     51
+    (       126.07044907     -13.2842713871      152.956715912) //     52
+    (      100.613664182     -13.2842713871      170.781748589) //     53
+    (      89.7088908564     -13.2842713871      109.622698279) //     54
+    (      72.3293929347     -13.2842713871      121.791953734) //     55
+    (       126.07044907     -28.2842715846      152.956715912) //     56
+    (      100.613664182     -28.2842715846      170.781748589) //     57
+    (      89.7088908564     -28.2842715846      109.622698279) //     58
+    (      72.3293929347     -28.2842715846      121.791953734) //     59
+    (      144.251227967      -56.568543179      174.623724478) //     60
+    (      71.5281115328     -56.5685431693      87.9556892035) //     61
+    (      71.5281115328      56.5685418206      87.9556892035) //     62
+    (       144.25122796      56.5685418206      174.623724471) //     63
+    (      71.5281115328                 30      87.9556892035) //     64
+    (      71.5281115328                -30      87.9556892035) //     65
+    (      114.755799642      -56.568543179      195.276645734) //     66
+    (      58.1872571424     -56.5685431693      97.2970560138) //     67
+    (      58.1872571424      56.5685418206      97.2970560138) //     68
+    (      114.755799637      56.5685418206      195.276645725) //     69
+    (      58.1872571424                 30      97.2970560138) //     70
+    (      58.1872571424                -30      97.2970560138) //     71
+    (      138.543243714       -11.03547257      178.620498068) //     72
+    (      120.463783883       -11.03547257      191.279872128) //     73
+    (      120.463783883        11.03547257      191.279872128) //     74
+    (      138.543243714        11.03547257      178.620498068) //     75
+    (      106.977860404     -6.64213569356       166.32549042) //     76
+    (      106.977860404      6.64213569356       166.32549042) //     77
+    (      119.706252848      6.64213569356      157.412974081) //     78
+    (      119.706252848     -6.64213569356      157.412974081) //     79
+    (      76.6742674151     -6.64213569356       118.74963987) //     80
+    (      76.6742674151      6.64213569356       118.74963987) //     81
+    (       85.364016376      6.64213569356      112.665012142) //     82
+    (       85.364016376     -6.64213569356      112.665012142) //     83
+    (      68.1928979352                -15       90.291030906) //     84
+    (      68.1928979352                 15       90.291030906) //     85
+    (        61.52247074                -15      94.9617143112) //     86
+    (        61.52247074                 15      94.9617143112) //     87
+);
+
+edges
+(
+);
+
+blocks
+(
+    //      0
+    hex (    72    75    74    73     3     2     1     0)  ($d6    $d8    $d0   ) simpleGrading (1 1 1)
+    //      1
+    hex (    26    27    72    73     5     4     3     0)  ($d8    $d1    $d0   ) simpleGrading (1 1 1)
+    //      2
+    hex (    25    26    73    74     6     5     0     1)  ($d6    $d1    $d0   ) simpleGrading (1 1 1)
+    //      3
+    hex (    24    25    74    75     7     6     1     2)  ($d8    $d1    $d0   ) simpleGrading (1 1 1)
+    //      4
+    hex (    24    75    72    27     7     2     3     4)  ($d1    $d6    $d0   ) simpleGrading (1 1 1)
+    //      5
+    hex (    44    46    50    48    10    19     8     9)  ($d9    $d2    $d3   ) simpleGrading (1 1 1)
+    //      6
+    hex (    48    50    62    63     9     8    16    17)  ($d9    $d4    $d3   ) simpleGrading (1 1 1)
+    //      7
+    hex (    46    64    62    50    19    20    16     8)  ($d4    $d2    $d3   ) simpleGrading (1 1 1)
+    //      8
+    hex (    24    44    48    63    18    10     9    17)  ($d4    $d2    $d3   ) simpleGrading (1 1 1)
+    //      9
+    hex (    44    52    54    46    10    22    13    19)  ($d6    $d9    $d3   ) simpleGrading (1 1 1)
+    //     10
+    hex (    24    27    52    44    18    21    22    10)  ($d6    $d4    $d3   ) simpleGrading (1 1 1)
+    //     11
+    hex (    52    56    58    54    22    11    12    13)  ($d7    $d9    $d3   ) simpleGrading (1 1 1)
+    //     12
+    hex (    56    60    61    58    11    14    15    12)  ($d4    $d9    $d3   ) simpleGrading (1 1 1)
+    //     13
+    hex (    27    60    56    52    21    14    11    22)  ($d7    $d4    $d3   ) simpleGrading (1 1 1)
+    //     14
+    hex (    54    58    61    65    13    12    15    23)  ($d7    $d4    $d3   ) simpleGrading (1 1 1)
+    //     15
+    hex (    46    54    65    64    19    13    23    20)  ($d6    $d4    $d3   ) simpleGrading (1 1 1)
+    //     16
+    hex (    48    63    69    49    44    24    25    45)  ($d4    $d8    $d2   ) simpleGrading (1 1 1)
+    //     17
+    hex (    74    75    78    77    25    24    44    45)  ($d8    $d4    $d1   ) simpleGrading (1 1 1)
+    //     18
+    hex (    72    79    78    75    27    52    44    24)  ($d4    $d6    $d1   ) simpleGrading (1 1 1)
+    //     19
+    hex (    26    53    42    41    25    45    30    38)  ($d4    $d5    $d6   ) simpleGrading (1 1 1)
+    //     20
+    hex (    29    49    69    37    30    45    25    38)  ($d5    $d4    $d2   ) simpleGrading (1 1 1)
+    //     21
+    hex (    73    74    77    76    26    25    45    53)  ($d6    $d4    $d1   ) simpleGrading (1 1 1)
+    //     22
+    hex (    31    57    53    42    34    66    26    41)  ($d5    $d7    $d4   ) simpleGrading (1 1 1)
+    //     23
+    hex (    56    57    66    60    52    53    26    27)  ($d8    $d4    $d7   ) simpleGrading (1 1 1)
+    //     24
+    hex (    72    73    76    79    27    26    53    52)  ($d8    $d4    $d1   ) simpleGrading (1 1 1)
+    //     25
+    hex (    45    49    51    47    30    29    28    39)  ($d2    $d9    $d5   ) simpleGrading (1 1 1)
+    //     26
+    hex (    49    69    68    51    29    37    36    28)  ($d4    $d9    $d5   ) simpleGrading (1 1 1)
+    //     27
+    hex (    47    51    68    70    39    28    36    40)  ($d2    $d4    $d5   ) simpleGrading (1 1 1)
+    //     28
+    hex (    45    47    55    53    30    39    33    42)  ($d9    $d6    $d5   ) simpleGrading (1 1 1)
+    //     29
+    hex (    53    55    59    57    42    33    32    31)  ($d9    $d7    $d5   ) simpleGrading (1 1 1)
+    //     30
+    hex (    57    59    67    66    31    32    35    34)  ($d9    $d4    $d5   ) simpleGrading (1 1 1)
+    //     31
+    hex (    55    71    67    59    33    43    35    32)  ($d4    $d7    $d5   ) simpleGrading (1 1 1)
+    //     32
+    hex (    47    70    71    55    39    40    43    33)  ($d4    $d6    $d5   ) simpleGrading (1 1 1)
+    //     33
+    hex (    48    49    51    50    44    45    47    46)  ($d8    $d9    $d2   ) simpleGrading (1 1 1)
+    //     34
+    hex (    77    78    82    81    45    44    46    47)  ($d8    $d9    $d1   ) simpleGrading (1 1 1)
+    //     35
+    hex (    78    79    83    82    44    52    54    46)  ($d6    $d9    $d1   ) simpleGrading (1 1 1)
+    //     36
+    hex (    76    77    81    80    53    45    47    55)  ($d6    $d9    $d1   ) simpleGrading (1 1 1)
+    //     37
+    hex (    62    68    70    64    50    51    47    46)  ($d8    $d2    $d4   ) simpleGrading (1 1 1)
+    //     38
+    hex (    82    83    84    85    46    54    65    64)  ($d6    $d4    $d1   ) simpleGrading (1 1 1)
+    //     39
+    hex (    81    82    85    87    47    46    64    70)  ($d8    $d4    $d1   ) simpleGrading (1 1 1)
+    //     40
+    hex (    80    81    87    86    55    47    70    71)  ($d6    $d4    $d1   ) simpleGrading (1 1 1)
+    //     41
+    hex (    62    63    69    68    50    48    49    51)  ($d9    $d8    $d4   ) simpleGrading (1 1 1)
+    //     42
+    hex (    56    58    59    57    52    54    55    53)  ($d9    $d8    $d7   ) simpleGrading (1 1 1)
+    //     43
+    hex (    76    80    83    79    53    55    54    52)  ($d9    $d8    $d1   ) simpleGrading (1 1 1)
+    //     44
+    hex (    61    65    71    67    58    54    55    59)  ($d7    $d8    $d4   ) simpleGrading (1 1 1)
+    //     45
+    hex (    80    86    84    83    55    71    65    54)  ($d4    $d8    $d1   ) simpleGrading (1 1 1)
+    //     46
+    hex (    60    61    67    66    56    58    59    57)  ($d9    $d8    $d4   ) simpleGrading (1 1 1)
+    //     47
+    hex (    76    79    78    77    73    72    75    74)  ($d8    $d6    $d4   ) simpleGrading (1 1 1)
+    //     48
+    hex (    80    83    82    81    76    79    78    77)  ($d8    $d6    $d9   ) simpleGrading (1 1 1)
+    //     49
+    hex (    84    85    87    86    83    82    81    80)  ($d6    $d8    $d4   ) simpleGrading (1 1 1)
+);
+
+boundary
+(
+    InletSmall
+    {
+        type patch;
+        faces
+        (
+            (     0     1     2     3) //      0
+            (     0     3     4     5) //      1
+            (     0     5     6     1) //      2
+            (     1     6     7     2) //      3
+            (     2     7     4     3) //      4
+      );
+    }
+    Outlet
+    {
+        type patch;
+        faces
+        (
+            (     8    19    10     9) //      0
+            (     8     9    17    16) //      1
+            (     8    16    20    19) //      2
+            (     9    10    18    17) //      3
+            (    10    19    13    22) //      4
+            (    10    22    21    18) //      5
+            (    11    22    13    12) //      6
+            (    11    12    15    14) //      7
+            (    11    14    21    22) //      8
+            (    12    13    23    15) //      9
+            (    13    19    20    23) //     10
+      );
+    }
+    SmallPipe
+    {
+        type wall;
+        faces
+        (
+            (     4     7    24    27) //      0
+            (     4    27    26     5) //      1
+            (     5    26    25     6) //      2
+            (     6    25    24     7) //      3
+      );
+    }
+    Inlet
+    {
+        type patch;
+        faces
+        (
+            (    28    29    30    39) //      0
+            (    28    36    37    29) //      1
+            (    28    39    40    36) //      2
+            (    29    37    38    30) //      3
+            (    30    42    33    39) //      4
+            (    30    38    41    42) //      5
+            (    31    32    33    42) //      6
+            (    31    34    35    32) //      7
+            (    31    42    41    34) //      8
+            (    32    35    43    33) //      9
+            (    33    43    40    39) //     10
+      );
+    }
+    BigPipe
+    {
+        type wall;
+        faces
+        (
+            (    14    21    27    60) //      0
+            (    14    15    61    60) //      1
+            (    15    23    65    61) //      2
+            (    16    17    63    62) //      3
+            (    16    62    64    20) //      4
+            (    17    63    24    18) //      5
+            (    18    24    27    21) //      6
+            (    20    64    65    23) //      7
+            (    24    63    69    25) //      8
+            (    25    69    37    38) //      9
+            (    25    38    41    26) //     10
+            (    26    41    34    66) //     11
+            (    26    66    60    27) //     12
+            (    34    66    67    35) //     13
+            (    35    67    71    43) //     14
+            (    36    68    69    37) //     15
+            (    36    40    70    68) //     16
+            (    40    43    71    70) //     17
+            (    60    61    67    66) //     18
+            (    61    65    71    67) //     19
+            (    62    63    69    68) //     20
+            (    62    68    70    64) //     21
+            (    64    85    84    65) //     22
+            (    64    70    87    85) //     23
+            (    65    84    86    71) //     24
+            (    70    71    86    87) //     25
+            (    84    85    87    86) //     26
+      );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/controlDict b/tutorials/mesh/moveDynamicMesh/bendJunction/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..2fdd223f837d9143fa3b915d4f187e34c3fe39cc
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/controlDict
@@ -0,0 +1,59 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2006                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+DebugSwitches
+{
+    pointBoundaryMesh   1;
+}
+
+application     moveDynamicMesh;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         10;
+
+deltaT          1;
+
+writeControl    timeStep;
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;  //binary;
+
+writePrecision  16;
+
+writeCompression false;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable yes;
+
+adjustTimeStep  yes;
+
+maxCo           0.1;
+maxAlphaCo      0.1;
+maxDeltaT       1;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/decomposeParDict b/tutorials/mesh/moveDynamicMesh/bendJunction/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..a3282112ad11ad20a8a9873519a3900c94de32d6
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/decomposeParDict
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  2;
+
+//- The decomposition method (mandatory)
+method          scotch;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSchemes b/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..59150f323dd356adce54d01b366712a60524c87c
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSchemes
@@ -0,0 +1,45 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2006                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{}
+
+laplacianSchemes
+{
+    default         Gauss linear orthogonal;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         orthogonal;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSolution b/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..96c25bcf0cbf1c05b209c9411e0bdee12df3910b
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/fvSolution
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2006                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    "cellDisplacement.*"
+    {
+        solver          GAMG;
+        tolerance       1e-08;
+        relTol          0;
+        smoother        GaussSeidel;
+    }
+}
+
+PIMPLE
+{}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/bendJunction/system/surfaceFeatureExtractDict b/tutorials/mesh/moveDynamicMesh/bendJunction/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..846e80c94de1594e52f0d0693bd358d609f8f68b
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/bendJunction/system/surfaceFeatureExtractDict
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+geometry.obj
+{
+    // How to obtain raw features (extractFromFile || extractFromSurface)
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       135;
+
+    // Write features to obj format for postprocessing
+    writeObj            yes;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/0/pointDisplacement b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/0/pointDisplacement
new file mode 100644
index 0000000000000000000000000000000000000000..038119bc3eba906ee07c7d33edabeac433c07ca3
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/0/pointDisplacement
@@ -0,0 +1,68 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  2309                                  |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    arch        "LSB;label=32;scalar=64";
+    class       pointVectorField;
+    location    "0";
+    object      pointDisplacement;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dimensions      [0 1 0 0 0 0 0];
+
+internalField   uniform (0 0 0);
+
+boundaryField
+{
+    movingZone
+    {
+        type            uniformFixedValue;
+        uniformValue    table
+        (
+            ( 0.0        (0 0 0))
+            ( 5.0        (0.2 0 0))
+            (10.0        (0 0 0))
+        );
+    }
+    movingZoneEdges
+    {
+        //type            slip;
+        ${movingZone}
+    }
+
+    minX
+    {
+        type    slip;
+    }
+    maxX
+    {
+        $minX
+    }
+    minY
+    {
+        $minX
+    }
+    maxY
+    {
+        $minX
+    }
+    minZ
+    {
+        $minX
+    }
+    maxZ
+    {
+        $minX
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allclean b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..5ef46f9d35db1f707b94b73f1b5c3903b6e47332
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allclean
@@ -0,0 +1,17 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+cleanCase
+
+rm -rf constant/extendedFeatureEdgeMesh
+
+#- From pointMesh generation
+rm -rf constant/pointMesh
+rm -f constant/triSurface/blockMesh.obj
+
+#- From surfaceFeatureExtract
+rm -f constant/triSurface/box222.eMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allrun b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..5a120500ec10cbf6ed53c3a0e833affe90b5f23f
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/Allrun
@@ -0,0 +1,47 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+#- Generate mesh
+runApplication blockMesh
+
+#- Create faceZone (on unrotated mesh so is easy to select box of faces)
+runApplication topoSet
+
+#- Rotate a bit
+#runApplication transformPoints -rotate-z -45
+
+#- Generate pointMesh with additional feature patches
+#  (in constant/pointMesh/boundary)
+# - extracted surface is not used
+# - specify illegal patchname so none will be extracted (could use
+#   '-excludePatches' instead)
+# - extract feature points of faceZone
+# - additionally extract all points of faceZone (-extractZonePoints)
+runApplication surfaceMeshExtract \
+    -featureAngle 45 \
+    -patches '(ZZZZZZ)' \
+    -faceZones '(movingZone)' -extractZonePoints \
+    constant/triSurface/blockMesh.obj
+
+#- For postprocessing: extract new pointPatches as vtk files
+setSet <<EOF
+pointSet p0 new patchToPoint movingZone
+pointSet p1 new patchToPoint movingZoneEdges
+EOF
+
+#- TBD. move triSurfaces to resources
+#mkdir -p constant/triSurface
+#cp -f \
+#    "$FOAM_TUTORIALS"/resources/geometry/box222.obj \
+#    constant/triSurface/
+
+#- Extract features from surface. Writes .eMesh
+runApplication surfaceFeatureExtract
+
+#- Morph mesh to the surface (.obj file) and feature-edges (.eMesh file)
+#- Note: needs point-based motion solver
+runApplication moveDynamicMesh
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/README.txt b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6a21ff07233062b83c03301bc5e81b3f7bec6ab9
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/README.txt
@@ -0,0 +1,2 @@
+Demo of applying mesh motion to internal faces. Note: using point-based
+motion-solver since no boundary faces to put motion bcs on.
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/dynamicMeshDict b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..deeaf753bc4abf1ffa393c19ab632f93392b330a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/dynamicMeshDict
@@ -0,0 +1,31 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+// For point-bcs
+motionSolverLibs (fvMotionSolvers);
+
+motionSolver    displacementPointSmoothing;
+displacementPointSmoothingCoeffs
+{
+    // Use geometricElementTransform to maintain relative sizes
+    pointSmoother           geometricElementTransform;
+    transformationParameter 0.667;
+    nPointSmootherIter      10;
+}
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/triSurface/box222.obj b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/triSurface/box222.obj
new file mode 100644
index 0000000000000000000000000000000000000000..f1aceeca48a77cbe62aea577f651b129de3fa96d
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/constant/triSurface/box222.obj
@@ -0,0 +1,79 @@
+# Generated by Visualization Toolkit
+v -1 -1 -1
+v -1 -1 1
+v -1 1 -1
+v -1 1 1
+v 1 -1 -1
+v 1 -1 1
+v 1 1 -1
+v 1 1 1
+v -1 -1 -1
+v -1 -1 1
+v 1 -1 -1
+v 1 -1 1
+v -1 1 -1
+v -1 1 1
+v 1 1 -1
+v 1 1 1
+v -1 -1 -1
+v 1 -1 -1
+v -1 1 -1
+v 1 1 -1
+v -1 -1 1
+v 1 -1 1
+v -1 1 1
+v 1 1 1
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn -1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 1 0 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 -1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 1 0
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 -1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vn 0 0 1
+vt -0.5 -0.5
+vt 1.5 -0.5
+vt -0.5 1.5
+vt 1.5 1.5
+vt 0.5 -0.5
+vt -1.5 -0.5
+vt 0.5 1.5
+vt -1.5 1.5
+vt 0.5 0.5
+vt 0.5 -1.5
+vt -1.5 0.5
+vt -1.5 -1.5
+vt -0.5 0.5
+vt -0.5 -1.5
+vt 1.5 0.5
+vt 1.5 -1.5
+vt 0.5 -0.5
+vt -1.5 -0.5
+vt 0.5 1.5
+vt -1.5 1.5
+vt -0.5 -0.5
+vt 1.5 -0.5
+vt -0.5 1.5
+vt 1.5 1.5
+f 1/1/1 2/2/2 4/4/4 3/3/3
+f 5/5/5 7/7/7 8/8/8 6/6/6
+f 9/9/9 11/11/11 12/12/12 10/10/10
+f 13/13/13 14/14/14 16/16/16 15/15/15
+f 17/17/17 19/19/19 20/20/20 18/18/18
+f 21/21/21 22/22/22 24/24/24 23/23/23
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/blockMeshDict b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..29c9c50eea362de74a6f67c3e9c0a4a447c2157b
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/blockMeshDict
@@ -0,0 +1,95 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    // Inner block
+    (-2 -2 -2)
+    ( 2 -2 -2)
+    ( 2  2 -2)
+    (-2  2 -2)
+    (-2 -2  2)
+    ( 2 -2  2)
+    ( 2  2  2)
+    (-2  2  2)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (20 20 20) grading (1 10 1)  // Inner block
+);
+
+boundary
+(
+    minX
+    {
+        type patch;
+        faces
+        (
+            (0 0)  // block 0: x-min
+        );
+    }
+
+    maxX
+    {
+        type patch;
+        faces
+        (
+            (0 1)  // block 0: x-max
+        );
+    }
+
+    minY
+    {
+        type patch;
+        faces
+        (
+            (0 2)  // block 0: y-min
+        );
+    }
+
+    maxY
+    {
+        type patch;
+        faces
+        (
+            (0 3)  // block 0: y-max
+        );
+    }
+
+    minZ
+    {
+        type patch;
+        faces
+        (
+            (0 4)  // block 0: z-min
+        );
+    }
+
+    maxZ
+    {
+        type patch;
+        faces
+        (
+            (0 5)  // block 0: z-max
+        );
+    }
+);
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/controlDict b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..f7bf44fca761a8dfcc42bf1e0743c56cd3362daa
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/controlDict
@@ -0,0 +1,53 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+DebugSwitches
+{
+    pointBoundaryMesh   1;
+}
+
+application     moveDynamicMesh;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         10;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  6;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSchemes b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..dce45d04ae700d8dc803ec1a4749fef42b01ad9a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSchemes
@@ -0,0 +1,44 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ddtSchemes
+{}
+
+gradSchemes
+{
+    default         Gauss linear;
+}
+
+divSchemes
+{}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSolution b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..eaff818230d35f16dff830ce18b781ad43ace4d3
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/fvSolution
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    "cellDisplacement.*"
+    {
+        solver          GAMG;
+        tolerance       1e-08;
+        relTol          0;
+        smoother        GaussSeidel;
+    }
+}
+
+
+PIMPLE
+{}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/surfaceFeatureExtractDict b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..9039408675c88bdcb9ca01631b684db47c22448a
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/surfaceFeatureExtractDict
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+box222.obj
+{
+    // How to obtain raw features (extractFromFile || extractFromSurface)
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       135;
+
+    // Write features to obj format for postprocessing
+    writeObj            yes;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/topoSetDict b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/topoSetDict
new file mode 100644
index 0000000000000000000000000000000000000000..3438cbf62d83886265b1abdbcf79e418c4a719b8
--- /dev/null
+++ b/tutorials/mesh/moveDynamicMesh/faceZoneBlock/system/topoSetDict
@@ -0,0 +1,43 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      topoSetDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+actions
+(
+    {
+        name    c0;
+        type    cellSet;
+        action  new;
+        source  boxToCell;
+        box     (-1 -1 -1)(1 1 1);
+    }
+    {
+        name    movingZoneFaces;
+        type    faceSet;
+        action  new;
+        source  cellToFace;
+        set     c0;
+        option  outside;
+    }
+    {
+        name    movingZone;
+        type    faceZoneSet;
+        action  new;
+        source  setToFaceZone;
+        faceSet movingZoneFaces;
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/blockMeshDict b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/blockMeshDict
index a4f374de0b4180b9015f7f7cac1d71ce40df03ca..84172915a09b9ca78f1207b4d709081624d4c669 100644
--- a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/blockMeshDict
+++ b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/blockMeshDict
@@ -18,14 +18,14 @@ scale   1;
 
 vertices
 (
-    (-1 -1 -1)
-    ( 2 -1 -1)
-    ( 2  0 -1)
-    (-1  0 -1)
-    (-1 -1  1)
-    ( 2 -1  1)
-    ( 2  0  1)
-    (-1  0  1)
+    (-1 -0.8 -1)
+    ( 2 -0.8 -1)
+    ( 2 -0.2 -1)
+    (-1 -0.2 -1)
+    (-1 -0.8  1)
+    ( 2 -0.8  1)
+    ( 2 -0.2  1)
+    (-1 -0.2  1)
 );
 
 blocks
@@ -44,14 +44,30 @@ boundary
         type patch;
         faces
         (
-            (3 7 6 2)
-            (1 5 4 0)  //back
             (2 6 5 1)  //outlet
             (0 4 7 3)  //inlet
             (0 3 2 1)  //lowerWall
             (4 5 6 7)  //upperWall
         );
     }
+
+    front
+    {
+        type symmetryPlane;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+
+    back
+    {
+        type symmetryPlane;
+        faces
+        (
+            (1 5 4 0)  //back
+        );
+    }
 );
 
 
diff --git a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSchemes b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSchemes
index 3475759928b38316ad4e0134f29ddc794551f1ec..9994fe78511e4476b32099aa2868f3993e877f8c 100644
--- a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSchemes
+++ b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSchemes
@@ -5,14 +5,14 @@
 |   \\  /    A nd           | Website:  www.openfoam.com                      |
 |    \\/     M anipulation  |                                                 |
 \*---------------------------------------------------------------------------*/
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 FoamFile
 {
-    version     2.0;
-    format      ascii;
-    class       dictionary;
-    object      fvSchemes;
+    version         2;
+    format          ascii;
+    class           dictionary;
+    object          fvSchemes;
 }
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 ddtSchemes
 {
@@ -20,6 +20,7 @@ ddtSchemes
 
 gradSchemes
 {
+    default         Gauss linear;
 }
 
 divSchemes
@@ -28,14 +29,17 @@ divSchemes
 
 laplacianSchemes
 {
+    default         Gauss linear corrected;
 }
 
 interpolationSchemes
 {
+    default         linear;
 }
 
 snGradSchemes
 {
+    default         corrected;
 }
 
 wallDist
diff --git a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSolution b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSolution
index c89b4c70181b9c46cda8e2e104927bd749728cd2..5771a4eb9e8a9c657308c3ac77af37bf0087ffc9 100644
--- a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSolution
+++ b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/fvSolution
@@ -16,6 +16,13 @@ FoamFile
 
 solvers
 {
+    "cellDisplacement.*"
+    {
+        solver          GAMG;
+        tolerance       1e-08;
+        relTol          0;
+        smoother        GaussSeidel;
+    }
 }
 
 
diff --git a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/snappyHexMeshDict b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/snappyHexMeshDict
index a6ad5526da27b94f000b4d8ded2df29d2e3b34b1..97fd5130dc7fa7ec3316250939fe80018e6cd0aa 100644
--- a/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/snappyHexMeshDict
+++ b/tutorials/mesh/snappyHexMesh/airfoilWithLayers/system/snappyHexMeshDict
@@ -14,6 +14,11 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Type of mesh generation:
+//  - castellated (default)
+//  - castellatedBufferLayer
+//type            castellatedBufferLayer;
+
 // Which of the steps to run
 castellatedMesh true;
 snap            true;
@@ -427,6 +432,31 @@ castellatedMeshControls
     //nCellZoneErodeIter 2;
 }
 
+
+// Internal macro for mesh-motion solver to use
+_meshMotionSolver
+{
+    solver  displacementPointSmoothing;
+    displacementPointSmoothingCoeffs
+    {
+        //// Use geometricElementTransform to maintain relative sizes
+        //pointSmoother           geometricElementTransform;
+        //transformationParameter 0.667;
+        //nPointSmootherIter      10;
+
+        // Use laplacian to untangle problem areas
+        pointSmoother           laplacian;
+        nPointSmootherIter      10;
+
+        //relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+        //meshQuality
+        //{
+        //    #includeEtc "caseDicts/meshQualityDict"
+        //}        
+    }
+}
+
+
 // Settings for the snapping.
 snapControls
 {
@@ -501,6 +531,10 @@ snapControls
         //- Attract points only to the surface they originate from. Default
         //  false. This can improve snapping of intersecting surfaces.
         strictRegionSnap true;
+
+
+    // Motion solver to use (when in  castellatedBufferLayer)
+    ${_meshMotionSolver}
 }
 
 // Settings for the layer addition.
@@ -601,19 +635,27 @@ addLayersControls
         // motion solvers. It needs specification of the solver to use and
         // its control dictionary.
         //meshShrinker displacementMotionSolver;
-        //solver displacementLaplacian;
-        //displacementLaplacianCoeffs
+        //solver      multiDisplacement;
+        //solvers
         //{
-        //    diffusivity quadratic inverseDistance
-        //    (
-        //        sphere.stl_firstSolid
-        //        maxY
-        //    );
+        //    displacementLaplacian
+        //    {
+        //        // Note that e.g. displacementLaplacian needs entries in
+        //        // fvSchemes, fvSolution. Also specify a minIter > 1 when
+        //        // solving
+        //        // cellDisplacement since otherwise solution might not be
+        //        // sufficiently accurate on points.
+        //        solver              displacementLaplacian;
+        //        diffusivity quadratic inverseDistance
+        //        (
+        //            aerofoil
+        //        );
+        //    }
+        //    displacementPointSmoothing
+        //    {
+        //        ${_meshMotionSolver}
+        //    }
         //}
-        // Note that e.g. displacementLaplacian needs entries in
-        // fvSchemes, fvSolution. Also specify a minIter > 1 when solving
-        // cellDisplacement since otherwise solution might not be sufficiently
-        // accurate on points.
 
 
     // Medial axis analysis (for use with default displacementMedialAxis)
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/Allclean b/tutorials/mesh/snappyHexMesh/rotated_block/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..5574bad3101ee40ee0d5117a5615dea54af4e839
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/Allclean
@@ -0,0 +1,10 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+rm -rf constant/extendedFeatureEdgeMesh
+rm -rf constant/triSurface/block.eMesh
+cleanCase0
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/Allrun b/tutorials/mesh/snappyHexMesh/rotated_block/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..f40a167c84ce598bf8ab52d7ba5a9c310fe9cfc9
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/Allrun
@@ -0,0 +1,24 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+#mkdir -p constant/triSurface
+#cp -f \
+#    "$FOAM_TUTORIALS"/resources/geometry/flange.stl.gz \
+#    constant/triSurface
+
+runApplication blockMesh
+
+runApplication surfaceFeatureExtract
+
+runApplication snappyHexMesh
+
+runApplication checkMesh -writeFields '(nonOrthoAngle)'
+
+# Run parallel a bit as well
+runApplication decomposePar
+runParallel -s parallel snappyHexMesh
+runParallel -s parallel checkMesh -writeFields '(nonOrthoAngle)'
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/README.txt b/tutorials/mesh/snappyHexMesh/rotated_block/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..19009dfc524e2249e7a37692996d45812d8a21fc
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/README.txt
@@ -0,0 +1,2 @@
+- rotated block inside regular blockMesh
+- set up to add buffer layers after smoothing outside
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/constant/dynamicMeshDict b/tutorials/mesh/snappyHexMesh/rotated_block/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..fdf87f68acae84535f75c22673ea84691e3681b8
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/constant/dynamicMeshDict
@@ -0,0 +1,41 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+solver          displacementPointSmoothing;
+
+displacementPointSmoothingCoeffs
+{
+    //// Use geometricElementTransform to maintain relative sizes
+    //pointSmoother           geometricElementTransform;
+    //transformationParameter 0.667;
+    //nPointSmootherIter      10;
+
+    // Use laplacian to untangle problem areas
+    pointSmoother           laplacian;
+    nPointSmootherIter      100;
+
+    //relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+    //meshQuality
+    //{
+    //    #includeEtc "caseDicts/meshQualityDict"
+    //}        
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/constant/transportProperties b/tutorials/mesh/snappyHexMesh/rotated_block/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..fc05a376222c9ce0fd94d4e4134855e949ee5d28
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/constant/transportProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+nu              0.01;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/constant/triSurface/block.obj b/tutorials/mesh/snappyHexMesh/rotated_block/constant/triSurface/block.obj
new file mode 100644
index 0000000000000000000000000000000000000000..b8fa074e6ed3e01a4155021920ee05abb2198910
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/constant/triSurface/block.obj
@@ -0,0 +1,38 @@
+# Wavefront OBJ file written 2024-01-24T16:36:27
+o block
+
+# points : 8
+# faces  : 6
+# zones  : 6
+#   0  maxY  (nFaces: 1)
+#   1  minX  (nFaces: 1)
+#   2  minZ  (nFaces: 1)
+#   3  maxX  (nFaces: 1)
+#   4  maxZ  (nFaces: 1)
+#   5  minY  (nFaces: 1)
+
+# <points count="8">
+v 0 0 0
+v -0.5773502691896258 -0.2113248654051871 0.7886751345948129
+v -1.154700538379252 0.5773502691896258 0.5773502691896258
+v -0.5773502691896258 0.7886751345948129 -0.2113248654051871
+v 0.5773502691896258 0.5773502691896258 0.5773502691896258
+v 0 1.366025403784439 0.3660254037844388
+v -0.5773502691896258 1.154700538379252 1.154700538379252
+v 0 0.3660254037844388 1.366025403784439
+# </points>
+
+# <faces count="6">
+g maxY
+f 4 3 7 6
+g minX
+f 1 2 3 4
+g minZ
+f 1 4 6 5
+g maxX
+f 5 6 7 8
+g maxZ
+f 2 8 7 3
+g minY
+f 1 5 8 2
+# </faces>
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..bcfd580bf0617a579a6b3b3cac2ea219a132eaad
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict
@@ -0,0 +1,96 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (-2   -1   -1)
+    ( 1   -1   -1)
+    ( 1    2   -1)
+    (-2    2   -1)
+    (-2   -1    2)
+    ( 1   -1    2)
+    ( 1    2    2)
+    (-2    2    2)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (20 20 20) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    minX
+    {
+        type wall;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    maxX
+    {
+        type wall;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+
+
+    minY
+    {
+        type wall;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    maxY
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+
+
+    minZ
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    maxZ
+    {
+        type wall;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict.block b/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict.block
new file mode 100644
index 0000000000000000000000000000000000000000..20b44b2bf6c039ae96de2581af638fddaa8ddc6e
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/blockMeshDict.block
@@ -0,0 +1,97 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (0   0   0)
+    (1   0   0)
+    (1   1   0)
+    (0   1   0)
+    (0   0   1)
+    (1   0   1)
+    (1   1   1)
+    (0   1   1)
+);
+
+blocks
+(
+    //hex (0 1 2 3 4 5 6 7) (20 20 10) simpleGrading (100 100 1)
+    hex (0 1 2 3 4 5 6 7) (1 1 1) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    minX
+    {
+        type wall;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    maxX
+    {
+        type wall;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+
+
+    minY
+    {
+        type wall;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    maxY
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+
+
+    minZ
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    maxZ
+    {
+        type wall;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/controlDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..953725e2fb32b82dd05f7740e7c1c51b43a13dec
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/controlDict
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     snappyHexMesh;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          writeNow;
+
+endTime         30;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  16;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/decomposeParDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..1577bf4039ae4980f51693f4376c5570f4a883d4
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/decomposeParDict
@@ -0,0 +1,24 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- The total number of domains (mandatory)
+numberOfSubdomains  5;
+
+//- The decomposition method (mandatory)
+method          scotch; //random;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSchemes b/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..fd610a97b38961fd361d0cc2ba623c7c139a09da
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSchemes
@@ -0,0 +1,59 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//geometry
+//{
+//    type            highAspectRatio;
+//    minAspect       0;
+//    maxAspect       0;
+//}
+
+
+ddtSchemes
+{
+    default         Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(p)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear orthogonal;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         orthogonal;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSolution b/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..fa297c1118f4b55e8bbdcaffbd0116aea0463b39
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/fvSolution
@@ -0,0 +1,52 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-06;
+        relTol          0.05;
+    }
+
+    pFinal
+    {
+        $p;
+        relTol          0;
+    }
+
+    U
+    {
+        solver          smoothSolver;
+        smoother        symGaussSeidel;
+        tolerance       1e-05;
+        relTol          0;
+    }
+}
+
+PISO
+{
+    nCorrectors     2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell        0;
+    pRefValue       0;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/meshQualityDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/meshQualityDict
new file mode 100644
index 0000000000000000000000000000000000000000..1a0afa5f754e90e763ba4fee639cdef03495e87f
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/meshQualityDict
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      meshQualityDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Include defaults parameters from master dictionary
+#includeEtc "caseDicts/meshQualityDict"
+
+//maxNonOrtho         180;
+//maxConcave          180;
+//minVol              -1e30;
+maxBoundarySkewness -1;
+maxInternalSkewness -1;
+//minTetQuality       -1e30;
+//minDeterminant      -1e30;
+//minTwist            -1;
+//minFaceWeight       -1;
+//minVolRatio         -1;
+//minDeterminant      -1;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/snappyHexMeshDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/snappyHexMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..b6bf90d2eff4a15abdac8a4fea1e3508b6c55bc2
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/snappyHexMeshDict
@@ -0,0 +1,364 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      snappyHexMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Type of mesh generation:
+//  - castellated (default)
+//  - castellatedBufferLayer
+type            castellatedBufferLayer;
+
+// Which of the steps to run
+castellatedMesh true;
+snap            true;
+addLayers       false;  //true;
+
+
+// Geometry. Definition of all surfaces. All surfaces are of class
+// searchableSurface.
+// Surfaces are used
+// - to specify refinement for any mesh cell intersecting it
+// - to specify refinement for any mesh cell inside/outside/near
+// - to 'snap' the mesh boundary to the surface
+geometry
+{
+    block
+    {
+        type triSurfaceMesh;
+        file "block.obj";
+    }
+}
+
+
+// Settings for the castellatedMesh generation.
+castellatedMeshControls
+{
+
+    // Refinement parameters
+    // ~~~~~~~~~~~~~~~~~~~~~
+
+    // If local number of cells is >= maxLocalCells on any processor
+    // switches from from refinement followed by balancing
+    // (current method) to (weighted) balancing before refinement.
+    maxLocalCells 100000;
+
+    // Overall cell limit (approximately). Refinement will stop immediately
+    // upon reaching this number so a refinement level might not complete.
+    // Note that this is the number of cells before removing the part which
+    // is not 'visible' from the keepPoint. The final number of cells might
+    // actually be a lot less.
+    maxGlobalCells 2000000;
+
+    // The surface refinement loop might spend lots of iterations refining just a
+    // few cells. This setting will cause refinement to stop if <= minimumRefine
+    // are selected for refinement. Note: it will at least do one iteration
+    // (unless the number of cells to refine is 0)
+    minRefinementCells 0;
+
+    // Number of buffer layers between different levels.
+    // 1 means normal 2:1 refinement restriction, larger means slower
+    // refinement.
+    nCellsBetweenLevels 1;
+
+
+
+    // Explicit feature edge refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies a level for any cell intersected by its edges.
+    // This is a featureEdgeMesh, read from constant/triSurface for now.
+    features
+    (
+        {
+            file "block.eMesh";
+            level 0;
+        }
+    );
+
+
+
+    // Surface based refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies two levels for every surface. The first is the minimum level,
+    // every cell intersecting a surface gets refined up to the minimum level.
+    // The second level is the maximum level. Cells that 'see' multiple
+    // intersections where the intersections make an
+    // angle > resolveFeatureAngle get refined up to the maximum level.
+
+    refinementSurfaces
+    {
+        block
+        {
+            // Surface-wise min and max refinement level
+            level (2 2);
+            faceZone    block;
+            faceType    internal;
+            //addBufferLayers true;
+        }
+    }
+
+    resolveFeatureAngle 180;
+
+
+    // Region-wise refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies refinement level for cells in relation to a surface. One of
+    // three modes
+    // - distance. 'levels' specifies per distance to the surface the
+    //   wanted refinement level. The distances need to be specified in
+    //   descending order.
+    // - inside. 'levels' is only one entry and only the level is used. All
+    //   cells inside the surface get refined up to the level. The surface
+    //   needs to be closed for this to be possible.
+    // - outside. Same but cells outside.
+
+    refinementRegions
+    {
+    }
+
+
+    // Mesh selection
+    // ~~~~~~~~~~~~~~
+
+    // After refinement patches get added for all refinementSurfaces and
+    // all cells intersecting the surfaces get put into these patches. The
+    // section reachable from the locationInMesh is kept.
+    // NOTE: This point should never be on a face, always inside a cell, even
+    // after refinement.
+    // This is an outside point locationInMesh (-0.033 -0.033 0.0033);
+    locationInMesh (0.00013 0.00013 0.00013); // Inside point
+
+    // Whether any faceZones (as specified in the refinementSurfaces)
+    // are only on the boundary of corresponding cellZones or also allow
+    // free-standing zone faces. Not used if there are no faceZones.
+    allowFreeStandingZoneFaces false;
+
+    nCellZoneErodeIter -1;
+}
+
+
+
+// Internal macro for mesh-motion solver to use
+_meshMotionSolver
+{
+    solver  displacementPointSmoothing;
+    displacementPointSmoothingCoeffs
+    {
+        //// Use geometricElementTransform to maintain relative sizes
+        //pointSmoother           geometricElementTransform;
+        //transformationParameter 0.667;
+        //nPointSmootherIter      10;
+
+        // Use laplacian to untangle problem areas
+        pointSmoother           laplacian;
+        nPointSmootherIter      10;
+
+        //relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+        //meshQuality
+        //{
+        //    #includeEtc "caseDicts/meshQualityDict"
+        //}        
+    }
+}
+
+
+// Settings for the snapping.
+snapControls
+{
+    //- Number of patch smoothing iterations before finding correspondence
+    //  to surface
+    nSmoothPatch 3;
+
+    //- Relative distance for points to be attracted by surface feature point
+    //  or edge. True distance is this factor times local
+    //  maximum edge length.
+    tolerance 1.0;
+
+    //- When to split face with diagonal attraction:
+    //      0 : only if perfect alignment (angle = 0) with feature itself
+    //    180 : always
+    concaveAngle 180;
+
+    //- When to split distorted face: not split if areas would differ too
+    //  much (ideal is equal size i.e. area-ratio 1). -1 : disable check
+    minAreaRatio -1;
+
+    //- Number of mesh displacement relaxation iterations.
+    nSolveIter 300;
+
+    //- Maximum number of snapping relaxation iterations. Should stop
+    //  before upon reaching a correct mesh.
+    nRelaxIter 5;
+
+    // Feature snapping
+
+        //- Number of feature edge snapping iterations.
+        //  Leave out altogether to disable.
+        nFeatureSnapIter 10;
+
+        //- Detect (geometric) features by sampling the surface
+        implicitFeatureSnap true;
+
+        //- Use castellatedMeshControls::features
+        explicitFeatureSnap true;
+
+        //- Detect features between multiple surfaces
+        //  (only for explicitFeatureSnap, default = false)
+        multiRegionFeatureSnap true;
+
+
+    // Motion solver to use
+    ${_meshMotionSolver}
+}
+
+
+
+// Settings for the layer addition.
+addLayersControls
+{
+    // Are the thickness parameters below relative to the undistorted
+    // size of the refined cell outside layer (true) or absolute sizes (false).
+    relativeSizes true;
+
+    // Per final patch (so not geometry!) the layer information
+    layers
+    {
+        "block_.*"
+        {
+            nSurfaceLayers 1;
+        }
+    }
+
+    // Expansion factor for layer mesh
+    expansionRatio 1.0;
+
+
+    // Wanted thickness of final added cell layer. If multiple layers
+    // is the thickness of the layer furthest away from the wall.
+    // Relative to undistorted size of cell outside layer.
+    // See relativeSizes parameter.
+    finalLayerThickness 0.5;
+
+    // Minimum thickness of cell layer. If for any reason layer
+    // cannot be above minThickness do not add layer.
+    // See relativeSizes parameter.
+    minThickness 0.1;
+
+    // If points get not extruded do nGrow layers of connected faces that are
+    // also not grown. This helps convergence of the layer addition process
+    // close to features.
+    nGrow 0;
+
+
+    // Advanced settings
+
+    // When not to extrude surface. 0 is flat surface, 90 is when two faces
+    // are perpendicular
+    featureAngle 30;
+
+    // Maximum number of snapping relaxation iterations. Should stop
+    // before upon reaching a correct mesh.
+    nRelaxIter 5;
+
+    // Number of smoothing iterations of surface normals
+    nSmoothSurfaceNormals 1;
+
+    // Number of smoothing iterations of interior mesh movement direction
+    nSmoothNormals 3;
+
+    // Smooth layer thickness over surface patches
+    nSmoothThickness 10;
+
+    // Stop layer growth on highly warped cells
+    maxFaceThicknessRatio 0.5;
+
+    // Reduce layer growth where ratio thickness to medial
+    // distance is large
+    maxThicknessToMedialRatio 0.3;
+
+    // Angle used to pick up medial axis points
+    minMedialAxisAngle 90;
+
+    // Create buffer region for new layer terminations
+    nBufferCellsNoExtrude 0;
+
+
+
+    //- Use displacementMotionSolver to shrink mesh
+    meshShrinker displacementMotionSolver;
+
+    // Motion solver to use
+    ${_meshMotionSolver}
+
+
+    // Overall max number of layer addition iterations. The mesher will exit
+    // if it reaches this number of iterations; possibly with an illegal
+    // mesh.
+    nLayerIter 50;
+
+    // Max number of iterations after which relaxed meshQuality controls
+    // get used. Up to nRelaxIter it uses the settings in meshQualityControls,
+    // after nRelaxIter it uses the values in meshQualityControls::relaxed.
+    nRelaxedIter 20;
+}
+
+
+
+// Generic mesh quality settings. At any undoable phase these determine
+// where to undo.
+meshQualityControls
+{
+    #include "meshQualityDict"
+
+    // Optional : some meshing phases allow usage of relaxed rules.
+    // See e.g. addLayersControls::nRelaxedIter.
+    relaxed
+    {
+        //- Maximum non-orthogonality allowed. Set to 180 to disable.
+        maxNonOrtho 75;
+    }
+
+    // Advanced
+
+    //- Number of error distribution iterations
+    nSmoothScale 4;
+    //- Amount to scale back displacement at error points
+    errorReduction 0.75;
+}
+
+
+// Advanced
+
+// Write flags
+writeFlags
+(
+//    scalarLevels    // write volScalarField with cellLevel for postprocessing
+//    layerSets       // write cellSets, faceSets of faces in layer
+//    layerFields     // write volScalarField for layer coverage
+);
+
+//debugFlags
+//(
+//    mesh
+//    attraction
+//);
+
+// Merge tolerance. Is fraction of overall bounding box of initial mesh.
+// Note: the write tolerance needs to be higher than this.
+mergeTolerance 1E-6;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/rotated_block/system/surfaceFeatureExtractDict b/tutorials/mesh/snappyHexMesh/rotated_block/system/surfaceFeatureExtractDict
new file mode 100644
index 0000000000000000000000000000000000000000..603b48fb73cee64cda011c4b214c37cd7b59d4a2
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/rotated_block/system/surfaceFeatureExtractDict
@@ -0,0 +1,35 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      surfaceFeatureExtractDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+block.obj
+{
+    // How to obtain raw features (extractFromFile || extractFromSurface)
+    extractionMethod    extractFromSurface;
+
+    // Mark edges whose adjacent surface normals are at an angle less
+    // than includedAngle as features
+    // - 0  : selects no edges
+    // - 180: selects all edges
+    includedAngle       150;
+
+    // Write options
+
+    // Write features to obj format for postprocessing
+    writeObj            yes;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allclean b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allclean
new file mode 100755
index 0000000000000000000000000000000000000000..f158c3703aafa62a5c0b40356ebfd4fcc74b0460
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allclean
@@ -0,0 +1,9 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions      # Tutorial clean functions
+#------------------------------------------------------------------------------
+
+cleanCase0
+rm -f *.obj
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allrun b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allrun
new file mode 100755
index 0000000000000000000000000000000000000000..9b1617bc41a2469f79ee6fffc5b7c9be46c53bc1
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/Allrun
@@ -0,0 +1,12 @@
+#!/bin/sh
+cd "${0%/*}" || exit                                # Run from this directory
+. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions        # Tutorial run functions
+#------------------------------------------------------------------------------
+
+runApplication blockMesh
+
+runApplication snappyHexMesh
+
+runApplication checkMesh -writeFields '(nonOrthoAngle)'
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/README.txt b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..98188ecdffa4ae577d3af548b41da33ae27d6535
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/README.txt
@@ -0,0 +1,2 @@
+- sphere with inside and outside meshed
+- demonstrates buffer layers
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/dynamicMeshDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/dynamicMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..fdf87f68acae84535f75c22673ea84691e3681b8
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/dynamicMeshDict
@@ -0,0 +1,41 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      dynamicMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+dynamicFvMesh   dynamicMotionSolverFvMesh;
+
+solver          displacementPointSmoothing;
+
+displacementPointSmoothingCoeffs
+{
+    //// Use geometricElementTransform to maintain relative sizes
+    //pointSmoother           geometricElementTransform;
+    //transformationParameter 0.667;
+    //nPointSmootherIter      10;
+
+    // Use laplacian to untangle problem areas
+    pointSmoother           laplacian;
+    nPointSmootherIter      100;
+
+    //relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+    //meshQuality
+    //{
+    //    #includeEtc "caseDicts/meshQualityDict"
+    //}        
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/transportProperties b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/transportProperties
new file mode 100644
index 0000000000000000000000000000000000000000..fc05a376222c9ce0fd94d4e4134855e949ee5d28
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/constant/transportProperties
@@ -0,0 +1,21 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "constant";
+    object      transportProperties;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+nu              0.01;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/blockMeshDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/blockMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..154b6ad584b0c2103a91b54246242eb399d9d932
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/blockMeshDict
@@ -0,0 +1,96 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      blockMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+scale   1;
+
+vertices
+(
+    (-1   -1   -1)
+    ( 1   -1   -1)
+    ( 1    1   -1)
+    (-1    1   -1)
+    (-1   -1    1)
+    ( 1   -1    1)
+    ( 1    1    1)
+    (-1    1    1)
+);
+
+blocks
+(
+    hex (0 1 2 3 4 5 6 7) (20 20 20) simpleGrading (1 1 1)
+);
+
+edges
+(
+);
+
+boundary
+(
+    minX
+    {
+        type wall;
+        faces
+        (
+            (0 4 7 3)
+        );
+    }
+    maxX
+    {
+        type wall;
+        faces
+        (
+            (2 6 5 1)
+        );
+    }
+
+
+    minY
+    {
+        type wall;
+        faces
+        (
+            (1 5 4 0)
+        );
+    }
+    maxY
+    {
+        type wall;
+        faces
+        (
+            (3 7 6 2)
+        );
+    }
+
+
+    minZ
+    {
+        type wall;
+        faces
+        (
+            (0 3 2 1)
+        );
+    }
+    maxZ
+    {
+        type wall;
+        faces
+        (
+            (4 5 6 7)
+        );
+    }
+);
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/controlDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/controlDict
new file mode 100644
index 0000000000000000000000000000000000000000..b5e76eec7a348962a1ed39dbee640b02d7c42308
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/controlDict
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      controlDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+application     snappyHexMesh;
+
+startFrom       startTime;
+
+startTime       0;
+
+stopAt          endTime;
+
+endTime         30;
+
+deltaT          1;
+
+writeControl    timeStep;
+
+writeInterval   1;
+
+purgeWrite      0;
+
+writeFormat     ascii;
+
+writePrecision  16;
+
+writeCompression off;
+
+timeFormat      general;
+
+timePrecision   6;
+
+runTimeModifiable true;
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/decomposeParDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/decomposeParDict
new file mode 100644
index 0000000000000000000000000000000000000000..1aa9426aaec602bb2e572903b579b36889356d1e
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/decomposeParDict
@@ -0,0 +1,30 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    note        "mesh decomposition control dictionary";
+    object      decomposeParDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+////- The total number of domains (mandatory)
+//numberOfSubdomains  2;
+//
+////- The decomposition method (mandatory)
+//method          random;
+
+//- The total number of domains (mandatory)
+numberOfSubdomains 11;
+
+//- The decomposition method (mandatory)
+method          scotch;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSchemes b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSchemes
new file mode 100644
index 0000000000000000000000000000000000000000..58d3cb94a88175bb2fdf1549a860411c3a2411eb
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSchemes
@@ -0,0 +1,59 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSchemes;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//geometry
+//{
+//    type            highAspectRatio;
+//    minAspect       0;
+//    maxAspect       0;
+//}
+
+
+ddtSchemes
+{
+    default         Euler;
+}
+
+gradSchemes
+{
+    default         Gauss linear;
+    grad(p)         Gauss linear;
+}
+
+divSchemes
+{
+    default         none;
+    div(phi,U)      Gauss linear;
+}
+
+laplacianSchemes
+{
+    default         Gauss linear corrected;
+}
+
+interpolationSchemes
+{
+    default         linear;
+}
+
+snGradSchemes
+{
+    default         corrected;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSolution b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSolution
new file mode 100644
index 0000000000000000000000000000000000000000..16f43147ae24c76b5860a3db8f8ee46517c3e10c
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/fvSolution
@@ -0,0 +1,57 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    location    "system";
+    object      fvSolution;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+solvers
+{
+    p
+    {
+        solver          PCG;
+        preconditioner  DIC;
+        tolerance       1e-06;
+        relTol          0.05;
+    }
+
+    pFinal
+    {
+        $p;
+        relTol          0;
+    }
+
+    U
+    {
+        solver          smoothSolver;
+        smoother        symGaussSeidel;
+        tolerance       1e-05;
+        relTol          0;
+    }
+
+    cellDisplacement
+    {
+        $pFinal;
+    }
+}
+
+PISO
+{
+    nCorrectors     2;
+    nNonOrthogonalCorrectors 0;
+    pRefCell        0;
+    pRefValue       0;
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/meshQualityDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/meshQualityDict
new file mode 100644
index 0000000000000000000000000000000000000000..1a0afa5f754e90e763ba4fee639cdef03495e87f
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/meshQualityDict
@@ -0,0 +1,32 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1812                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      meshQualityDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Include defaults parameters from master dictionary
+#includeEtc "caseDicts/meshQualityDict"
+
+//maxNonOrtho         180;
+//maxConcave          180;
+//minVol              -1e30;
+maxBoundarySkewness -1;
+maxInternalSkewness -1;
+//minTetQuality       -1e30;
+//minDeterminant      -1e30;
+//minTwist            -1;
+//minFaceWeight       -1;
+//minVolRatio         -1;
+//minDeterminant      -1;
+
+// ************************************************************************* //
diff --git a/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/snappyHexMeshDict b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/snappyHexMeshDict
new file mode 100644
index 0000000000000000000000000000000000000000..c6ceef408c60a102630e7fc3806c1a83a0a95cbc
--- /dev/null
+++ b/tutorials/mesh/snappyHexMesh/sphere_multiRegion/system/snappyHexMeshDict
@@ -0,0 +1,380 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v2312                                 |
+|   \\  /    A nd           | Website:  www.openfoam.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      snappyHexMeshDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Type of mesh generation:
+//  - castellated (default)
+//  - castellatedBufferLayer (adds single layer of cells before snapping)
+type            castellatedBufferLayer;
+
+// Which of the steps to run
+castellatedMesh true;
+snap            true;
+addLayers       true;
+
+
+// Geometry. Definition of all surfaces. All surfaces are of class
+// searchableSurface.
+// Surfaces are used
+// - to specify refinement for any mesh cell intersecting it
+// - to specify refinement for any mesh cell inside/outside/near
+// - to 'snap' the mesh boundary to the surface
+geometry
+{
+    sphere
+    {
+        type    sphere;
+        origin  (0.0 0 0);
+        radius  0.5;
+    }
+
+    outside
+    {
+        type box;
+        min  (-0.91 -0.91 -0.91);
+        max  ( 0.91  0.91  0.91);
+    }
+}
+
+
+// Settings for the castellatedMesh generation.
+castellatedMeshControls
+{
+
+    // Refinement parameters
+    // ~~~~~~~~~~~~~~~~~~~~~
+
+    // If local number of cells is >= maxLocalCells on any processor
+    // switches from from refinement followed by balancing
+    // (current method) to (weighted) balancing before refinement.
+    maxLocalCells 100000;
+
+    // Overall cell limit (approximately). Refinement will stop immediately
+    // upon reaching this number so a refinement level might not complete.
+    // Note that this is the number of cells before removing the part which
+    // is not 'visible' from the keepPoint. The final number of cells might
+    // actually be a lot less.
+    maxGlobalCells 2000000;
+
+    // The surface refinement loop might spend lots of iterations refining just a
+    // few cells. This setting will cause refinement to stop if <= minimumRefine
+    // are selected for refinement. Note: it will at least do one iteration
+    // (unless the number of cells to refine is 0)
+    minRefinementCells 0;
+
+    // Number of buffer layers between different levels.
+    // 1 means normal 2:1 refinement restriction, larger means slower
+    // refinement.
+    nCellsBetweenLevels 1;
+
+
+
+    // Explicit feature edge refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies a level for any cell intersected by its edges.
+    // This is a featureEdgeMesh, read from constant/triSurface for now.
+    features
+    (
+    );
+
+
+
+    // Surface based refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies two levels for every surface. The first is the minimum level,
+    // every cell intersecting a surface gets refined up to the minimum level.
+    // The second level is the maximum level. Cells that 'see' multiple
+    // intersections where the intersections make an
+    // angle > resolveFeatureAngle get refined up to the maximum level.
+
+    refinementSurfaces
+    {
+        sphere
+        {
+            // Surface-wise min and max refinement level
+            level (1 1);
+            addBufferLayers true;
+        }
+        outside
+        {
+            // Surface-wise min and max refinement level
+            level (1 1);
+            // Disable buffer layers
+            addBufferLayers false;
+        }
+    }
+
+    resolveFeatureAngle 180;
+
+
+    // Region-wise refinement
+    // ~~~~~~~~~~~~~~~~~~~~~~
+
+    // Specifies refinement level for cells in relation to a surface. One of
+    // three modes
+    // - distance. 'levels' specifies per distance to the surface the
+    //   wanted refinement level. The distances need to be specified in
+    //   descending order.
+    // - inside. 'levels' is only one entry and only the level is used. All
+    //   cells inside the surface get refined up to the level. The surface
+    //   needs to be closed for this to be possible.
+    // - outside. Same but cells outside.
+
+    refinementRegions
+    {
+    }
+
+
+    // Mesh selection
+    // ~~~~~~~~~~~~~~
+
+    // After refinement patches get added for all refinementSurfaces and
+    // all cells intersecting the surfaces get put into these patches. The
+    // section reachable from the locationInMesh is kept.
+    // NOTE: This point should never be on a face, always inside a cell, even
+    // after refinement.
+    // This is an outside point locationInMesh (-0.033 -0.033 0.0033);
+    locationsInMesh
+    (
+        (( 0.001 0.001  0.001) sphere)
+        (( 0.701 0.701  0.701) outside)
+    );
+
+    // Whether any faceZones (as specified in the refinementSurfaces)
+    // are only on the boundary of corresponding cellZones or also allow
+    // free-standing zone faces. Not used if there are no faceZones.
+    allowFreeStandingZoneFaces false;
+}
+
+
+
+// Internal macro for mesh-motion solver to use
+_meshMotionSolver
+{
+    solver  displacementPointSmoothing;
+    displacementPointSmoothingCoeffs
+    {
+        //// Use geometricElementTransform to maintain relative sizes
+        //pointSmoother           geometricElementTransform;
+        //transformationParameter 0.667;
+        //nPointSmootherIter      10;
+
+        // Use laplacian to untangle problem areas
+        pointSmoother           laplacian;
+        nPointSmootherIter      10;
+
+        //relaxationFactors       (1.0 0.8 0.6 0.4 0.2 0.0);
+        //meshQuality
+        //{
+        //    #includeEtc "caseDicts/meshQualityDict"
+        //}        
+    }
+}
+
+
+// Settings for the snapping.
+snapControls
+{
+    //- Number of patch smoothing iterations before finding correspondence
+    //  to surface
+    nSmoothPatch 3;
+
+    //- Relative distance for points to be attracted by surface feature point
+    //  or edge. True distance is this factor times local
+    //  maximum edge length.
+    tolerance 1.0;
+
+    //- When to split face with diagonal attraction:
+    //      0 : only if perfect alignment (angle = 0) with feature itself
+    //    180 : always
+    concaveAngle 180;
+
+    //- When to split distorted face: not split if areas would differ too
+    //  much (ideal is equal size i.e. area-ratio 1). -1 : disable check
+    minAreaRatio -1;
+
+    //- Number of mesh displacement relaxation iterations.
+    nSolveIter 10;
+
+    //- Maximum number of snapping relaxation iterations. Should stop
+    //  before upon reaching a correct mesh.
+    nRelaxIter 5;
+
+    // Feature snapping
+
+        //- Number of feature edge snapping iterations.
+        //  Leave out altogether to disable.
+        nFeatureSnapIter 10;
+
+        //- Detect (geometric) features by sampling the surface
+        implicitFeatureSnap true;
+
+        //- Use castellatedMeshControls::features
+        explicitFeatureSnap true;
+
+        //- Detect features between multiple surfaces
+        //  (only for explicitFeatureSnap, default = false)
+        multiRegionFeatureSnap true;
+
+
+    // Motion solver to use
+    ${_meshMotionSolver}
+}
+
+
+// Settings for the layer addition.
+addLayersControls
+{
+    // Are the thickness parameters below relative to the undistorted
+    // size of the refined cell outside layer (true) or absolute sizes (false).
+    relativeSizes true;
+
+    // Per final patch (so not geometry!) the layer information
+    layers
+    {
+        "(sphere_to_outside|outside_to_sphere)"
+        {
+            nSurfaceLayers 3;
+        }
+    }
+
+    // Expansion factor for layer mesh
+    expansionRatio 1.4;
+
+
+    // Wanted thickness of final added cell layer. If multiple layers
+    // is the thickness of the layer furthest away from the wall.
+    // Relative to undistorted size of cell outside layer.
+    // See relativeSizes parameter.
+    finalLayerThickness 0.5;
+
+    // Minimum thickness of cell layer. If for any reason layer
+    // cannot be above minThickness do not add layer.
+    // See relativeSizes parameter.
+    minThickness 0.01;
+
+    // If points get not extruded do nGrow layers of connected faces that are
+    // also not grown. This helps convergence of the layer addition process
+    // close to features.
+    nGrow 0;
+
+
+    // Advanced settings
+
+    // When not to extrude surface. 0 is flat surface, 90 is when two faces
+    // are perpendicular
+    featureAngle 30;
+
+    // Maximum number of snapping relaxation iterations. Should stop
+    // before upon reaching a correct mesh.
+    nRelaxIter 5;
+
+    // Number of smoothing iterations of surface normals
+    nSmoothSurfaceNormals 1;
+
+    // Number of smoothing iterations of interior mesh movement direction
+    nSmoothNormals 3;
+
+    // Smooth layer thickness over surface patches
+    nSmoothThickness 10;
+
+    // Stop layer growth on highly warped cells
+    maxFaceThicknessRatio 0.5;
+
+    // Reduce layer growth where ratio thickness to medial
+    // distance is large
+    maxThicknessToMedialRatio 0.3;
+
+    // Angle used to pick up medial axis points
+    minMedialAxisAngle 90;
+
+    // Create buffer region for new layer terminations
+    nBufferCellsNoExtrude 0;
+
+
+
+    //- Use displacementMotionSolver to shrink mesh
+    meshShrinker displacementMotionSolver;
+
+    // Motion solver to use
+    ${_meshMotionSolver}
+    // Do some more iterations since shrinking is over a larger distance.
+    // Note: laplacian smoothing does destroy the cell sizing - maybe use
+    //       the geometricElementTransform smoother instead.
+    displacementPointSmoothingCoeffs
+    {
+        nPointSmootherIter 100;
+    }
+
+    // Overall max number of layer addition iterations. The mesher will exit
+    // if it reaches this number of iterations; possibly with an illegal
+    // mesh.
+    nLayerIter 50;
+
+    // Max number of iterations after which relaxed meshQuality controls
+    // get used. Up to nRelaxIter it uses the settings in meshQualityControls,
+    // after nRelaxIter it uses the values in meshQualityControls::relaxed.
+    nRelaxedIter 20;
+}
+
+
+
+// Generic mesh quality settings. At any undoable phase these determine
+// where to undo.
+meshQualityControls
+{
+    #include "meshQualityDict"
+
+    // Optional : some meshing phases allow usage of relaxed rules.
+    // See e.g. addLayersControls::nRelaxedIter.
+    relaxed
+    {
+        //- Maximum non-orthogonality allowed. Set to 180 to disable.
+        maxNonOrtho 75;
+    }
+
+    // Advanced
+
+    //- Number of error distribution iterations
+    nSmoothScale 4;
+    //- Amount to scale back displacement at error points
+    errorReduction 0.75;
+}
+
+
+// Advanced
+
+// Write flags
+writeFlags
+(
+//    scalarLevels    // write volScalarField with cellLevel for postprocessing
+//    layerSets       // write cellSets, faceSets of faces in layer
+//    layerFields     // write volScalarField for layer coverage
+);
+
+debugFlags
+(
+//    mesh
+//    attraction
+);
+
+// Merge tolerance. Is fraction of overall bounding box of initial mesh.
+// Note: the write tolerance needs to be higher than this.
+mergeTolerance 1E-6;
+
+
+// ************************************************************************* //