]> OCCT Git - occt-copy.git/commitdiff
0028379: BRepMesh produces mangled mesh for a cone
authoroan <oan@opencascade.com>
Fri, 2 Nov 2018 13:50:47 +0000 (16:50 +0300)
committerapn <apn@opencascade.com>
Tue, 13 Nov 2018 12:45:19 +0000 (15:45 +0300)
Split seam edge of a cone according to the specified parameters.
Seam edge functor is called before check of triangulation consistency in order to keep face status consistent.
The cause is that split seam edge can set Outdated flag when Reused is set by another functor without reset which can lead to refusement of such face by triangulation procedure.
Fix compilation error on VS2008

src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx
src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx
src/BRepMesh/BRepMesh_ModelPreProcessor.cxx
tests/bugs/mesh/bug25042

index 8900fa870b9f786b5b26b13b54cf75ff446220dd..da28dd093c11c618c1c382c00cffde020839e289 100644 (file)
 #include <GCPnts_TangentialDeflection.hxx>
 
 //=======================================================================
-// Function: GenerateSurfaceNodes
+// Function: GetSplitSteps
 // Purpose : 
 //=======================================================================
-Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes(
-  const IMeshTools_Parameters& theParameters) const
+std::pair<Standard_Real, Standard_Real> BRepMesh_ConeRangeSplitter::GetSplitSteps(
+  const IMeshTools_Parameters&                   theParameters,    
+  std::pair<Standard_Integer, Standard_Integer>& theStepsNb) const
 {
   const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
   const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
@@ -43,15 +44,33 @@ Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes(
   Du = aDiffU / (nbU + 1);
   Dv = aDiffV / (nbV + 1);
 
+  theStepsNb.first  = nbU;
+  theStepsNb.second = nbV;
+  return std::make_pair (Du, Dv);
+}
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose : 
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes(
+  const IMeshTools_Parameters& theParameters) const
+{
+  const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+  const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+
+  std::pair<Standard_Integer, Standard_Integer> aStepsNb;
+  std::pair<Standard_Real, Standard_Real> aSteps = GetSplitSteps (theParameters, aStepsNb);
+
   const Handle(NCollection_IncAllocator) aTmpAlloc =
     new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
   Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
 
-  const Standard_Real aPasMaxV = aRangeV.second - Dv*0.5;
-  const Standard_Real aPasMaxU = aRangeU.second - Du*0.5;
-  for (Standard_Real aPasV = aRangeV.first + Dv; aPasV < aPasMaxV; aPasV += Dv)
+  const Standard_Real aPasMaxV = aRangeV.second - aSteps.second*0.5;
+  const Standard_Real aPasMaxU = aRangeU.second - aSteps.first *0.5;
+  for (Standard_Real aPasV = aRangeV.first + aSteps.second; aPasV < aPasMaxV; aPasV += aSteps.second)
   {
-    for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du)
+    for (Standard_Real aPasU = aRangeU.first + aSteps.first; aPasU < aPasMaxU; aPasU += aSteps.first)
     {
       aNodes->Append(gp_Pnt2d(aPasU, aPasV));
     }
index 779c1cadad1a94ae9552a43eff9bab86109e157a..e9abf42fec75134c52a78032cd70486494d65993 100644 (file)
@@ -35,6 +35,13 @@ public:
   {
   }
 
+  //! Returns split intervals along U and V direction.
+  //! @param theParameters meshing parameters.
+  //! @param[out] theStepsNb number of steps along corresponding direction. 
+  std::pair<Standard_Real, Standard_Real> GetSplitSteps(
+    const IMeshTools_Parameters&                   theParameters,    
+    std::pair<Standard_Integer, Standard_Integer>& theStepsNb) const;
+
   //! Returns list of nodes generated using surface data and specified parameters.
   Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
     const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
index a583a9997eaa51797effa5f4840ae2283334a7e7..7ec3d4040cffd3a2b7d71d2b954361e57e3fad9d 100644 (file)
@@ -21,6 +21,7 @@
 #include <IMeshData_Wire.hxx>
 #include <IMeshData_PCurve.hxx>
 #include <OSD_Parallel.hxx>
+#include <BRepMesh_ConeRangeSplitter.hxx>
 
 namespace
 {
@@ -88,6 +89,137 @@ namespace
 
     Handle(IMeshData_Model) myModel;
   };
+
+  //! Adds additional points to seam edges on specific surfaces.
+  class SeamEdgeAmplifier
+  {
+  public:
+    //! Constructor
+    SeamEdgeAmplifier(const Handle(IMeshData_Model)& theModel,
+                      const IMeshTools_Parameters&   theParameters)
+      : myModel (theModel)
+      , myParameters (theParameters)
+    {
+    }
+
+    //! Main functor.
+    void operator()(const Standard_Integer theFaceIndex) const
+    {
+      const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
+      if (aDFace->GetSurface()->GetType() != GeomAbs_Cone)
+      {
+        return;
+      }
+
+      const IMeshData::IWireHandle& aDWire = aDFace->GetWire (0);
+      for (Standard_Integer aEdgeIdx = 0; aEdgeIdx < aDWire->EdgesNb() - 1; ++aEdgeIdx)
+      {
+        const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIdx);
+        
+        if (aDEdge->GetPCurve(aDFace.get(), TopAbs_FORWARD) != aDEdge->GetPCurve(aDFace.get(), TopAbs_REVERSED))
+        {
+          if (aDEdge->GetCurve()->ParametersNb() == 2)
+          {
+            if (splitEdge (aDEdge, Abs (getConeStep (aDFace))))
+            {
+              TopLoc_Location aLoc;
+              const Handle (Poly_Triangulation)& aTriangulation =
+                BRep_Tool::Triangulation (aDFace->GetFace (), aLoc);
+
+              if (!aTriangulation.IsNull ())
+              {
+                aDFace->SetStatus (IMeshData_Outdated);
+              }
+            }
+          }
+          return;
+        } 
+      }
+    }
+
+  private:
+
+    //! Returns step for splitting seam edge of a cone.
+    Standard_Real getConeStep(const IMeshData::IFaceHandle& theDFace) const
+    {
+      BRepMesh_ConeRangeSplitter aSplitter;
+      aSplitter.Reset (theDFace, myParameters);
+
+      const IMeshData::IWireHandle& aDWire = theDFace->GetWire (0);
+      for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
+      {
+        const IMeshData::IEdgeHandle    aDEdge  = aDWire->GetEdge(aEdgeIt);
+        const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
+          theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
+
+        for (Standard_Integer aPointIt = 0; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
+        {
+          const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
+          aSplitter.AddPoint(aPnt2d);
+        }
+      }
+
+      std::pair<Standard_Integer, Standard_Integer> aStepsNb;
+      std::pair<Standard_Real, Standard_Real> aSteps = aSplitter.GetSplitSteps (myParameters, aStepsNb);
+      return aSteps.second;
+    } 
+
+    //! Splits 3D and all pcurves accoring using the specified step.
+    Standard_Boolean splitEdge(const IMeshData::IEdgePtr& theDEdge,
+                               const Standard_Real        theDU) const
+    {
+      if (!splitCurve<gp_XYZ> (theDEdge->GetCurve (), theDU))
+      {
+        return Standard_False;
+      }
+
+      for (Standard_Integer aPCurveIdx = 0; aPCurveIdx < theDEdge->PCurvesNb(); ++aPCurveIdx)
+      {
+        splitCurve<gp_XY> (theDEdge->GetPCurve (aPCurveIdx), theDU);
+      }
+
+      return Standard_True;
+    }
+
+    //! Splits the given curve using the specified step.
+    template<class PointType, class Curve>
+    Standard_Boolean splitCurve(Curve& theCurve, const Standard_Real theDU) const
+    {
+      Standard_Boolean isUpdated = Standard_False;
+      PointType aDir = theCurve->GetPoint(theCurve->ParametersNb() - 1).Coord() - theCurve->GetPoint(0).Coord();
+      const Standard_Real aModulus = aDir.Modulus();
+      if (aModulus < gp::Resolution())
+      {
+        return isUpdated;
+      }
+      aDir /= aModulus;
+
+      const Standard_Real    aLastParam = theCurve->GetParameter(theCurve->ParametersNb() - 1);
+      const Standard_Boolean isReversed = theCurve->GetParameter(0) > aLastParam;  
+      for (Standard_Integer aPointIdx = 1; ; ++aPointIdx)
+      {
+        const Standard_Real aCurrParam = theCurve->GetParameter(0) + aPointIdx * theDU * (isReversed ? -1.0 : 1.0); 
+        if (( isReversed &&  (aCurrParam < aLastParam)) ||
+            (!isReversed && !(aCurrParam < aLastParam)))
+        {
+          break;
+        }
+
+        theCurve->InsertPoint(theCurve->ParametersNb() - 1,
+          theCurve->GetPoint(0).Translated (aDir * aPointIdx * theDU),
+          aCurrParam);
+
+        isUpdated = Standard_True;
+      }
+
+      return isUpdated;
+    }
+
+  private:
+
+    Handle(IMeshData_Model) myModel;
+    IMeshTools_Parameters   myParameters;
+  };
 }
 
 //=======================================================================
@@ -119,7 +251,8 @@ Standard_Boolean BRepMesh_ModelPreProcessor::Perform(
     return Standard_False;
   }
 
-  OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel);
+  OSD_Parallel::For(0, theModel->FacesNb(), SeamEdgeAmplifier(theModel, theParameters), !theParameters.InParallel);
+  OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel),         !theParameters.InParallel);
 
   // Clean edges and faces from outdated polygons.
   Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE));
index 6fa2292bbd211403c98a90cf872909f0b3520a0e..b44908d565ab478c1766225b869014493a1c2ff7 100644 (file)
@@ -1,6 +1,3 @@
-puts "TODO 0025042 All: Error: Number of triangles = 931 is not equal to expected 957"
-puts "TODO 0025042 All: Error: Number of nodes = 532 is not equal to expected 558"
-
 puts "=========="
 puts "0025042: Cone Meshing: Missing two connecting edges."
 puts "=========="