From 0af1e0b7228cf6a5e160ea4f519861f6867300d7 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Mon, 12 Jun 2017 15:47:01 +0200
Subject: [PATCH] BUG: minor regression. STL reading in double, not float
 (issue #491)

- By definition, binary STL uses float (not double) when reading.
  The ascii STL should be the same. This reduces memory overhead when
  loading files. The older triSurface reader had float, the surfMesh
  reader had double, but now has float.

- Inconsistency in the STL merge-tolerances between triSurface reader,
  surfMesh reader and WM_SP vs WM_DP. Now use consistent tolerances
  conrresponding to 10,100 * doubleSMALL.

- Similar float/double code adjustments for TRI format since this is
  very similar to the STL reader and had a similar inconsistency between
  the triSurface and surfMesh version. The AC3D reader still uses
  double when reading, but this can be revisited in the future (and can
  then remove the stichTriangles method too).
---
 src/fileFormats/stl/STLReader.C               | 35 +++++++++++++
 src/fileFormats/stl/STLReader.H               | 13 ++++-
 src/fileFormats/stl/STLReaderASCII.L          |  4 +-
 .../surfaceFormats/stl/STLsurfaceFormat.C     | 40 +++++++++++----
 .../surfaceFormats/tri/TRIsurfaceFormat.C     | 39 +++++++++++----
 .../surfaceFormats/tri/TRIsurfaceFormatCore.C | 50 +++++++++++++++++--
 .../surfaceFormats/tri/TRIsurfaceFormatCore.H | 38 +++++++-------
 .../triSurface/interfaces/STL/readSTL.C       | 28 +++--------
 8 files changed, 182 insertions(+), 65 deletions(-)

diff --git a/src/fileFormats/stl/STLReader.C b/src/fileFormats/stl/STLReader.C
index b7b91a0bb75..ca7451d886a 100644
--- a/src/fileFormats/stl/STLReader.C
+++ b/src/fileFormats/stl/STLReader.C
@@ -26,6 +26,7 @@ License
 #include "STLReader.H"
 #include "Map.H"
 #include "IFstream.H"
+#include "mergePoints.H"
 
 #undef DEBUG_STLBINARY
 
@@ -202,4 +203,38 @@ void Foam::fileFormats::STLReader::clear()
 }
 
 
+Foam::label Foam::fileFormats::STLReader::mergePointsMap
+(
+    labelList& pointMap
+) const
+{
+    // With the merge distance depending on the input format (ASCII | BINARY),
+    // but must be independent of WM_SP or WM_DP flag.
+    // - floatScalarSMALL  = 1e-6
+    // - doubleScalarSMALL = 1e-15
+
+    return mergePointsMap
+    (
+        (format_ == BINARY ? 10 : 100) * doubleScalarSMALL,
+        pointMap
+    );
+}
+
+
+Foam::label Foam::fileFormats::STLReader::mergePointsMap
+(
+    const scalar mergeTol,
+    labelList& pointMap
+) const
+{
+    return Foam::mergePoints
+    (
+        points_,
+        mergeTol,
+        false, // verbose
+        pointMap
+    );
+}
+
+
 // ************************************************************************* //
diff --git a/src/fileFormats/stl/STLReader.H b/src/fileFormats/stl/STLReader.H
index 9ed6838bc13..e9873aafe74 100644
--- a/src/fileFormats/stl/STLReader.H
+++ b/src/fileFormats/stl/STLReader.H
@@ -61,7 +61,7 @@ class STLReader
         bool sorted_;
 
         //- The points supporting the facets
-        pointField points_;
+        List<STLpoint> points_;
 
         //- The zones associated with the faces
         List<label> zoneIds_;
@@ -117,6 +117,15 @@ public:
         //- Flush all values
         void clear();
 
+        //- Calculate merge points mapping, return old to new pointMap.
+        //  The merge tolerance based on ASCII or BINARY input format.
+        //  \return number of unique points
+        label mergePointsMap(labelList& pointMap) const;
+
+        //- Calculate merge points mapping, return old to new pointMap.
+        //  \return number of unique points
+        label mergePointsMap(const scalar mergeTol, labelList& pointMap) const;
+
         //- File read was already sorted?
         inline bool sorted() const
         {
@@ -124,7 +133,7 @@ public:
         }
 
         //- Return full access to the points
-        inline pointField& points()
+        inline List<STLpoint>& points()
         {
             return points_;
         }
diff --git a/src/fileFormats/stl/STLReaderASCII.L b/src/fileFormats/stl/STLReaderASCII.L
index 1e60c2a241e..46c9ab1a853 100644
--- a/src/fileFormats/stl/STLReaderASCII.L
+++ b/src/fileFormats/stl/STLReaderASCII.L
@@ -77,7 +77,7 @@ class STLASCIILexer
         label lineNo_;
         word  startError_;
 
-        DynamicList<point> points_;
+        DynamicList<STLpoint> points_;
         DynamicList<label> facets_;
         DynamicList<word>  names_;
         DynamicList<label> sizes_;
@@ -105,7 +105,7 @@ public:
         }
 
         //- A list of unstitched triangle points
-        inline DynamicList<point>& points()
+        inline DynamicList<STLpoint>& points()
         {
             return points_;
         }
diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
index f9e335c39eb..a746232d18a 100644
--- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
@@ -24,7 +24,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "STLsurfaceFormat.H"
-#include "labelledTri.H"
 #include "triPointRef.H"
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
@@ -126,13 +125,25 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
 {
     this->clear();
 
-    // read in the values
+    // Read in the values
     STLReader reader(filename);
 
-    // transfer points
-    this->storedPoints().transfer(reader.points());
+    // Get the map for stitched surface points, with merge tolerance depending
+    // on the input format
+    labelList pointMap;
+    const label nUniquePoints = reader.mergePointsMap(pointMap);
 
-    // retrieve the original zone information
+    const auto& readpts = reader.points();
+
+    // Assign points
+    pointField& pointLst = this->storedPoints();
+    pointLst.setSize(nUniquePoints);
+    forAll(readpts, pointi)
+    {
+        pointLst[pointMap[pointi]] = readpts[pointi];
+    }
+
+    // Retrieve the original zone information
     List<word>  names(reader.names().xfer());
     List<label> sizes(reader.sizes().xfer());
     List<label> zoneIds(reader.zoneIds().xfer());
@@ -142,16 +153,21 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
 
     if (reader.sorted())
     {
-        // already sorted - generate directly
+        // Already sorted - generate directly
         forAll(faceLst, facei)
         {
             const label startPt = 3*facei;
-            faceLst[facei] = Face{startPt, startPt+1, startPt+2};
+            faceLst[facei] = Face
+            {
+                pointMap[startPt],
+                pointMap[startPt+1],
+                pointMap[startPt+2]
+            };
         }
     }
     else
     {
-        // unsorted - determine the sorted order:
+        // Unsorted - determine the sorted order:
         // avoid SortableList since we discard the main list anyhow
         List<label> faceMap;
         sortedOrder(zoneIds, faceMap);
@@ -160,7 +176,12 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
         forAll(faceMap, facei)
         {
             const label startPt = 3*faceMap[facei];
-            faceLst[facei] = Face{startPt, startPt+1, startPt+2};
+            faceLst[facei] = Face
+            {
+                pointMap[startPt],
+                pointMap[startPt+1],
+                pointMap[startPt+2]
+            };
         }
     }
     zoneIds.clear();
@@ -177,7 +198,6 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
         this->addZones(sizes);
     }
     this->addZonesToFaces(); // for labelledTri
-    this->stitchFaces(SMALL);
 
     return true;
 }
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
index cb2aa80823b..b36c5fd321d 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormat.C
@@ -78,13 +78,24 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
 {
     this->clear();
 
-    // read in the values
+    // Read in the values
     TRIsurfaceFormatCore reader(filename);
 
-    // transfer points
-    this->storedPoints().transfer(reader.points());
+    // Get the map for stitched surface points
+    labelList pointMap;
+    const label nUniquePoints = reader.mergePointsMap(pointMap);
 
-    // retrieve the original zone information
+    const auto& readpts = reader.points();
+
+    // Assign points
+    pointField& pointLst = this->storedPoints();
+    pointLst.setSize(nUniquePoints);
+    forAll(readpts, pointi)
+    {
+        pointLst[pointMap[pointi]] = readpts[pointi];
+    }
+
+    // Retrieve the original zone information
     List<label> sizes(reader.sizes().xfer());
     List<label> zoneIds(reader.zoneIds().xfer());
 
@@ -93,16 +104,21 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
 
     if (reader.sorted())
     {
-        // already sorted - generate directly
+        // Already sorted - generate directly
         forAll(faceLst, facei)
         {
             const label startPt = 3*facei;
-            faceLst[facei] = Face{startPt, startPt+1, startPt+2};
+            faceLst[facei] = Face
+            {
+                pointMap[startPt],
+                pointMap[startPt+1],
+                pointMap[startPt+2]
+            };
         }
     }
     else
     {
-        // unsorted - determine the sorted order:
+        // Unsorted - determine the sorted order:
         // avoid SortableList since we discard the main list anyhow
         List<label> faceMap;
         sortedOrder(zoneIds, faceMap);
@@ -111,7 +127,12 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
         forAll(faceMap, facei)
         {
             const label startPt = 3*faceMap[facei];
-            faceLst[facei] = Face{startPt, startPt+1, startPt+2};
+            faceLst[facei] = Face
+            {
+                pointMap[startPt],
+                pointMap[startPt+1],
+                pointMap[startPt+2]
+            };
         }
     }
     zoneIds.clear();
@@ -121,7 +142,7 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
 
     this->addZones(sizes);
     this->addZonesToFaces(); // for labelledTri
-    this->stitchFaces(SMALL);
+
     return true;
 }
 
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C
index 87cc04d20ec..8f473d11203 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C
+++ b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,6 +27,7 @@ License
 #include "IFstream.H"
 #include "IOmanip.H"
 #include "IStringStream.H"
+#include "mergePoints.H"
 #include "Map.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -71,7 +72,7 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
 
     // uses similar structure as STL, just some points
     // the rest of the reader resembles the STL binary reader
-    DynamicList<point> dynPoints;
+    DynamicList<STLpoint> dynPoints;
     DynamicList<label> dynZones;
     DynamicList<label> dynSizes;
     HashTable<label>   lookup;
@@ -94,7 +95,7 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
 
         IStringStream lineStream(line);
 
-        point p
+        STLpoint p
         (
             readScalar(lineStream),
             readScalar(lineStream),
@@ -106,7 +107,7 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
         dynPoints.append(p);
         dynPoints.append
         (
-            point
+            STLpoint
             (
                 readScalar(lineStream),
                 readScalar(lineStream),
@@ -115,7 +116,7 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
         );
         dynPoints.append
         (
-            point
+            STLpoint
             (
                 readScalar(lineStream),
                 readScalar(lineStream),
@@ -179,4 +180,43 @@ bool Foam::fileFormats::TRIsurfaceFormatCore::read
 }
 
 
+void Foam::fileFormats::TRIsurfaceFormatCore::clear()
+{
+    sorted_ = true;
+    points_.clear();
+    zoneIds_.clear();
+    sizes_.clear();
+}
+
+
+Foam::label Foam::fileFormats::TRIsurfaceFormatCore::mergePointsMap
+(
+    labelList& pointMap
+) const
+{
+    // Use merge tolerance as per STL ascii
+    return mergePointsMap
+    (
+        100 * doubleScalarSMALL,
+        pointMap
+    );
+}
+
+
+Foam::label Foam::fileFormats::TRIsurfaceFormatCore::mergePointsMap
+(
+    const scalar mergeTol,
+    labelList& pointMap
+) const
+{
+    return Foam::mergePoints
+    (
+        points_,
+        mergeTol,
+        false, // verbose
+        pointMap
+    );
+}
+
+
 // ************************************************************************* //
diff --git a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H
index 12ce08e3725..5d4b76fd6e0 100644
--- a/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H
+++ b/src/surfMesh/surfaceFormats/tri/TRIsurfaceFormatCore.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -36,7 +36,7 @@ SourceFiles
 #define TRIsurfaceFormatCore_H
 
 #include "surfaceFormatsCore.H"
-#include "triFace.H"
+#include "STLpoint.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -58,7 +58,7 @@ class TRIsurfaceFormatCore
         bool sorted_;
 
         //- The points supporting the facets
-        pointField points_;
+        List<STLpoint> points_;
 
         //- The zones associated with the faces
         List<label> zoneIds_;
@@ -83,7 +83,7 @@ public:
     // Constructors
 
         //- Read from file, filling in the information
-        TRIsurfaceFormatCore(const fileName&);
+        TRIsurfaceFormatCore(const fileName& filename);
 
 
     //- Destructor
@@ -92,35 +92,39 @@ public:
 
     // Member Functions
 
+        //- Flush all values
+        void clear();
+
+        //- Calculate merge points mapping, return old to new pointMap.
+        //  Use merge tolerance as per STL ascii
+        //  \return number of unique points
+        label mergePointsMap(labelList& pointMap) const;
+
+        //- Calculate merge points mapping, return old to new pointMap.
+        //  \return number of unique points
+        label mergePointsMap(const scalar mergeTol, labelList& pointMap) const;
+
+
         //- File read was already sorted
-        bool sorted() const
+        inline bool sorted() const
         {
             return sorted_;
         }
 
-        //- Flush all values
-        void clear()
-        {
-            sorted_ = true;
-            points_.clear();
-            zoneIds_.clear();
-            sizes_.clear();
-        }
-
         //- Return full access to the points
-        pointField& points()
+        inline List<STLpoint>& points()
         {
             return points_;
         }
 
         //- Return full access to the zones
-        List<label>& zoneIds()
+        inline List<label>& zoneIds()
         {
             return zoneIds_;
         }
 
         //- The list of zone sizes in the order of their first appearance
-        List<label>& sizes()
+        inline List<label>& sizes()
         {
             return sizes_;
         }
diff --git a/src/surfMesh/triSurface/interfaces/STL/readSTL.C b/src/surfMesh/triSurface/interfaces/STL/readSTL.C
index 43c9453a524..70b1e9f4445 100644
--- a/src/surfMesh/triSurface/interfaces/STL/readSTL.C
+++ b/src/surfMesh/triSurface/interfaces/STL/readSTL.C
@@ -24,7 +24,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "STLReader.H"
-#include "mergePoints.H"
 #include "triSurface.H"
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
@@ -42,22 +41,13 @@ bool Foam::triSurface::readSTL(const fileName& STLfileName, bool forceBinary)
         )
     );
 
-    // Stitch points
+    // Get the map for stitched surface points, with merge tolerance depending
+    // on the input format
     labelList pointMap;
-    label nUniquePoints = mergePoints
-    (
-        reader.points(),
-        (
-            // With the merge distance depending on the input format
-            (reader.stlFormat() == fileFormats::STLCore::BINARY ? 10 : 100)
-          * SMALL
-        ),
-        false,                  // verbose
-        pointMap                // old to new point map
-    );
+    const label nUniquePoints = reader.mergePointsMap(pointMap);
 
-    const pointField& readpts = reader.points();
-    const labelList&  zoneIds = reader.zoneIds();
+    const auto& readpts = reader.points();
+    const labelList& zoneIds = reader.zoneIds();
 
     pointField& pointLst = storedPoints();
     List<Face>& faceLst  = storedFaces();
@@ -84,18 +74,16 @@ bool Foam::triSurface::readSTL(const fileName& STLfileName, bool forceBinary)
         f.region() = zoneIds[i];
     }
 
-    // Set patch names (and sizes)
-    // - there is likely a more efficient means of doing this
+    // Set patch name/index.
     if (reader.stlFormat() == fileFormats::STLCore::ASCII)
     {
         const List<word>& names = reader.names();
 
         patches_.setSize(names.size());
-        forAll(names, namei)
+        forAll(patches_, patchi)
         {
-            patches_[namei].name() = names[namei];
+            patches_[patchi] = geometricSurfacePatch(names[patchi], patchi);
         }
-        setDefaultPatches();
     }
 
     return true;
-- 
GitLab