diff --git a/src/sampling/surface/cuttingPlane/cuttingPlane.C b/src/sampling/surface/cuttingPlane/cuttingPlane.C
index 051a60c1cbd4f1a7d3c42e7b25d19f5ab426a653..1650dc311b584cba93476c653cc4cad7ae9b58b9 100644
--- a/src/sampling/surface/cuttingPlane/cuttingPlane.C
+++ b/src/sampling/surface/cuttingPlane/cuttingPlane.C
@@ -56,6 +56,23 @@ namespace Foam
     }
 
 
+    // Classify sides of plane (0=BACK, 1=ONPLANE, 2=FRONT) for each point
+    inline PackedList<2> classifySides(const plane& pln, const pointField& pts)
+    {
+        const label len = pts.size();
+
+        PackedList<2> output(len);
+
+        // From signed (-1,0,+1) to (0,1,2) for PackedList
+        for (label i=0; i < len; ++i)
+        {
+            output.set(i, unsigned(1 + pln.sign(pts[i], SMALL)));
+        }
+
+        return output;
+    }
+
+
     // Check for face/plane intersection based on crossings
     // Took (-1,0,+1) from plane::sign and packed as (0,1,2).
     // Now use for left shift to obtain (1,2,4).
@@ -78,35 +95,11 @@ namespace Foam
         return (accum == 3 || accum >= 5);
     }
 
-
-    //- For hashing face point labels, which are pre-sorted.
-    typedef HashSet<labelList, labelList::Hash<>> labelListHashSet;
-
 } // End namespace Foam
 
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-Foam::PackedList<2> Foam::cuttingPlane::classifySides
-(
-    const plane& pln,
-    const pointField& pts
-)
-{
-    const label len = pts.size();
-
-    PackedList<2> output(len);
-
-    // From signed (-1,0,+1) to (0,1,2) for PackedList
-    for (label i=0; i < len; ++i)
-    {
-        output.set(i, unsigned(1 + pln.sign(pts[i], SMALL)));
-    }
-
-    return output;
-}
-
-
 Foam::label Foam::cuttingPlane::calcCellCuts
 (
     const primitiveMesh& mesh,
@@ -231,12 +224,18 @@ Foam::label Foam::cuttingPlane::calcCellCuts
 void Foam::cuttingPlane::walkCellCuts
 (
     const primitiveMesh& mesh,
-    const PackedList<2>& sides,
     const bitSet& cellCuts,
+    const PackedList<2>& sides,
     const bool triangulate,
     label nFaceCuts
 )
 {
+    // Information required from the mesh
+    const faceList& faces = mesh.faces();
+    const cellList& cells = mesh.cells();
+    const pointField& points = mesh.points();
+
+
     // Dynamic lists to handle triangulation and/or missed cuts etc
     const label nCellCuts = cellCuts.count();
 
@@ -250,12 +249,6 @@ void Foam::cuttingPlane::walkCellCuts
         nFaceCuts = 4*nCellCuts;
     }
 
-    // Information required from the mesh
-    const faceList& faces = mesh.faces();
-    const cellList& cells = mesh.cells();
-    const pointField& points = mesh.points();
-
-
     // Edge to pointId mapping
     EdgeMap<label> handledEdges(4*nFaceCuts);
 
@@ -273,8 +266,8 @@ void Foam::cuttingPlane::walkCellCuts
     // that "owns" the point.
     Map<label> endPoints;
 
-    // Hash of faces (face points) exactly on-plane
-    labelListHashSet onPlaneFaces;
+    // Hash of faces (face points) that are exactly on a cell face
+    HashSet<labelList, labelList::Hash<>> onCellFace;
 
 
     // Failure handling
@@ -363,7 +356,6 @@ void Foam::cuttingPlane::walkCellCuts
                 // Expected id for the cut point
                 cutPointId = dynCutPoints.size();
 
-
                 const point& p0 = points[e[0]];
                 const point& p1 = points[e[1]];
 
@@ -429,16 +421,16 @@ void Foam::cuttingPlane::walkCellCuts
         }
 
 
-        // Handling cuts between two cells (on-plane cuts)
-        // After the previous intersectEdgeOrient call, the edge is oriented
-        // to have 0-1 in the positive plane normal.
+        // Handling cuts between two cells
+        // After the previous intersectEdgeOrient call, the edge oriented
+        // according to the gradient.
         // If we only ever cut at the same edge end we know that we have
-        // an on-plane cut.
+        // a cut coinciding with a cell face.
 
         if (pointCutType == 1 || pointCutType == 2)
         {
             // Hash the face-points to avoid duplicate faces
-            if (!onPlaneFaces.insert(HashTableOps::values(localEdges, true)))
+            if (!onCellFace.insert(HashTableOps::values(localEdges, true)))
             {
                 DebugInfo
                     <<"skip duplicate on-place cut for cell " << celli
@@ -451,7 +443,12 @@ void Foam::cuttingPlane::walkCellCuts
         }
 
 
-        // Start somewhere
+        // Start somewhere.
+
+        // Since the local edges are oriented according to the gradient,
+        // they can also be used to determine the correct face orientation.
+
+        const edge refEdge = localFaces.begin().key();
         label nextFace = localFaces.begin().object()[0];
 
         DebugInfo
@@ -471,6 +468,7 @@ void Foam::cuttingPlane::walkCellCuts
                 DebugInfo
                     << "lookup " << nextFace << " in " << iter.object() << nl;
 
+                // Find local index (0,1) or -1 on failure
                 const label got = iter.object().which(nextFace);
 
                 if (got != -1)
@@ -507,7 +505,7 @@ void Foam::cuttingPlane::walkCellCuts
         if (nTargetLoop != localFaceLoop.size())
         {
             DebugInfo
-                <<"Warn expected " << nTargetLoop << " but got "
+                << "Warn expected " << nTargetLoop << " but got "
                 << localFaceLoop.size() << endl;
 
             unwindWalk(celli);
@@ -520,9 +518,8 @@ void Foam::cuttingPlane::walkCellCuts
 
         face f(localFaceLoop);
 
-        // Action #3: orient face
-        // Orient face to point in the same direction as the plane normal
-        if ((f.areaNormal(dynCutPoints) & this->normal()) < 0)
+        // Orient face to point in the same direction as the edge gradient
+        if ((f.areaNormal(dynCutPoints) & refEdge.vec(points)) < 0)
         {
             f.flip();
         }
@@ -646,7 +643,7 @@ void Foam::cuttingPlane::performCut
     const label nFaceCuts = calcCellCuts(mesh, sides, cellCuts);
 
     // Find closed loop from cell cuts
-    walkCellCuts(mesh, sides, cellCuts, triangulate, nFaceCuts);
+    walkCellCuts(mesh, cellCuts, sides, triangulate, nFaceCuts);
 }
 
 
diff --git a/src/sampling/surface/cuttingPlane/cuttingPlane.H b/src/sampling/surface/cuttingPlane/cuttingPlane.H
index 224712bcc4231d9d2c8083921fc230bf97906dac..ff19cbdfa5a339a691ee0c595fd936475016a6cc 100644
--- a/src/sampling/surface/cuttingPlane/cuttingPlane.H
+++ b/src/sampling/surface/cuttingPlane/cuttingPlane.H
@@ -77,14 +77,12 @@ class cuttingPlane
 
     // Private Member Functions
 
-        //- Classify sides of plane (0=BACK, 1=ONPLANE, 2=FRONT) for each point
-        static PackedList<2> classifySides
-        (
-            const plane& pln,
-            const pointField& pts
-        );
-
         //- Determine cut cells, possibly restricted to a list of cells
+        //
+        //  \param cellCuts [in,out] On input an empty set (ie, no restriction)
+        //      or subsetted cells. On output, the cells cut according to the
+        //      planeSides detection.
+        //
         //  \return number of faces cut
         label calcCellCuts
         (
@@ -94,11 +92,13 @@ class cuttingPlane
         );
 
         //- Walk the cell cuts to create faces
+        //
+        //  \param planeSides [in] Used to determine edge cuts
         void walkCellCuts
         (
             const primitiveMesh& mesh,
-            const PackedList<2>& planeSides,
             const bitSet& cellCuts,
+            const PackedList<2>& planeSides,
             const bool triangulate,
             const label nFaceCuts = 0
         );