Salome HOME
0021031: EDF 1646 GEOM: Modify Location leads to Position driver failed
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
index 8ae11d5f007b84ad2c6eb7ec88a06ded95018870..54d149b3a625b3fca8706082fe915d45f14c576c 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -18,6 +18,7 @@
 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include <GEOMImpl_ShapeDriver.hxx>
 
@@ -30,6 +31,7 @@
 // OCCT Includes
 #include <ShapeFix_Wire.hxx>
 #include <ShapeFix_Edge.hxx>
+#include <ShapeFix_Shape.hxx>
 
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
 #include <BRepClass3d_SolidClassifier.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <BRepBuilderAPI_Sewing.hxx>
+#include <BRepLib.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <BRepAdaptor_Curve.hxx>
 
 #include <ShapeAnalysis_FreeBounds.hxx>
+#include <ElCLib.hxx>
 
 #include <TopAbs.hxx>
 #include <TopoDS.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_HSequenceOfShape.hxx>
 
+#include <TColStd_SequenceOfReal.hxx>
 #include <TColStd_HSequenceOfTransient.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <TColGeom_Array1OfBSplineCurve.hxx>
+#include <TColGeom_HArray1OfBSplineCurve.hxx>
+
+#include <GeomAbs_CurveType.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomConvert_CompCurveToBSplineCurve.hxx>
+#include <GeomConvert.hxx>
+#include <GeomLProp.hxx>
 
 #include <Precision.hxx>
 #include <Standard_NullObject.hxx>
@@ -103,92 +121,66 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
 
   if (aType == WIRE_EDGES) {
     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
-    unsigned int ind, nbshapes = aShapes->Length();
-
     TopoDS_Wire aWire;
     B.MakeWire(aWire);
-    BRepBuilderAPI_MakeWire MW;
-    bool isMWDone = true;
 
     // add edges
-    for (ind = 1; ind <= nbshapes; ind++) {
+    for (unsigned int ind = 1; ind <= aShapes->Length(); ind++) {
       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
       TopoDS_Shape aShape_i = aRefShape->GetValue();
       if (aShape_i.IsNull()) {
         Standard_NullObject::Raise("Shape for wire construction is null");
       }
-      if (aShape_i.ShapeType() == TopAbs_EDGE) {
-        B.Add(aWire, TopoDS::Edge(aShape_i));
-        MW.Add(TopoDS::Edge(aShape_i));
-        if (!MW.IsDone()) {
-          // check status after each edge/wire addition, because the final status
-          // can be OK even in case, when some edges/wires was not accepted.
-          isMWDone = false;
-        }
-      } else if (aShape_i.ShapeType() == TopAbs_WIRE) {
-        TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
-        for (; exp.More(); exp.Next()) {
-          B.Add(aWire, TopoDS::Edge(exp.Current()));
-          MW.Add(TopoDS::Edge(exp.Current()));
-          if (!MW.IsDone()) {
-            // check status after each edge/wire addition, because the final status
-            // can be OK even in case, when some edges/wires was not accepted.
-            isMWDone = false;
-          }
-        }
-      } else {
-        Standard_TypeMismatch::Raise
-          ("Shape for wire construction is neither an edge nor a wire");
-      }
+     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
+       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
+       for (; exp.More(); exp.Next())
+         B.Add(aWire, TopoDS::Edge(exp.Current()));
+     } else {
+       Standard_TypeMismatch::Raise
+         ("Shape for wire construction is neither an edge nor a wire");
+     }
     }
 
-    if (isMWDone) {
-      aShape = MW;
+    // fix edges order
+    Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
+    aFW->Load(aWire);
+    aFW->FixReorder();
+    
+    if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
+      Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
+    } else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
+      Standard_ConstructionError::Raise("Wire construction failed");
     } else {
-      // fix edges order
-      Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
-      aFW->Load(aWire);
-      aFW->FixReorder();
-
-      if        (aFW->StatusReorder(ShapeExtend_FAIL1)) {
-        Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
-      } else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
-        Standard_ConstructionError::Raise("Wire construction failed");
-      //} else if (aFW->StatusReorder(ShapeExtend_DONE2)) {
-      //  Standard_ConstructionError::Raise("Wire construction failed: some gaps detected");
-      } else {
-      }
-
-      // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
-      Standard_Real aTolerance = aCI.GetTolerance();
-      if (aTolerance < Precision::Confusion())
-        aTolerance = Precision::Confusion();
+    }
 
-      aFW->ClosedWireMode() = Standard_False;
-      aFW->FixConnected(aTolerance);
-      if (aFW->StatusConnected(ShapeExtend_FAIL)) {
-        Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
-      }
-      // IMP 0019766
-      if (aFW->StatusConnected(ShapeExtend_DONE3)) {
-        // Confused with <prec> but not Analyzer.Precision(), set the same
-        aFW->FixGapsByRangesMode() = Standard_True;
-        if (aFW->FixGaps3d()) {
-          Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
-          Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
-          for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
-            TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
-            aFe->FixVertexTolerance(aEdge);
-            aFe->FixSameParameter(aEdge);
-          }
-        }
-        else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
-          Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
+    // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
+    Standard_Real aTolerance = aCI.GetTolerance();
+    if (aTolerance < Precision::Confusion())
+      aTolerance = Precision::Confusion();
+    
+    aFW->ClosedWireMode() = Standard_False;
+    aFW->FixConnected(aTolerance);
+    if (aFW->StatusConnected(ShapeExtend_FAIL)) {
+      Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
+    }
+    // IMP 0019766
+    if (aFW->StatusConnected(ShapeExtend_DONE3)) {
+      // Confused with <prec> but not Analyzer.Precision(), set the same
+      aFW->FixGapsByRangesMode() = Standard_True;
+      if (aFW->FixGaps3d()) {
+        Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
+        Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
+        for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
+          TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
+          aFe->FixVertexTolerance(aEdge);
+          aFe->FixSameParameter(aEdge);
         }
       }
-
-      aShape = aFW->WireAPIMake();
+      else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
+        Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
+      }
     }
+      aShape = aFW->WireAPIMake();
   }
   else if (aType == FACE_WIRE) {
     Handle(GEOM_Function) aRefBase = aCI.GetBase();
@@ -466,6 +458,342 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
       aShape = tds;
     }
   }
+  else if (aType == EDGE_WIRE) {
+    Handle(GEOM_Function) aRefBase = aCI.GetBase();
+    TopoDS_Shape aWire = aRefBase->GetValue();
+    Standard_Real LinTol = aCI.GetTolerance();
+    Standard_Real AngTol = aCI.GetAngularTolerance();
+    if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
+
+    TopoDS_Edge ResEdge;
+
+    BRepLib::BuildCurves3d(aWire);
+    Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
+    Fixer->SetPrecision(LinTol);
+    Fixer->SetMaxTolerance(LinTol);
+    Fixer->Perform();
+    TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
+
+    TColGeom_SequenceOfCurve CurveSeq;
+    TopTools_SequenceOfShape LocSeq;
+    TColStd_SequenceOfReal FparSeq;
+    TColStd_SequenceOfReal LparSeq;
+    TColStd_SequenceOfReal TolSeq;
+    GeomAbs_CurveType CurType;
+    TopoDS_Vertex FirstVertex, LastVertex;
+
+    BRepTools_WireExplorer wexp(theWire) ;
+    for (; wexp.More(); wexp.Next())
+    {
+      TopoDS_Edge anEdge = wexp.Current();
+      Standard_Real fpar, lpar;
+      TopLoc_Location aLoc;
+      Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
+      if (aCurve.IsNull())
+       continue;
+
+      BRepAdaptor_Curve BAcurve(anEdge);
+      GeomAbs_CurveType aType = BAcurve.GetType();
+
+      Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
+
+      if (aBasisCurve->IsPeriodic())
+       ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
+                              Precision::PConfusion(), fpar, lpar);
+
+      if (CurveSeq.IsEmpty())
+      {
+       CurveSeq.Append(aCurve);
+       TopoDS_Shape aLocShape;
+       aLocShape.Location(aLoc);
+       aLocShape.Orientation(wexp.Orientation());
+       LocSeq.Append(aLocShape);
+       FparSeq.Append(fpar);
+       LparSeq.Append(lpar);
+       CurType = aType;
+       FirstVertex = wexp.CurrentVertex();
+      }
+      else
+      {
+       Standard_Boolean Done = Standard_False;
+       Standard_Real NewFpar, NewLpar;
+       GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
+       TopoDS_Vertex CurVertex = wexp.CurrentVertex();
+       TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
+       TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
+       if (aCurve == CurveSeq.Last())
+       {
+         NewFpar = fpar;
+         NewLpar = lpar;
+         if (aBasisCurve->IsPeriodic())
+         {
+           if (NewLpar < NewFpar)
+             NewLpar += aBasisCurve->Period();
+           if (ConnectByOrigin == TopAbs_FORWARD)
+             ElCLib::AdjustPeriodic(FparSeq.Last(),
+                                    FparSeq.Last() + aBasisCurve->Period(),
+                                    Precision::PConfusion(), NewFpar, NewLpar);
+           else
+             ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
+                                    FparSeq.Last(),
+                                    Precision::PConfusion(), NewFpar, NewLpar);
+         }
+         Done = Standard_True;
+       }
+       else if (aType == CurType &&
+                aType != GeomAbs_BezierCurve &&
+                aType != GeomAbs_BSplineCurve &&
+                aType != GeomAbs_OtherCurve)
+       {
+         switch (aType)
+         {
+         case GeomAbs_Line:
+           {
+             gp_Lin aLine    = BAcurve.Line();
+             gp_Lin PrevLine = GAprevcurve.Line(); 
+             if (aLine.Contains(PrevLine.Location(), LinTol) &&
+                 aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
+             {
+               gp_Pnt P1 = ElCLib::Value(fpar, aLine);
+               gp_Pnt P2 = ElCLib::Value(lpar, aLine);
+               NewFpar = ElCLib::Parameter(PrevLine, P1);
+               NewLpar = ElCLib::Parameter(PrevLine, P2);
+               if (NewLpar < NewFpar)
+               {
+                 Standard_Real MemNewFpar = NewFpar;
+                 NewFpar = NewLpar;
+                 NewLpar = MemNewFpar;
+                 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
+               }
+               Done = Standard_True;
+             }
+             break;
+           }
+         case GeomAbs_Circle:
+           {
+             gp_Circ aCircle    = BAcurve.Circle();
+             gp_Circ PrevCircle = GAprevcurve.Circle();
+             if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
+                 Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
+                 aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
+             {
+               if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
+               {
+                 Standard_Real memfpar = fpar;
+                 fpar = lpar;
+                 lpar = memfpar;
+                 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
+               }
+               gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
+               gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
+               NewFpar = ElCLib::Parameter(PrevCircle, P1);
+               NewLpar = ElCLib::Parameter(PrevCircle, P2);
+               if (NewLpar < NewFpar)
+                 NewLpar += 2.*PI;
+               //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
+               if (ConnectByOrigin == TopAbs_FORWARD)
+                 ElCLib::AdjustPeriodic(FparSeq.Last(),
+                                        FparSeq.Last() + 2.*PI,
+                                        Precision::PConfusion(), NewFpar, NewLpar);
+               else
+                 ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*PI,
+                                        FparSeq.Last(),
+                                        Precision::PConfusion(), NewFpar, NewLpar);
+               Done = Standard_True;
+             }
+             break;
+           }
+         case GeomAbs_Ellipse:
+           {
+             gp_Elips anEllipse   = BAcurve.Ellipse();
+             gp_Elips PrevEllipse = GAprevcurve.Ellipse();
+             if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
+                 anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
+                 Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
+                 Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
+                 anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
+             {
+               if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
+               {
+                 Standard_Real memfpar = fpar;
+                 fpar = lpar;
+                 lpar = memfpar;
+                 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
+               }
+               gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
+               gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
+               NewFpar = ElCLib::Parameter(PrevEllipse, P1);
+               NewLpar = ElCLib::Parameter(PrevEllipse, P2);
+               if (NewLpar < NewFpar)
+                 NewLpar += 2.*PI;
+               if (ConnectByOrigin == TopAbs_FORWARD)
+                 ElCLib::AdjustPeriodic(FparSeq.Last(),
+                                        FparSeq.Last() + 2.*PI,
+                                        Precision::PConfusion(), NewFpar, NewLpar);
+               else
+                 ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*PI,
+                                        FparSeq.Last(),
+                                        Precision::PConfusion(), NewFpar, NewLpar);
+               Done = Standard_True;
+             }
+             break;
+           }
+         case GeomAbs_Hyperbola:
+           {
+             gp_Hypr aHypr    = BAcurve.Hyperbola();
+             gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
+             if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
+                 aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
+                 Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
+                 Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
+                 aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
+             {
+               gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
+               gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
+               NewFpar = ElCLib::Parameter(PrevHypr, P1);
+               NewLpar = ElCLib::Parameter(PrevHypr, P2);
+               if (NewLpar < NewFpar)
+               {
+                 Standard_Real MemNewFpar = NewFpar;
+                 NewFpar = NewLpar;
+                 NewLpar = MemNewFpar;
+                 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
+               }
+               Done = Standard_True;
+             }
+             break;
+           }
+         case GeomAbs_Parabola:
+           {
+             gp_Parab aParab    = BAcurve.Parabola();
+             gp_Parab PrevParab = GAprevcurve.Parabola();
+             if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
+                 aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
+                 Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
+                 aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
+             {
+               gp_Pnt P1 = ElCLib::Value(fpar, aParab);
+               gp_Pnt P2 = ElCLib::Value(lpar, aParab);
+               NewFpar = ElCLib::Parameter(PrevParab, P1);
+               NewLpar = ElCLib::Parameter(PrevParab, P2);
+               if (NewLpar < NewFpar)
+               {
+                 Standard_Real MemNewFpar = NewFpar;
+                 NewFpar = NewLpar;
+                 NewLpar = MemNewFpar;
+                 ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
+               }
+               Done = Standard_True;
+             }
+             break;
+           }
+         } //end of switch (aType)
+       } // end of else if (aType == CurType && ...
+       if (Done)
+       {
+         if (NewFpar < FparSeq.Last())
+           FparSeq(FparSeq.Length()) = NewFpar;
+         else
+           LparSeq(LparSeq.Length()) = NewLpar;
+       }
+       else
+       {
+         CurveSeq.Append(aCurve);
+         TopoDS_Shape aLocShape;
+         aLocShape.Location(aLoc);
+         aLocShape.Orientation(wexp.Orientation());
+         LocSeq.Append(aLocShape);
+         FparSeq.Append(fpar);
+         LparSeq.Append(lpar);
+         TolSeq.Append(BRep_Tool::Tolerance(CurVertex));
+         CurType = aType;
+       }
+      } // end of else (CurveSeq.IsEmpty()) -> not first time
+    } // end for (; wexp.More(); wexp.Next())
+
+    LastVertex = wexp.CurrentVertex();
+    TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
+
+    if (!CurveSeq.IsEmpty())
+    {
+      Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
+      TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
+      TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
+      
+      Standard_Integer i;
+      
+      if (nb_curve > 1)
+      {
+       for (i = 1; i <= nb_curve; i++)
+       {
+         if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
+           CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
+         
+         Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
+         tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
+         tab(i-1)->Transform(LocSeq(i).Location().Transformation());
+         GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
+         if (LocSeq(i).Orientation() == TopAbs_REVERSED)
+           tab(i-1)->Reverse();
+         
+         //Temporary
+         //char* name = new char[100];
+         //sprintf(name, "c%d", i);
+         //DrawTrSurf::Set(name, tab(i-1));
+         
+         if (i > 1)
+           tabtolvertex(i-2) = TolSeq(i-1);
+       } // end for (i = 1; i <= nb_curve; i++)
+       tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
+       
+       Standard_Boolean closed_flag = Standard_False;
+       Standard_Real closed_tolerance = 0.;
+       if (FirstVertex.IsSame(LastVertex) &&
+           GeomLProp::Continuity(tab(0), tab(nb_curve-1),
+                                 tab(0)->FirstParameter(),
+                                 tab(nb_curve-1)->LastParameter(),
+                                 Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
+       {
+         closed_flag = Standard_True ;
+         closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
+       }
+       
+       Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
+       Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
+       GeomConvert::ConcatC1(tab,
+                             tabtolvertex,
+                             ArrayOfIndices,
+                             concatcurve,
+                             closed_flag,
+                             closed_tolerance);   //C1 concatenation
+       
+       if (concatcurve->Length() > 1)
+       {
+         GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
+         
+         for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
+           Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
+         
+         concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
+       }
+       
+       ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
+                                  FirstVertex, LastVertex);
+      }
+      else
+      {
+       if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
+         CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
+       
+       CurveSeq(1)->Transform(LocSeq(1).Location().Transformation());
+       ResEdge = BRepLib_MakeEdge(CurveSeq(1),
+                                  FirstVertex, LastVertex,
+                                  FparSeq(1), LparSeq(1));
+      }
+    }
+      
+    aShape = ResEdge;
+  }
 
   if (aShape.IsNull()) return 0;
 
@@ -500,10 +828,10 @@ Standard_EXPORT Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_()
 
   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_ShapeDriver",
-                                                        sizeof(GEOMImpl_ShapeDriver),
-                                                        1,
-                                                        (Standard_Address)_Ancestors,
-                                                        (Standard_Address)NULL);
+                                                         sizeof(GEOMImpl_ShapeDriver),
+                                                         1,
+                                                         (Standard_Address)_Ancestors,
+                                                         (Standard_Address)NULL);
 
   return _aType;
 }