+ }
+ }
+ */
+ 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;
+ Standard_Boolean FinalReverse = Standard_False;
+
+ 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();
+ if (anEdge.Orientation() == TopAbs_REVERSED)
+ FinalReverse = Standard_True;
+ }
+ 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.*M_PI;
+ //Standard_Real MemNewFpar = NewFpar, MemNewLpar = NewLpar;
+ if (ConnectByOrigin == TopAbs_FORWARD)
+ ElCLib::AdjustPeriodic(FparSeq.Last(),
+ FparSeq.Last() + 2.*M_PI,
+ Precision::PConfusion(), NewFpar, NewLpar);
+ else
+ ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_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.*M_PI;
+ if (ConnectByOrigin == TopAbs_FORWARD)
+ ElCLib::AdjustPeriodic(FparSeq.Last(),
+ FparSeq.Last() + 2.*M_PI,
+ Precision::PConfusion(), NewFpar, NewLpar);
+ else
+ ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_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));
+
+ TopoDS_Vertex FirstVtx_final = (FinalReverse)? LastVertex : FirstVertex;
+ FirstVtx_final.Orientation(TopAbs_FORWARD);
+ TopoDS_Vertex LastVtx_final = (FinalReverse)? FirstVertex : LastVertex;
+ LastVtx_final.Orientation(TopAbs_REVERSED);
+
+ 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());
+ }
+ // rnc : prevents the driver from building an edge without C1 continuity
+ if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
+ Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
+ }
+ ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
+ FirstVtx_final, LastVtx_final,
+ concatcurve->Value(concatcurve->Lower())->FirstParameter(),
+ concatcurve->Value(concatcurve->Lower())->LastParameter());
+ }
+ else
+ {
+ if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
+ CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
+
+ CurveSeq(1)->Transform(LocSeq(1).Location().Transformation());
+ ResEdge = BRepLib_MakeEdge(CurveSeq(1),
+ FirstVtx_final, LastVtx_final,
+ FparSeq(1), LparSeq(1));
+ }
+ }
+
+ if (FinalReverse)
+ ResEdge.Reverse();
+
+ aShape = ResEdge;
+ }
+ else if (aType == EDGE_CURVE_LENGTH) {
+ GEOMImpl_IVector aVI (aFunction);
+
+ // RefCurve
+ Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
+ if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
+ TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
+ if (aRefShape1.ShapeType() != TopAbs_EDGE) {
+ Standard_TypeMismatch::Raise
+ ("Edge On Curve creation aborted : curve shape is not an edge");
+ }
+ TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
+
+ // RefPoint
+ TopoDS_Vertex aRefVertex;
+ Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
+ if (aRefPoint.IsNull()) {
+ aRefVertex = V1;
+ }
+ else {
+ TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
+ if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
+ Standard_TypeMismatch::Raise
+ ("Edge On Curve creation aborted : start point shape is not a vertex");
+ }
+ aRefVertex = TopoDS::Vertex(aRefShape2);
+ }
+ gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
+
+ // Length
+ Standard_Real aLength = aVI.GetParameter();
+ //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
+ //if (aLength > aCurveLength) {
+ // Standard_ConstructionError::Raise
+ // ("Edge On Curve creation aborted : given length is greater than edges length");
+ //}
+ if (fabs(aLength) < Precision::Confusion()) {
+ Standard_ConstructionError::Raise
+ ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
+ }
+
+ // Check orientation
+ Standard_Real UFirst, ULast;
+ Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
+ Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
+
+ Standard_Real dU = ULast - UFirst;
+ Standard_Real par1 = UFirst + 0.1 * dU;
+ Standard_Real par2 = ULast - 0.1 * dU;
+
+ gp_Pnt P1 = EdgeCurve->Value(par1);
+ gp_Pnt P2 = EdgeCurve->Value(par2);
+
+ if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
+ ReOrientedCurve = EdgeCurve->Reversed();
+ UFirst = EdgeCurve->ReversedParameter(ULast);
+ }
+
+ // Get the point by length
+ GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
+ GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
+ Standard_Real aParam = anAbsPnt.Parameter();
+
+ if (AdapCurve.IsClosed() && aLength < 0.0) {
+ Standard_Real aTmp = aParam;
+ aParam = UFirst;
+ UFirst = aTmp;
+ }
+
+ BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
+ if (aME.IsDone())
+ aShape = aME.Shape();
+ }
+ else {