diff --git a/bin/foamCreateBashCompletions b/bin/foamCreateBashCompletions
index a941a23f33c0dfda0df5f7cec92c98a4f9b72616..ea366c1f0fb0b4b62c6a4c44ffc2ab2b303ba1c0 100755
--- a/bin/foamCreateBashCompletions
+++ b/bin/foamCreateBashCompletions
@@ -40,7 +40,7 @@ Usage: $Script [OPTION] <file>
 
 * Create bash completions for OpenFOAM applications and write to <file>.
   By default searches directories \$FOAM_APPBIN and \$FOAM_USER_APPBIN
-  
+
 
 Options:
   -d | -directory   Directory to process
@@ -149,10 +149,10 @@ do
         echo "Processing $appName"
 
         # Options with args
-        optsWithArgs=($(awk '/^ *-[a-z]/ && /</ {print $1}' <<< "$appHelp"))
+        optsWithArgs=($(awk '/^ {0,4}-[a-z]/ && /</ {print $1}' <<< "$appHelp"))
 
         # Options without args
-        opts=($(awk '/^ *-[a-z]/ && !/</ {print $1}' <<< "$appHelp"))
+        opts=($(awk '/^ {0,4}-[a-z]/ && !/</ {print $1}' <<< "$appHelp"))
 
         cat<<WRITECOMPLETION >> $outFile
 unset -f _${appName}
diff --git a/src/OpenFOAM/meshes/meshTools/mergePoints.C b/src/OpenFOAM/meshes/meshTools/mergePoints.C
index 2b99235b72b3fabf38346b39b5937317c11c2567..041a6f819440b3ed6b88f06b1a21d1296d4b8c53 100644
--- a/src/OpenFOAM/meshes/meshTools/mergePoints.C
+++ b/src/OpenFOAM/meshes/meshTools/mergePoints.C
@@ -41,22 +41,28 @@ Foam::label Foam::mergePoints
 {
     typedef typename PointList::value_type point_type;
 
-    // Create a old to new point mapping array
-    pointMap.setSize(points.size());
+    const label nPoints = points.size();
+
+    // Create an old to new point mapping array
+    pointMap.setSize(nPoints);
     pointMap = -1;
 
-    if (points.empty())
+    if (!nPoints)
     {
         return 0;
     }
 
-    // Explicitly convert to Field to support various list types
-    tmp<Field<point_type>> tPoints(new Field<point_type>(points));
-
     point_type compareOrigin = origin;
     if (origin == point_type::max)
     {
-        compareOrigin = sum(tPoints())/points.size();
+        // Use average of input points to define a comparison origin.
+        // Same as sum(points)/nPoints, but handles different list types
+        compareOrigin = points[0];
+        for (label pointi=1; pointi < nPoints; ++pointi)
+        {
+            compareOrigin += points[pointi];
+        }
+        compareOrigin /= nPoints;
     }
 
     // We're comparing distance squared to origin first.
@@ -68,34 +74,31 @@ Foam::label Foam::mergePoints
     //     x^2+y^2+z^2 + 2*mergeTol*(x+z+y) + mergeTol^2*...
     // so the difference will be 2*mergeTol*(x+y+z)
 
-    const scalar mergeTolSqr = Foam::sqr(scalar(mergeTol));
+    const scalar mergeTolSqr = Foam::sqr(mergeTol);
 
     // Sort points by magSqr
-    const Field<point_type> d(tPoints - compareOrigin);
-
-    List<scalar> magSqrD(d.size());
-    forAll(d, pointi)
+    List<scalar> magSqrDist(nPoints);
+    forAll(points, pointi)
     {
-        magSqrD[pointi] = magSqr(d[pointi]);
+        magSqrDist[pointi] = magSqr(points[pointi] - compareOrigin);
     }
     labelList order;
-    Foam::sortedOrder(magSqrD, order);
+    Foam::sortedOrder(magSqrDist, order);
 
 
-    Field<scalar> sortedTol(points.size());
+    Field<scalar> sortedTol(nPoints);
     forAll(order, sortI)
     {
-        const label pointi = order[sortI];
+        const point_type& pt = points[order[sortI]];
 
-        // Convert to scalar precision
-        // NOTE: not yet using point_type template parameter
-        const point pt
-        (
-            scalar(d[pointi].x()),
-            scalar(d[pointi].y()),
-            scalar(d[pointi].z())
-        );
-        sortedTol[sortI] = 2*mergeTol*(mag(pt.x())+mag(pt.y())+mag(pt.z()));
+        // Use scalar precision
+        sortedTol[sortI] =
+            2*mergeTol*
+            (
+                mag(scalar(pt.x() - compareOrigin.x())),
+              + mag(scalar(pt.y() - compareOrigin.y())),
+              + mag(scalar(pt.z() - compareOrigin.z()))
+            );
     }
 
     label newPointi = 0;
@@ -104,11 +107,11 @@ Foam::label Foam::mergePoints
     label pointi = order[0];
     pointMap[pointi] = newPointi++;
 
-    for (label sortI = 1; sortI < order.size(); sortI++)
+    for (label sortI = 1; sortI < order.size(); ++sortI)
     {
         // Get original point index
         const label pointi = order[sortI];
-        const scalar mag2 = magSqrD[order[sortI]];
+        const scalar mag2 = magSqrDist[order[sortI]];
 
         // Convert to scalar precision
         // NOTE: not yet using point_type template parameter
@@ -127,8 +130,8 @@ Foam::label Foam::mergePoints
         (
             label prevSortI = sortI - 1;
             prevSortI >= 0
-         && (mag(magSqrD[order[prevSortI]] - mag2) <= sortedTol[sortI]);
-            prevSortI--
+         && (mag(magSqrDist[order[prevSortI]] - mag2) <= sortedTol[sortI]);
+            --prevSortI
         )
         {
             const label prevPointi = order[prevSortI];
diff --git a/src/conversion/fire/FIREMeshWriter.C b/src/conversion/fire/FIREMeshWriter.C
index 9c6146c3e00a9f4470432cd98807b7478df8cc58..2fc9de6e1f3574f832c14ad0fea8d551dae2739a 100644
--- a/src/conversion/fire/FIREMeshWriter.C
+++ b/src/conversion/fire/FIREMeshWriter.C
@@ -281,22 +281,22 @@ bool Foam::fileFormats::FIREMeshWriter::write(const fileName& meshName) const
         if (FIRECore::file3dExtensions.hasEnum(ext))
         {
             FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext];
-            if (fireFileType == FIRECore::POLY_ASCII)
+            if (fireFileType == FIRECore::fileExt3d::POLY_ASCII)
             {
                 useBinary   = false;
                 useCompress = false;
             }
-            else if (fireFileType == FIRECore::POLY_BINARY)
+            else if (fireFileType == FIRECore::fileExt3d::POLY_BINARY)
             {
                 useBinary   = true;
                 useCompress = false;
             }
-            else if (fireFileType == FIRECore::POLY_ASCII_COMPRESSED)
+            else if (fireFileType == FIRECore::fileExt3d::POLY_ASCII_Z)
             {
                 useBinary   = false;
                 useCompress = true;
             }
-            else if (fireFileType == FIRECore::POLY_BINARY_COMPRESSED)
+            else if (fireFileType == FIRECore::fileExt3d::POLY_BINARY_Z)
             {
                 useBinary   = true;
                 useCompress = true;
diff --git a/src/fileFormats/coordSet/coordSet.C b/src/fileFormats/coordSet/coordSet.C
index 5d7dd92b79a49cff7462f972e5186bc1ea672717..c4149dc943582a3a4723846a98c744437016b1c5 100644
--- a/src/fileFormats/coordSet/coordSet.C
+++ b/src/fileFormats/coordSet/coordSet.C
@@ -27,26 +27,15 @@ License
 
 // * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * * //
 
-namespace Foam
-{
-    template<>
-    const char* Foam::NamedEnum
-    <
-        Foam::coordSet::coordFormat,
-        5
-    >::names[] =
+const Foam::Enum<Foam::coordSet::coordFormat>
+    Foam::coordSet::coordFormatNames_
     {
-        "xyz",
-        "x",
-        "y",
-        "z",
-        "distance"
+        { coordFormat::XYZ, "xyz" },
+        { coordFormat::X, "x" },
+        { coordFormat::Y, "y" },
+        { coordFormat::Z, "z" },
+        { coordFormat::DISTANCE, "distance" }
     };
-}
-
-
-const Foam::NamedEnum<Foam::coordSet::coordFormat, 5>
-    Foam::coordSet::coordFormatNames_;
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
diff --git a/src/fileFormats/coordSet/coordSet.H b/src/fileFormats/coordSet/coordSet.H
index 5492f37b4351f98bbb1395118d2efd836f44a11d..bf764cc143cb87213e9bbd48b939ae74fafab75c 100644
--- a/src/fileFormats/coordSet/coordSet.H
+++ b/src/fileFormats/coordSet/coordSet.H
@@ -37,6 +37,7 @@ SourceFiles
 
 #include "pointField.H"
 #include "word.H"
+#include "Enum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -70,7 +71,7 @@ public:
 private:
 
         //- String representation of coordFormat enums
-        static const NamedEnum<coordFormat, 5> coordFormatNames_;
+        static const Enum<coordFormat> coordFormatNames_;
 
 
 protected:
diff --git a/src/fileFormats/fire/FIRECore.C b/src/fileFormats/fire/FIRECore.C
index ab576116348cdc4d698b2966e16b4b1a7b69b051..4cf98960801fec203d0017f4ee69fd4ff270401a 100644
--- a/src/fileFormats/fire/FIRECore.C
+++ b/src/fileFormats/fire/FIRECore.C
@@ -27,24 +27,14 @@ License
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-const Foam::NamedEnum<Foam::fileFormats::FIRECore::fileExt3d, 4>
-    Foam::fileFormats::FIRECore::file3dExtensions;
-
-namespace Foam
-{
-    template<>
-    const char* Foam::NamedEnum
-    <
-        Foam::fileFormats::FIRECore::fileExt3d,
-        4
-    >::names[] =
+const Foam::Enum<Foam::fileFormats::FIRECore::fileExt3d>
+    Foam::fileFormats::FIRECore::file3dExtensions
     {
-        "fpma",
-        "fpmb",
-        "fpmaz",
-        "fpmbz"
+        { fileExt3d::POLY_ASCII, "fpma" },
+        { fileExt3d::POLY_BINARY, "fpmb" },
+        { fileExt3d::POLY_ASCII_Z, "fpmaz" },
+        { fileExt3d::POLY_BINARY_Z, "fpmbz" }
     };
-}
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
diff --git a/src/fileFormats/fire/FIRECore.H b/src/fileFormats/fire/FIRECore.H
index 3f9c654cc1ea1acdf0b5027a140d2014a3e44859..96eb73ee5f31669d2b34a0889a52e6e7878dd460 100644
--- a/src/fileFormats/fire/FIRECore.H
+++ b/src/fileFormats/fire/FIRECore.H
@@ -40,7 +40,7 @@ SourceFiles
 #include "labelList.H"
 #include "pointField.H"
 #include "IOstreams.H"
-#include "NamedEnum.H"
+#include "Enum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -86,8 +86,8 @@ public:
         {
             POLY_ASCII,
             POLY_BINARY,
-            POLY_ASCII_COMPRESSED,
-            POLY_BINARY_COMPRESSED
+            POLY_ASCII_Z,
+            POLY_BINARY_Z
         };
 
 
@@ -97,11 +97,12 @@ public:
         //- Float type (binary format)
         typedef double  fireReal_t;
 
+
 protected:
 
     // Protected Data
 
-        static const NamedEnum<fileExt3d, 4>  file3dExtensions;
+        static const Enum<fileExt3d>  file3dExtensions;
 
 
     // Protected Member Functions
diff --git a/src/fileFormats/starcd/STARCDCore.C b/src/fileFormats/starcd/STARCDCore.C
index 7ea833b488ae291e55cbbc68f7c260ba903200ee..412738131e200a35e3625a31ed50aacefbfcdf94 100644
--- a/src/fileFormats/starcd/STARCDCore.C
+++ b/src/fileFormats/starcd/STARCDCore.C
@@ -33,40 +33,22 @@ License
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-const Foam::NamedEnum<Foam::fileFormats::STARCDCore::fileHeader, 3>
-    Foam::fileFormats::STARCDCore::fileHeaders_;
-
-const Foam::NamedEnum<Foam::fileFormats::STARCDCore::fileExt, 4>
-    Foam::fileFormats::STARCDCore::fileExtensions_;
-
-namespace Foam
-{
-    template<>
-    const char* Foam::NamedEnum
-    <
-        Foam::fileFormats::STARCDCore::fileHeader,
-        3
-    >::names[] =
+const Foam::Enum<Foam::fileFormats::STARCDCore::fileHeader>
+    Foam::fileFormats::STARCDCore::fileHeaders_
     {
-        "PROSTAR_CELL",
-        "PROSTAR_VERTEX",
-        "PROSTAR_BOUNDARY"
+        { fileHeader::HEADER_CEL, "PROSTAR_CELL" },
+        { fileHeader::HEADER_VRT, "PROSTAR_VERTEX" },
+        { fileHeader::HEADER_BND, "PROSTAR_BOUNDARY" }
     };
 
-    template<>
-    const char* Foam::NamedEnum
-    <
-        Foam::fileFormats::STARCDCore::fileExt,
-        4
-    >::names[] =
+const Foam::Enum<Foam::fileFormats::STARCDCore::fileExt>
+    Foam::fileFormats::STARCDCore::fileExtensions_
     {
-        "cel",
-        "vrt",
-        "bnd",
-        "inp"
+        { fileExt::CEL_FILE, "cel" },
+        { fileExt::VRT_FILE, "vrt" },
+        { fileExt::BND_FILE, "bnd" },
+        { fileExt::INP_FILE, "inp" }
     };
-}
-
 
 const char* const Foam::fileFormats::STARCDCore::defaultBoundaryName =
     "Default_Boundary_Region";
diff --git a/src/fileFormats/starcd/STARCDCore.H b/src/fileFormats/starcd/STARCDCore.H
index cae3d1e7c0de7a8e7a6a3e6d305f49642f354cff..21f64cae72c50ad5c6a5fcd43d9d9393d8aa7728 100644
--- a/src/fileFormats/starcd/STARCDCore.H
+++ b/src/fileFormats/starcd/STARCDCore.H
@@ -36,7 +36,7 @@ SourceFiles
 #define STARCDCore_H
 
 #include "IFstream.H"
-#include "NamedEnum.H"
+#include "Enum.H"
 #include "pointField.H"
 #include "Map.H"
 #include "FixedList.H"
@@ -113,8 +113,8 @@ private:
 
     // Private Data
 
-        static const NamedEnum<fileHeader, 3> fileHeaders_;
-        static const NamedEnum<fileExt, 4>    fileExtensions_;
+        static const Enum<fileHeader> fileHeaders_;
+        static const Enum<fileExt>    fileExtensions_;
 
 
 protected:
diff --git a/src/fileFormats/stl/STLReader.C b/src/fileFormats/stl/STLReader.C
index b7b91a0bb755574f216bb4d4f37a941286939610..ca7451d886a2ad7726a6b1f8d1a290a371414eaa 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 9ed6838bc136feb7954060ad70bb93d7f0d2ba45..e9873aafe74bad823e3c4db840698f82efdfaf7a 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 0ea759151c2a05f59b2aa437dd74f11928bd952d..46c9ab1a853195dd9c28254f436a50b46f5eb478 100644
--- a/src/fileFormats/stl/STLReaderASCII.L
+++ b/src/fileFormats/stl/STLReaderASCII.L
@@ -23,9 +23,10 @@ License
 
 \*---------------------------------------------------------------------------*/
 
-%{
+%option prefix="yySTL"
+%option yyclass="yySTLFlexLexer"
 
-#undef yyFlexLexer
+%{
 
  /* ------------------------------------------------------------------------ *\
    ------ local definitions
@@ -35,9 +36,9 @@ License
 #include "OSspecific.H"
 
 using namespace Foam;
-
 // Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
 //! \cond dummy
+#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34
 int yyFlexLexer::yylex()
 {
     FatalErrorInFunction
@@ -45,29 +46,29 @@ int yyFlexLexer::yylex()
         << abort(FatalError);
     return 0;
 }
+#endif
 //! \endcond
 
 // Dummy yywrap to keep yylex happy at compile time.
 // It is called by yylex but is not used as the mechanism to change file.
 // See <<EOF>>
 //! \cond dummy
-#if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34
+#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34
 extern "C" int yywrap()
 #else
-int yyFlexLexer::yywrap()
+int yySTLFlexLexer::yywrap()
 #endif
 {
     return 1;
 }
 //! \endcond
 
-
 //- A lexer for parsing STL ASCII files.
 //  Returns DynamicList(s) of points and facets (zoneIds).
 //  The facets are within a solid/endsolid grouping
 class STLASCIILexer
 :
-    public yyFlexLexer
+    public yySTLFlexLexer
 {
     // Private data
 
@@ -76,7 +77,7 @@ class STLASCIILexer
         label lineNo_;
         word  startError_;
 
-        DynamicList<point> points_;
+        DynamicList<STLpoint> points_;
         DynamicList<label> facets_;
         DynamicList<word>  names_;
         DynamicList<label> sizes_;
@@ -95,7 +96,7 @@ public:
         //- The lexer function itself
         int lex();
 
-    // Access
+      // Access
 
         //- Do all the solid groups appear in order?
         inline bool sorted() const
@@ -104,7 +105,7 @@ public:
         }
 
         //- A list of unstitched triangle points
-        inline DynamicList<point>& points()
+        inline DynamicList<STLpoint>& points()
         {
             return points_;
         }
@@ -132,7 +133,7 @@ public:
 
 STLASCIILexer::STLASCIILexer(istream* is, const label approxNpoints)
 :
-    yyFlexLexer(is),
+    yySTLFlexLexer(is),
     sorted_(true),
     groupID_(-1),
     lineNo_(1),
@@ -145,6 +146,7 @@ STLASCIILexer::STLASCIILexer(istream* is, const label approxNpoints)
    ------ cppLexer::yylex()
  \* ------------------------------------------------------------------------ */
 
+#undef YY_DECL
 #define YY_DECL int STLASCIILexer::lex()
 
 %}
@@ -202,9 +204,9 @@ endsolid              {space}("endsolid"|"ENDSOLID")({some_space}{word})*
     // End of read character pointer returned by strtof
     // char* endPtr;
 
-    STLpoint normal;
+    label cmpt = 0;   // Component index when reading vertex
     STLpoint vertex;
-    label cmpt = 0;   // component index used for reading vertex
+    // STLpoint normal;
 
     static const char* stateNames[7] =
     {
@@ -237,154 +239,167 @@ endsolid              {space}("endsolid"|"ENDSOLID")({some_space}{word})*
  /*                      ------ Reading control header ------                */
 
 {solid} {
-        BEGIN(readSolidName);
-    }
+    BEGIN(readSolidName);
+}
 
 <readSolidName>{string} {
-        word name(Foam::string::validate<word>(YYText()));
+    const word solidName(Foam::string::validate<word>(YYText()));
 
-        HashTable<label>::const_iterator fnd = lookup_.find(name);
-        if (fnd != lookup_.end())
+    auto iter = lookup_.cfind(solidName);
+    if (iter.found())
+    {
+        if (groupID_ != iter.object())
         {
-            if (groupID_ != fnd())
-            {
-                // group appeared out of order
-                sorted_ = false;
-            }
-            groupID_ = fnd();
+            sorted_ = false;  // Group appeared out of order
+            groupID_ = iter.object();
         }
-        else
+    }
+    else
+    {
+        groupID_ = sizes_.size();
+        if (lookup_.insert(solidName, groupID_))
         {
-            groupID_ = sizes_.size();
-            lookup_.insert(name, groupID_);
-            names_.append(name);
+            names_.append(solidName);
             sizes_.append(0);
         }
-        BEGIN(INITIAL);
+        else
+        {
+            FatalErrorInFunction<< "Duplicate solid-name: " << solidName
+                << exit(FatalError);
+        }
     }
+    BEGIN(INITIAL);
+}
 
 <readSolidName>{space}\n {
-        word name("solid");
+    const word solidName("solid");  // Could also use solid0, solid1, ...
 
-        HashTable<label>::const_iterator fnd = lookup_.find(name);
-        if (fnd != lookup_.end())
+    auto iter = lookup_.cfind(solidName);
+    if (iter.found())
+    {
+        if (groupID_ != iter.object())
         {
-            if (groupID_ != fnd())
-            {
-                // group appeared out of order
-                sorted_ = false;
-            }
-            groupID_ = fnd();
+            sorted_ = false;  // Group appeared out of order
+            groupID_ = iter.object();
         }
-        else
+    }
+    else
+    {
+        groupID_ = sizes_.size();
+        if (lookup_.insert(solidName, groupID_))
         {
-            groupID_ = sizes_.size();
-            lookup_.insert(name, groupID_);
-            names_.append(name);
+            names_.append(solidName);
             sizes_.append(0);
         }
-
-        lineNo_++;
-        BEGIN(INITIAL);
+        else
+        {
+            FatalErrorInFunction<< "Duplicate solid-name: " << solidName
+                << exit(FatalError);
+        }
     }
 
+    ++lineNo_;
+    BEGIN(INITIAL);
+}
+
 {color} {
-    }
+    /* ignore 'color' */
+}
 
 {facet} {
-        BEGIN(readFacet);
-    }
+    BEGIN(readFacet);
+}
 
 <readFacet>{normal} {
-        BEGIN(readNormal);
-    }
+    BEGIN(readNormal);
+}
 
 <readNormal>{point} {
-        /*
-         skip reading normals:
-         normal.x() = strtof(YYText(), &endPtr);
-         normal.y() = strtof(endPtr, &endPtr);
-         normal.z() = strtof(endPtr, &endPtr);
-         normals_.append(normal);
-         */
-        BEGIN(readFacet);
-    }
+    /*
+     skip reading normals:
+     normal.x() = strtof(YYText(), &endPtr);
+     normal.y() = strtof(endPtr, &endPtr);
+     normal.z() = strtof(endPtr, &endPtr);
+     normals_.append(normal);
+     */
+    BEGIN(readFacet);
+}
 
 <readFacet>{outerloop} {
-        BEGIN(readVertices);
-    }
+    BEGIN(readVertices);
+}
 
 <readVertices>{vertex} {
-        BEGIN(readVertex);
-    }
+    BEGIN(readVertex);
+}
 
 <readVertex>{space}{signedInteger}{space} {
-        vertex[cmpt++] = atol(YYText());
+    vertex[cmpt++] = atol(YYText());
 
-        if (cmpt == 3)
-        {
-            cmpt = 0;
-            points_.append(vertex);
-            BEGIN(readVertices);
-        }
+    if (cmpt == 3)
+    {
+        cmpt = 0;
+        points_.append(vertex);
+        BEGIN(readVertices);
     }
+}
 
 <readVertex>{space}{floatNum}{space} {
-        vertex[cmpt++] = atof(YYText());
+    vertex[cmpt++] = atof(YYText());
 
-        if (cmpt == 3)
-        {
-            cmpt = 0;
-            points_.append(vertex);
-            BEGIN(readVertices);
-        }
+    if (cmpt == 3)
+    {
+        cmpt = 0;
+        points_.append(vertex);
+        BEGIN(readVertices);
     }
+}
 
 <readVertices>{endloop} {
-        BEGIN(readFacet);
-    }
+    BEGIN(readFacet);
+}
 
 <readFacet>{endfacet} {
-        facets_.append(groupID_);
-        sizes_[groupID_]++;
-        BEGIN(INITIAL);
-    }
+    facets_.append(groupID_);
+    sizes_[groupID_]++;
+    BEGIN(INITIAL);
+}
 
 {endsolid} {
-    }
+}
 
 
- /* ------------------ Ignore remaining space and \n s. -------------------- */
+ /* ---------------- Ignore remaining spaces and newlines ------------------ */
 
 <*>{space} {}
-<*>\n      { lineNo_++; }
+<*>\n      { ++lineNo_; }
 
 
  /* ------------------- Any other characters are errors -------------------- */
 
 <*>. {
-        startError_ = YYText();
-        yy_push_state(stlError);
-    }
+    startError_ = YYText();
+    yy_push_state(stlError);
+}
 
 
  /* ---------------------------- Error handler ----------------------------- */
 
 <stlError>.* {
-        yy_pop_state();
-        FatalErrorInFunction
-            << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
-            << "    expected " << stateExpects[YY_START]
-            << " but found '" << startError_.c_str() << YYText() << "'"
-            << exit(FatalError);
-    }
+    yy_pop_state();
+    FatalErrorInFunction
+        << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
+        << "    expected " << stateExpects[YY_START]
+        << " but found '" << startError_.c_str() << YYText() << "'"
+        << exit(FatalError);
+}
 
 
  /*  ------------------------ On EOF terminate ----------------------------  */
 
 <<EOF>> {
-            yyterminate();
-    }
+    yyterminate();
+}
 %%
 
 
diff --git a/src/fileFormats/stl/STLpoint.H b/src/fileFormats/stl/STLpoint.H
index 3c432c09ee307fd7d33bc4ca305774fe4c946d69..f6c1f2ea922f691c690660b328d70a835f6388a3 100644
--- a/src/fileFormats/stl/STLpoint.H
+++ b/src/fileFormats/stl/STLpoint.H
@@ -47,7 +47,7 @@ namespace Foam
 
 class STLpoint
 :
-    public Vector<float>
+    public floatVector
 {
 
 public:
@@ -58,28 +58,34 @@ public:
         inline STLpoint()
         {}
 
+        //- Construct from base class
+        inline STLpoint(const floatVector& v)
+        :
+            floatVector(v)
+        {}
+
         //- Construct from components
         inline STLpoint(float x, float y, float z)
         :
-            Vector<float>(x, y, z)
+            floatVector(x, y, z)
         {}
 
         //- Construct from components
         inline STLpoint(double x, double y, double z)
         :
-            Vector<float>(float(x), float(y), float(z))
+            floatVector(float(x), float(y), float(z))
         {}
 
         //- Construct from point
         inline STLpoint(const point& pt)
         :
-            Vector<float>(float(pt.x()), float(pt.y()), float(pt.z()))
+            floatVector(float(pt.x()), float(pt.y()), float(pt.z()))
         {}
 
         //- Construct from istream
         inline STLpoint(Istream& is)
         :
-            Vector<float>(is)
+            floatVector(is)
         {}
 
 
diff --git a/src/fileFormats/vtk/read/vtkUnstructuredReader.C b/src/fileFormats/vtk/read/vtkUnstructuredReader.C
index d834f4d5ebab183b171a2053f929833d1cec1106..153c16578263edc40d1cbd951d702a73fd26202e 100644
--- a/src/fileFormats/vtk/read/vtkUnstructuredReader.C
+++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.C
@@ -35,49 +35,38 @@ License
 namespace Foam
 {
     defineTypeNameAndDebug(vtkUnstructuredReader, 1);
+}
 
-    template<>
-    const char*
-    NamedEnum<vtkUnstructuredReader::vtkDataType, 8>::names[] =
+const Foam::Enum<Foam::vtkUnstructuredReader::vtkDataType>
+    Foam::vtkUnstructuredReader::vtkDataTypeNames
     {
-        "int",
-        "unsigned_int",
-        "long",
-        "unsigned_long",
-        "float",
-        "double",
-        "string",
-        "vtkIdType"
+        { vtkDataType::VTK_INT, "int" },
+        { vtkDataType::VTK_UINT, "unsigned_int" },
+        { vtkDataType::VTK_LONG, "long" },
+        { vtkDataType::VTK_ULONG, "unsigned_long" },
+        { vtkDataType::VTK_FLOAT, "float" },
+        { vtkDataType::VTK_DOUBLE, "double" },
+        { vtkDataType::VTK_STRING, "string" },
+        { vtkDataType::VTK_ID, "vtkIdType" }
     };
-    const NamedEnum<vtkUnstructuredReader::vtkDataType, 8>
-    vtkUnstructuredReader::vtkDataTypeNames;
-
 
-    template<>
-    const char*
-    NamedEnum<vtkUnstructuredReader::vtkDataSetType, 3>::names[] =
+const Foam::Enum<Foam::vtkUnstructuredReader::vtkDataSetType>
+    Foam::vtkUnstructuredReader::vtkDataSetTypeNames
     {
-        "FIELD",
-        "SCALARS",
-        "VECTORS"
+        { vtkDataSetType::VTK_FIELD, "FIELD" },
+        { vtkDataSetType::VTK_SCALARS, "SCALARS" },
+        { vtkDataSetType::VTK_VECTORS, "VECTORS" }
     };
-    const NamedEnum<vtkUnstructuredReader::vtkDataSetType, 3>
-    vtkUnstructuredReader::vtkDataSetTypeNames;
 
-
-    template<>
-    const char*
-    NamedEnum<vtkUnstructuredReader::parseMode, 5>::names[] =
+const Foam::Enum<Foam::vtkUnstructuredReader::parseMode>
+    Foam::vtkUnstructuredReader::parseModeNames
     {
-        "NOMODE",
-        "UNSTRUCTURED_GRID",
-        "POLYDATA",
-        "CELL_DATA",
-        "POINT_DATA"
+        { parseMode::NOMODE, "NOMODE" },
+        { parseMode::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" },
+        { parseMode::POLYDATA, "POLYDATA" },
+        { parseMode::CELL_DATA, "CELL_DATA" },
+        { parseMode::POINT_DATA, "POINT_DATA" }
     };
-    const NamedEnum<vtkUnstructuredReader::parseMode, 5>
-    vtkUnstructuredReader::parseModeNames;
-}
 
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
diff --git a/src/fileFormats/vtk/read/vtkUnstructuredReader.H b/src/fileFormats/vtk/read/vtkUnstructuredReader.H
index 77bd71b4aac8f6ebcbaf9b90e1e1023871bae610..48dc38890a843b60b6dd1bf2d3823afeb032999c 100644
--- a/src/fileFormats/vtk/read/vtkUnstructuredReader.H
+++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.H
@@ -51,7 +51,7 @@ SourceFiles
 #include "objectRegistry.H"
 #include "cellShapeList.H"
 #include "HashSet.H"
-#include "NamedEnum.H"
+#include "Enum.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -83,7 +83,7 @@ public:
             VTK_ID
         };
 
-        static const NamedEnum<vtkDataType, 8> vtkDataTypeNames;
+        static const Enum<vtkDataType> vtkDataTypeNames;
 
 
         //- Enumeration defining the vtk dataset types
@@ -94,11 +94,10 @@ public:
             VTK_VECTORS
         };
 
-        static const NamedEnum<vtkDataSetType, 3> vtkDataSetTypeNames;
+        static const Enum<vtkDataSetType> vtkDataSetTypeNames;
 
 
-        //- Enumeration defining the parse mode - what type of data is being
-        //  read
+        //- Enumeration defining the parse mode - type of data being read
         enum parseMode
         {
             NOMODE,
@@ -108,7 +107,7 @@ public:
             POINT_DATA
         };
 
-        static const NamedEnum<parseMode, 5> parseModeNames;
+        static const Enum<parseMode> parseModeNames;
 
 
 private:
diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
index 4cbfb60d561c486b225e6d90d819cc72451bb768..de258c1010b627d4dca7107f909eb481b304c981 100644
--- a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C
@@ -222,7 +222,7 @@ void Foam::fileFormats::FLMAsurfaceFormat<Face>::write
     // Set the precision of the points data to 10
     os.precision(10);
 
-    Info<< "points: " << pointLst.size() << endl;
+    Info<< nl << "points: " << pointLst.size() << endl;
     putFireLabel(os, pointLst.size());
     newline(os);
 
diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C
index f9e335c39eb8dd7cca3f629b277f68c197e86077..a746232d18aafdcb371dcb74c7ed7f42828d17e6 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 cb2aa80823b8b074fc90c665010a7236b245cd51..b36c5fd321d6c668069709f0b5493a47dc3ca15c 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 87cc04d20ec49afcef7da2ff05adef49922aaae6..8f473d11203f5553a5b6907b45814ec375eae1d2 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 12ce08e3725fdc72d03e1f4b96313f7879baa186..5d4b76fd6e0d122fb238e2433fca22430043a90f 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 43c9453a524e045805b69c0561a878d819b626a9..70b1e9f44454d172af6031f59e0127d865efb751 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;