0028995: UnifySameDomain produces invalid shape
[occt.git] / src / BRep / BRep_Tool.cxx
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();