From: ifv Date: Fri, 17 Jul 2015 06:43:21 +0000 (+0300) Subject: 0026426: Draft angle algorithm modifies input argument + the result of the operation... X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=d2f91e962468317cdb239c0cbebcf785bad27278;p=occt-copy.git 0026426: Draft angle algorithm modifies input argument + the result of the operation have very large tolerance values This is not yet final version of the fix. --- diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cdl index fb8ea45146..d15e837305 100644 --- a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cdl @@ -46,6 +46,7 @@ uses Face from TopoDS, ShapeModification from BRepBuilderAPI, ListOfShape from TopTools, + DataMapOfShapeShape from TopTools, Dir from gp, Pln from gp, ErrorStatus from Draft @@ -261,9 +262,18 @@ is returns ListOfShape from TopTools is redefined virtual; + ModifiedShape (me; S : Shape from TopoDS) + ---Purpose: Returns the modified shape corresponding to . + -- S can correspond to the entire initial shape or to its subshape. + -- Raises exceptions Standard_NoSuchObject if S is not the initial shape or + -- a subshape of the initial shape to which the transformation has been applied. + returns Shape from TopoDS is redefined virtual; + + CorrectVertexTol(me: in out) is private; + fields - myModifiedShapes : ListOfShape from TopTools; + myVtxToReplace : DataMapOfShapeShape from TopTools; end DraftAngle; diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx index 98bd5c8f5c..b4189bb769 100644 --- a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx @@ -107,12 +107,12 @@ void BRepOffsetAPI_DraftAngle::Init (const TopoDS_Shape& S) //======================================================================= void BRepOffsetAPI_DraftAngle::Add(const TopoDS_Face& F, - const gp_Dir& D, - const Standard_Real Angle, - const gp_Pln& Plane, - const Standard_Boolean Flag) + const gp_Dir& D, + const Standard_Real Angle, + const gp_Pln& Plane, + const Standard_Boolean Flag) { -// POP-DPF : protection + // POP-DPF : protection if ( Abs(Angle) <= 1.e-04 ) return; Standard_NullObject_Raise_if(myInitialShape.IsNull(),""); @@ -175,7 +175,7 @@ Draft_ErrorStatus BRepOffsetAPI_DraftAngle::Status () const //======================================================================= const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::ConnectedFaces - (const TopoDS_Face& F) const + (const TopoDS_Face& F) const { Standard_NullObject_Raise_if(myInitialShape.IsNull(),""); return (*((Handle(Draft_Modification)*)&myModification))->ConnectedFaces(F); @@ -211,7 +211,7 @@ const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::Generated(const TopoDS_Sha Standard_Boolean RW,RF; if (DMod->NewSurface(TopoDS::Face(S), Surf, L, Tol, RW, RF)) { myGenerated.Append(ModifiedShape (S)); - + } } return myGenerated; @@ -233,18 +233,35 @@ const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::Modified(const TopoDS_Shap TopLoc_Location L; Standard_Real Tol; Standard_Boolean RW,RF; - + if (!DMod->NewSurface(TopoDS::Face(S), Surf, L, Tol, RW, RF)) { // Ce n est pas une generation => peut etre une modif myGenerated.Append(ModifiedShape (S)); if (myGenerated.Extent() == 1 && myGenerated.First().IsSame(S)) { - myGenerated.Clear(); + myGenerated.Clear(); } } } return myGenerated; } +//======================================================================= +//function : ModifiedShape +//purpose : +//======================================================================= + +TopoDS_Shape BRepOffsetAPI_DraftAngle::ModifiedShape + (const TopoDS_Shape& S) const +{ + if(S.ShapeType() == TopAbs_VERTEX) + { + if(myVtxToReplace.IsBound(S)) + { + return myVtxToReplace(S); + } + } + return myModifier.ModifiedShape(S); +} //======================================================================= //function : Build @@ -259,9 +276,8 @@ void BRepOffsetAPI_DraftAngle::Build() } else { DoModif(myInitialShape); - //BRepLib::SameParameter( myShape, 1.0e-7, Standard_True ); //patch CorrectWires(); - BRepLib::SameParameter( myShape, 1.0e-7, Standard_True ); //patch + CorrectVertexTol(); } } @@ -283,29 +299,29 @@ void BRepOffsetAPI_DraftAngle::CorrectWires() TopExp_Explorer fexp( myShape, TopAbs_FACE ); for (; fexp.More(); fexp.Next()) + { + CurFace = fexp.Current(); + wit.Initialize( CurFace ); + for (; wit.More(); wit.Next()) { - CurFace = fexp.Current(); - wit.Initialize( CurFace ); - for (; wit.More(); wit.Next()) - { - CurWire = wit.Value(); - TopTools_MapOfShape emap; - eit.Initialize( CurWire ); - for (; eit.More(); eit.Next()) - emap.Add( eit.Value() ); - TopTools_MapIteratorOfMapOfShape mapit( emap ); - for (; mapit.More(); mapit.Next()) - { - CurEdge = mapit.Key(); - if (BRepTools::IsReallyClosed( TopoDS::Edge(CurEdge), TopoDS::Face(CurFace) )) - { - Eseq.Append( CurEdge ); - Wseq.Append( CurWire ); - Fseq.Append( CurFace ); - } - } - } + CurWire = wit.Value(); + TopTools_MapOfShape emap; + eit.Initialize( CurWire ); + for (; eit.More(); eit.Next()) + emap.Add( eit.Value() ); + TopTools_MapIteratorOfMapOfShape mapit( emap ); + for (; mapit.More(); mapit.Next()) + { + CurEdge = mapit.Key(); + if (BRepTools::IsReallyClosed( TopoDS::Edge(CurEdge), TopoDS::Face(CurFace) )) + { + Eseq.Append( CurEdge ); + Wseq.Append( CurWire ); + Fseq.Append( CurFace ); + } + } } + } BRepFill_DataMapOfShapeSequenceOfReal Emap; @@ -318,551 +334,639 @@ void BRepOffsetAPI_DraftAngle::CorrectWires() TopTools_DataMapOfShapeShape WFmap; TopTools_DataMapOfShapeListOfShape WWmap; for (i = 1; i <= Eseq.Length(); i++) + { + CurEdge = Eseq(i); + CurWire = Wseq(i); + CurFace = Fseq(i); + wit.Initialize( CurFace ); + for (; wit.More(); wit.Next()) { - CurEdge = Eseq(i); - CurWire = Wseq(i); - CurFace = Fseq(i); - wit.Initialize( CurFace ); - for (; wit.More(); wit.Next()) - { - TopoDS_Shape aWire = wit.Value(); - if (! aWire.IsSame( CurWire )) - { - TColgp_SequenceOfPnt pts; - TopTools_SequenceOfShape edges; - TColStd_SequenceOfReal pars; - Standard_Boolean Wadd = Standard_False; - eit.Initialize( aWire ); - for (; eit.More(); eit.Next()) - { - TopoDS_Shape anEdge = eit.Value(); - TopOpeBRep_EdgesIntersector EInter; - EInter.SetFaces( CurFace, CurFace ); - EInter.ForceTolerances( TolInter, TolInter ); - EInter.Perform( CurEdge, anEdge ); - if (EInter.IsEmpty()) - { - EInter.Perform( CurEdge.Reversed(), anEdge ); - if (EInter.IsEmpty()) - continue; - } - Wadd = Standard_True; - if (! WFmap.IsBound( aWire )) - WFmap.Bind( aWire, CurFace ); - Standard_Integer ind = 0; - for (j = 1; j <= NonSeam.Length(); j++) - if (anEdge.IsSame( NonSeam(j) )) - { - ind = j; - break; - } - if (ind == 0) - { - NonSeam.Append( anEdge ); - NonSeamWires.Append( aWire ); - ind = NonSeam.Length(); - TColStd_SequenceOfReal emptyseq1, emptyseq2; - TopTools_SequenceOfShape emptyedgeseq; - ParsNonSeam.Append( emptyseq1 ); - Seam.Append( emptyedgeseq ); - ParsSeam.Append( emptyseq2 ); - } - if (! Emap.IsBound( CurEdge )) - { - TColStd_SequenceOfReal emptyseq; - Emap.Bind( CurEdge, emptyseq ); - } - EInter.InitPoint(); - for (; EInter.MorePoint(); EInter.NextPoint()) - { - const TopOpeBRep_Point2d& bp = EInter.Point(); - if (bp.IsVertex(2)) - { - gp_Pnt Pnt = bp.Value(); - Standard_Integer ied = 0; - for (j = 1; j <= pts.Length(); j++) - if (Pnt.IsEqual( pts(j), Precision::Confusion() )) - { - ied = j; - break; - } - if (ied == 0) - { - pts.Append( Pnt ); - edges.Append( anEdge ); - pars.Append( bp.Parameter(2) ); - Emap(CurEdge).Append( bp.Parameter(1) ); - ParsNonSeam(ind).Append( bp.Parameter(2) ); - Seam(ind).Append( CurEdge ); - ParsSeam(ind).Append( bp.Parameter(1) ); - } - /* - else - { - Standard_Real ParOnSeam = bp.Parameter(1); - Standard_Real Par1 = pars(ied); - Standard_Real Par2 = bp.Parameter(2); - BRepAdaptor_Curve2d SeamCurve( CurEdge, CurFace ); - BRepAdaptor_Curve2d Curve1( edges(ied), CurFace ); - BRepAdaptor_Curve2d Curve2( anEdge. CurFace ); - gp_Pnt2d P2d; - gp_Vec2d SeamDer, Der1, Der2; - //SeamCurve->D1( ParOnSeam, P2d, SeamDer ); - //Curve1->D1( Par1, P2d, Der1 ); - //Curve2->D1( Par2, P2d, Der2 ); - Standard_Real Crossed1 = SeamDer ^ Der1; - Standard_Real Crossed2 = SeamDer ^ Der2; - //if (Crossed1 > 0 - } - */ - } - else // ! bp.IsVertex(2) - { - //Temporary the case of tangency is not implemented - Emap(CurEdge).Append( bp.Parameter(1) ); - ParsNonSeam(ind).Append( bp.Parameter(2) ); - Seam(ind).Append( CurEdge ); - ParsSeam(ind).Append( bp.Parameter(1) ); - } - } //for (; EInter.MorePoint(); EInter.NextPoint()) - } //for (; eit.More(); eit.Next()) - if (Wadd) - { - if (! WWmap.IsBound( CurWire )) - { - TopTools_ListOfShape emptylist; - WWmap.Bind( CurWire, emptylist ); - } - WWmap(CurWire).Append( aWire ); - } - } //if (! aWire.IsSame( CurWire )) - } //for (; wit.More(); wit.Next()) - } //for (i = 1; i <= Eseq.Length(); i++) + TopoDS_Shape aWire = wit.Value(); + if (! aWire.IsSame( CurWire )) + { + TColgp_SequenceOfPnt pts; + TopTools_SequenceOfShape edges; + TColStd_SequenceOfReal pars; + Standard_Boolean Wadd = Standard_False; + eit.Initialize( aWire ); + for (; eit.More(); eit.Next()) + { + TopoDS_Shape anEdge = eit.Value(); + TopOpeBRep_EdgesIntersector EInter; + EInter.SetFaces( CurFace, CurFace ); + EInter.ForceTolerances( TolInter, TolInter ); + EInter.Perform( CurEdge, anEdge ); + if (EInter.IsEmpty()) + { + EInter.Perform( CurEdge.Reversed(), anEdge ); + if (EInter.IsEmpty()) + continue; + } + Wadd = Standard_True; + if (! WFmap.IsBound( aWire )) + WFmap.Bind( aWire, CurFace ); + Standard_Integer ind = 0; + for (j = 1; j <= NonSeam.Length(); j++) + if (anEdge.IsSame( NonSeam(j) )) + { + ind = j; + break; + } + if (ind == 0) + { + NonSeam.Append( anEdge ); + NonSeamWires.Append( aWire ); + ind = NonSeam.Length(); + TColStd_SequenceOfReal emptyseq1, emptyseq2; + TopTools_SequenceOfShape emptyedgeseq; + ParsNonSeam.Append( emptyseq1 ); + Seam.Append( emptyedgeseq ); + ParsSeam.Append( emptyseq2 ); + } + if (! Emap.IsBound( CurEdge )) + { + TColStd_SequenceOfReal emptyseq; + Emap.Bind( CurEdge, emptyseq ); + } + EInter.InitPoint(); + for (; EInter.MorePoint(); EInter.NextPoint()) + { + const TopOpeBRep_Point2d& bp = EInter.Point(); + if (bp.IsVertex(2)) + { + gp_Pnt Pnt = bp.Value(); + Standard_Integer ied = 0; + for (j = 1; j <= pts.Length(); j++) + if (Pnt.IsEqual( pts(j), Precision::Confusion() )) + { + ied = j; + break; + } + if (ied == 0) + { + pts.Append( Pnt ); + edges.Append( anEdge ); + pars.Append( bp.Parameter(2) ); + Emap(CurEdge).Append( bp.Parameter(1) ); + ParsNonSeam(ind).Append( bp.Parameter(2) ); + Seam(ind).Append( CurEdge ); + ParsSeam(ind).Append( bp.Parameter(1) ); + } + /* + else + { + Standard_Real ParOnSeam = bp.Parameter(1); + Standard_Real Par1 = pars(ied); + Standard_Real Par2 = bp.Parameter(2); + BRepAdaptor_Curve2d SeamCurve( CurEdge, CurFace ); + BRepAdaptor_Curve2d Curve1( edges(ied), CurFace ); + BRepAdaptor_Curve2d Curve2( anEdge. CurFace ); + gp_Pnt2d P2d; + gp_Vec2d SeamDer, Der1, Der2; + //SeamCurve->D1( ParOnSeam, P2d, SeamDer ); + //Curve1->D1( Par1, P2d, Der1 ); + //Curve2->D1( Par2, P2d, Der2 ); + Standard_Real Crossed1 = SeamDer ^ Der1; + Standard_Real Crossed2 = SeamDer ^ Der2; + //if (Crossed1 > 0 + } + */ + } + else // ! bp.IsVertex(2) + { + //Temporary the case of tangency is not implemented + Emap(CurEdge).Append( bp.Parameter(1) ); + ParsNonSeam(ind).Append( bp.Parameter(2) ); + Seam(ind).Append( CurEdge ); + ParsSeam(ind).Append( bp.Parameter(1) ); + } + } //for (; EInter.MorePoint(); EInter.NextPoint()) + } //for (; eit.More(); eit.Next()) + if (Wadd) + { + if (! WWmap.IsBound( CurWire )) + { + TopTools_ListOfShape emptylist; + WWmap.Bind( CurWire, emptylist ); + } + WWmap(CurWire).Append( aWire ); + } + } //if (! aWire.IsSame( CurWire )) + } //for (; wit.More(); wit.Next()) + } //for (i = 1; i <= Eseq.Length(); i++) //Sorting for (i = 1; i <= NonSeam.Length(); i++) for (j = 1; j < ParsNonSeam(i).Length(); j++) for (k = j+1; k <= ParsNonSeam(i).Length(); k++) - if (ParsNonSeam(i)(k) < ParsNonSeam(i)(j)) - { - Standard_Real temp = ParsNonSeam(i)(j); - ParsNonSeam(i)(j) = ParsNonSeam(i)(k); - ParsNonSeam(i)(k) = temp; - TopoDS_Shape tmp = Seam(i)(j); - Seam(i)(j) = Seam(i)(k); - Seam(i)(k) = tmp; - temp = ParsSeam(i)(j); - ParsSeam(i)(j) = ParsSeam(i)(k); - ParsSeam(i)(k) = temp; - } - BRepFill_DataMapIteratorOfDataMapOfShapeSequenceOfReal iter( Emap ); - for (; iter.More(); iter.Next()) - { - TColStd_SequenceOfReal Seq; - Seq = iter.Value(); - for (i = 1; i < Seq.Length(); i++) - for (j = i+1; j <= Seq.Length(); j++) - if (Seq(j) < Seq(i)) - { - Standard_Real temp = Seq(i); - Seq(i) = Seq(j); - Seq(j) = temp; - } - Emap( iter.Key() ) = Seq; - } - BRepFill_DataMapOfShapeSequenceOfReal EPmap; - TopTools_DataMapOfShapeSequenceOfShape EVmap; //Seam - TopTools_DataMapOfShapeSequenceOfShape EWmap; //Seam and wires intersecting it - iter.Initialize( Emap ); - for (; iter.More(); iter.Next()) - { - TColStd_SequenceOfReal parseq; - EPmap.Bind( iter.Key(), parseq ); - TopTools_SequenceOfShape shapeseq; - EVmap.Bind( iter.Key(), shapeseq ); - TopTools_SequenceOfShape shapeseq2; - EWmap.Bind( iter.Key(), shapeseq2 ); - } + if (ParsNonSeam(i)(k) < ParsNonSeam(i)(j)) + { + Standard_Real temp = ParsNonSeam(i)(j); + ParsNonSeam(i)(j) = ParsNonSeam(i)(k); + ParsNonSeam(i)(k) = temp; + TopoDS_Shape tmp = Seam(i)(j); + Seam(i)(j) = Seam(i)(k); + Seam(i)(k) = tmp; + temp = ParsSeam(i)(j); + ParsSeam(i)(j) = ParsSeam(i)(k); + ParsSeam(i)(k) = temp; + } + BRepFill_DataMapIteratorOfDataMapOfShapeSequenceOfReal iter( Emap ); + for (; iter.More(); iter.Next()) + { + TColStd_SequenceOfReal Seq; + Seq = iter.Value(); + for (i = 1; i < Seq.Length(); i++) + for (j = i+1; j <= Seq.Length(); j++) + if (Seq(j) < Seq(i)) + { + Standard_Real temp = Seq(i); + Seq(i) = Seq(j); + Seq(j) = temp; + } + Emap( iter.Key() ) = Seq; + } + BRepFill_DataMapOfShapeSequenceOfReal EPmap; + TopTools_DataMapOfShapeSequenceOfShape EVmap; //Seam + TopTools_DataMapOfShapeSequenceOfShape EWmap; //Seam and wires intersecting it + iter.Initialize( Emap ); + for (; iter.More(); iter.Next()) + { + TColStd_SequenceOfReal parseq; + EPmap.Bind( iter.Key(), parseq ); + TopTools_SequenceOfShape shapeseq; + EVmap.Bind( iter.Key(), shapeseq ); + TopTools_SequenceOfShape shapeseq2; + EWmap.Bind( iter.Key(), shapeseq2 ); + } + + //Reconstruction of non-seam edges + BRepTools_Substitution aSub; + BRep_Builder BB; + for (i = 1; i <= NonSeam.Length(); i++) + { + TopoDS_Edge anEdge = TopoDS::Edge( NonSeam(i) ); + TopTools_ListOfShape NewEdges; + TopoDS_Edge NewE; + TopoDS_Vertex Vfirst, Vlast; + TopExp::Vertices( anEdge, Vfirst, Vlast ); + Standard_Real par, FirstPar, LastPar; + BRep_Tool::Range( anEdge, FirstPar, LastPar ); + Standard_Integer firstind = 1; + par = ParsNonSeam(i)(1); + TopoDS_Edge SeamEdge = TopoDS::Edge( Seam(i)(1) ); + //Find the face + for (j = 1; j <= Eseq.Length(); j++) + if (SeamEdge.IsSame( Eseq(j) )) + break; + TopoDS_Face theFace = TopoDS::Face( Fseq(j) ); + TopLoc_Location L; + Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( theFace, L ); + if (Abs(par-FirstPar) <= Precision::Confusion()) + { + BB.UpdateVertex( Vfirst, ParsSeam(i)(1), SeamEdge, BRep_Tool::Tolerance(Vfirst) ); + EPmap( SeamEdge ).Append( ParsSeam(i)(1) ); + EVmap( SeamEdge ).Append( Vfirst ); + EWmap( SeamEdge ).Append( NonSeamWires(i) ); + firstind = 2; + } + Standard_Real prevpar = FirstPar; + TopoDS_Vertex PrevV = Vfirst; + for (j = firstind; j <= ParsNonSeam(i).Length(); j++) + { + TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); + NewE = TopoDS::Edge( aLocalShape ); + //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); + TopoDS_Vertex NewV; + par = ParsNonSeam(i)(j); + BB.Range( NewE, prevpar, par ); + SeamEdge = TopoDS::Edge( Seam(i)(j) ); + if (j == ParsNonSeam(i).Length() && Abs(par-LastPar) <= Precision::Confusion()) + { + NewV = Vlast; + if (firstind == 2 && j == 2) + { + BB.UpdateVertex( Vlast, ParsSeam(i)(j), SeamEdge, BRep_Tool::Tolerance(Vlast) ); + EPmap( SeamEdge ).Append( ParsSeam(i)(j) ); + EVmap( SeamEdge ).Append( Vlast ); + EWmap( SeamEdge ).Append( NonSeamWires(i) ); + break; + } + } + else + { + BRepAdaptor_Curve bcur( NewE ); + gp_Pnt Point = bcur.Value( par ); + NewV = BRepLib_MakeVertex( Point ); + BB.UpdateVertex( NewV, par, NewE, 10.*Precision::Confusion() ); + } + BB.UpdateVertex( NewV, ParsSeam(i)(j), SeamEdge, 10.*Precision::Confusion() ); + NewE.Orientation( TopAbs_FORWARD ); + BB.Add( NewE, PrevV.Oriented(TopAbs_FORWARD) ); + BB.Add( NewE, NewV.Oriented(TopAbs_REVERSED) ); + + NewEdges.Append( NewE ); + EPmap( SeamEdge ).Append( ParsSeam(i)(j) ); + EVmap( SeamEdge ).Append( NewV ); + EWmap( SeamEdge ).Append( NonSeamWires(i) ); + + prevpar = par; + PrevV = NewV; + } + //The last edge + TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); + NewE = TopoDS::Edge( aLocalShape ); + //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); + par = LastPar; + if (Abs(prevpar-par) > Precision::Confusion()) + { + BB.Range( NewE, prevpar, par ); + NewE.Orientation( TopAbs_FORWARD ); + BB.Add( NewE, PrevV.Oriented(TopAbs_FORWARD) ); + BB.Add( NewE, Vlast.Oriented(TopAbs_REVERSED) ); + NewEdges.Append( NewE ); + } + + //Substitute anEdge by NewEdges + aSub.Substitute( anEdge, NewEdges ); + } + + //Sorting of EPmap and EVmap and removing repeating points from them + iter.Initialize( EPmap ); + for (; iter.More(); iter.Next()) + { + TColStd_SequenceOfReal Seq; + Seq = iter.Value(); + TopTools_SequenceOfShape SeqShape; + SeqShape = EVmap( iter.Key() ); + TopTools_SequenceOfShape SeqShape2; + SeqShape2 = EWmap( iter.Key() ); + for (i = 1; i < Seq.Length(); i++) + for (j = i+1; j <= Seq.Length(); j++) + if (Seq(j) < Seq(i)) + { + Standard_Real temp = Seq(i); + Seq(i) = Seq(j); + Seq(j) = temp; + TopoDS_Shape tmp = SeqShape(i); + SeqShape(i) = SeqShape(j); + SeqShape(j) = tmp; + tmp = SeqShape2(i); + SeqShape2(i) = SeqShape2(j); + SeqShape2(j) = tmp; + } + EPmap( iter.Key() ) = Seq; + EVmap( iter.Key() ) = SeqShape; + EWmap( iter.Key() ) = SeqShape2; + } + iter.Initialize( EPmap ); + for (; iter.More(); iter.Next()) + { + TColStd_SequenceOfReal Seq; + Seq = iter.Value(); + TopTools_SequenceOfShape SeqShape; + SeqShape = EVmap( iter.Key() ); + TopTools_SequenceOfShape SeqShape2; + SeqShape2 = EWmap( iter.Key() ); + Standard_Boolean remove = Standard_True; + while (remove) + { + remove = Standard_False; + for (i = 1; i < Seq.Length(); i++) + if (Abs(Seq(i)-Seq(i+1)) <= Precision::Confusion()) + { + Seq.Remove(i+1); + SeqShape.Remove(i+1); + SeqShape2.Remove(i+1); + remove = Standard_True; + } + } + EPmap( iter.Key() ) = Seq; + EVmap( iter.Key() ) = SeqShape; + EWmap( iter.Key() ) = SeqShape2; + } + + //Reconstruction of seam edges + TopTools_DataMapOfShapeShape VEmap; + iter.Initialize( Emap ); + for (; iter.More(); iter.Next()) + { + TopoDS_Edge anEdge = TopoDS::Edge( iter.Key() ); + Standard_Boolean onepoint = Standard_False; + TopTools_ListOfShape NewEdges; + TColStd_SequenceOfReal Seq; + Seq = iter.Value(); + TColStd_SequenceOfReal Seq2; + Seq2 = EPmap( anEdge ); + TopTools_SequenceOfShape SeqVer; + SeqVer = EVmap( anEdge ); + TopTools_SequenceOfShape SeqWire; + SeqWire = EWmap( anEdge ); + TopoDS_Vertex Vfirst, Vlast; + TopExp::Vertices( anEdge, Vfirst, Vlast ); + Standard_Real fpar, lpar, FirstPar, LastPar; + BRep_Tool::Range( anEdge, FirstPar, LastPar ); + fpar = FirstPar; + lpar = Seq(1); + TopoDS_Edge NewE; + Standard_Integer firstind = 1; + if (Abs(fpar-lpar) <= Precision::Confusion()) + { + firstind = 2; + fpar = Seq(1); + lpar = Seq(2); + } + else + { + if (Seq.Length()%2 != 0) + { + VEmap.Bind( Vfirst, anEdge ); + firstind = 2; + fpar = Seq(1); + if (Seq.Length() > 2) + lpar = Seq(2); + else + onepoint = Standard_True; + } + } + if (!onepoint) + { + TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); + NewE = TopoDS::Edge( aLocalShape ); + //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); + BB.Range( NewE, fpar, lpar ); + NewE.Orientation( TopAbs_FORWARD ); + if (firstind == 1) + { + BB.Add( NewE, Vfirst.Oriented(TopAbs_FORWARD) ); + aLocalShape = SeqVer(1).Oriented(TopAbs_REVERSED); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(1).Oriented(TopAbs_REVERSED) ) ); + } + else + { + aLocalShape = SeqVer(1).Oriented(TopAbs_FORWARD); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + aLocalShape = SeqVer(2).Oriented(TopAbs_REVERSED); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(1).Oriented(TopAbs_FORWARD) ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(2).Oriented(TopAbs_REVERSED) ) ); + } + NewEdges.Append( NewE ); + + firstind++; + for (i = firstind; i < Seq.Length(); i += 2) + { + aLocalShape = anEdge.EmptyCopied(); + NewE = TopoDS::Edge( aLocalShape ); + //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); + fpar = Seq(i); + lpar = Seq(i+1); + BB.Range( NewE, fpar, lpar ); + //Find vertices + for (j = 1; j <= Seq2.Length(); j++) + if (Abs(fpar-Seq2(j)) <= Precision::Confusion()) + break; + NewE.Orientation( TopAbs_FORWARD ); + TopoDS_Shape aLocalShape = SeqVer(j).Oriented(TopAbs_FORWARD); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + aLocalShape = SeqVer(j+1).Oriented(TopAbs_REVERSED); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(j).Oriented(TopAbs_FORWARD) ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(j+1).Oriented(TopAbs_REVERSED) ) ); + NewEdges.Append( NewE ); + } + } + + i = Seq.Length(); + fpar = Seq(i); + lpar = LastPar; + if (Abs(fpar-lpar) <= Precision::Confusion()) + continue; + TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); + NewE = TopoDS::Edge( aLocalShape ); + //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); + BB.Range( NewE, fpar, lpar ); + NewE.Orientation( TopAbs_FORWARD ); + aLocalShape = SeqVer(SeqVer.Length()).Oriented(TopAbs_FORWARD); + BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); + //BB.Add( NewE, TopoDS::Vertex( SeqVer(SeqVer.Length()).Oriented(TopAbs_FORWARD) ) ); + BB.Add( NewE, Vlast.Oriented(TopAbs_REVERSED) ); + NewEdges.Append( NewE ); + + //Substitute anEdge by NewEdges + aSub.Substitute( anEdge, NewEdges ); + } + + //Removing edges connected with missing extremities of seam edges + TopTools_DataMapIteratorOfDataMapOfShapeShape itve( VEmap ); + for (; itve.More(); itve.Next()) + { + TopoDS_Shape V = itve.Key(); + TopoDS_Shape E = itve.Value(); + TopoDS_Shape W; + for (i = 1; i <= Eseq.Length(); i++) + if (E.IsSame( Eseq(i) )) + { + W = Wseq(i); + break; + } + TopoDS_Shape Etoremove; + eit.Initialize( W ); + for (; eit.More(); eit.Next()) + { + TopoDS_Edge CurE = TopoDS::Edge( eit.Value() ); + if (CurE.IsSame( E )) + continue; + TopoDS_Vertex Vfirst, Vlast; + TopExp::Vertices( CurE, Vfirst, Vlast ); + if (Vfirst.IsSame( V ) || Vlast.IsSame( V )) + { + Etoremove = CurE; + break; + } + } + if (! Etoremove.IsNull()) + { + W.Free( Standard_True ); + BB.Remove( W, Etoremove ); + } + } + + aSub.Build( myShape ); + if (aSub.IsCopied( myShape )) + { + const TopTools_ListOfShape& listSh = aSub.Copy( myShape ); + if (! listSh.IsEmpty()) + myShape = listSh.First(); + } + + //Reconstruction of wires + TopTools_ListOfShape theCopy; + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itww( WWmap ); + for (; itww.More(); itww.Next()) + { + CurWire = itww.Key(); + theCopy = aSub.Copy( CurWire ); + CurWire = theCopy.First(); + CurWire.Free( Standard_True ); + TopTools_ListIteratorOfListOfShape itl( itww.Value() ); + for (; itl.More(); itl.Next()) + { + TopoDS_Shape aWire = itl.Value(); + CurFace = WFmap( aWire ); + theCopy = aSub.Copy( aWire ); + aWire = theCopy.First(); + //Adjusting period + TopLoc_Location L; + Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( TopoDS::Face(CurFace), L ); + eit.Initialize( aWire ); + for (; eit.More(); eit.Next()) + { + TopoDS_Edge anEdge = TopoDS::Edge( eit.Value() ); + gp_Pnt2d Pfirst, Plast, Pmid; + BRep_Tool::UVPoints( anEdge, TopoDS::Face(CurFace), Pfirst, Plast ); + BRepAdaptor_Curve2d bc2d( anEdge, TopoDS::Face(CurFace) ); + Pmid = bc2d.Value( (bc2d.FirstParameter()+bc2d.LastParameter())/2. ); + gp_Vec2d offset; + Standard_Boolean translate = Standard_False; + if (Pfirst.X()-2.*M_PI > Precision::Confusion() || + Plast.X()-2.*M_PI > Precision::Confusion() || + Pmid.X()-2.*M_PI > Precision::Confusion()) + { + offset.SetCoord( -2.*M_PI, 0 ); + translate = Standard_True; + } + if (Pfirst.X() < -Precision::Confusion() || + Plast.X() < -Precision::Confusion() || + Pmid.X() < -Precision::Confusion()) + { + offset.SetCoord( 2.*M_PI, 0 ); + translate = Standard_True; + } + if (translate) + { + const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape()); + BRep_ListIteratorOfListOfCurveRepresentation itcr( TE->ChangeCurves() ); + Handle(BRep_GCurve) GC; + + for (; itcr.More(); itcr.Next()) + { + GC = Handle(BRep_GCurve)::DownCast(itcr.Value()); + if (!GC.IsNull() && GC->IsCurveOnSurface( theSurf, L )) + { + Handle(Geom2d_Curve) PC = GC->PCurve(); + PC = Handle(Geom2d_Curve)::DownCast( PC->Translated( offset ) ); + GC->PCurve( PC ); + TE->ChangeCurves().Remove( itcr ); + TE->ChangeCurves().Append( GC ); + break; + } + } + } + } + /////////////////// + eit.Initialize( aWire, Standard_False ); + for (; eit.More(); eit.Next()) + { + TopoDS_Shape anEdge = eit.Value(); + BB.Add( CurWire, anEdge ); + } + if (aSub.IsCopied( CurFace )) + { + theCopy = aSub.Copy( CurFace ); + CurFace = theCopy.First(); + } + CurFace.Free( Standard_True ); + BB.Remove( CurFace, aWire ); + } + } +} +//======================================================================= +//function : CorrectVertexTol +//purpose : +//======================================================================= - //Reconstruction of non-seam edges - BRepTools_Substitution aSub; - BRep_Builder BB; - for (i = 1; i <= NonSeam.Length(); i++) - { - TopoDS_Edge anEdge = TopoDS::Edge( NonSeam(i) ); - TopTools_ListOfShape NewEdges; - TopoDS_Edge NewE; - TopoDS_Vertex Vfirst, Vlast; - TopExp::Vertices( anEdge, Vfirst, Vlast ); - Standard_Real par, FirstPar, LastPar; - BRep_Tool::Range( anEdge, FirstPar, LastPar ); - Standard_Integer firstind = 1; - par = ParsNonSeam(i)(1); - TopoDS_Edge SeamEdge = TopoDS::Edge( Seam(i)(1) ); - //Find the face - for (j = 1; j <= Eseq.Length(); j++) - if (SeamEdge.IsSame( Eseq(j) )) - break; - TopoDS_Face theFace = TopoDS::Face( Fseq(j) ); - TopLoc_Location L; - Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( theFace, L ); - if (Abs(par-FirstPar) <= Precision::Confusion()) - { - BB.UpdateVertex( Vfirst, ParsSeam(i)(1), SeamEdge, BRep_Tool::Tolerance(Vfirst) ); - EPmap( SeamEdge ).Append( ParsSeam(i)(1) ); - EVmap( SeamEdge ).Append( Vfirst ); - EWmap( SeamEdge ).Append( NonSeamWires(i) ); - firstind = 2; - } - Standard_Real prevpar = FirstPar; - TopoDS_Vertex PrevV = Vfirst; - for (j = firstind; j <= ParsNonSeam(i).Length(); j++) - { - TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); - NewE = TopoDS::Edge( aLocalShape ); - //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); - TopoDS_Vertex NewV; - par = ParsNonSeam(i)(j); - BB.Range( NewE, prevpar, par ); - SeamEdge = TopoDS::Edge( Seam(i)(j) ); - if (j == ParsNonSeam(i).Length() && Abs(par-LastPar) <= Precision::Confusion()) - { - NewV = Vlast; - if (firstind == 2 && j == 2) - { - BB.UpdateVertex( Vlast, ParsSeam(i)(j), SeamEdge, BRep_Tool::Tolerance(Vlast) ); - EPmap( SeamEdge ).Append( ParsSeam(i)(j) ); - EVmap( SeamEdge ).Append( Vlast ); - EWmap( SeamEdge ).Append( NonSeamWires(i) ); - break; - } - } - else - { - BRepAdaptor_Curve bcur( NewE ); - gp_Pnt Point = bcur.Value( par ); - NewV = BRepLib_MakeVertex( Point ); - BB.UpdateVertex( NewV, par, NewE, 10.*Precision::Confusion() ); - } - BB.UpdateVertex( NewV, ParsSeam(i)(j), SeamEdge, 10.*Precision::Confusion() ); - NewE.Orientation( TopAbs_FORWARD ); - BB.Add( NewE, PrevV.Oriented(TopAbs_FORWARD) ); - BB.Add( NewE, NewV.Oriented(TopAbs_REVERSED) ); - - NewEdges.Append( NewE ); - EPmap( SeamEdge ).Append( ParsSeam(i)(j) ); - EVmap( SeamEdge ).Append( NewV ); - EWmap( SeamEdge ).Append( NonSeamWires(i) ); - - prevpar = par; - PrevV = NewV; - } - //The last edge - TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); - NewE = TopoDS::Edge( aLocalShape ); - //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); - par = LastPar; - if (Abs(prevpar-par) > Precision::Confusion()) - { - BB.Range( NewE, prevpar, par ); - NewE.Orientation( TopAbs_FORWARD ); - BB.Add( NewE, PrevV.Oriented(TopAbs_FORWARD) ); - BB.Add( NewE, Vlast.Oriented(TopAbs_REVERSED) ); - NewEdges.Append( NewE ); - } - - //Substitute anEdge by NewEdges - aSub.Substitute( anEdge, NewEdges ); - } - - //Sorting of EPmap and EVmap and removing repeating points from them - iter.Initialize( EPmap ); - for (; iter.More(); iter.Next()) - { - TColStd_SequenceOfReal Seq; - Seq = iter.Value(); - TopTools_SequenceOfShape SeqShape; - SeqShape = EVmap( iter.Key() ); - TopTools_SequenceOfShape SeqShape2; - SeqShape2 = EWmap( iter.Key() ); - for (i = 1; i < Seq.Length(); i++) - for (j = i+1; j <= Seq.Length(); j++) - if (Seq(j) < Seq(i)) - { - Standard_Real temp = Seq(i); - Seq(i) = Seq(j); - Seq(j) = temp; - TopoDS_Shape tmp = SeqShape(i); - SeqShape(i) = SeqShape(j); - SeqShape(j) = tmp; - tmp = SeqShape2(i); - SeqShape2(i) = SeqShape2(j); - SeqShape2(j) = tmp; - } - EPmap( iter.Key() ) = Seq; - EVmap( iter.Key() ) = SeqShape; - EWmap( iter.Key() ) = SeqShape2; - } - iter.Initialize( EPmap ); - for (; iter.More(); iter.Next()) +void BRepOffsetAPI_DraftAngle::CorrectVertexTol() +{ + TopTools_MapOfShape anInitVertices, anInitEdges, aNewEdges; + TopExp_Explorer anExp(myInitialShape, TopAbs_EDGE); + for(; anExp.More(); anExp.Next()) + { + anInitEdges.Add(anExp.Current()); + TopoDS_Iterator anIter(anExp.Current()); + for(; anIter.More(); anIter.Next()) { - TColStd_SequenceOfReal Seq; - Seq = iter.Value(); - TopTools_SequenceOfShape SeqShape; - SeqShape = EVmap( iter.Key() ); - TopTools_SequenceOfShape SeqShape2; - SeqShape2 = EWmap( iter.Key() ); - Standard_Boolean remove = Standard_True; - while (remove) - { - remove = Standard_False; - for (i = 1; i < Seq.Length(); i++) - if (Abs(Seq(i)-Seq(i+1)) <= Precision::Confusion()) - { - Seq.Remove(i+1); - SeqShape.Remove(i+1); - SeqShape2.Remove(i+1); - remove = Standard_True; - } - } - EPmap( iter.Key() ) = Seq; - EVmap( iter.Key() ) = SeqShape; - EWmap( iter.Key() ) = SeqShape2; + anInitVertices.Add(anIter.Value()); } - - //Reconstruction of seam edges - TopTools_DataMapOfShapeShape VEmap; - iter.Initialize( Emap ); - for (; iter.More(); iter.Next()) + } + // + + BRep_Builder aBB; + myVtxToReplace.Clear(); + anExp.Init(myShape, TopAbs_EDGE); + for(; anExp.More(); anExp.Next()) + { + const TopoDS_Shape& anE = anExp.Current(); + //Skip old (not modified) edges + if(anInitEdges.Contains(anE)) + continue; + // + //Skip processed edges + if(aNewEdges.Contains(anE)) + continue; + // + aNewEdges.Add(anE); + // + Standard_Real anETol = BRep_Tool::Tolerance(TopoDS::Edge(anE)); + TopoDS_Iterator anIter(anE); + for(; anIter.More(); anIter.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge( iter.Key() ); - Standard_Boolean onepoint = Standard_False; - TopTools_ListOfShape NewEdges; - TColStd_SequenceOfReal Seq; - Seq = iter.Value(); - TColStd_SequenceOfReal Seq2; - Seq2 = EPmap( anEdge ); - TopTools_SequenceOfShape SeqVer; - SeqVer = EVmap( anEdge ); - TopTools_SequenceOfShape SeqWire; - SeqWire = EWmap( anEdge ); - TopoDS_Vertex Vfirst, Vlast; - TopExp::Vertices( anEdge, Vfirst, Vlast ); - Standard_Real fpar, lpar, FirstPar, LastPar; - BRep_Tool::Range( anEdge, FirstPar, LastPar ); - fpar = FirstPar; - lpar = Seq(1); - TopoDS_Edge NewE; - Standard_Integer firstind = 1; - if (Abs(fpar-lpar) <= Precision::Confusion()) - { - firstind = 2; - fpar = Seq(1); - lpar = Seq(2); - } + const TopoDS_Vertex& aVtx = TopoDS::Vertex(anIter.Value()); + if(anInitVertices.Contains(aVtx)) + { + if(myVtxToReplace.IsBound(aVtx)) + { + aBB.UpdateVertex(TopoDS::Vertex(myVtxToReplace(aVtx)), anETol + Epsilon(anETol)); + } + else + { + Standard_Real aVTol = BRep_Tool::Tolerance(aVtx); + if(aVTol < anETol) + { + TopoDS_Vertex aNewVtx; + gp_Pnt aVPnt = BRep_Tool::Pnt(aVtx); + aBB.MakeVertex(aNewVtx, aVPnt,anETol + Epsilon(anETol)); + myVtxToReplace.Bind(aVtx, aNewVtx); + } + } + } else - { - if (Seq.Length()%2 != 0) - { - VEmap.Bind( Vfirst, anEdge ); - firstind = 2; - fpar = Seq(1); - if (Seq.Length() > 2) - lpar = Seq(2); - else - onepoint = Standard_True; - } - } - if (!onepoint) - { - TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); - NewE = TopoDS::Edge( aLocalShape ); - //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); - BB.Range( NewE, fpar, lpar ); - NewE.Orientation( TopAbs_FORWARD ); - if (firstind == 1) - { - BB.Add( NewE, Vfirst.Oriented(TopAbs_FORWARD) ); - aLocalShape = SeqVer(1).Oriented(TopAbs_REVERSED); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(1).Oriented(TopAbs_REVERSED) ) ); - } - else - { - aLocalShape = SeqVer(1).Oriented(TopAbs_FORWARD); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - aLocalShape = SeqVer(2).Oriented(TopAbs_REVERSED); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(1).Oriented(TopAbs_FORWARD) ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(2).Oriented(TopAbs_REVERSED) ) ); - } - NewEdges.Append( NewE ); - - firstind++; - for (i = firstind; i < Seq.Length(); i += 2) - { - aLocalShape = anEdge.EmptyCopied(); - NewE = TopoDS::Edge( aLocalShape ); - //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); - fpar = Seq(i); - lpar = Seq(i+1); - BB.Range( NewE, fpar, lpar ); - //Find vertices - for (j = 1; j <= Seq2.Length(); j++) - if (Abs(fpar-Seq2(j)) <= Precision::Confusion()) - break; - NewE.Orientation( TopAbs_FORWARD ); - TopoDS_Shape aLocalShape = SeqVer(j).Oriented(TopAbs_FORWARD); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - aLocalShape = SeqVer(j+1).Oriented(TopAbs_REVERSED); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(j).Oriented(TopAbs_FORWARD) ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(j+1).Oriented(TopAbs_REVERSED) ) ); - NewEdges.Append( NewE ); - } - } - - i = Seq.Length(); - fpar = Seq(i); - lpar = LastPar; - if (Abs(fpar-lpar) <= Precision::Confusion()) - continue; - TopoDS_Shape aLocalShape = anEdge.EmptyCopied(); - NewE = TopoDS::Edge( aLocalShape ); - //NewE = TopoDS::Edge( anEdge.EmptyCopied() ); - BB.Range( NewE, fpar, lpar ); - NewE.Orientation( TopAbs_FORWARD ); - aLocalShape = SeqVer(SeqVer.Length()).Oriented(TopAbs_FORWARD); - BB.Add( NewE, TopoDS::Vertex( aLocalShape ) ); - //BB.Add( NewE, TopoDS::Vertex( SeqVer(SeqVer.Length()).Oriented(TopAbs_FORWARD) ) ); - BB.Add( NewE, Vlast.Oriented(TopAbs_REVERSED) ); - NewEdges.Append( NewE ); - - //Substitute anEdge by NewEdges - aSub.Substitute( anEdge, NewEdges ); - } - - //Removing edges connected with missing extremities of seam edges - TopTools_DataMapIteratorOfDataMapOfShapeShape itve( VEmap ); - for (; itve.More(); itve.Next()) - { - TopoDS_Shape V = itve.Key(); - TopoDS_Shape E = itve.Value(); - TopoDS_Shape W; - for (i = 1; i <= Eseq.Length(); i++) - if (E.IsSame( Eseq(i) )) - { - W = Wseq(i); - break; - } - TopoDS_Shape Etoremove; - eit.Initialize( W ); - for (; eit.More(); eit.Next()) - { - TopoDS_Edge CurE = TopoDS::Edge( eit.Value() ); - if (CurE.IsSame( E )) - continue; - TopoDS_Vertex Vfirst, Vlast; - TopExp::Vertices( CurE, Vfirst, Vlast ); - if (Vfirst.IsSame( V ) || Vlast.IsSame( V )) - { - Etoremove = CurE; - break; - } - } - if (! Etoremove.IsNull()) - { - W.Free( Standard_True ); - BB.Remove( W, Etoremove ); - } + { + aBB.UpdateVertex(aVtx, anETol + Epsilon(anETol)); + } } - + } + // + if(myVtxToReplace.IsEmpty()) + { + return; + } + // + BRepTools_Substitution aSub; + TopTools_DataMapIteratorOfDataMapOfShapeShape anIter(myVtxToReplace); + for(; anIter.More(); anIter.Next()) + { + TopTools_ListOfShape aSubVtx; + aSubVtx.Append(anIter.Value()); + aSub.Substitute(anIter.Key(), aSubVtx); + } aSub.Build( myShape ); if (aSub.IsCopied( myShape )) - { - const TopTools_ListOfShape& listSh = aSub.Copy( myShape ); - if (! listSh.IsEmpty()) - myShape = listSh.First(); - } - - //Reconstruction of wires - TopTools_ListOfShape theCopy; - TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itww( WWmap ); - for (; itww.More(); itww.Next()) - { - CurWire = itww.Key(); - theCopy = aSub.Copy( CurWire ); - CurWire = theCopy.First(); - CurWire.Free( Standard_True ); - TopTools_ListIteratorOfListOfShape itl( itww.Value() ); - for (; itl.More(); itl.Next()) - { - TopoDS_Shape aWire = itl.Value(); - CurFace = WFmap( aWire ); - theCopy = aSub.Copy( aWire ); - aWire = theCopy.First(); - //Adjusting period - TopLoc_Location L; - Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( TopoDS::Face(CurFace), L ); - eit.Initialize( aWire ); - for (; eit.More(); eit.Next()) - { - TopoDS_Edge anEdge = TopoDS::Edge( eit.Value() ); - gp_Pnt2d Pfirst, Plast, Pmid; - BRep_Tool::UVPoints( anEdge, TopoDS::Face(CurFace), Pfirst, Plast ); - BRepAdaptor_Curve2d bc2d( anEdge, TopoDS::Face(CurFace) ); - Pmid = bc2d.Value( (bc2d.FirstParameter()+bc2d.LastParameter())/2. ); - gp_Vec2d offset; - Standard_Boolean translate = Standard_False; - if (Pfirst.X()-2.*M_PI > Precision::Confusion() || - Plast.X()-2.*M_PI > Precision::Confusion() || - Pmid.X()-2.*M_PI > Precision::Confusion()) - { - offset.SetCoord( -2.*M_PI, 0 ); - translate = Standard_True; - } - if (Pfirst.X() < -Precision::Confusion() || - Plast.X() < -Precision::Confusion() || - Pmid.X() < -Precision::Confusion()) - { - offset.SetCoord( 2.*M_PI, 0 ); - translate = Standard_True; - } - if (translate) - { - const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape()); - BRep_ListIteratorOfListOfCurveRepresentation itcr( TE->ChangeCurves() ); - Handle(BRep_GCurve) GC; - - for (; itcr.More(); itcr.Next()) - { - GC = Handle(BRep_GCurve)::DownCast(itcr.Value()); - if (!GC.IsNull() && GC->IsCurveOnSurface( theSurf, L )) - { - Handle(Geom2d_Curve) PC = GC->PCurve(); - PC = Handle(Geom2d_Curve)::DownCast( PC->Translated( offset ) ); - GC->PCurve( PC ); - TE->ChangeCurves().Remove( itcr ); - TE->ChangeCurves().Append( GC ); - break; - } - } - } - } - /////////////////// - eit.Initialize( aWire, Standard_False ); - for (; eit.More(); eit.Next()) - { - TopoDS_Shape anEdge = eit.Value(); - BB.Add( CurWire, anEdge ); - } - if (aSub.IsCopied( CurFace )) - { - theCopy = aSub.Copy( CurFace ); - CurFace = theCopy.First(); - } - CurFace.Free( Standard_True ); - BB.Remove( CurFace, aWire ); - } - } + { + const TopTools_ListOfShape& listSh = aSub.Copy( myShape ); + if (! listSh.IsEmpty()) + myShape = listSh.First(); + } + // } diff --git a/src/Draft/Draft_Modification.cxx b/src/Draft/Draft_Modification.cxx index 5faf59e8b0..b57867bca8 100644 --- a/src/Draft/Draft_Modification.cxx +++ b/src/Draft/Draft_Modification.cxx @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -48,11 +49,83 @@ #include #include #include +#include +// +static Standard_Real EvalTol(const Handle(Geom_Curve)& C3d, + const Handle(Geom2d_Curve) C2d, + const Handle(Geom_Surface)& S, + const Standard_Real f, + const Standard_Real l) +{ + Standard_Real first = f, last = l; + //Set first, last to avoid ErrosStatus = 2 because of + //too strong checking of limits in class CheckCurveOnSurface + // + if(!C3d->IsPeriodic()) + { + first = Max(first, C3d->FirstParameter()); + last = Min(last, C3d->LastParameter()); + } + if(!C2d->IsPeriodic()) + { + first = Max(first, C2d->FirstParameter()); + last = Min(last, C2d->LastParameter()); + } -#include + GeomLib_CheckCurveOnSurface CT(C3d, S, first, last); + CT.Perform(C2d); + if(CT.IsDone()) + { + return CT.MaxDistance(); + } + else + { + if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 && + (C3d->IsPeriodic() || C2d->IsPeriodic()))) + { + //Try to estimate by sample points + Standard_Integer nbint = 22; + Standard_Real dt = (last - first) / nbint; + dt = Max(dt, Precision::Confusion()); + Standard_Real d, dmax = 0.; + gp_Pnt2d aP2d; + gp_Pnt aPC, aPS; + Standard_Integer cnt = 0; + Standard_Real t = first; + for(; t <= last; t += dt) + { + cnt++; + C2d->D0(t, aP2d); + C3d->D0(t, aPC); + S->D0(aP2d.X(), aP2d.Y(), aPS); + d = aPS.SquareDistance(aPC); + if(d > dmax) + { + dmax = d; + } + } + if(cnt < nbint + 1) + { + t = last; + C2d->D0(t, aP2d); + C3d->D0(t, aPC); + S->D0(aP2d.X(), aP2d.Y(), aPS); + d = aPS.SquareDistance(aPC); + if(d > dmax) + { + dmax = d; + } + } -#include -#include + dmax = 1.2 * Sqrt(dmax); + return dmax; + } + else + { + return 0.; + } + } +} //======================================================================= //function : Draft_Modification @@ -445,6 +518,15 @@ Standard_Boolean Draft_Modification::NewCurve2d(const TopoDS_Edge& E, C->Translate(aV2DT); } } + // + Handle(Geom_Curve) aC3d = BRep_Tool::Curve(NewE, Fp, Lp); + Standard_Real newtol = EvalTol(aC3d, C, SB, Fp, Lp); + if(newtol > Tol) + { + Tol = newtol; + BRep_Builder B; + B.UpdateEdge(NewE, newtol); + } return Standard_True; } diff --git a/src/Draft/Draft_Modification_1.cxx b/src/Draft/Draft_Modification_1.cxx index 072f21e443..7e53f85bf1 100644 --- a/src/Draft/Draft_Modification_1.cxx +++ b/src/Draft/Draft_Modification_1.cxx @@ -1211,14 +1211,14 @@ void Draft_Modification::Perform () Extrema_ExtPC myExtPC( pfv, TheCurve ); Dist2Min = RealLast(); for (i = 1; i <= myExtPC.NbExt(); i++) - { - Dist2 = myExtPC.SquareDistance(i); - if (Dist2 < Dist2Min) - { - Dist2Min = Dist2; - pmin = myExtPC.Point(i).Parameter(); - } - } + { + Dist2 = myExtPC.SquareDistance(i); + if (Dist2 < Dist2Min) + { + Dist2Min = Dist2; + pmin = myExtPC.Point(i).Parameter(); + } + } newC->D1(pmin,pfv,newd1); Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.; @@ -1503,6 +1503,7 @@ void Draft_Modification::Perform () for (Vinf.InitEdgeIterator();Vinf.MoreEdge(); Vinf.NextEdge()) { const TopoDS_Edge& Edg = Vinf.Edge(); + Standard_Real initpar = Vinf.Parameter(Edg); //const Draft_EdgeInfo& Einf = myEMap(Edg); Draft_EdgeInfo& Einf = myEMap(Edg); //Vinf.ChangeParameter(Edg) = Parameter(Einf.Geometry(),pvt); @@ -1515,8 +1516,20 @@ void Draft_Modification::Perform () Vinf.ChangeParameter(Edg) = SmartParameter( Einf, BRep_Tool::Tolerance(Edg), pvt, done, S1, S2 ); } else + { + if(Abs(initpar - param) > Precision::PConfusion()) + { + Standard_Real f, l; + TopLoc_Location Loc; + const Handle(Geom_Curve)& aC = BRep_Tool::Curve(Edg, Loc, f, l); + if(aC->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) + { + Einf.SetNewGeometry(Standard_True); + } + } Vinf.ChangeParameter(Edg) = param; } + } itv.Next(); } } diff --git a/src/Geom/Geom_BSplineCurve.cdl b/src/Geom/Geom_BSplineCurve.cdl index 40ba005ce4..37ab870949 100644 --- a/src/Geom/Geom_BSplineCurve.cdl +++ b/src/Geom/Geom_BSplineCurve.cdl @@ -789,6 +789,15 @@ is raises DimensionError; ---Purpose : -- Raised if the length of K is not equal to the number of knots. + Knots (me) + returns Array1OfReal from TColStd + ---Purpose : returns the knot values of the B-spline curve; + -- Warning + -- A knot with a multiplicity greater than 1 is not + -- repeated in the knot table. The Multiplicity function + -- can be used to obtain the multiplicity of each knot. + ---C++ : return const & + is static; KnotSequence (me; K : out Array1OfReal from TColStd) @@ -845,6 +854,12 @@ is -- Standard_DimensionError if the array K is not of -- the appropriate length.Returns the knots sequence. raises DimensionError; + KnotSequence (me) + returns Array1OfReal from TColStd + ---Purpose : returns the knots of the B-spline curve. + -- Knots with multiplicit greater than 1 are repeated + ---C++ : return const & + is static; @@ -910,6 +925,11 @@ is raises DimensionError; ---Purpose : -- Raised if the length of M is not equal to NbKnots. + Multiplicities (me) + returns Array1OfInteger from TColStd + ---Purpose : returns the multiplicity of the knots of the curve. + ---C++ : return const & + is static; NbKnots (me) returns Integer; @@ -933,6 +953,11 @@ is raises DimensionError; ---Purpose : -- Raised if the length of P is not equal to the number of poles. + Poles (me) + returns Array1OfPnt from TColgp + ---Purpose : Returns the poles of the B-spline curve; + ---C++ : return const & + is static; StartPoint (me) returns Pnt; @@ -954,6 +979,11 @@ is raises DimensionError; ---Purpose : -- Raised if the length of W is not equal to NbPoles. + Weights (me) + returns Array1OfReal from TColStd + ---Purpose : Returns the weights of the B-spline curve; + ---C++ : return const & + is static; diff --git a/src/Geom/Geom_BSplineCurve_1.cxx b/src/Geom/Geom_BSplineCurve_1.cxx index ec08ce5a43..7cc8d4f803 100644 --- a/src/Geom/Geom_BSplineCurve_1.cxx +++ b/src/Geom/Geom_BSplineCurve_1.cxx @@ -437,6 +437,11 @@ void Geom_BSplineCurve::Knots (TColStd_Array1OfReal& K) const K = knots->Array1(); } +const TColStd_Array1OfReal& Geom_BSplineCurve::Knots() const +{ + return knots->Array1(); +} + //======================================================================= //function : KnotSequence //purpose : @@ -449,6 +454,11 @@ void Geom_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const K = flatknots->Array1(); } +const TColStd_Array1OfReal& Geom_BSplineCurve::KnotSequence() const +{ + return flatknots->Array1(); +} + //======================================================================= //function : LastUKnotIndex //purpose : @@ -668,6 +678,11 @@ void Geom_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const M = mults->Array1(); } +const TColStd_Array1OfInteger& Geom_BSplineCurve::Multiplicities() const +{ + return mults->Array1(); +} + //======================================================================= //function : NbKnots //purpose : @@ -708,6 +723,11 @@ void Geom_BSplineCurve::Poles (TColgp_Array1OfPnt& P) const P = poles->Array1(); } +const TColgp_Array1OfPnt& Geom_BSplineCurve::Poles() const +{ + return poles->Array1(); +} + //======================================================================= //function : StartPoint //purpose : @@ -757,6 +777,13 @@ void Geom_BSplineCurve::Weights } } +const TColStd_Array1OfReal& Geom_BSplineCurve::Weights() const +{ + if (IsRational()) + return weights->Array1(); + return BSplCLib::NoWeights(); +} + //======================================================================= //function : IsRational //purpose : diff --git a/src/Geom2d/Geom2d_BSplineCurve.cdl b/src/Geom2d/Geom2d_BSplineCurve.cdl index 0196187a54..64c93263c9 100644 --- a/src/Geom2d/Geom2d_BSplineCurve.cdl +++ b/src/Geom2d/Geom2d_BSplineCurve.cdl @@ -843,6 +843,11 @@ is raises DimensionError; --- Purpose : -- Raised if the length of K is not equal to the number of knots. + Knots (me) + returns Array1OfReal from TColStd + ---Purpose : returns the knot values of the B-spline curve; + ---C++ : return const & + is static; KnotSequence (me; K : out Array1OfReal from TColStd) @@ -854,6 +859,15 @@ is raises DimensionError; --- Purpose : -- Raised if the length of K is not equal to NbPoles + Degree + 1 + KnotSequence (me) + returns Array1OfReal from TColStd + ---Purpose : Returns the knots sequence. + -- In this sequence the knots with a multiplicity greater than 1 + -- are repeated. + -- Example : + -- K = {k1, k1, k1, k2, k3, k3, k4, k4, k4} + ---C++ : return const & + is static; @@ -919,6 +933,11 @@ is raises DimensionError; --- Purpose : -- Raised if the length of M is not equal to NbKnots. + Multiplicities (me) + returns Array1OfInteger from TColStd + ---Purpose : returns the multiplicity of the knots of the curve. + ---C++ : return const & + is static; NbKnots (me) returns Integer; @@ -942,6 +961,11 @@ is raises DimensionError; --- Purpose : -- Raised if the length of P is not equal to the number of poles. + Poles (me) + returns Array1OfPnt2d from TColgp + ---Purpose : Returns the poles of the B-spline curve; + ---C++ : return const & + is static; StartPoint (me) returns Pnt2d; @@ -963,6 +987,11 @@ is raises DimensionError; --- Purpose : -- Raised if the length of W is not equal to NbPoles. + Weights (me) + returns Array1OfReal from TColStd + ---Purpose : Returns the weights of the B-spline curve; + ---C++ : return const & + is static; diff --git a/src/Geom2d/Geom2d_BSplineCurve_1.cxx b/src/Geom2d/Geom2d_BSplineCurve_1.cxx index b80b4151e2..3541ed8e97 100644 --- a/src/Geom2d/Geom2d_BSplineCurve_1.cxx +++ b/src/Geom2d/Geom2d_BSplineCurve_1.cxx @@ -440,6 +440,11 @@ void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const K = knots->Array1(); } +const TColStd_Array1OfReal& Geom2d_BSplineCurve::Knots() const +{ + return knots->Array1(); +} + //======================================================================= //function : KnotSequence //purpose : @@ -452,6 +457,11 @@ void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const K = flatknots->Array1(); } +const TColStd_Array1OfReal& Geom2d_BSplineCurve::KnotSequence() const +{ + return flatknots->Array1(); +} + //======================================================================= //function : LastUKnotIndex //purpose : @@ -676,6 +686,11 @@ void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const M = mults->Array1(); } +const TColStd_Array1OfInteger& Geom2d_BSplineCurve::Multiplicities() const +{ + return mults->Array1(); +} + //======================================================================= //function : NbKnots //purpose : @@ -716,6 +731,11 @@ void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const P = poles->Array1(); } +const TColgp_Array1OfPnt2d& Geom2d_BSplineCurve::Poles() const +{ + return poles->Array1(); +} + //======================================================================= //function : StartPoint //purpose : @@ -764,6 +784,13 @@ void Geom2d_BSplineCurve::Weights } } +const TColStd_Array1OfReal& Geom2d_BSplineCurve::Weights() const +{ + if (IsRational()) + return weights->Array1(); + return BSplCLib::NoWeights(); +} + //======================================================================= //function : IsRational //purpose : diff --git a/src/GeomLib/FILES b/src/GeomLib/FILES index a6b44fa64d..b02600b998 100755 --- a/src/GeomLib/FILES +++ b/src/GeomLib/FILES @@ -1 +1,3 @@ GeomLib_CMPLRS.edl +GeomLib_CheckCurveOnSurface.cxx +GeomLib_CheckCurveOnSurface.hxx diff --git a/src/GeomLib/GeomLib_CheckCurveOnSurface.cxx b/src/GeomLib/GeomLib_CheckCurveOnSurface.cxx new file mode 100644 index 0000000000..1fde4f57fa --- /dev/null +++ b/src/GeomLib/GeomLib_CheckCurveOnSurface.cxx @@ -0,0 +1,653 @@ +// Created by: Nikolai BUKHALOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class GeomLib_CheckCurveOnSurface_TargetFunc; + +static +Standard_Boolean MinComputing( + GeomLib_CheckCurveOnSurface_TargetFunc& theFunction, + const Standard_Real theEpsilon, //1.0e-3 + const Standard_Integer theNbParticles, + Standard_Real& theBestValue, + Standard_Real& theBestParameter); + +static Standard_Integer FillSubIntervals( const Handle(Geom_Curve)& theCurve3d, + const Handle(Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + Standard_Integer &theNbParticles, + TColStd_Array1OfReal* const theSubIntervals = 0); + +//======================================================================= +//class : GeomLib_CheckCurveOnSurface_TargetFunc +//purpose : Target function (to be minimized) +//======================================================================= +class GeomLib_CheckCurveOnSurface_TargetFunc : + public math_MultipleVarFunctionWithHessian +{ + public: + GeomLib_CheckCurveOnSurface_TargetFunc( const Adaptor3d_Curve& theC3D, + const Adaptor3d_Curve& theAdCS, + const Standard_Real theFirst, + const Standard_Real theLast): + myCurve1(theC3D), + myCurve2(theAdCS), + myFirst(theFirst), + myLast(theLast) + { + } + + //returns the number of parameters of the function + //(the function is one-dimension). + virtual Standard_Integer NbVariables() const { + return 1; + } + + //returns value of the function when parameters are equal to theX + virtual Standard_Boolean Value(const math_Vector& theX, + Standard_Real& theFVal) + { + return Value(theX(1), theFVal); + } + + //returns value of the one-dimension-function when parameter + //is equal to theX + Standard_Boolean Value( const Standard_Real theX, + Standard_Real& theFVal) const + { + try + { + OCC_CATCH_SIGNALS + if (!CheckParameter(theX)) + return Standard_False; + + const gp_Pnt aP1(myCurve1.Value(theX)), + aP2(myCurve2.Value(theX)); + + theFVal = -1.0*aP1.SquareDistance(aP2); + } + catch(Standard_Failure) { + return Standard_False; + } + // + return Standard_True; + } + + //see analogical method for abstract owner class math_MultipleVarFunction + virtual Standard_Integer GetStateNumber() + { + return 0; + } + + //returns the gradient of the function when parameters are + //equal to theX + virtual Standard_Boolean Gradient(const math_Vector& theX, + math_Vector& theGrad) + { + return Derive(theX(1), theGrad(1)); + } + + //returns 1st derivative of the the one-dimension-function when + //parameter is equal to theX + Standard_Boolean Derive(const Standard_Real theX, Standard_Real& theDeriv) const + { + try + { + OCC_CATCH_SIGNALS + if (!CheckParameter(theX)) + { + return Standard_False; + } + // + gp_Pnt aP1, aP2; + gp_Vec aDC1, aDC2; + // + myCurve1.D1(theX, aP1, aDC1); + myCurve2.D1(theX, aP2, aDC2); + + const gp_Vec aVec1(aP1, aP2), aVec2(aDC2-aDC1); + // + theDeriv = -2.0*aVec1.Dot(aVec2); + } + catch(Standard_Failure) + { + return Standard_False; + } + + return Standard_True; + } + + //returns value and gradient + virtual Standard_Boolean Values(const math_Vector& theX, + Standard_Real& theVal, + math_Vector& theGrad) + { + if (!Value(theX, theVal)) + { + return Standard_False; + } + // + if (!Gradient(theX, theGrad)) { + return Standard_False; + } + // + return Standard_True; + } + + //returns value, gradient and hessian + virtual Standard_Boolean Values(const math_Vector& theX, + Standard_Real& theVal, + math_Vector& theGrad, + math_Matrix& theHessian) + { + if (!Value(theX, theVal)) + { + return Standard_False; + } + // + if (!Gradient(theX, theGrad)) + { + return Standard_False; + } + // + theHessian(1,1) = theGrad(1); + // + return Standard_True; + } + // + Standard_Real FirstParameter() const + { + return myFirst; + } + + // + Standard_Real LastParameter() const + { + return myLast; + } + + private: + GeomLib_CheckCurveOnSurface_TargetFunc operator=(GeomLib_CheckCurveOnSurface_TargetFunc&); + + //checks if the function can be computed when its parameter is + //equal to theParam + Standard_Boolean CheckParameter(const Standard_Real theParam) const + { + return ((myFirst <= theParam) && (theParam <= myLast)); + } + + const Adaptor3d_Curve& myCurve1; + const Adaptor3d_Curve& myCurve2; + const Standard_Real myFirst; + const Standard_Real myLast; +}; + +//======================================================================= +//class : GeomLib_CheckCurveOnSurface_Local +//purpose : Created for parallelization possibility only +//======================================================================= +class GeomLib_CheckCurveOnSurface_Local +{ +public: + GeomLib_CheckCurveOnSurface_Local( + const Handle(Geom_Curve)& theCurve3D, + const Handle(Geom2d_Curve)& theCurve2D, + const Handle(Geom_Surface)& theSurface, + const TColStd_Array1OfReal& theIntervalsArr, + const Standard_Real theEpsilonRange, + const Standard_Integer theNbParticles): + myCurve3D(theCurve3D), + myCurve2D(theCurve2D), + mySurface(theSurface), + mySubIntervals(theIntervalsArr), + myEpsilonRange(theEpsilonRange), + myNbParticles(theNbParticles), + myArrOfDist(theIntervalsArr.Lower(), theIntervalsArr.Upper()-1), + myArrOfParam(theIntervalsArr.Lower(), theIntervalsArr.Upper()-1) + { + } + + void operator()(const Standard_Integer& theIndex) const + { + //For every sub-interval (which is set by mySubIntervals array) this method + //computes optimal value of GeomLib_CheckCurveOnSurface_TargetFunc function. + //This optimal value will be put in corresponding (depending on theIndex - the + //identificator of the current interval in mySubIntervals array) cell of + //myArrOfDist and myArrOfParam arrays. + const GeomAdaptor_Curve anAC(myCurve3D); + const Handle(Adaptor2d_HCurve2d) anAd2dC = new Geom2dAdaptor_GHCurve(myCurve2D); + const Handle(Adaptor3d_HSurface) anAdS = new GeomAdaptor_HSurface(mySurface); + + const Adaptor3d_CurveOnSurface anACS(anAd2dC, anAdS); + + GeomLib_CheckCurveOnSurface_TargetFunc aFunc( anAC, anACS, + mySubIntervals.Value(theIndex), + mySubIntervals.Value(theIndex+1)); + + Standard_Real aMinDist = RealLast(), aPar = 0.0; + if(!MinComputing(aFunc, myEpsilonRange, myNbParticles, aMinDist, aPar)) + { + myArrOfDist(theIndex) = RealLast(); + myArrOfParam(theIndex) = aFunc.FirstParameter(); + return; + } + + myArrOfDist(theIndex) = aMinDist; + myArrOfParam(theIndex) = aPar; + } + + //Returns optimal value (inverse of square of maximal distance) + void OptimalValues(Standard_Real& theMinimalValue, Standard_Real& theParameter) const + { + //This method looks for the minimal value of myArrOfDist. + + const Standard_Integer aStartInd = myArrOfDist.Lower(); + theMinimalValue = myArrOfDist(aStartInd); + theParameter = myArrOfParam(aStartInd); + for(Standard_Integer i = aStartInd + 1; i <= myArrOfDist.Upper(); i++) + { + if(myArrOfDist(i) < theMinimalValue) + { + theMinimalValue = myArrOfDist(i); + theParameter = myArrOfParam(i); + } + } + } + +private: + GeomLib_CheckCurveOnSurface_Local operator=(GeomLib_CheckCurveOnSurface_Local&); + const Handle(Geom_Curve)& myCurve3D; + const Handle(Geom2d_Curve)& myCurve2D; + const Handle(Geom_Surface)& mySurface; + + const TColStd_Array1OfReal& mySubIntervals; + const Standard_Real myEpsilonRange; + const Standard_Integer myNbParticles; + mutable NCollection_Array1 myArrOfDist; + mutable NCollection_Array1 myArrOfParam; +}; + +//======================================================================= +//function : GeomLib_CheckCurveOnSurface +//purpose : +//======================================================================= +GeomLib_CheckCurveOnSurface::GeomLib_CheckCurveOnSurface() +: + myFirst(0.), + myLast(0.), + myErrorStatus(0), + myMaxDistance(RealLast()), + myMaxParameter(0.) +{ +} + +//======================================================================= +//function : GeomLib_CheckCurveOnSurface +//purpose : +//======================================================================= +GeomLib_CheckCurveOnSurface:: + GeomLib_CheckCurveOnSurface(const Handle(Geom_Curve)& theCurve, + const Handle(Geom_Surface)& theSurface, + const Standard_Real theFirst, + const Standard_Real theLast): + myCurve(theCurve), + mySurface(theSurface), + myFirst(theFirst), + myLast(theLast), + myErrorStatus(0), + myMaxDistance(RealLast()), + myMaxParameter(0.) +{ +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void GeomLib_CheckCurveOnSurface::Init() +{ + myCurve.Nullify(); + mySurface.Nullify(); + myFirst = 0.0; + myLast = 0.0; + myErrorStatus = 0; + myMaxDistance = RealLast(); + myMaxParameter = 0.0; +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void GeomLib_CheckCurveOnSurface::Init( const Handle(Geom_Curve)& theCurve, + const Handle(Geom_Surface)& theSurface, + const Standard_Real theFirst, + const Standard_Real theLast) +{ + myCurve = theCurve; + mySurface = theSurface; + myFirst = theFirst; + myLast = theLast; + myErrorStatus = 0; + myMaxDistance = RealLast(); + myMaxParameter = 0.0; +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= + +#ifndef HAVE_TBB +//After fixing bug # 26365, this fragment should be deleted +//(together the text "#ifdef HAVE_TBB") + +void GeomLib_CheckCurveOnSurface::Perform(const Handle(Geom2d_Curve)& thePCurve, + const Standard_Boolean) +{ + const Standard_Boolean isTheMTDisabled = Standard_True; +#else +void GeomLib_CheckCurveOnSurface::Perform(const Handle(Geom2d_Curve)& thePCurve, + const Standard_Boolean isTheMTDisabled) +{ +#endif + if( myCurve.IsNull() || + mySurface.IsNull() || + thePCurve.IsNull()) + { + myErrorStatus = 1; + return; + } + + if( (myCurve->FirstParameter() > myFirst) || + (myCurve->LastParameter() < myLast) || + (thePCurve->FirstParameter() > myFirst) || + (thePCurve->LastParameter() < myLast)) + { + myErrorStatus = 2; + return; + } + + const Standard_Real anEpsilonRange = 1.e-3; + + Standard_Integer aNbParticles = 3; + + //Polynomial function with degree n has not more than n-1 maxima and + //minima (degree of 1st derivative is equal to n-1 => 1st derivative has + //no greater than n-1 roots). Consequently, this function has + //maximum n monotonicity intervals. That is a good idea to try to put + //at least one particle in every monotonicity interval. Therefore, + //number of particles should be equal to n. + + const Standard_Integer aNbSubIntervals = + FillSubIntervals( myCurve, thePCurve, + myFirst, myLast, aNbParticles); + + if(!aNbSubIntervals) + { + myErrorStatus = 3; + return; + } + + try { + OCC_CATCH_SIGNALS + + TColStd_Array1OfReal anIntervals(1, aNbSubIntervals+1); + FillSubIntervals(myCurve, thePCurve, myFirst, myLast, aNbParticles, &anIntervals); + + GeomLib_CheckCurveOnSurface_Local aComp(myCurve, thePCurve, + mySurface, anIntervals, anEpsilonRange, aNbParticles); + + OSD_Parallel::For(anIntervals.Lower(), anIntervals.Upper(), aComp, isTheMTDisabled); + + aComp.OptimalValues(myMaxDistance, myMaxParameter); + + myMaxDistance = sqrt(Abs(myMaxDistance)); + } + catch (Standard_Failure) { + myErrorStatus = 3; + } +} + +//======================================================================= +// Function : FillSubIntervals +// purpose : Divides [theFirst, theLast] interval on parts +// in order to make searching-algorithm more precisely +// (fills theSubIntervals array). +// Returns number of subintervals. +//======================================================================= +Standard_Integer FillSubIntervals(const Handle(Geom_Curve)& theCurve3d, + const Handle(Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + Standard_Integer &theNbParticles, + TColStd_Array1OfReal* const theSubIntervals) +{ + const Standard_Real anArrTempC[2] = {theFirst, theLast}; + const TColStd_Array1OfReal anArrTemp(anArrTempC[0], 1, 2); + + theNbParticles = 3; + Handle(Geom2d_BSplineCurve) aBS2DCurv; + Handle(Geom_BSplineCurve) aBS3DCurv; + + // + if (theCurve3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) + { + aBS3DCurv = Handle(Geom_BSplineCurve):: + DownCast(Handle(Geom_TrimmedCurve):: + DownCast(theCurve3d)->BasisCurve()); + } + else + { + aBS3DCurv = Handle(Geom_BSplineCurve)::DownCast(theCurve3d); + } + + if (theCurve2d->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) + { + aBS2DCurv = Handle(Geom2d_BSplineCurve):: + DownCast(Handle(Geom2d_TrimmedCurve):: + DownCast(theCurve2d)->BasisCurve()); + } + else + { + aBS2DCurv = Handle(Geom2d_BSplineCurve)::DownCast(theCurve2d); + } + + const TColStd_Array1OfReal &anArrKnots3D = !aBS3DCurv.IsNull() ? + aBS3DCurv->Knots() : + anArrTemp; + const TColStd_Array1OfReal &anArrKnots2D = !aBS2DCurv.IsNull() ? + aBS2DCurv->Knots() : + anArrTemp; + + Standard_Integer aNbSubIntervals = 1; + + try + { + OCC_CATCH_SIGNALS + const Standard_Integer anIndMax3D = anArrKnots3D.Upper(), + anIndMax2D = anArrKnots2D.Upper(); + + Standard_Integer anIndex3D = anArrKnots3D.Lower(), + anIndex2D = anArrKnots2D.Lower(); + + if(theSubIntervals) + theSubIntervals->ChangeValue(aNbSubIntervals) = theFirst; + + while((anIndex3D <= anIndMax3D) && (anIndex2D <= anIndMax2D)) + { + const Standard_Real aVal3D = anArrKnots3D.Value(anIndex3D), + aVal2D = anArrKnots2D.Value(anIndex2D); + const Standard_Real aDelta = aVal3D - aVal2D; + + if(aDelta < Precision::PConfusion()) + {//aVal3D <= aVal2D + if((aVal3D > theFirst) && (aVal3D < theLast)) + { + aNbSubIntervals++; + + if(theSubIntervals) + theSubIntervals->ChangeValue(aNbSubIntervals) = aVal3D; + } + + anIndex3D++; + + if(-aDelta < Precision::PConfusion()) + {//aVal3D == aVal2D + anIndex2D++; + } + } + else + {//aVal2D < aVal3D + if((aVal2D > theFirst) && (aVal2D < theLast)) + { + aNbSubIntervals++; + + if(theSubIntervals) + theSubIntervals->ChangeValue(aNbSubIntervals) = aVal2D; + } + + anIndex2D++; + } + } + + if(theSubIntervals) + theSubIntervals->ChangeValue(aNbSubIntervals+1) = theLast; + + if(!aBS3DCurv.IsNull()) + { + theNbParticles = Max(theNbParticles, aBS3DCurv->Degree()); + } + + if(!aBS2DCurv.IsNull()) + { + theNbParticles = Max(theNbParticles, aBS2DCurv->Degree()); + } + } + catch(Standard_Failure) + { +#ifdef OCCT_DEBUG + cout << "ERROR! BRepLib_CheckCurveOnSurface.cxx, " + "FillSubIntervals(): Incorrect filling!" << endl; +#endif + + aNbSubIntervals = 0; + } + + return aNbSubIntervals; +} + +//======================================================================= +//class : MinComputing +//purpose : Performs computing minimal value +//======================================================================= +Standard_Boolean MinComputing ( + GeomLib_CheckCurveOnSurface_TargetFunc& theFunction, + const Standard_Real theEpsilon, //1.0e-3 + const Standard_Integer theNbParticles, + Standard_Real& theBestValue, + Standard_Real& theBestParameter) +{ + try + { + OCC_CATCH_SIGNALS + + //They are used for finding a position of theNbParticles worst places + const Standard_Integer aNbControlPoints = 3*theNbParticles; + // + math_Vector aParInf(1, 1), aParSup(1, 1), anOutputParam(1, 1), aStepPar(1,1); + aParInf(1) = theFunction.FirstParameter(); + aParSup(1) = theFunction.LastParameter(); + theBestParameter = aParInf(1); + theBestValue = RealLast(); + + const Standard_Real aDeltaParam = aParSup(1) - aParInf(1); + if(aDeltaParam < Precision::PConfusion()) + return Standard_False; + + aStepPar(1) = theEpsilon*aDeltaParam; + + math_PSOParticlesPool aParticles(theNbParticles, 1); + + const Standard_Real aStep = aDeltaParam/(aNbControlPoints-1); + Standard_Integer aCount = 1; + for(Standard_Real aPrm = aParInf(1); aCount <= aNbControlPoints; aCount++, + aPrm = (aCount == aNbControlPoints)? aParSup(1) : aPrm+aStep) + { + Standard_Real aVal = RealLast(); + theFunction.Value(aPrm, aVal); + + PSO_Particle* aParticle = aParticles.GetWorstParticle(); + + if(aVal > aParticle->BestDistance) + continue; + + aParticle->Position[0] = aPrm; + aParticle->BestPosition[0] = aPrm; + aParticle->Distance = aVal; + aParticle->BestDistance = aVal; + } + + math_PSO aPSO(&theFunction, aParInf, aParSup, aStepPar); + aPSO.Perform(aParticles, theNbParticles, theBestValue, anOutputParam); + + //Here, anOutputParam contains parameter, which is near to optimal. + //It needs to be more precise. Precision is made by math_NewtonMinimum. + math_NewtonMinimum anA(theFunction); + anA.Perform(theFunction, anOutputParam); + + if(!anA.IsDone()) + { +#ifdef OCCT_DEBUG + cout << "BRepLib_CheckCurveOnSurface::Compute(): No solution found!" << endl; +#endif + return Standard_False; + } + + anA.Location(anOutputParam); + theBestParameter = anOutputParam(1); + theBestValue = anA.Minimum(); + } + catch(Standard_Failure) + { +#ifdef OCCT_DEBUG + cout << "BRepLib_CheckCurveOnSurface.cxx: Exception in MinComputing()!" << endl; +#endif + return Standard_False; + } + + return Standard_True; +} diff --git a/src/GeomLib/GeomLib_CheckCurveOnSurface.hxx b/src/GeomLib/GeomLib_CheckCurveOnSurface.hxx new file mode 100644 index 0000000000..f0ff6ad24b --- /dev/null +++ b/src/GeomLib/GeomLib_CheckCurveOnSurface.hxx @@ -0,0 +1,117 @@ +// Created by: Nikolai BUKHALOV +// Copyright (c) 2015 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomLib_CheckCurveOnSurface_HeaderFile +#define _GeomLib_CheckCurveOnSurface_HeaderFile + +#include +#include + +class Geom_Surface; +class Geom2d_Curve; + +//! Computes the max distance between 3D-curve and 2D-curve +//! in some surface. +class GeomLib_CheckCurveOnSurface +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Default contructor + Standard_EXPORT GeomLib_CheckCurveOnSurface(void); + + //! Contructor + Standard_EXPORT GeomLib_CheckCurveOnSurface(const Handle(Geom_Curve)& theCurve, + const Handle(Geom_Surface)& theSurface, + const Standard_Real theFirst, + const Standard_Real theLast); + + //! Sets the data for the algorithm + Standard_EXPORT void Init (const Handle(Geom_Curve)& theCurve, + const Handle(Geom_Surface)& theSurface, + const Standard_Real theFirst, + const Standard_Real theLast); + + //! Initializes all members by dafault values + Standard_EXPORT void Init(); + + //! Computes the max distance for the 3d curve + //! and 2d curve + //! If isTheMultyTheadDisabled == TRUE then computation will be made + //! without any parallelization. + Standard_EXPORT void Perform(const Handle(Geom2d_Curve)& thePCurve, + const Standard_Boolean isTheMultyTheradDisabled = Standard_False); + + //! Returns my3DCurve + const Handle(Geom_Curve)& Curve() const + { + return myCurve; + } + + //! Returns mySurface + const Handle(Geom_Surface)& Surface() const + { + return mySurface; + } + + //! Returns first and last parameter of the curves + //! (2D- and 3D-curves are considered to have same range) + void Range (Standard_Real& theFirst, Standard_Real& theLast) + { + theFirst = myFirst; + theLast = myLast; + } + + //! Returns true if the max distance has been found + Standard_Boolean IsDone() const + { + return (myErrorStatus == 0); + } + + //! Returns error status + //! The possible values are: + //! 0 - OK; + //! 1 - null curve or surface or 2d curve; + //! 2 - invalid parametric range; + //! 3 - error in calculations. + Standard_Integer ErrorStatus() const + { + return myErrorStatus; + } + + //! Returns max distance + Standard_Real MaxDistance() const + { + return myMaxDistance; + } + + //! Returns parameter in which the distance is maximal + Standard_Real MaxParameter() const + { + return myMaxParameter; + } + +private: + + Handle(Geom_Curve) myCurve; + Handle(Geom_Surface) mySurface; + Standard_Real myFirst; + Standard_Real myLast; + Standard_Integer myErrorStatus; + Standard_Real myMaxDistance; + Standard_Real myMaxParameter; +}; + +#endif // _BRepLib_CheckCurveOnSurface_HeaderFile diff --git a/tests/draft/angle/G2 b/tests/draft/angle/G2 index bb32173844..c6579f443b 100755 --- a/tests/draft/angle/G2 +++ b/tests/draft/angle/G2 @@ -1,5 +1,7 @@ #E6---------------------------------------------- -puts "TODO OCC22803 ALL: Faulty shapes in variables faulty_1 to faulty_" +#puts "TODO OCC22803 ALL: Faulty shapes in variables faulty_1 to faulty_" +puts "TODO OCC26426 ALL: Error: The tolerance of the resulting shape is too big " + ptorus pt 25 24 90 profile pr o 20 18 5 p 0 -1 0 1 0 0 l 10 t 0 30 \ diff --git a/tests/draft/angle/K5 b/tests/draft/angle/K5 index 068e4c6946..7ce428eee4 100644 --- a/tests/draft/angle/K5 +++ b/tests/draft/angle/K5 @@ -1,5 +1,5 @@ #C5---------------------------------------------- -puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_6" +puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_" plane ps 10 -3 0 1 0 0 0 .2 1 psphere ps ps 20 diff --git a/tests/draft/angle/K7 b/tests/draft/angle/K7 index 9f0420c715..7c60344507 100644 --- a/tests/draft/angle/K7 +++ b/tests/draft/angle/K7 @@ -1,5 +1,5 @@ #D3--------------------------------------------- -puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_6" +puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_" plane pt 0 0 0 1 0 0 ptorus pt pt 9 7 diff --git a/tests/draft/angle/M2 b/tests/draft/angle/M2 index 264566958f..ba4bd0cb83 100644 --- a/tests/draft/angle/M2 +++ b/tests/draft/angle/M2 @@ -1,8 +1,9 @@ # Original bug : pro12877 # Date : 02 Dec 98 -puts "TODO OCC22803 All: Error: The tolerance of the resulting shape is too big" +#puts "TODO OCC22803 All: Error: The tolerance of the resulting shape is too big" #puts "TODO OCC23511 Debian60-64: The area of the resulting shape is 186543" +puts "TODO OCC26426 All: Faulty shapes in variables faulty_1 to faulty_" restore [locate_data_file CFE903_pro12ggx.rle] base diff --git a/tests/draft/angle/M4 b/tests/draft/angle/M4 index 9b55646153..993347f5a2 100644 --- a/tests/draft/angle/M4 +++ b/tests/draft/angle/M4 @@ -1,7 +1,7 @@ # Original bug : pro16449 # Date : 18 Dec 98 -puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_4" +puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_" restore [locate_data_file CFE903_pro16gha.rle] base