Salome HOME
bos #18711: Windows compilation
authorNabil Ghodbane <nabil.ghodbane@cea.fr>
Mon, 11 Oct 2021 12:32:36 +0000 (14:32 +0200)
committerNabil Ghodbane <nabil.ghodbane@cea.fr>
Mon, 11 Oct 2021 12:32:36 +0000 (14:32 +0200)
applications/SALOME-master-windows.pyconf
products/CAS.pyconf
products/compil_scripts/netgen-6.2.2101.bat
products/netgen.pyconf
products/patches/netgen.101.windows.patch [new file with mode: 0644]
products/patches/netgen62ForSalome_windows.patch [new file with mode: 0644]

index 81bfa3037ff9d0e50713fb446a51c2d732df5e18..e62c741a50a7348435d9c39dd2d75a09c6e05538 100644 (file)
@@ -36,7 +36,7 @@ APPLICATION :
         alabaster : '0.7.6'
         Babel : '2.7.0'
         boost : '1.67.0'
-        CAS : {tag: '1e74e3eacd', section: 'version_V7_5_0_win'}
+        CAS : {tag: '1e74e3eacd', section: 'version_1e74e3eacd_win'}
         certifi : '2019.6.16'
         cgns : '4.1.1'
         chardet : '3.0.4'
index 9695459500751011232ae0fd81025125a0106659..6c4d2eb8e8139247ef7034f937aedef4ec19f725 100755 (executable)
@@ -76,13 +76,64 @@ version_V7_5_0 :
     }
 }
 
+version_1e74e3eacd_win :
+{
+    name : "CAS"
+    build_source : "script"
+    compil_script :  "CAS_7.5.bat"
+    get_source : "git"
+    git_info:
+    {
+        repo : "http://git.dev.opencascade.org/repos/occt.git"
+        repo_dev : $repo
+    }
+    environ :
+    {
+        CSF_OCCTBinPath          : $install_dir + $VARS.sep + "win64" + $VARS.sep + "vc14" + $VARS.sep + "bin"
+        CSF_OCCTLibPath          : $install_dir + $VARS.sep + "win64" + $VARS.sep + "vc14" + $VARS.sep + "lib"
+        CSF_OCCTIncludePath      : $install_dir + $VARS.sep + "inc"
+        CSF_OCCTResourcePath     : $install_dir + $VARS.sep + "src"
+        CSF_OCCTDataPath         : $install_dir + $VARS.sep + "data"
+        CSF_OCCTSamplesPath      : $install_dir + $VARS.sep + "samples"
+        CSF_OCCTTestsPath        : $install_dir + $VARS.sep + "tests"
+        CSF_OCCTDocPath          : $install_dir + $VARS.sep + "doc"
+        CSF_SHMessage            : $install_dir + $VARS.sep + "src" + $VARS.sep + "SHMessage"
+        CSF_MDTVTexturesDirectory: $install_dir + $VARS.sep + "src" + $VARS.sep + "Textures"
+        CSF_ShadersDirectory     : $install_dir + $VARS.sep + "src" + $VARS.sep + "Shaders"
+        CSF_XSMessage            : $install_dir + $VARS.sep + "src" + $VARS.sep + "XSMessage"
+        CSF_TObjMessage          : $install_dir + $VARS.sep + "src" + $VARS.sep + "TObj"
+        CSF_StandardDefaults     : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource"
+        CSF_PluginDefaults       : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource"
+        CSF_XCAFDefaults         : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource"
+        CSF_TObjDefaults         : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource"
+        CSF_StandardLiteDefaults : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource"
+        CSF_IGESDefaults         : $install_dir + $VARS.sep + "src" + $VARS.sep + "XSTEPResource"
+        CSF_STEPDefaults         : $install_dir + $VARS.sep + "src" + $VARS.sep + "XSTEPResource"
+        CSF_XmlOcafResource      : $install_dir + $VARS.sep + "src" + $VARS.sep + "XmlOcafResource"
+        CSF_MIGRATION_TYPES      : $install_dir + $VARS.sep + "src" + $VARS.sep + "StdResource" + $VARS.sep + "MigrationSheet.txt"
+        CSF_UnitsDefinition      : $install_dir + $VARS.sep + "src" + $VARS.sep + "UnitsAPI" + $VARS.sep + "Units.dat"
+        MMGT_CLEAR     : "1"
+        MMGT_REENTRANT : "1"
+        CSF_LANGUAGE   : "us"
+
+        env_script : "CAS.py"
+    }
+    depend : ['freetype', 'freeimage', 'tbb']
+    build_depend : ["cmake", "doxygen"]
+    source_dir : $APPLICATION.workdir + $VARS.sep + 'SOURCES' + $VARS.sep + $name
+    build_dir : $APPLICATION.workdir + $VARS.sep + 'BUILD' + $VARS.sep + $name
+    properties:
+    {
+      incremental : "no"
+    }
+}
+
 version_V7_5_0_win :
 {
     name : "CAS"
     build_source : "script"
     compil_script :  "CAS_7.5.bat"
-    #get_source : "git"
-    get_source : "archive"
+    get_source : "git"
     archive_info :
     {
         archive_name : "CAS-V7_5_0.tar.gz"
index 2c17eafbd39ff0b5416d7b377c153b7764981bc7..c328994e0c16a8b654bcb95a35d5b0e6ecf48bda 100644 (file)
@@ -13,31 +13,88 @@ if %SAT_DEBUG% == 1 (
   set PRODUCT_BUILD_TYPE=Debug
 )
 
-dos2unix -q %SOURCE_DIR%/libsrc/occ/*
-dos2unix -q %SOURCE_DIR%/libsrc/nglib/*
-
 if NOT exist "%PRODUCT_INSTALL%" mkdir %PRODUCT_INSTALL%
 REM clean BUILD directory
 if exist "%BUILD_DIR%" rmdir /Q /S %BUILD_DIR%
 mkdir %BUILD_DIR%
 
+echo **
+echo ** Build CMAKE 3.16.7
+
+cd %BUILD_DIR%
+7z x -y %SOURCE_DIR%\cmake-3.16.7.tar.gz
+7z x -y cmake-3.16.7.tar
+mv cmake-v3.16.7 cmake-3.16.7-SRC
+set CMAKE_PRODUCT_SOURCE_DIR=%BUILD_DIR%\cmake-3.16.7-SRC
+set CMAKE_PRODUCT_BUILD_DIR=%BUILD_DIR%\cmake-3.16.7-BUILD
+set CMAKE_PRODUCT_INSTALL_DIR=%BUILD_DIR%\cmake-3.16.7-X64
+
+mkdir %BUILD_DIR%\cmake-3.16.7-BUILD
+REM enter cmake build directory
+cd %CMAKE_PRODUCT_BUILD_DIR%
+
+set CMAKE_OPTIONS=-DCMAKE_INSTALL_PREFIX:STRING=%CMAKE_PRODUCT_INSTALL_DIR:\=/%
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_BUILD_TYPE:STRING=Release
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_GENERATOR=%CMAKE_GENERATOR%
+
+echo.
+echo --------------------------------------------------------------------------
+echo cmake %CMAKE_OPTIONS% %CMAKE_PRODUCT_SOURCE_DIR%
+echo --------------------------------------------------------------------------
+cmake %CMAKE_OPTIONS% %CMAKE_PRODUCT_SOURCE_DIR%
+if NOT %ERRORLEVEL% == 0 (
+    echo "ERROR on cmake"
+    exit 1
+)
+
+echo.
+echo --------------------------------------------------------------------------
+echo msbuild %MAKE_OPTIONS% /p:Configuration=Release /p:PlatformTarget=%PLATFORM_TARGET% ALL_BUILD.vcxproj
+echo --------------------------------------------------------------------------
+msbuild %MAKE_OPTIONS% /p:Configuration=Release /p:PlatformTarget=%PLATFORM_TARGET% ALL_BUILD.vcxproj
+if NOT %ERRORLEVEL% == 0 (
+    echo ERROR on msbuild ALL_BUILD.vcxproj
+    exit 2
+)
+
+echo.
+echo --------------------------------------------------------------------------
+echo msbuild %MAKE_OPTIONS% /p:Configuration=Release /p:PlatformTarget=%PLATFORM_TARGET% INSTALL.vcxproj
+echo --------------------------------------------------------------------------
+msbuild %MAKE_OPTIONS% /p:Configuration=Release /p:PlatformTarget=%PLATFORM_TARGET% INSTALL.vcxproj
+if NOT %ERRORLEVEL% == 0 (
+    echo ERROR on msbuild INSTALL.vcxproj
+    exit 3
+)
+
+REM expand PATH to use this cmake version
+set CMAKE_ROOT=%CMAKE_PRODUCT_INSTALL_DIR%
+set PATH=%CMAKE_ROOT%\bin;%PATH%
+
+cd %BUILD_DIR%
+
+cmake --version
+
+
 set CMAKE_OPTIONS=
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_GUI=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_PYTHON=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_MPI=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_OCC=ON
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DENABLE_UNIT_TESTS=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_INTERNAL_TCL=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DBUILD_STUB_FILES=OFF
-set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DOCC_INCLUDE_DIR=%CASROOT:\=/%/include/opencascade
-set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DOCC_LIBRARY_DIR=%CASROOT:\=/%/lib
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCASROOT=%CASROOT%
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DOCC_INCLUDE_DIR=%CASROOT:\=/%/inc
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DOCC_LIBRARY_DIR=%CASROOT:\=/%/win64/vc14/lib
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DZLIB_ROOT_DIR=%ZLIB_DIR:\=/%
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR:\=/%
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DUSE_SUPERBUILD=OFF
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_CXX_STANDARD=17
-set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_INSTALL_PREFIX=%PRODUCT_INSTALL%
+set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_INSTALL_PREFIX=%PRODUCT_INSTALL:\=/%
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_BUILD_TYPE=%PRODUCT_BUILD_TYPE%
-set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DZLIB_ROOT_DIR=%ZLIB_DIR%
-set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCASROOT=%CASROOT%
 set CMAKE_OPTIONS=%CMAKE_OPTIONS% -DCMAKE_GENERATOR="Visual Studio 15 2017 Win64"
 
-
 set MSBUILDDISABLENODEREUSE=1
 
 cd %BUILD_DIR%
@@ -77,13 +134,6 @@ if NOT %ERRORLEVEL% == 0 (
     exit 3
 )
 
-REM move DLL to bin, in order to reduce the PATH length..
-MOVE /Y %PRODUCT_INSTALL%\lib\nglib.dll  %PRODUCT_INSTALL%\bin\nglib.dll
-if NOT %ERRORLEVEL% == 0 (
-    echo ERROR could not move DLL to BIN directory...
-    exit 4
-)
-
 taskkill /F /IM "mspdbsrv.exe"
 
 echo.
index 56f5fe705964e3ffbb318fec2edc37b3b65f298e..c604cc046d981766e862ce36bebaffdecc41704b 100644 (file)
@@ -34,7 +34,14 @@ version_6_2_2101 :
 version_6_2_2101_win :
 {
    build_source : "script"
-   compil_script :  'netgen-6.2.2101.bat'
+   archive_info: {archive_name : "netgen-6.2.2101_cmake-3.16.7.tar.gz"}
+   patches : ['netgen62ForSalome_windows.patch', 'netgen.101.windows.patch']
+   compil_script :  'netgen-6.2.2101_2.bat'
+   properties :
+   {
+     incremental : "yes"
+     single_install_dir : "no"
+   }
 }
 
 version_5_3_1_with_CAS_7_2 :
diff --git a/products/patches/netgen.101.windows.patch b/products/patches/netgen.101.windows.patch
new file mode 100644 (file)
index 0000000..790061d
--- /dev/null
@@ -0,0 +1,95 @@
+diff -Naur netgen-6.2.2101_SRC_orig/libsrc/core/version.hpp netgen-6.2.2101_SRC_modif/libsrc/core/version.hpp
+--- netgen-6.2.2101_SRC_orig/libsrc/core/version.hpp   2021-03-26 15:27:42.000000000 +0300
++++ netgen-6.2.2101_SRC_modif/libsrc/core/version.hpp  2021-10-05 14:21:01.736494600 +0300
+@@ -41,7 +41,12 @@
+               if(!vstring.empty())
+                 {
+                   dot = vstring.find('-');
+-                  patch = std::stoi(vstring.substr(0,dot));
++                  try {
++                    patch = std::stoi(vstring.substr(0,dot));
++                  }
++                  catch (const std::exception& e) {
++                    patch = 0;
++                  }
+                   if(dot == size_t(-1)) vstring = "";
+                   else vstring = vstring.substr(dot+1, vstring.size()-dot-1);
+                   if(!vstring.empty())
+diff -Naur netgen-6.2.2101_SRC_orig/libsrc/stlgeom/stlgeom.hpp netgen-6.2.2101_SRC_modif/libsrc/stlgeom/stlgeom.hpp
+--- netgen-6.2.2101_SRC_orig/libsrc/stlgeom/stlgeom.hpp        2021-03-26 15:27:44.000000000 +0300
++++ netgen-6.2.2101_SRC_modif/libsrc/stlgeom/stlgeom.hpp       2021-10-05 14:51:15.044170800 +0300
+@@ -188,7 +188,7 @@
+       STLTopology::DoArchive(ar);
+     }
+-    void Clear();
++    DLL_HEADER void Clear();
+     virtual void Save (string filename) const override;
+@@ -369,19 +369,19 @@
+     ///Build EdgeSegments
+     void ClearEdges();
+-    void BuildEdges(const STLParameters& stlparam);
++    DLL_HEADER void BuildEdges(const STLParameters& stlparam);
+     void BuildEdgesPerPoint();
+     void UseExternalEdges();
+     void FindEdgesFromAngles(const STLParameters& stlparam);
+-    void CalcFaceNums();
++    DLL_HEADER void CalcFaceNums();
+     int GetNOBodys();
+     int GetNOFaces() {return facecnt;}
+-    void LinkEdges(const STLParameters& stlparam);
++    DLL_HEADER void LinkEdges(const STLParameters& stlparam);
+     void AddConeAndSpiralEdges(const STLParameters& stlparam);
+-    void AddFaceEdges(); //each face should have at least one starting edge (outherwise it won't be meshed)
++    DLL_HEADER void AddFaceEdges(); //each face should have at least one starting edge (outherwise it won't be meshed)
+     void GetDirtyChartTrigs(int chartnum, STLChart& chart, const Array<ChartId, STLTrigId>& outercharttrigs, 
+                           NgArray<ChartId>& chartpointchecked, NgArray<int>& dirtytrigs);
+@@ -398,7 +398,7 @@
+     //make charts with regions of a max. angle
+-    void MakeAtlas(class Mesh & mesh, const MeshingParameters& mparam, const STLParameters& stlparam);
++    DLL_HEADER void MakeAtlas(class Mesh & mesh, const MeshingParameters& mparam, const STLParameters& stlparam);
+     //outerchartspertrig, sorted!
+     int GetOCPTSize() const {return outerchartspertrig.Size();};
+@@ -460,7 +460,7 @@
+     int GetLineP(int lnr, int pnr) const {return lines.Get(lnr)->PNum(pnr);}
+     int GetLineNP(int nr) const {return lines.Get(nr)->NP();}
+-    void SetLineEndPoint(int pn);
++    DLL_HEADER void SetLineEndPoint(int pn);
+     int IsLineEndPoint(int pn);
+     int LineEndPointsSet() const {return lineendpoints.Size() == GetNP();}
+     void ClearLineEndPoints();
+diff -Naur netgen-6.2.2101_SRC_orig/libsrc/stlgeom/stltopology.hpp netgen-6.2.2101_SRC_modif/libsrc/stlgeom/stltopology.hpp
+--- netgen-6.2.2101_SRC_orig/libsrc/stlgeom/stltopology.hpp    2021-03-26 15:27:44.000000000 +0300
++++ netgen-6.2.2101_SRC_modif/libsrc/stlgeom/stltopology.hpp   2021-10-05 14:45:13.980762200 +0300
+@@ -342,7 +342,7 @@
+   int GetNP() const { return points.Size(); }
+   int AddPoint(const Point<3> & p) { points.Append(p); return points.Size(); }
+   const Point<3> & GetPoint(STLPointId nr) const { return points[nr]; } // .Get(nr); }
+-  int GetPointNum (const Point<3> & p);
++  DLL_HEADER int GetPointNum (const Point<3> & p);
+   void SetPoint(STLPointId nr, const Point<3> & p) { points[nr] = p; } // { points.Elem(nr) = p; }
+   auto & GetPoints() const { return points; }
+diff -Naur netgen-6.2.2101_SRC_orig/nglib/nglib.cpp netgen-6.2.2101_SRC_modif/nglib/nglib.cpp
+--- netgen-6.2.2101_SRC_orig/nglib/nglib.cpp   2021-09-21 17:05:14.000000000 +0300
++++ netgen-6.2.2101_SRC_modif/nglib/nglib.cpp  2021-10-05 14:55:59.205412900 +0300
+@@ -550,7 +550,7 @@
+    NgArray<STLReadTriangle> readtrias; //only before initstlgeometry
+-   NgArray<Point<3> > readedges; //only before init stlgeometry
++   DLL_HEADER NgArray<Point<3> > readedges; //only before init stlgeometry
+    // loads geometry from STL file
+    DLL_HEADER Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary)
diff --git a/products/patches/netgen62ForSalome_windows.patch b/products/patches/netgen62ForSalome_windows.patch
new file mode 100644 (file)
index 0000000..ba90e61
--- /dev/null
@@ -0,0 +1,293 @@
+diff --git a/libsrc/occ/occgenmesh.cpp b/libsrc/occ/occgenmesh.cpp
+index 314d405a..7c912bcc 100644
+--- a/libsrc/occ/occgenmesh.cpp
++++ b/libsrc/occ/occgenmesh.cpp
+@@ -49,7 +49,7 @@ namespace netgen
+   double ComputeH (double kappa, const MeshingParameters & mparam)
+   {
+     kappa *= mparam.curvaturesafety;
+-    /*
++    /**/
+     double hret;
+     if (mparam.maxh * kappa < 1)
+@@ -61,7 +61,7 @@ namespace netgen
+       hret = mparam.maxh;
+     return hret;
+-    */
++    /**/
+     // return min(mparam.maxh, 1/kappa);
+     return (mparam.maxh*kappa < 1) ? mparam.maxh : 1/kappa;
+   }
+@@ -253,10 +253,12 @@ namespace netgen
+       {
+         oldpnt = pnt;
+         pnt = c->Value(s0+(i/double(DIVIDEEDGESECTIONS))*(s1-s0));
++        // !!! no more than 1 segment per <edge length>/DIVIDEEDGESECTIONS
+         hvalue[i] = hvalue[i-1] +
+-          1.0/mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))*
+-          pnt.Distance(oldpnt);
++          min( 1.0,
++               1.0/mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))*
++               pnt.Distance(oldpnt));
+         //(*testout) << "mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z())) " << mesh.GetH(Point3d(pnt.X(), pnt.Y(), pnt.Z()))
+         //       <<  " pnt.Distance(oldpnt) " << pnt.Distance(oldpnt) << endl;
+@@ -299,7 +301,7 @@ namespace netgen
+         cout << "CORRECTED" << endl;
+         ps.SetSize (nsubedges-2);
+         params.SetSize (nsubedges);
+-        params[nsubedges] = s1;
++        params[nsubedges-1] = s1;
+       }
+   }
+@@ -323,6 +325,8 @@ namespace netgen
+     double eps = 1e-6 * geom.GetBoundingBox().Diam();
++    int first_vp = mesh.GetNP()+1;
++
+     tsearch.Start();
+     for (int i = 1; i <= nvertices; i++)
+       {
+@@ -481,22 +485,107 @@ namespace netgen
+                 if (!merge_solids)
+                   {
+-                    pnums[0] = geom.vmap.FindIndex (TopExp::FirstVertex (edge)) + PointIndex::BASE-1;
+-                    pnums.Last() = geom.vmap.FindIndex (TopExp::LastVertex (edge)) + PointIndex::BASE-1;
++                    //pnums[0] = geom.vmap.FindIndex (TopExp::FirstVertex (edge)) + PointIndex::BASE-1;
++                    //pnums.Last() = geom.vmap.FindIndex (TopExp::LastVertex (edge)) + PointIndex::BASE-1;
++                    const int dpi = PointIndex::BASE-1;
++                    MeshPoint dfltP ( Point<3> ( 0, 0, 0 ) );
++                    PointIndex *ipp[] = { &pnums[0], &pnums.Last() };
++                    TopoDS_Iterator vIt( edge, false );
++                    TopoDS_Vertex v[2];
++                    v[0] = TopoDS::Vertex( vIt.Value() ); vIt.Next();
++                    v[1] = TopoDS::Vertex( vIt.Value() );
++                    if ( v[0].Orientation() == TopAbs_REVERSED )
++                      std::swap( v[0], v[1] );
++                    for ( int i = 0; i < 2; ++i)
++                    {
++                      PointIndex &ip = *ipp[i];
++                      ip = geom.vmap.FindIndex ( v[i] ) + dpi;
++                      if ( ip == dpi || ip > nvertices + dpi )
++                      {
++                        PointIndex iv = ip;
++                        if ( ip == dpi )
++                          ip = iv = const_cast<OCCGeometry&>(geom).vmap.Add( v[i] );
++                        gp_Pnt pnt = BRep_Tool::Pnt( v[i] );
++                        MeshPoint mp( Point<3>(pnt.X(), pnt.Y(), pnt.Z()) );
++                        for (PointIndex pi = 1; pi < first_vp; pi++)
++                          if ( Dist2 (mesh.Point(pi), Point<3>(mp)) < 1e-100 )
++                          {
++                            ip = pi;
++                            if ( mesh.Point(ip).GetLayer() != dfltP.GetLayer() && mesh.Point(ip).GetLayer() != iv )
++                              continue;
++                            if ( mesh.Point(ip).GetLayer() == dfltP.GetLayer())
++                              mesh.Point(ip) = MeshPoint( mesh.Point(ip), iv );
++                            break;
++                          }
++                      }
++                      else
++                      {
++                        ip += first_vp - 1;
++                      }
++                    }
+                   }
+                 else
+                   {
+-                    Point<3> fp = occ2ng (BRep_Tool::Pnt (TopExp::FirstVertex (edge)));
+-                    Point<3> lp = occ2ng (BRep_Tool::Pnt (TopExp::LastVertex (edge)));
++                    TopoDS_Iterator vIt( edge, false );
++                    TopoDS_Vertex v1 = TopoDS::Vertex( vIt.Value() ); vIt.Next();
++                    TopoDS_Vertex v2 = TopoDS::Vertex( vIt.Value() );
++                    if ( v1.Orientation() == TopAbs_REVERSED )
++                      std::swap( v1, v2 );
++                    const bool isClosedEdge = v1.IsSame( v2 );
++
++                    Point<3> fp = occ2ng (BRep_Tool::Pnt (v1));
++                    Point<3> lp = occ2ng (BRep_Tool::Pnt (v2));
++                    double tol2 = std::min( eps*eps, 1e-6 * Dist2( fp, lp ));
++                    if ( isClosedEdge )
++                      tol2 = BRep_Tool::Tolerance( v1 ) * BRep_Tool::Tolerance( v1 );
+                     pnums[0] = PointIndex::INVALID;
+                     pnums.Last() = PointIndex::INVALID;
+                     for (PointIndex pi : vertexrange)
+                       {
+-                        if (Dist2 (mesh[pi], fp) < eps*eps) pnums[0] = pi;
+-                        if (Dist2 (mesh[pi], lp) < eps*eps) pnums.Last() = pi;
++                        if (Dist2 (mesh[pi], fp) < tol2) pnums[0] = pi;
++                        if (Dist2 (mesh[pi], lp) < tol2) pnums.Last() = pi;
+                       }
+-                  }
++                    if (( isClosedEdge && pnums[0] != pnums.Last() ) ||
++                        ( !isClosedEdge && pnums[0] == pnums.Last() ))
++                      pnums[0] = pnums.Last() = PointIndex::INVALID;
++                    if ( pnums[0] < PointIndex::BASE || pnums.Last() < PointIndex::BASE )
++                    {
++                      // take into account a possible large gap between a vertex and an edge curve
++                      // end and a large vertex tolerance covering the whole edge
++                      if ( pnums[0] < PointIndex::BASE )
++                      {
++                        double tol = BRep_Tool::Tolerance( v1 );
++                        for (PointIndex pi = 1; pi < first_ep; pi++)
++                          if (pi != pnums.Last() && Dist2 (mesh[pi], fp) < 2*tol*tol)
++                            pnums[0] = pi;
++
++                        if ( pnums[0] < PointIndex::BASE )
++                          pnums[0] = first_ep-1 - nvertices + geom.vmap.FindIndex ( v1 );
++                      }
++                      if ( isClosedEdge )
++                      {
++                        pnums.Last() = pnums[0];
++                      }
++                      else
++                      {
++                        if ( pnums.Last() < PointIndex::BASE )
++                        {
++                          double tol = BRep_Tool::Tolerance( v2 );
++                          for (PointIndex pi = 1; pi < first_ep; pi++)
++                            if (pi != pnums[0] && Dist2 (mesh[pi], lp) < 2*tol*tol)
++                              pnums.Last() = pi;
++
++                          if ( pnums.Last() < PointIndex::BASE )
++                            pnums.Last() = first_ep-1-nvertices + geom.vmap.FindIndex ( v2 );
++                        }
++
++                        if ( Dist2( fp, mesh[PointIndex(pnums[0])]) >
++                             Dist2( lp, mesh[PointIndex(pnums.Last())]))
++                          std::swap( pnums[0], pnums.Last() );
++                      }
++                    }
++                 }
+                 for (size_t i = 1; i <= mp.Size(); i++)
+                   {
+@@ -505,17 +594,19 @@ namespace netgen
+                     // for (PointIndex j = first_ep; j < mesh.Points().End(); j++)
+                     for (PointIndex j = first_ep; j < *mesh.Points().Range().end(); j++)
++                    {
++                      if (!merge_solids && mesh.Point(j).GetLayer() != geomedgenr ) continue;
+                       if ((mesh.Point(j)-Point<3>(mp[i-1])).Length() < eps)
+                         {
+                           exists = true;
+                           pnums[i] = j;
+                           break;
+                         }
+-                      
++                    }
+                     tsearch.Stop();
+                     
+                     if (!exists)
+-                      pnums[i] = mesh.AddPoint (mp[i-1]);
++                      pnums[i] = mesh.AddPoint (mp[i-1], geomedgenr);
+                   }
+                 if(geom.enames.Size() && geom.enames[curr-1] != "")
+                   mesh.SetCD2Name(geomedgenr, geom.enames[curr-1]);
+@@ -599,6 +690,9 @@ namespace netgen
+     //                                << " p1 " << mesh.LineSegment(i)[0] << " p2 " << mesh.LineSegment(i)[1] << endl;
+     //        exit(10);
++    for (int j = 1; j <= mesh.GetNP(); j++) // support SALOME fuse edges: set level to zero
++      mesh.Point(j) = MeshPoint( (Point<3>&) mesh.Point(j) );
++
+     mesh.CalcSurfacesOfNode();
+     multithread.task = savetask;
+   }
+@@ -652,7 +746,7 @@ namespace netgen
+         Box<3> bb = geom.GetBoundingBox();
+-        int projecttype = PLANESPACE;
++        //int projecttype = PLANESPACE;
+         
+         static Timer tinit("init");
+         tinit.Start();
+diff --git a/libsrc/occ/occmeshsurf.cpp b/libsrc/occ/occmeshsurf.cpp
+index 7fa5d237..9e05fd95 100644
+--- a/libsrc/occ/occmeshsurf.cpp
++++ b/libsrc/occ/occmeshsurf.cpp
+@@ -173,50 +173,6 @@ namespace netgen
+       gp_Vec du, dv;
+       occface->D1 (geominfo1.u, geominfo1.v, pnt, du, dv);
+-        // static Timer t("occ-defintangplane calculations");
+-        // RegionTimer reg(t);
+-
+-        Mat<3,2> D1_;
+-      D1_(0,0) = du.X(); D1_(1,0) = du.Y(); D1_(2,0) = du.Z();
+-      D1_(0,1) = dv.X(); D1_(1,1) = dv.Y(); D1_(2,1) = dv.Z();
+-        auto D1T_ = Trans(D1_);
+-      auto D1TD1_ = D1T_*D1_;
+-      if (Det (D1TD1_) == 0) throw SingularMatrixException();
+-        Mat<2,2> DDTinv_;
+-        CalcInverse (D1TD1_, DDTinv_);
+-
+-        Mat<3,2> Y_;
+-      Vec<3> y1_ = (ap2-ap1).Normalize();
+-      Vec<3> y2_ = Cross(n, y1_).Normalize();
+-      for (int i = 0; i < 3; i++)
+-        {
+-          Y_(i,0) = y1_(i);
+-          Y_(i,1) = y2_(i);
+-        }
+-
+-        auto A_ = DDTinv_ * D1T_ * Y_;
+-      Mat<2,2> Ainv_;
+-      if (Det(A_) == 0) throw SingularMatrixException();
+-      CalcInverse (A_, Ainv_);
+-
+-      Vec<2> temp_ = Ainv_ * (psp2-psp1);
+-      double r_ = temp_.Length();
+-        Mat<2,2> R_;
+-        R_(0,0) = temp_(0)/r_;
+-        R_(1,0) = temp_(1)/r_;
+-        R_(0,1) = -R_(1,0);
+-        R_(1,1) = R_(0,0);
+-
+-        A_ = A_ * R_;
+-        Ainv_ = Trans(R_) * Ainv_;
+-
+-        Amat = A_;
+-        Amatinv = Ainv_;
+-        
+-      // temp = Amatinv * (psp2-psp1);
+-        
+-
+-#ifdef OLD
+       DenseMatrix D1(3,2), D1T(2,3), DDTinv(2,2);
+       D1(0,0) = du.X(); D1(1,0) = du.Y(); D1(2,0) = du.Z();
+       D1(0,1) = dv.X(); D1(1,1) = dv.Y(); D1(2,1) = dv.Z();
+@@ -289,8 +245,7 @@ namespace netgen
+           }
+         // cout << "=?= Ainv = " << endl << Ainv << endl;
+       temp = Amatinv * (psp2-psp1);
+-        cout << " =?= Amatinv = " << Amatinv << endl;        
+-#endif
++        // cout << " =?= Amatinv = " << Amatinv << endl;        
+       };
+  
+   }
+@@ -380,6 +335,7 @@ namespace netgen
+     double u = gi.u;
+     double v = gi.v;
++    if ( 0 ) { // exclude Newton's method
+     gp_Pnt x = occface->Value (u,v);
+     if (p.SquareDistance(x) <= sqr(PROJECTION_TOLERANCE)) return;
+@@ -429,7 +385,7 @@ namespace netgen
+           }
+       }
+     while (count < 20);
+-    
++    }    
+     // Newton did not converge, use OCC projection