+ const Standard_Real aTol = BRep_Tool::Tolerance(aFace);
+ BRepBuilderAPI_MakeFace aMF(aSurface, aU1, aU2, aV1, aV2, aTol);
+
+ if (aMF.IsDone()) {
+ aShape = aMF.Shape();
+ }
+ }
+ }
+ } else if (aType == EXTRACTION) {
+ allowCompound = true;
+
+ GEOMImpl_IExtract aCI(aFunction);
+ Handle(GEOM_Function) aRefShape = aCI.GetShape();
+ TopoDS_Shape aShapeBase = aRefShape->GetValue();
+
+ if (aShapeBase.IsNull()) {
+ Standard_NullObject::Raise("Argument Shape is null");
+ return 0;
+ }
+
+ Handle(TColStd_HArray1OfInteger) anIDs = aCI.GetSubShapeIDs();
+ TopTools_ListOfShape aListSubShapes;
+ TopTools_IndexedMapOfShape anIndices;
+ int i;
+
+ TopExp::MapShapes(aShapeBase, anIndices);
+
+ if (!anIDs.IsNull()) {
+ const int anUpperID = anIDs->Upper();
+ const int aNbShapes = anIndices.Extent();
+
+ for (i = anIDs->Lower(); i <= anUpperID; ++i) {
+ const Standard_Integer anIndex = anIDs->Value(i);
+
+ if (anIndex < 1 || anIndex > aNbShapes) {
+ TCollection_AsciiString aMsg(" Invalid index: ");
+
+ aMsg += TCollection_AsciiString(anIndex);
+ StdFail_NotDone::Raise(aMsg.ToCString());
+ return 0;
+ }
+
+ const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex);
+
+ aListSubShapes.Append(aSubShape);
+ }
+ }
+
+ // Compute extraction.
+ GEOMAlgo_Extractor anExtractor;
+
+ anExtractor.SetShape(aShapeBase);
+ anExtractor.SetShapesToRemove(aListSubShapes);
+
+ anExtractor.Perform();
+
+ // Interpret results
+ Standard_Integer iErr = anExtractor.ErrorStatus();
+
+ // The detailed description of error codes is in GEOMAlgo_Extractor.cxx
+ if (iErr) {
+ TCollection_AsciiString aMsg(" iErr : ");
+
+ aMsg += TCollection_AsciiString(iErr);
+ StdFail_NotDone::Raise(aMsg.ToCString());
+ return 0;
+ }
+
+ aShape = anExtractor.GetResult();
+
+ if (aShape.IsNull()) {
+ Standard_ConstructionError::Raise("Result of extraction is empty");
+ }
+
+ // Get statistics.
+ const TopTools_ListOfShape &aRemoved = anExtractor.GetRemoved();
+ const TopTools_ListOfShape &aModified = anExtractor.GetModified();
+ const TopTools_ListOfShape &aNew = anExtractor.GetNew();
+ Handle(TColStd_HArray1OfInteger) aRemovedIDs =
+ GetShapeIDs(aRemoved, anIndices);
+ Handle(TColStd_HArray1OfInteger) aModifiedIDs =
+ GetShapeIDs(aModified, anIndices);
+ Handle(TColStd_HArray1OfInteger) aNewIDs;
+
+ if (!aShape.IsNull()) {
+ // Get newly created sub-shapes
+ TopTools_IndexedMapOfShape aNewIndices;
+
+ TopExp::MapShapes(aShape, aNewIndices);
+ aNewIDs = GetShapeIDs(aNew, aNewIndices);
+ }
+
+ if (!aRemovedIDs.IsNull()) {
+ aCI.SetRemovedIDs(aRemovedIDs);
+ }
+
+ if (!aModifiedIDs.IsNull()) {
+ aCI.SetModifiedIDs(aModifiedIDs);
+ }
+
+ if (!aNewIDs.IsNull()) {
+ aCI.SetAddedIDs(aNewIDs);
+ }
+ }
+ else {
+ }
+
+ if (aShape.IsNull()) return 0;
+
+ // Check shape validity
+ BRepCheck_Analyzer ana (aShape, true);
+ if (!ana.IsValid()) {
+ //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
+ // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
+ Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
+ aSfs->Perform();
+ aShape = aSfs->Shape();
+ }
+
+ // Check if the result shape is of expected type.
+ const TopAbs_ShapeEnum aShType = aShape.ShapeType();
+
+ bool ok = false;
+ if ( aShType == TopAbs_COMPOUND || aShType == TopAbs_COMPSOLID ) {
+ ok = allowCompound && checkCompound( aShape, anExpectedType );
+ }
+ else {
+ ok = ( anExpectedType == TopAbs_SHAPE ) || ( aShType == anExpectedType );
+ }
+ if (!ok)
+ Standard_ConstructionError::Raise("Result type check failed");
+
+ aFunction->SetValue(aShape);
+
+ log->SetTouched(Label());
+
+ if (!aWarning.IsEmpty())
+ Standard_Failure::Raise(aWarning.ToCString());
+
+ return 1;
+}
+
+TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
+ const Standard_Real theTolerance)
+{
+ BRep_Builder B;
+
+ TopoDS_Wire aWire;
+ B.MakeWire(aWire);
+
+ // add edges
+ for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
+ Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->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 || 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");
+ }
+ }
+
+ // 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 {
+ }
+
+ // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
+ aFW->ClosedWireMode() = Standard_False;
+ aFW->FixConnected(theTolerance);
+ 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");
+ }
+ }
+ aWire = aFW->WireAPIMake();
+
+ return aWire;
+}
+
+TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
+ const Standard_Real LinTol,
+ const Standard_Real AngTol)
+{
+ 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_Real aPntShiftDist = 0.;
+
+ 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;
+ Handle(Geom_Geometry) aTrsfGeom = CurveSeq.Last()->Transformed
+ (LocSeq.Last().Location().Transformation());
+ GeomAdaptor_Curve GAprevcurve(Handle(Geom_Curve)::DownCast(aTrsfGeom));
+ 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() && aLoc.IsEqual(LocSeq.Last().Location()))
+ {
+ 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);
+
+ // Compute shift
+ if (ConnectByOrigin == TopAbs_FORWARD) {
+ gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
+
+ aPntShiftDist += P2.Distance(aNewP2);
+ } else {
+ gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
+
+ aPntShiftDist += P1.Distance(aNewP1);
+ }
+
+ 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))
+ {
+ const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
+
+ 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);
+
+ // Compute shift
+ if (isFwd) {
+ gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
+
+ aPntShiftDist += P2.Distance(aNewP2);
+ } else {
+ gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
+
+ aPntShiftDist += P1.Distance(aNewP1);
+ }
+
+ 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))
+ {
+ const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
+
+ 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);
+
+ // Compute shift
+ if (isFwd) {
+ gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
+
+ aPntShiftDist += P2.Distance(aNewP2);
+ } else {
+ gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
+
+ aPntShiftDist += P1.Distance(aNewP1);
+ }
+
+ 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);
+
+ // Compute shift
+ if (ConnectByOrigin == TopAbs_FORWARD) {
+ gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
+
+ aPntShiftDist += P2.Distance(aNewP2);
+ } else {
+ gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
+
+ aPntShiftDist += P1.Distance(aNewP1);
+ }
+
+ 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);
+
+ // Compute shift
+ if (ConnectByOrigin == TopAbs_FORWARD) {
+ gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
+
+ aPntShiftDist += P2.Distance(aNewP2);
+ } else {
+ gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
+
+ aPntShiftDist += P1.Distance(aNewP1);
+ }
+
+ 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(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
+ aPntShiftDist = 0.;
+ CurType = aType;
+ }
+ } // end of else (CurveSeq.IsEmpty()) -> not first time
+ } // end for (; wexp.More(); wexp.Next())
+
+ LastVertex = wexp.CurrentVertex();
+ TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
+
+ FirstVertex.Orientation(TopAbs_FORWARD);
+ LastVertex.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");
+ }
+
+ Standard_Boolean isValidEndVtx = Standard_True;
+
+ if (closed_flag) {
+ // Check if closed curve is reordered.
+ Handle(Geom_BSplineCurve) aCurve = concatcurve->Value(concatcurve->Lower());
+ Standard_Real aFPar = aCurve->FirstParameter();
+ gp_Pnt aPFirst;
+ gp_Pnt aPntVtx = BRep_Tool::Pnt(FirstVertex);
+ Standard_Real aTolVtx = BRep_Tool::Tolerance(FirstVertex);
+
+ aCurve->D0(aFPar, aPFirst);
+
+ if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
+ // The curve is reordered. Find the new first and last vertices.
+ TopTools_IndexedMapOfShape aMapVtx;
+ TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
+
+ const Standard_Integer aNbVtx = aMapVtx.Extent();
+ Standard_Integer iVtx;
+
+ for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
+ const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
+ const gp_Pnt aPnt = BRep_Tool::Pnt(aVtx);
+ const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
+
+ if (aPFirst.IsEqual(aPnt, aTol)) {
+ // The coincident vertex is found.
+ FirstVertex = aVtx;
+ LastVertex = aVtx;
+ FirstVertex.Orientation(TopAbs_FORWARD);
+ LastVertex.Orientation(TopAbs_REVERSED);
+ break;
+ }
+ }
+
+ if (iVtx > aNbVtx) {
+ // It is necessary to create new vertices.
+ isValidEndVtx = Standard_False;
+ }
+ }
+ }
+
+ if (isValidEndVtx) {
+ ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
+ FirstVertex, LastVertex,
+ concatcurve->Value(concatcurve->Lower())->FirstParameter(),
+ concatcurve->Value(concatcurve->Lower())->LastParameter());
+ } else {
+ ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
+ 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();
+
+ Handle(Geom_Curve) aNewCurve =
+ Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
+
+ aNewCurve->Transform(LocSeq(1).Location().Transformation());
+
+ if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
+ const TopoDS_Vertex aVtxTmp = FirstVertex;
+
+ FirstVertex = LastVertex;
+ LastVertex = aVtxTmp;
+ FirstVertex.Orientation(TopAbs_FORWARD);
+ LastVertex.Orientation(TopAbs_REVERSED);
+ }
+
+ ResEdge = BRepLib_MakeEdge(aNewCurve,
+ FirstVertex, LastVertex,
+ FparSeq(1), LparSeq(1));
+
+ if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
+ ResEdge.Reverse();
+ }
+ }
+ }
+
+ return ResEdge;
+}
+
+//=============================================================================
+/*!
+ * \brief Returns an isoline for a face.
+ */
+//=============================================================================
+
+TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
+ (const TopoDS_Face &theFace,
+ const bool IsUIso,
+ const double theParameter) const
+{
+ TopoDS_Shape aResult;
+ GEOMUtils::Hatcher aHatcher(theFace);
+ const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
+
+ aHatcher.Init(aType, theParameter);
+ aHatcher.Perform();
+
+ if (!aHatcher.IsDone()) {
+ Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
+ }
+
+ const Handle(TColStd_HArray1OfInteger) &anIndices =
+ (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
+
+ if (anIndices.IsNull()) {
+ Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
+ }
+
+ const Standard_Integer anIsoInd = anIndices->Lower();
+ const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
+
+ if (aHatchingIndex == 0) {
+ Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
+ }
+
+ const Standard_Integer aNbDomains =
+ aHatcher.GetNbDomains(aHatchingIndex);
+
+ if (aNbDomains < 0) {
+ Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
+ }
+
+ // The hatching is performed successfully. Create the 3d Curve.
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
+ Handle(Geom_Curve) anIsoCurve = (IsUIso ?
+ aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
+ Handle(Geom2d_Curve) aPIsoCurve =
+ aHatcher.GetHatching(aHatchingIndex);
+ const Standard_Real aTol = Precision::Confusion();
+ Standard_Integer anIDom = 1;
+ Standard_Real aV1;
+ Standard_Real aV2;
+ BRep_Builder aBuilder;
+ Standard_Integer aNbEdges = 0;
+
+ for (; anIDom <= aNbDomains; anIDom++) {
+ if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
+ // Check first and last parameters.
+ if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
+ // Create an edge.
+ TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
+
+ // Update it with a parametric curve on face.
+ aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
+ aNbEdges++;
+
+ if (aNbEdges > 1) {
+ // Result is a compond.
+ if (aNbEdges == 2) {
+ // Create a new compound.
+ TopoDS_Compound aCompound;
+
+ aBuilder.MakeCompound(aCompound);
+ aBuilder.Add(aCompound, aResult);
+ aResult = aCompound;
+ }
+
+ // Add an edge to the compound.
+ aBuilder.Add(aResult, anEdge);
+ } else {
+ // Result is the edge.
+ aResult = anEdge;
+ }
+ }
+ }
+ }
+
+ if (aNbEdges == 0) {
+ Standard_ConstructionError::Raise("MakeIsoline : Empty result");
+ }
+
+ return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Returns an extended edge.
+ */
+//=============================================================================
+
+TopoDS_Shape GEOMImpl_ShapeDriver::ExtendEdge
+ (const TopoDS_Edge &theEdge,
+ const Standard_Real theMin,
+ const Standard_Real theMax) const
+{
+ TopoDS_Shape aResult;
+ Standard_Real aF;
+ Standard_Real aL;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aF, aL);
+ const Standard_Real aTol = BRep_Tool::Tolerance(theEdge);
+ Standard_Real aRange2d = aL - aF;
+
+ if (aCurve.IsNull() == Standard_False && aRange2d > aTol) {
+ Standard_Real aMin = aF + aRange2d*theMin;
+ Standard_Real aMax = aF + aRange2d*theMax;
+
+ Handle(Standard_Type) aType = aCurve->DynamicType();
+
+ // Get the curve of original type
+ while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
+ Handle(Geom_TrimmedCurve) aTrCurve =
+ Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+
+ aCurve = aTrCurve->BasisCurve();
+ aType = aCurve->DynamicType();
+ }
+
+ if (aCurve->IsPeriodic()) {
+ // The curve is periodic. Check if a new range is less then a period.
+ if (aMax - aMin > aCurve->Period()) {
+ aMax = aMin + aCurve->Period();
+ }
+ } else {
+ // The curve is not periodic. Check if aMin and aMax within bounds.
+ aMin = Max(aMin, aCurve->FirstParameter());
+ aMax = Min(aMax, aCurve->LastParameter());
+ }
+
+ if (aMax - aMin > aTol) {
+ // Create a new edge.
+ BRepBuilderAPI_MakeEdge aME (aCurve, aMin, aMax);
+
+ if (aME.IsDone()) {
+ aResult = aME.Shape();
+ }
+ }
+ }
+
+ return aResult;
+}
+
+//=============================================================================
+/*!
+ * \brief Returns an extended face.
+ */
+//=============================================================================
+
+TopoDS_Shape GEOMImpl_ShapeDriver::ExtendFace
+ (const TopoDS_Face &theFace,
+ const Standard_Real theUMin,
+ const Standard_Real theUMax,
+ const Standard_Real theVMin,
+ const Standard_Real theVMax) const
+{
+ TopoDS_Shape aResult;
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
+ const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
+ Standard_Real aU1;
+ Standard_Real aU2;
+ Standard_Real aV1;
+ Standard_Real aV2;
+
+ // Get U, V bounds of the face.
+ ShapeAnalysis::GetFaceUVBounds(theFace, aU1, aU2, aV1, aV2);
+
+ const Standard_Real aURange = aU2 - aU1;
+ const Standard_Real aVRange = aV2 - aV1;
+
+ if (aSurface.IsNull() == Standard_False &&
+ aURange > aTol && aURange > aTol) {
+ Handle(Standard_Type) aType = aSurface->DynamicType();
+
+ // Get the surface of original type
+ while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+ Handle(Geom_RectangularTrimmedSurface) aTrSurface =
+ Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+
+ aSurface = aTrSurface->BasisSurface();
+ aType = aSurface->DynamicType();
+ }
+
+ Standard_Real aUMin = aU1 + aURange*theUMin;
+ Standard_Real aUMax = aU1 + aURange*theUMax;
+ Standard_Real aVMin = aV1 + aVRange*theVMin;
+ Standard_Real aVMax = aV1 + aVRange*theVMax;
+
+ aSurface->Bounds(aU1, aU2, aV1, aV2);
+
+ if (aSurface->IsUPeriodic()) {
+ // The surface is U-periodic. Check if a new U range is less
+ // then a period.
+ if (aUMax - aUMin > aSurface->UPeriod()) {
+ aUMax = aUMin + aSurface->UPeriod();
+ }
+ } else {
+ // The surface is not V-periodic. Check if aUMin and aUMax
+ // within bounds.
+ aUMin = Max(aUMin, aU1);
+ aUMax = Min(aUMax, aU2);
+ }
+
+ if (aSurface->IsVPeriodic()) {
+ // The surface is V-periodic. Check if a new V range is less
+ // then a period.
+ if (aVMax - aVMin > aSurface->VPeriod()) {
+ aVMax = aVMin + aSurface->VPeriod();
+ }
+ } else {
+ // The surface is not V-periodic. Check if aVMin and aVMax
+ // within bounds.
+ aVMin = Max(aVMin, aV1);
+ aVMax = Min(aVMax, aV2);
+ }
+
+ if (aUMax - aUMin > aTol && aVMax - aVMin > aTol) {
+ // Create a new edge.
+ BRepBuilderAPI_MakeFace aMF
+ (aSurface, aUMin, aUMax, aVMin, aVMax, aTol);
+
+ if (aMF.IsDone()) {
+ aResult = aMF.Shape();
+ }
+ }
+ }
+
+ return aResult;
+}
+
+//================================================================================
+/*!
+ * \brief Returns a name of creation operation and names and values of creation parameters
+ */
+//================================================================================
+
+bool GEOMImpl_ShapeDriver::
+GetCreationInformation(std::string& theOperationName,
+ std::vector<GEOM_Param>& theParams)
+{
+ if (Label().IsNull()) return 0;
+ Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
+
+ GEOMImpl_IShapes aCI( function );
+ Standard_Integer aType = function->GetType();
+
+ switch ( aType ) {
+ case WIRE_EDGES:
+ theOperationName = "WIRE";
+ AddParam( theParams, "Wires/edges", aCI.GetShapes() );
+ AddParam( theParams, "Tolerance", aCI.GetTolerance() );
+ break;
+ case FACE_WIRE:
+ theOperationName = "FACE";
+ AddParam( theParams, "Wire/edge", aCI.GetBase() );
+ AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
+ break;
+ case FACE_WIRES:
+ theOperationName = "FACE";
+ AddParam( theParams, "Wires/edges", aCI.GetShapes() );
+ AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
+ break;
+ case FACE_FROM_SURFACE:
+ {
+ theOperationName = "FACE";
+
+ Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
+
+ if (shapes.IsNull() == Standard_False) {
+ Standard_Integer aNbShapes = shapes->Length();
+
+ if (aNbShapes > 0) {
+ AddParam(theParams, "Face", shapes->Value(1));
+
+ if (aNbShapes > 1) {
+ AddParam(theParams, "Wire", shapes->Value(2));
+ }
+ }
+ }
+ break;
+ }
+ case SHELL_FACES:
+ theOperationName = "SHELL";
+ AddParam( theParams, "Objects", aCI.GetShapes() );
+ break;
+ case SOLID_SHELLS:
+ theOperationName = "SOLID";
+ AddParam( theParams, "Objects", aCI.GetShapes() );
+ break;
+ case SOLID_FACES:
+ theOperationName = "SOLID_FROM_FACES";
+ AddParam( theParams, "Objects", aCI.GetShapes() );
+ AddParam( theParams, "Is intersect", aCI.GetIsIntersect() );
+ break;
+ case COMPOUND_SHAPES:
+ theOperationName = "COMPOUND";
+ AddParam( theParams, "Objects", aCI.GetShapes() );
+ break;
+ case EDGE_WIRE:
+ theOperationName = "EDGE";
+ AddParam( theParams, "Wire", aCI.GetBase() );
+ AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
+ AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
+ break;
+ case EDGE_CURVE_LENGTH:
+ theOperationName = "EDGE";
+ {
+ GEOMImpl_IVector aCI( function );
+ AddParam( theParams, "Edge", aCI.GetPoint1() );
+ AddParam( theParams, "Start point", aCI.GetPoint2() );
+ AddParam( theParams, "Length", aCI.GetParameter() );
+ }
+ break;
+ case SHAPES_ON_SHAPE:
+ {
+ theOperationName = "GetShapesOnShapeAsCompound";
+ Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
+ if ( !shapes.IsNull() && shapes->Length() > 0 )
+ AddParam( theParams, "Check shape", shapes->Value(1) );
+ if ( !shapes.IsNull() && shapes->Length() > 1 )
+ AddParam( theParams, "Shape", shapes->Value(2) );
+ AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
+ AddParam( theParams, "State" );
+ GEOMAlgo_State st = GEOMAlgo_State( (int) ( aCI.GetTolerance()+0.1 ) );
+ const char* stName[] = { "UNKNOWN","IN","OUT","ON","ONIN","ONOUT","INOUT" };
+ if ( 0 <= st && st <= GEOMAlgo_ST_INOUT )
+ theParams.back() << stName[ st ];
+ else
+ theParams.back() << (int) st;
+ break;
+ }
+ case SHAPE_ISOLINE:
+ {
+ GEOMImpl_IIsoline aII (function);
+
+ theOperationName = "ISOLINE";
+ AddParam(theParams, "Face", aII.GetFace());
+ AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
+ AddParam(theParams, "Parameter", aII.GetParameter());
+ break;
+ }
+ case EDGE_UV:
+ {
+ GEOMImpl_IShapeExtend aSE (function);
+
+ theOperationName = "EDGE_EXTEND";
+ AddParam(theParams, "Edge", aSE.GetShape());
+ AddParam(theParams, "Min", aSE.GetUMin());
+ AddParam(theParams, "Max", aSE.GetUMax());
+ break;
+ }
+ case FACE_UV:
+ {
+ GEOMImpl_IShapeExtend aSE (function);
+
+ theOperationName = "FACE_EXTEND";
+ AddParam(theParams, "Face", aSE.GetShape());
+ AddParam(theParams, "UMin", aSE.GetUMin());
+ AddParam(theParams, "UMax", aSE.GetUMax());
+ AddParam(theParams, "VMin", aSE.GetVMin());
+ AddParam(theParams, "VMax", aSE.GetVMax());
+ break;
+ }
+ case SURFACE_FROM_FACE:
+ {
+ GEOMImpl_IShapeExtend aSE (function);
+
+ theOperationName = "SURFACE_FROM_FACE";
+ AddParam(theParams, "Face", aSE.GetShape());
+ break;
+ }
+ case EXTRACTION:
+ {
+ GEOMImpl_IExtract aCI (function);
+
+ theOperationName = "EXTRACTION";
+ AddParam(theParams, "Main Shape", aCI.GetShape());
+ AddParam(theParams, "Sub-shape IDs", aCI.GetSubShapeIDs());
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
+
+//modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
+#include <TopoDS_Iterator.hxx>
+#include <TopTools_HSequenceOfShape.hxx>
+#include <ShapeAnalysis_FreeBounds.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_MapOfOrientedShape.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Wire.hxx>
+
+//=======================================================================
+//function : KeepEdgesOrder
+//purpose :
+//=======================================================================
+/*
+void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
+ const Handle(TopTools_HSequenceOfShape)& aWires)
+{
+ Standard_Integer aNbWires, aNbEdges;
+ //
+ if (aEdges.IsNull()) {
+ return;
+ }
+ //
+ if (aWires.IsNull()) {
+ return;
+ }
+ //
+ aNbEdges=aEdges->Length();
+ aNbWires=aWires->Length();
+ if (!aNbEdges || !aNbWires) {
+ return;
+ }
+ //-----
+ Standard_Boolean bClosed;
+ Standard_Integer i, j;
+ TopoDS_Wire aWy;
+ TopoDS_Iterator aIt;
+ BRep_Builder aBB;
+ TopTools_MapOfOrientedShape aMEx;
+ //
+ for (i=1; i<=aNbWires; ++i) {
+ const TopoDS_Shape& aWx=aWires->Value(i);
+ //
+ aMEx.Clear();
+ aIt.Initialize (aWx);
+ for (; aIt.More(); aIt.Next()) {
+ const TopoDS_Shape& aEx=aIt.Value();
+ aMEx.Add(aEx);
+ }
+ // aWy
+ aBB.MakeWire (aWy);
+ for (j=1; j<=aNbEdges; ++j) {
+ const TopoDS_Shape& aE=aEdges->Value(j);
+ if (aMEx.Contains(aE)) {
+ aBB.Add(aWy, aE);
+ }
+ }
+ //
+ bClosed=aWx.Closed();
+ aWy.Closed(bClosed);
+ //
+ aWires->Append(aWy);
+ }// for (i=1; i<=aNbWires; ++i) {
+ //
+ aWires->Remove(1, aNbWires);