0028995: UnifySameDomain produces invalid shape
authoremv <emv@opencascade.com>
Fri, 18 Aug 2017 10:31:57 +0000 (13:31 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 30 Aug 2017 09:42:41 +0000 (12:42 +0300)
Synchronization of the ShapeAnalysis_Edge behavior with the BRepCheck_Edge by adding check for 2d curves on planes.

Implementation of the BRep_Tool::CurveOnPlane method to avoid code duplication for making PCurve of the edge on planar face.

src/BRep/BRep_Tool.cxx
src/BRep/BRep_Tool.hxx
src/ShapeAnalysis/ShapeAnalysis_Edge.cxx
tests/bugs/modalg_7/bug27004
tests/bugs/modalg_7/bug28995 [new file with mode: 0644]
tests/de/step_3/C5
tests/heal/unify_same_domain/B4
tests/heal/unify_same_domain/B5

index d87c2ca..9118d62 100644 (file)
@@ -321,8 +321,23 @@ Handle(Geom2d_Curve) BRep_Tool::CurveOnSurface(const TopoDS_Edge& E,
     itcr.Next();
   }
 
-  // for planar surface and 3d curve try a projection
-  // modif 21-05-97 : for RectangularTrimmedSurface, try a projection
+  // Curve is not found. Try projection on plane
+  return CurveOnPlane(E, S, L, First, Last);
+}
+
+//=======================================================================
+//function : CurveOnPlane
+//purpose  : For planar surface returns projection of the edge on the plane
+//=======================================================================
+Handle(Geom2d_Curve) BRep_Tool::CurveOnPlane(const TopoDS_Edge& E,
+                                             const Handle(Geom_Surface)& S,
+                                             const TopLoc_Location& L,
+                                             Standard_Real& First,
+                                             Standard_Real& Last)
+{
+  First = Last = 0.;
+
+  // Check if the surface is planar
   Handle(Geom_Plane) GP;
   Handle(Geom_RectangularTrimmedSurface) GRTS;
   GRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
@@ -330,64 +345,51 @@ Handle(Geom2d_Curve) BRep_Tool::CurveOnSurface(const TopoDS_Edge& E,
     GP = Handle(Geom_Plane)::DownCast(GRTS->BasisSurface());
   else
     GP = Handle(Geom_Plane)::DownCast(S);
-  //fin modif du 21-05-97
-
-  if (!GP.IsNull())
-  {
-    Handle(GeomAdaptor_HCurve) HC;
-    Handle(GeomAdaptor_HSurface) HS;
-
-    HC = new GeomAdaptor_HCurve();
-    HS = new GeomAdaptor_HSurface();
 
-    TopLoc_Location aCurveLocation;
+  if (GP.IsNull())
+    // not a plane
+    return nullPCurve;
 
-    Standard_Real f, l;// for those who call with (u,u).
-    Handle(Geom_Curve) C3d = BRep_Tool::Curve(E, aCurveLocation, f, l);
+  // Check existence of 3d curve in edge
+  Standard_Real f, l;
+  TopLoc_Location aCurveLocation;
+  Handle(Geom_Curve) C3D = BRep_Tool::Curve(E, aCurveLocation, f, l);
 
-    if (C3d.IsNull())
-    {
-      First = Last = 0.;
-      return nullPCurve;
-    }
-
-    aCurveLocation = aCurveLocation.Predivided(L);
-    First = f; Last = l; //Range of edge must not be modified
+  if (C3D.IsNull())
+    // no 3d curve
+    return nullPCurve;
 
-    if (!aCurveLocation.IsIdentity())
-    {
-      const gp_Trsf& T = aCurveLocation.Transformation();
-      Handle(Geom_Geometry) GC3d = C3d->Transformed(T);
-      C3d = Handle(Geom_Curve)::DownCast (GC3d);
-      f = C3d->TransformedParameter(f, T);
-      l = C3d->TransformedParameter(l, T);
-    }
-    GeomAdaptor_Surface& GAS = HS->ChangeSurface();
-    GAS.Load(GP);
+  aCurveLocation = aCurveLocation.Predivided(L);
+  First = f; Last = l;
 
-    Handle(Geom_Curve) ProjOnPlane = 
-      GeomProjLib::ProjectOnPlane(new Geom_TrimmedCurve(C3d,f,l,Standard_True,Standard_False),
-                                  GP,
-                                  GP->Position().Direction(),
-                                  Standard_True);
+  // Transform curve and update parameters in account of scale factor
+  if (!aCurveLocation.IsIdentity())
+  {
+    const gp_Trsf& aTrsf = aCurveLocation.Transformation();
+    C3D = Handle(Geom_Curve)::DownCast(C3D->Transformed(aTrsf));
+    f = C3D->TransformedParameter(f, aTrsf);
+    l = C3D->TransformedParameter(l, aTrsf);
+  }
 
-    GeomAdaptor_Curve& GAC = HC->ChangeCurve();
-    GAC.Load(ProjOnPlane);
+  // Perform projection
+  Handle(Geom_Curve) ProjOnPlane =
+    GeomProjLib::ProjectOnPlane(new Geom_TrimmedCurve(C3D, f, l, Standard_True, Standard_False),
+                                GP,
+                                GP->Position().Direction(),
+                                Standard_True);
 
-    ProjLib_ProjectedCurve Proj(HS,HC);
-    Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);
+  Handle(GeomAdaptor_HSurface) HS = new GeomAdaptor_HSurface(GP);
+  Handle(GeomAdaptor_HCurve)   HC = new GeomAdaptor_HCurve(ProjOnPlane);
 
-    if (pc->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
-      Handle(Geom2d_TrimmedCurve) TC = 
-        Handle(Geom2d_TrimmedCurve)::DownCast (pc);
-      pc = TC->BasisCurve();
-    }
+  ProjLib_ProjectedCurve Proj(HS, HC);
+  Handle(Geom2d_Curve) pc = Geom2dAdaptor::MakeCurve(Proj);
 
-    return pc;
+  if (pc->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
+    Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(pc);
+    pc = TC->BasisCurve();
   }
-  
-  First = Last = 0.;
-  return nullPCurve;
+
+  return pc;
 }
 
 //=======================================================================
@@ -438,35 +440,34 @@ void  BRep_Tool::CurveOnSurface(const TopoDS_Edge& E,
                                 Standard_Real& Last,
                                 const Standard_Integer Index)
 {
-  Standard_Integer i = 0;
-  Standard_Boolean Eisreversed = (E.Orientation() == TopAbs_REVERSED);
+  if (Index < 1)
+    return;
 
+  Standard_Integer i = 0;
   // find the representation
   const BRep_TEdge* TE = static_cast<const BRep_TEdge*>(E.TShape().get());
   BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
-
-  while (itcr.More()) {
+  for (; itcr.More(); itcr.Next())
+  {
     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
-    if (cr->IsCurveOnSurface()) {
+    if (cr->IsCurveOnSurface())
+    {
       const BRep_GCurve* GC = static_cast<const BRep_GCurve*>(cr.get());
-      i++;
-      if (i > Index) break;
-      if (i == Index) {
-        // JMB le 21 Mai 1999
-        // it is done as in the other CurveOnSurface methods, ie. take into account
-        // the orientation in case of cut edges (return PCurve2)
-        // otherwise there is a risk to loop curves or to not get the prover one.
-        if (GC->IsCurveOnClosedSurface() && Eisreversed)
-          C = GC->PCurve2();
-        else
-          C = GC->PCurve();
-        S = GC->Surface();
-        L = E.Location() * GC->Location();
-        GC->Range(First,Last);
-        return;
-      }
+      ++i;
+      // Compare index taking into account the fact that for the curves on
+      // closed surfaces there are two PCurves
+      if (i == Index)
+        C = GC->PCurve();
+      else if (GC->IsCurveOnClosedSurface() && (++i == Index))
+        C = GC->PCurve2();
+      else
+        continue;
+
+      S = GC->Surface();
+      L = E.Location() * GC->Location();
+      GC->Range(First, Last);
+      return;
     }
-    itcr.Next();
   }
   
   C.Nullify();
index 332db23..e81a3ef 100644 (file)
@@ -103,6 +103,16 @@ public:
   //! handle  if this curve does  not exist.  Returns in
   //! <First> and <Last> the parameter range.
   Standard_EXPORT static Handle(Geom2d_Curve) CurveOnSurface (const TopoDS_Edge& E, const Handle(Geom_Surface)& S, const TopLoc_Location& L, Standard_Real& First, Standard_Real& Last);
+
+  //! For the planar surface builds the 2d curve for the edge
+  //! by projection of the edge on plane.
+  //! Returns a NULL handle if the surface is not planar or
+  //! the projection failed.
+  Standard_EXPORT static Handle(Geom2d_Curve) CurveOnPlane (const TopoDS_Edge& E,
+                                                            const Handle(Geom_Surface)& S,
+                                                            const TopLoc_Location& L,
+                                                            Standard_Real& First,
+                                                            Standard_Real& Last);
   
   //! Returns in <C>, <S>, <L> a 2d curve, a surface and
   //! a location for the edge <E>. <C> and <S>  are null
index 1cde3aa..333a3c8 100644 (file)
@@ -800,93 +800,112 @@ Standard_Boolean ShapeAnalysis_Edge::CheckSameParameter (const TopoDS_Edge& edge
   if (BRep_Tool::Degenerated (edge)) return Standard_False;
 
   maxdev = 0;
-  
+
+  // Get same parameter flag
   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&edge.TShape());
   Standard_Boolean SameParameter = TE->SameParameter();
 
-  GeomAdaptor_Curve AC3d;
-
-  // find 3d curve
-  BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
-  for ( ; itcr.More(); itcr.Next() ) {
-    Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
-    if ( GC.IsNull() || ! GC->IsCurve3D() ) continue;
-    Handle(Geom_Curve) C3d = GC->Curve3D();
-    if ( C3d.IsNull() ) continue; //:s1 abv 22 Apr 99: PRO7226 #489490
-    TopLoc_Location loc = GC->Location();
-    if ( ! loc.IsIdentity() )
-      C3d = Handle(Geom_Curve)::DownCast ( C3d->Transformed ( loc ) );
-    else C3d = Handle(Geom_Curve)::DownCast ( C3d->Copy() ); //:s4 abv 26 Apr 99: sim6049.igs 21677: necessary to get True SP (!!?)
-    Standard_Real First, Last;
-    GC->Range ( First, Last );
-    AC3d.Load ( C3d, First, Last );
-    break;
-  }
-
-  if ( ! itcr.More() ) {
-    myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
+  // Get 3D curve of the edge
+  Standard_Real aFirst, aLast;
+  TopLoc_Location aCurveLoc;
+  Handle(Geom_Curve) aC3D = BRep_Tool::Curve(edge, aCurveLoc, aFirst, aLast);
+  if (aC3D.IsNull()) {
+    myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL1);
     return Standard_False;
   }
 
-  Handle(Geom_Surface) aFaceSurf;
-  TopLoc_Location L;
-  if ( !face.IsNull() )
+  if (!aCurveLoc.IsIdentity())
   {
-    aFaceSurf = BRep_Tool::Surface(face, L);
+    const gp_Trsf& aTrsf = aCurveLoc.Transformation();
+    aC3D = Handle(Geom_Curve)::DownCast(aC3D->Transformed(aTrsf));
+    aFirst = aC3D->TransformedParameter(aFirst, aTrsf);
+    aLast = aC3D->TransformedParameter(aLast, aTrsf);
   }
 
-  // iterate on pcurves
-  itcr.Initialize ( TE->Curves() );
-  for ( ; itcr.More(); itcr.Next() )
+  // Create adaptor for the curve
+  GeomAdaptor_Curve aGAC(aC3D, aFirst, aLast);
+
+  Handle(Geom_Surface) aFaceSurf;
+  TopLoc_Location aFaceLoc;
+  if (!face.IsNull())
+    aFaceSurf = BRep_Tool::Surface(face, aFaceLoc);
+
+  Standard_Boolean IsPCurveFound = Standard_False;
+  Standard_Integer i = 1;
+
+  // Iterate on all curve representations
+  for (;;)
   {
-    Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
-    if ( GC.IsNull() || ! GC->IsCurveOnSurface() ) continue;
+    Handle(Geom2d_Curve) aPC;
+    Handle(Geom_Surface) aS;
+    TopLoc_Location aLoc;
+    Standard_Real f, l;
+
+    BRep_Tool::CurveOnSurface(edge, aPC, aS, aLoc, f, l, i);
+
+    if (aPC.IsNull())
+      // No more curves
+      break;
+
+    ++i;
 
-    if ( !(face.IsNull()) ) // Face is not null.
+    // If the input face is not null, check that the curve is on its surface
+    if (!aFaceSurf.IsNull())
     {
-      // Check for different surface.
-      if (!GC->IsCurveOnSurface(aFaceSurf, GC->Location()))
+      if (aFaceSurf != aS || aFaceLoc != aLoc)
+      {
         continue;
+      }
     }
 
-    Standard_Real f, l;
-    GC->Range ( f, l );
-    Handle(Geom_Surface) Su = GC->Surface();
-    TopLoc_Location loc = GC->Location();
-    if (!loc.IsIdentity())
-      Su = Handle(Geom_Surface)::DownCast ( Su->Transformed ( loc ) );
-    Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(Su);
-    
-    Handle(Geom2d_Curve) PC = GC->PCurve();
-    Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(PC,f,l);
-    //Adaptor3d_CurveOnSurface ACS(GHPC,GAHS);
-    Adaptor3d_CurveOnSurface ACS;
-    ACS.Load(GHPC, GAHS);
-    if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) )
+    IsPCurveFound = Standard_True;
+
+    // Apply transformations for the surface
+    Handle(Geom_Surface) aST = Handle(Geom_Surface)::
+      DownCast(aS->Transformed(aLoc.Transformation()));
+
+    // Compute deviation between curves
+    Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(aPC, f, l);
+    Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(aST);
+
+    Adaptor3d_CurveOnSurface ACS(GHPC, GAHS);
+    if (!ComputeDeviation(aGAC, ACS, SameParameter, maxdev, NbControl - 1))
     {
       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
     }
+  }
 
-    if ( GC->IsCurveOnClosedSurface() )
+  // For the planar face and non-existing  2d curve
+  // check the deviation for the projection of the 3d curve on plane
+  if (!IsPCurveFound && !aFaceSurf.IsNull())
+  {
+    Standard_Real f, l;
+    Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnPlane(edge, aFaceSurf, aFaceLoc, f, l);
+    if (!aPC.IsNull())
     {
-      GHPC->ChangeCurve2d().Load ( GC->PCurve2(), f, l ); // same bounds
-      ACS.Load(GHPC, GAHS); // sans doute inutile
-      if ( ! ComputeDeviation ( AC3d, ACS, SameParameter, maxdev, NbControl-1 ) )
+      Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve(aPC, aFirst, aLast);
+
+      Handle(Geom_Surface) aST =
+        Handle(Geom_Surface)::DownCast(aFaceSurf->Transformed(aFaceLoc.Transformation()));
+      Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(aST);
+
+      Adaptor3d_CurveOnSurface ACS(GHPC, GAHS);
+
+      if (!ComputeDeviation(aGAC, ACS, SameParameter, maxdev, NbControl - 1))
       {
-        myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
+        myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL2);
       }
     }
   }
-  
-  if ( maxdev > TE->Tolerance() ) 
-    myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
-  if ( ! SameParameter ) 
-    myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
+
+  if (maxdev > TE->Tolerance())
+    myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
+  if (!SameParameter)
+    myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
 
   return Status ( ShapeExtend_DONE );
 }
 
-
 //=======================================================================
 //function : IsOverlapPartEdges
 //purpose  : 
index 486efaa..b3b20f5 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC27004 ALL: Faulty shapes in variables faulty_1 to"
-
 puts "========"
 puts "OCC27004"
 puts "========"
@@ -26,4 +24,7 @@ unifysamedom result r
 
 checkshape result
 
+checknbshapes result -vertex 12 -edge 18 -wire 8 -face 8 -solid 1
+checkprops result -s 223704 -v 3.27888e+006
+
 checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug28995 b/tests/bugs/modalg_7/bug28995
new file mode 100644 (file)
index 0000000..82e0f17
--- /dev/null
@@ -0,0 +1,35 @@
+puts "======="
+puts "0028995"
+puts "======="
+puts ""
+##################################################
+# UnifySameDomain produces invalid shape
+##################################################
+
+brestore [locate_data_file bug28995_s1.brep] s1
+brestore [locate_data_file bug28995_s2.brep] s2
+
+# perform fuse operation
+bfuse rfuse s1 s2
+
+# check the result of fuse
+checkshape rfuse 
+
+if {![regexp "This shape seems to be OK" [bopcheck rfuse]]} {
+  puts "Error: The result of FUSE operation is a self-intersecting shape."
+}
+
+# unify faces and edges in the fused shape
+unifysamedom result rfuse
+
+# check unified result
+checkshape result
+
+if {![regexp "This shape seems to be OK" [bopcheck result]]} {
+  puts "Error: The result of UnifySameDomain algorithm is a self-intersecting shape."
+}
+
+checknbshapes result -vertex 200 -edge 300 -wire 104 -face 103 -solid 1
+checkprops result -s 1.59154e+006 -v 1.1497e+007
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index c990ac4..06365ff 100644 (file)
@@ -1,5 +1,3 @@
-# !!!! This file is generated automatically, do not edit manually! See end script
-puts "TODO CR23096 ALL: CHECKSHAPE : Faulty" 
 puts "TODO CR23096 ALL: STATSHAPE : Faulty" 
 
 
index 7c8139a..de31b2f 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC28995 ALL: Faulty shapes"
-
 puts "======="
 puts "0028913"
 puts "======="
index 3599e69..4a65cef 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC28995 ALL: Faulty shapes"
-
 puts "======="
 puts "0028913"
 puts "======="