// File: BRepFill_OffsetWire.cxx // Created: Thu Apr 20 10:33:55 1995 // Author: Bruno DUMORTIER // // Modified by skv - Fri Jul 8 11:21:38 2005 OCC9145 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DRAW #include #include #include #include #endif #if defined(DRAW) || defined(DEB) static Standard_Boolean AffichEdge = Standard_False; #endif #ifdef DRAW static Standard_Boolean AffichGeom = Standard_False; static Standard_Boolean Affich2d = Standard_False; static Standard_Integer NbTRIMEDGES = 0; static Standard_Integer NbOFFSET = 0; static Standard_Integer NbBISSEC = 0; #ifndef WNT static char tname[100]; static Standard_CString name = tname ; #endif #endif // Modified by Sergey KHROMOV - Thu Nov 16 17:24:39 2000 Begin static void QuasiFleche(const Adaptor3d_Curve& C, const Standard_Real Deflection2, const Standard_Real Udeb, const gp_Pnt& Pdeb, const gp_Vec& Vdeb, const Standard_Real Ufin, const gp_Pnt& Pfin, const gp_Vec& Vfin, const Standard_Integer Nbmin, const Standard_Real Eps, TColStd_SequenceOfReal& Parameters, TColgp_SequenceOfPnt& Points); static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters, TColgp_SequenceOfPnt& Points, const Adaptor3d_Curve& C, const Standard_Real Deflection, const Standard_Real U1, const Standard_Real U2, const Standard_Real EPSILON, const Standard_Integer Nbmin); static void CheckBadEdges(const TopoDS_Face& Spine, const Standard_Real Offset, const BRepMAT2d_BisectingLocus& Locus, const BRepMAT2d_LinkTopoBilo& Link, TopTools_ListOfShape& BadEdges); static Standard_Integer CutEdge (const TopoDS_Edge& E, const TopoDS_Face& F, Standard_Integer ForceCut, TopTools_ListOfShape& Cuts); static void CutCurve (const Handle(Geom2d_TrimmedCurve)& C, const Standard_Integer nbParts, TColGeom2d_SequenceOfCurve& theCurves); // Modified by Sergey KHROMOV - Thu Nov 16 17:24:47 2000 End static void EdgeVertices (const TopoDS_Edge& E, TopoDS_Vertex& V1, TopoDS_Vertex& V2) { if (E.Orientation() == TopAbs_REVERSED) { TopExp::Vertices(E,V2,V1); } else { TopExp::Vertices(E,V1,V2); } } static void UpdateDetromp (TopTools_ListOfShape& Detromp1, TopTools_ListOfShape& Detromp2, const TopTools_SequenceOfShape& Vertices, const TColgp_SequenceOfPnt& Params, const Bisector_Bisec& Bisec, const Standard_Boolean SOnE, const Standard_Boolean EOnE, const BRepFill_TrimEdgeTool& Trim); static Standard_Boolean VertexFromNode (const Handle(MAT_Node)& aNode, const Standard_Real Offset, gp_Pnt2d& PN, BRepFill_DataMapOfNodeShape& MapNodeVertex, TopoDS_Vertex& VN); static void StoreInMap (const TopoDS_Shape& V1, const TopoDS_Shape& V2, TopTools_IndexedDataMapOfShapeShape& MapVV); static void TrimEdge (const TopoDS_Edge& CurrentEdge, const TopTools_ListOfShape& D, TopTools_SequenceOfShape& Sv, TColStd_SequenceOfReal& MapverPar, TopTools_SequenceOfShape& S, TopTools_IndexedDataMapOfShapeShape& MapVV); static Standard_Boolean DoubleOrNotInside (const TopTools_ListOfShape& EC, const TopoDS_Vertex& V); static Standard_Boolean IsSmallClosedEdge(const TopoDS_Edge& anEdge, const TopoDS_Vertex& aVertex); static void MakeCircle (const TopoDS_Edge& E, const TopoDS_Vertex& V, const TopoDS_Face& F, const Standard_Real Offset, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map, const Handle(Geom_Plane)& RefPlane); static void MakeOffset (const TopoDS_Edge& E, const TopoDS_Face& F, const Standard_Real Offset, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map, const Handle(Geom_Plane)& RefPlane); //======================================================================= //function : KPartCircle //purpose : //======================================================================= static Standard_Boolean KPartCircle (const TopoDS_Face& mySpine, const Standard_Real myOffset, const Standard_Real Alt, TopoDS_Shape& myShape, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& myMap, Standard_Boolean& myIsDone) { // Un seul contour qui est un cercle ferme TopExp_Explorer exp(mySpine,TopAbs_EDGE); Standard_Integer NbEdges = 0; TopoDS_Edge E; for (; exp.More(); exp.Next()) { NbEdges++; E = TopoDS::Edge(exp.Current()); if (NbEdges > 1) return Standard_False; } TopoDS_Vertex V1,V2; TopExp::Vertices(E,V1,V2); if (!V1.IsSame(V2)) return Standard_False; Standard_Real f,l; TopLoc_Location L; Handle(Geom_Curve) C = BRep_Tool::Curve(E,L,f,l); if (C->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { Handle(Geom_TrimmedCurve) Ct = Handle(Geom_TrimmedCurve)::DownCast(C); C = Ct->BasisCurve(); } if (!C->IsKind(STANDARD_TYPE(Geom_Circle))) return Standard_False; Handle(Geom_Circle) CE = Handle(Geom_Circle)::DownCast(C); Standard_Real anOffset = myOffset; if (E.Orientation() == TopAbs_REVERSED) anOffset *= -1; if (anOffset < 0. || Abs(anOffset) < CE->Radius()) { Handle(Geom_Circle) OC = new Geom_Circle (CE->Position(),CE->Radius() - anOffset); myShape = BRepLib_MakeEdge(OC,f,l); myShape.Orientation(E.Orientation()); myShape.Location(L); if (Alt != 0.) { BRepAdaptor_Surface S(mySpine,0); gp_Ax1 Nor = S.Plane().Axis(); gp_Trsf T; gp_Vec Trans(Nor.Direction()); Trans = Alt*Trans; T.SetTranslation(Trans); myShape.Move(TopLoc_Location(T)); } TopTools_ListOfShape LL; LL.Append(myShape); myMap.Add(E,LL); } myIsDone = Standard_True; return Standard_True; } //======================================================================= //function : BRepFill_OffsetWire //purpose : //======================================================================= BRepFill_OffsetWire::BRepFill_OffsetWire() :myIsDone(Standard_False) { } //======================================================================= //function : BRepFill_OffsetWire //purpose : //======================================================================= BRepFill_OffsetWire::BRepFill_OffsetWire(const TopoDS_Face& Spine, const GeomAbs_JoinType Join ) { Init(Spine,Join); } //======================================================================= //function : Init //purpose : //======================================================================= void BRepFill_OffsetWire::Init(const TopoDS_Face& Spine, const GeomAbs_JoinType Join ) { Standard_NotImplemented_Raise_if(Join > GeomAbs_Arc, "Only GeomAbs_Arc is implemented"); myIsDone = Standard_False; TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD); mySpine = TopoDS::Face(aLocalShape); // mySpine = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD)); myJoinType = Join; myMap.Clear(); myMapSpine.Clear(); //------------------------------------------------------------------ // decoupe du spine pour les lieux bissecteurs. //------------------------------------------------------------------ // Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 Begin static BRepMAT2d_Explorer Exp; Exp.Perform(mySpine); // TopoDS_Face anOldSpine = mySpine; mySpine = TopoDS::Face(Exp.ModifiedShape(mySpine)); PrepareSpine (); // Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 End TopoDS_Shape aShape; BRepFill_IndexedDataMapOfOrientedShapeListOfShape aMap; Standard_Boolean Done; if (KPartCircle(myWorkSpine,1.,0.,aShape,aMap,Done)) return; //----------------------------------------------------- // Calcul de la carte des lieux bissecteurs a gauche. // et des Liens Topologie -> elements de base de la carte. //----------------------------------------------------- // Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 Begin // static BRepMAT2d_Explorer Exp; // Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 End Exp.Perform(myWorkSpine); myBilo.Compute(Exp,1,MAT_Left); myLink.Perform(Exp,myBilo); } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean BRepFill_OffsetWire::IsDone() const { return myIsDone; } //======================================================================= //function : Spine //purpose : //======================================================================= const TopoDS_Face& BRepFill_OffsetWire::Spine() const { return mySpine; } //======================================================================= //function : Shape //purpose : //======================================================================= const TopoDS_Shape& BRepFill_OffsetWire::Shape() const { return myShape; } //======================================================================= //function : GeneratedShapes //purpose : //======================================================================= const TopTools_ListOfShape& BRepFill_OffsetWire::GeneratedShapes (const TopoDS_Shape& SpineShape) { if (!myCallGen) { if (!myMapSpine.IsEmpty()) { // myMapSpine peut etre vide si on est passe par PerformWithBilo. TopTools_DataMapIteratorOfDataMapOfShapeShape it(myMapSpine); for (; it.More(); it.Next()) { if (myMap.Contains(it.Key())) { if (!myMap.Contains(it.Value())) { TopTools_ListOfShape L; myMap.Add(it.Value(),L); } if ( !it.Value().IsSame(it.Key())) { myMap.ChangeFromKey(it.Value()).Append(myMap.ChangeFromKey(it.Key())); //myMap.UnBind(it.Key()); TopoDS_Shape LastShape = myMap.FindKey(myMap.Extent()); TopTools_ListOfShape LastList; LastList.Append(myMap(myMap.Extent())); myMap.RemoveLast(); if (myMap.FindIndex(it.Key()) != 0) myMap.Substitute(myMap.FindIndex(it.Key()), LastShape, LastList); } } if (myMap.Contains(it.Key().Reversed())) { if (!myMap.Contains(it.Value().Reversed())) { TopTools_ListOfShape L; myMap.Add(it.Value().Reversed(),L); } if ( !it.Value().IsSame(it.Key())) { myMap.ChangeFromKey(it.Value().Reversed()).Append(myMap.ChangeFromKey(it.Key().Reversed())); //myMap.UnBind(it.Key().Reversed()); TopoDS_Shape LastShape = myMap.FindKey(myMap.Extent()); TopTools_ListOfShape LastList; LastList.Append(myMap(myMap.Extent())); myMap.RemoveLast(); if (myMap.FindIndex(it.Key().Reversed()) != 0) myMap.Substitute(myMap.FindIndex(it.Key().Reversed()), LastShape, LastList); } } } } myCallGen = Standard_True; } if (myMap.Contains(SpineShape)) { return myMap.FindFromKey(SpineShape); } else { static TopTools_ListOfShape Empty; return Empty; } } //======================================================================= //function : JoinType //purpose : //======================================================================= GeomAbs_JoinType BRepFill_OffsetWire::JoinType() const { return myJoinType; } //======================================================================= //function : Perform //purpose : //======================================================================= void BRepFill_OffsetWire::Perform (const Standard_Real Offset, const Standard_Real Alt) { // Modified by skv - Fri Jul 8 11:21:38 2005 OCC9145 Begin try { OCC_CATCH_SIGNALS myCallGen = Standard_False; if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone)) return; TopoDS_Face oldWorkSpain = myWorkSpine; TopTools_ListOfShape BadEdges; CheckBadEdges(myWorkSpine,Offset,myBilo,myLink,BadEdges); if(!BadEdges.IsEmpty()) { // Modification of myWorkSpine; //cout << "Modification of myWorkSpine : " << BadEdges.Extent() << endl; BRepTools_Substitution aSubst; TopTools_ListIteratorOfListOfShape it(BadEdges); TopTools_ListOfShape aL; Standard_Real aDefl = .01 * Abs(Offset); TColStd_SequenceOfReal Parameters; TColgp_SequenceOfPnt Points; for(; it.More(); it.Next()) { aL.Clear(); Parameters.Clear(); Points.Clear(); const TopoDS_Shape& anE = it.Value(); TopoDS_Vertex Vf, Vl; TopExp::Vertices(TopoDS::Edge(anE), Vf, Vl); Standard_Real f, l; Handle(Geom_Curve) G3d = BRep_Tool::Curve(TopoDS::Edge(anE),f,l); GeomAdaptor_Curve AC(G3d,f,l); PerformCurve(Parameters, Points, AC, aDefl, f, l, Precision::Confusion(), 2); Standard_Integer NPnts = Points.Length(); if(NPnts > 2) { //cout << NPnts << " points " << endl; TopoDS_Vertex FV = Vf; TopoDS_Vertex LV; TopoDS_Edge newE; Standard_Integer np; for(np = 2; np < NPnts; np++) { gp_Pnt LP = Points(np); LV = BRepLib_MakeVertex(LP); newE = BRepLib_MakeEdge(FV, LV); aL.Append(newE); FV = LV; } LV = Vl; newE = BRepLib_MakeEdge(FV, LV); aL.Append(newE); } else { //cout << " 2 points " << endl; TopoDS_Edge newE = (TopoDS_Edge) BRepLib_MakeEdge(Vf, Vl); aL.Append(newE); } //Update myMapSpine if (myMapSpine.IsBound( anE )) { TopTools_ListIteratorOfListOfShape newit( aL ); for (; newit.More(); newit.Next()) { TopoDS_Edge NewEdge = TopoDS::Edge( newit.Value() ); myMapSpine.Bind( NewEdge, myMapSpine(anE) ); TopoDS_Vertex NewV1, NewV2; EdgeVertices( NewEdge, NewV1, NewV2 ); if (!myMapSpine.IsBound(NewV1)) myMapSpine.Bind( NewV1, myMapSpine(anE) ); if (!myMapSpine.IsBound(NewV2)) myMapSpine.Bind( NewV2, myMapSpine(anE) ); } myMapSpine.UnBind( anE ); } /////////////////// aSubst.Substitute(anE, aL); } TopTools_DataMapOfShapeListOfShape wwmap; TopoDS_Iterator itws( myWorkSpine ); for (; itws.More(); itws.Next()) { TopoDS_Shape aWire = itws.Value(); aSubst.Build( aWire ); if (aSubst.IsCopied(aWire)) { TopoDS_Wire NewWire = TopoDS::Wire( aSubst.Copy(aWire).First() ); NewWire.Closed( aWire.Closed() ); TopTools_ListOfShape Lw; Lw.Append( NewWire ); wwmap.Bind( aWire, Lw ); } } aSubst.Clear(); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itmap( wwmap ); for (; itmap.More(); itmap.Next()) aSubst.Substitute( itmap.Key(), itmap.Value() ); aSubst.Build(myWorkSpine); if(aSubst.IsCopied(myWorkSpine)) { myWorkSpine = TopoDS::Face(aSubst.Copy(myWorkSpine).First()); //sprintf(name,"WS1"); //DBRep::Set(name,myWorkSpine); BRepMAT2d_Explorer newExp; newExp.Perform(myWorkSpine); BRepMAT2d_BisectingLocus newBilo; BRepMAT2d_LinkTopoBilo newLink; newBilo.Compute(newExp,1,MAT_Left); newLink.Perform(newExp,newBilo); PerformWithBiLo(myWorkSpine,Offset,newBilo,newLink,myJoinType,Alt); myWorkSpine = oldWorkSpain; } else { PerformWithBiLo(myWorkSpine,Offset,myBilo,myLink,myJoinType,Alt); } } else { PerformWithBiLo(myWorkSpine,Offset,myBilo,myLink,myJoinType,Alt); } } catch (Standard_Failure) { myShape.Nullify(); myIsDone = Standard_False; return; } // Modified by skv - Fri Jul 8 11:21:38 2005 OCC9145 End // Modified by Sergey KHROMOV - Thu Mar 14 10:48:15 2002 Begin TopExp_Explorer anExp(myShape, TopAbs_WIRE); for (; anExp.More(); anExp.Next()) { const TopoDS_Shape &aWire = anExp.Current(); if (!aWire.Closed()) { myShape.Nullify(); myIsDone = Standard_False; Standard_ConstructionError::Raise("Offset wire is not closed."); } } // Modified by Sergey KHROMOV - Thu Mar 14 10:48:16 2002 End } //======================================================================= //function : Compute //purpose : //======================================================================= void Compute (const TopoDS_Face& Spine, TopoDS_Shape& aShape, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map, const Standard_Real Alt) { BRep_Builder B; B.MakeCompound(TopoDS::Compound(aShape)); Standard_Real ALT = Alt; if ( Spine.Orientation() == TopAbs_REVERSED) ALT = -Alt; gp_Trsf T; T.SetTranslation(gp_Vec(0.,0.,ALT)); TopLoc_Location L(T); for ( TopExp_Explorer exp(Spine,TopAbs_WIRE); exp.More(); exp.Next()) { const TopoDS_Wire& CurW = TopoDS::Wire(exp.Current()); TopoDS_Shape aLocalShape = CurW.Moved(L); TopoDS_Wire NewW = TopoDS::Wire(aLocalShape); // TopoDS_Wire NewW = TopoDS::Wire(CurW.Moved(L)); B.Add(aShape,NewW); // mise a jour de la Map. TopoDS_Iterator it1( CurW); TopoDS_Iterator it2( NewW); for ( ; it1.More(); it1.Next(), it2.Next()) { TopTools_ListOfShape List; List.Append(it2.Value()); Map.Add(it1.Value(), List); } } } //======================================================================= //function : PerformWithBiLo //purpose : //======================================================================= void BRepFill_OffsetWire::PerformWithBiLo (const TopoDS_Face& Spine, const Standard_Real Offset, const BRepMAT2d_BisectingLocus& Locus, BRepMAT2d_LinkTopoBilo& Link, const GeomAbs_JoinType Join, const Standard_Real Alt) { Standard_NotImplemented_Raise_if (Join > GeomAbs_Arc, "Only GeomAbs_Arc is implemented"); myIsDone = Standard_False; TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD); myWorkSpine = TopoDS::Face(aLocalShape); // myWorkSpine = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD)); myJoinType = Join; myOffset = Offset ; myShape.Nullify(); if (mySpine.IsNull()) { TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD); mySpine = TopoDS::Face(aLocalShape); // mySpine = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD)); } myMap.Clear(); //***************************************** // si myOffset = 0, on ne s'emmerde pas !! //***************************************** if ( Abs(myOffset) < Precision::Confusion()) { Compute(mySpine,myShape,myMap,Alt); myIsDone = Standard_True; return; } //****************************** // Calcul pour un offset non nul //****************************** if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone)) return; BRep_Builder myBuilder; myBuilder.MakeCompound(TopoDS::Compound(myShape)); //--------------------------------------------------------------------- // MapNodeVertex : associe a chaque noeud de la carte (key1) et // a chaque element du profil (key2) un vertex (item). // MapBis : ensemble des edges ou vertex (item) generes par // une bisectrice sur une face ou un edge (key)des // tuyaux ou revol. // MapVerPar : Map des parametres des vertex sur les edges paralleles // la liste contenue dans MapVerPar (E) correspond aux // parametres sur E des vertex contenu dans MapBis(E); //--------------------------------------------------------------------- BRepFill_DataMapOfNodeShape MapNodeVertex; TopTools_DataMapOfShapeSequenceOfShape MapBis; BRepFill_DataMapOfShapeSequenceOfReal MapVerPar; TopTools_DataMapOfShapeShape EmptyMap; TopTools_SequenceOfShape EmptySeq; TopTools_ListOfShape EmptyList; TColStd_SequenceOfReal EmptySeqOfReal; Standard_Real ALT = Alt; Handle(Geom_Plane) RefPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(myWorkSpine)); if ( myWorkSpine.Orientation() == TopAbs_REVERSED) ALT = -Alt; RefPlane = Handle(Geom_Plane)::DownCast (RefPlane->Translated( ALT * gp_Vec(RefPlane->Axis().Direction() ))); //--------------------------------------------------------------- // Construction des Cercles et des OffsetCurves //--------------------------------------------------------------- for (Standard_Integer ic = 1; ic <= Locus.NumberOfContours(); ic++) { TopoDS_Shape PEE = Link.GeneratingShape(Locus.BasicElt(ic,Locus.NumberOfElts(ic))); TopoDS_Shape& PE = PEE ; for (Standard_Integer ie = 1; ie <= Locus.NumberOfElts(ic); ie++) { const TopoDS_Shape& SE = Link.GeneratingShape(Locus.BasicElt(ic,ie)); if (SE.ShapeType() == TopAbs_VERTEX) { MakeCircle (TopoDS::Edge(PE),TopoDS::Vertex(SE), myWorkSpine,myOffset,myMap,RefPlane); } else { MakeOffset (TopoDS::Edge(SE),myWorkSpine,myOffset,myMap,RefPlane); PE = SE; } } } #ifdef DEB if (AffichEdge) { cout << " Fin Construction des primitives geometriques"<NumberOfArcs(); i++) { CurrentArc = Locus.Graph()->Arc(i); Bisector_Bisec Bisec = Locus.GeomBis(CurrentArc,Reverse); #ifdef DRAW if ( AffichGeom) { sprintf(name,"BISSEC_%d",NbBISSEC++); DrawTrSurf::Set(name,Bisec.Value()); } #endif //----------------------------------------------------------------------- // Recuperation des elements du spine correspondant aux basicElts separes. //----------------------------------------------------------------------- S [0] = Link.GeneratingShape(CurrentArc->FirstElement()); S [1] = Link.GeneratingShape(CurrentArc->SecondElement()); TopTools_SequenceOfShape Vertices; TColgp_SequenceOfPnt Params; TopTools_DataMapOfShapeSequenceOfShape MapSeqVer; BRepFill_DataMapOfShapeSequenceOfPnt MapSeqPar; //----------------------------------------------------------- // Recuperation des edges paralleles sur chaque face. // Si pas d offset generees => saut a la bissectrice suivante. //-------------------------------------------------------------- if (myMap.Contains(S[0]) && myMap.Contains(S[1])) { E [0] = TopoDS::Edge(myMap.FindFromKey(S[0]).First()); E [1] = TopoDS::Edge(myMap.FindFromKey(S[1]).First()); } else continue; //----------------------------------------------------------- // Construction des vertex correspondant au noeud de la carte. // si ils sont sur l offset. //----------------------------------------------------------- TopoDS_Vertex VS,VE; Handle(MAT_Node) Node1, Node2; if (Reverse) { Node1 = CurrentArc->SecondNode(); Node2 = CurrentArc->FirstNode(); } else { Node1 = CurrentArc->FirstNode(); Node2 = CurrentArc->SecondNode(); } Standard_Boolean StartOnEdge = 0, EndOnEdge = 0; if (!Node1->Infinite()) { gp_Pnt2d aLocalPnt2d = Locus.GeomElt(Node1); StartOnEdge = VertexFromNode(Node1, myOffset, aLocalPnt2d ,MapNodeVertex,VS); // StartOnEdge = VertexFromNode(Node1, myOffset, Locus.GeomElt(Node1), // MapNodeVertex,VS); } if (!Node2->Infinite()) { gp_Pnt2d aLocalPnt2d = Locus.GeomElt(Node2) ; EndOnEdge = VertexFromNode(Node2, myOffset, aLocalPnt2d ,MapNodeVertex,VE); // EndOnEdge = VertexFromNode(Node2, myOffset, Locus.GeomElt(Node2), // MapNodeVertex,VE); } //--------------------------------------------- // Construction des geometries. //--------------------------------------------- BRepFill_TrimEdgeTool Trim (Bisec, Locus.GeomElt(CurrentArc->FirstElement()), Locus.GeomElt(CurrentArc->SecondElement()), myOffset); //----------------------------------------------------------- // Construction des vertex sur les edges paralleles au spine. //----------------------------------------------------------- Trim.IntersectWith(E [0], E [1], Params); for (Standard_Integer s = 1; s <= Params.Length(); s++) { TopoDS_Vertex VC; myBuilder.MakeVertex (VC); gp_Pnt2d P2 = Bisec.Value()->Value(Params.Value(s).X()); gp_Pnt PVC(P2.X(),P2.Y(),0.); myBuilder.UpdateVertex(VC,PVC,Precision::Confusion()); Vertices.Append(VC); } if (StartOnEdge) { Standard_Boolean Start = 1; Trim.AddOrConfuse(Start, E[0], E[1], Params); if (Params.Length() == Vertices.Length()) Vertices.SetValue(1,VS); else // le point n avait pas ete trouve par IntersectWith Vertices.Prepend(VS); } if (EndOnEdge) { Standard_Boolean Start = 0; Trim.AddOrConfuse(Start, E[0], E[1], Params); if (Params.Length() == Vertices.Length()) Vertices.SetValue(Params.Length(),VE); else // le point n avait pas ete trouve par IntersectWith Vertices.Append(VE); } //------------------------------------------------------------ // Mise a jour Detromp. // Detromp permetra de supprimer les vertex sur l offset // correspondant a des zones de tangences // dans Detromp sont ranges les vertex qui limitent // les portions de la bissectrices situes entre le spine et // l offset. //------------------------------------------------------------ if (!Detromp.IsBound(S[0])) Detromp.Bind(S[0],EmptyList); if (!Detromp.IsBound(S[1])) Detromp.Bind(S[1],EmptyList); UpdateDetromp (Detromp(S[0]), Detromp(S[1]), Vertices, Params, Bisec, StartOnEdge, EndOnEdge, Trim); //---------------------------------------------- // Stockage des vertex sur les edges paralleles. // on remplit MapBis et MapVerPar. //---------------------------------------------- if (!Vertices.IsEmpty()) { for (k = 0; k <= 1; k++) { if (!MapBis.IsBound(E[k])) { MapBis .Bind(E[k],EmptySeq); MapVerPar.Bind(E[k],EmptySeqOfReal); } for (Standard_Integer ii = 1; ii <= Vertices.Length(); ii++) { MapBis (E[k]).Append(Vertices.Value(ii)); if (k == 0) MapVerPar (E[k]).Append(Params.Value(ii).Y()); else MapVerPar (E[k]).Append(Params.Value(ii).Z()); } } } else { //------------------------------------------------------------ //POUR LES CERCLES COMPLETS . la parallele peut etre contenue // dans la zone sans intersection avec la frontiere // pas d intersection // si myoffset est < distance des noeuds la parallele peut etre // valide. //------------------------------------------------------------- for (k = 0; k <= 1; k++) { if (!MapBis.IsBound(E[k])) { if (Node1->Distance() > myOffset && Node2->Distance() > myOffset) { MapBis .Bind(E[k],EmptySeq); MapVerPar.Bind(E[k],EmptySeqOfReal); } } } } } #ifdef DEB if (AffichEdge) { cout << " Fin Construction des vertex sur les offsets"<Value(P.X(),P.Y()); myBuilder.UpdateVertex(V,P, Precision::Confusion()); } } // Constructions des courbes 3d. BRepLib::BuildCurves3d(myShape); MapVertex.Clear(); TopExp_Explorer Explo( myShape, TopAbs_EDGE ); for (; Explo.More(); Explo.Next()) { TopoDS_Edge E = TopoDS::Edge( Explo.Current() ); TopoDS_Vertex V1, V2; TopExp::Vertices( E, V1, V2 ); Handle(BRep_TVertex)& TV1 = *((Handle(BRep_TVertex)*) &(V1).TShape()); Handle(BRep_TVertex)& TV2 = *((Handle(BRep_TVertex)*) &(V2).TShape()); TopLoc_Location loc; Standard_Real f, l; Handle( Geom_Curve ) theCurve = BRep_Tool::Curve( E, loc, f, l ); theCurve = Handle( Geom_Curve )::DownCast( theCurve->Copy() ); theCurve->Transform( loc.Transformation() ); gp_Pnt f3d = theCurve->Value( f ); gp_Pnt l3d = theCurve->Value( l ); Standard_Real dist1, dist2; dist1 = f3d.Distance( TV1->Pnt() ); dist2 = l3d.Distance( TV2->Pnt() ); if (! MapVertex.Contains( V1 )) { TV1->Pnt( f3d ); MapVertex.Add( V1 ); } else TV1->UpdateTolerance( 1.5*dist1 ); if (! MapVertex.Contains( V2 )) { TV2->Pnt( l3d ); MapVertex.Add( V2 ); } else TV2->UpdateTolerance( 1.5*dist2 ); } FixHoles(); myIsDone = Standard_True; } //======================================================================= //function : Generated //purpose : //======================================================================= BRepFill_IndexedDataMapOfOrientedShapeListOfShape& BRepFill_OffsetWire::Generated() { return myMap; } //======================================================================= //function : PrepareSpine //purpose : //======================================================================= void BRepFill_OffsetWire::PrepareSpine() { BRep_Builder B; TopTools_ListOfShape Cuts; TopTools_ListIteratorOfListOfShape IteCuts; TopoDS_Vertex V1,V2; myWorkSpine.Nullify(); myMapSpine.Clear(); TopLoc_Location L; const Handle(Geom_Surface)& S = BRep_Tool::Surface (mySpine,L); Standard_Real TolF = BRep_Tool::Tolerance(mySpine); B.MakeFace(myWorkSpine,S,L,TolF); for (TopoDS_Iterator IteF(mySpine) ; IteF.More(); IteF.Next()) { TopoDS_Wire NW; B.MakeWire (NW); // Modified by Sergey KHROMOV - Thu Nov 16 17:29:55 2000 Begin Standard_Integer ForcedCut = 0; Standard_Integer nbResEdges = -1; TopTools_IndexedMapOfShape EdgeMap; TopExp::MapShapes(IteF.Value(), TopAbs_EDGE, EdgeMap); Standard_Integer nbEdges = EdgeMap.Extent(); if (nbEdges == 1) ForcedCut = 2; // Modified by Sergey KHROMOV - Thu Nov 16 17:29:48 2000 End for (TopoDS_Iterator IteW(IteF.Value()); IteW.More(); IteW.Next()) { const TopoDS_Edge& E = TopoDS::Edge(IteW.Value()); EdgeVertices(E,V1,V2); myMapSpine.Bind(V1,V1); myMapSpine.Bind(V2,V2); Cuts.Clear(); // Decoupe TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD); // Modified by Sergey KHROMOV - Thu Nov 16 17:29:29 2000 Begin if (nbEdges == 2 && nbResEdges == 0) ForcedCut = 1; // Modified by Sergey KHROMOV - Thu Nov 16 17:29:33 2000 End nbResEdges = CutEdge (TopoDS::Edge(aLocalShape), mySpine, ForcedCut, Cuts); if (Cuts.IsEmpty()) { B.Add(NW,E); myMapSpine.Bind(E,E); } else { for (IteCuts.Initialize(Cuts); IteCuts.More(); IteCuts.Next()) { TopoDS_Edge NE = TopoDS::Edge(IteCuts.Value()); NE.Orientation(E.Orientation()); B.Add(NW,NE); myMapSpine.Bind(NE,E); EdgeVertices(NE,V1,V2); if (!myMapSpine.IsBound(V1)) myMapSpine.Bind(V1,E); if (!myMapSpine.IsBound(V2)) myMapSpine.Bind(V2,E); } } } // Modified by Sergey KHROMOV - Thu Mar 7 09:17:41 2002 Begin TopoDS_Vertex aV1; TopoDS_Vertex aV2; TopExp::Vertices(NW, aV1, aV2); NW.Closed(aV1.IsSame(aV2)); // Modified by Sergey KHROMOV - Thu Mar 7 09:17:43 2002 End B.Add(myWorkSpine, NW); } #ifdef DRAW if ( AffichEdge) { sprintf(name,"WS"); DBRep::Set(name,myWorkSpine); } #endif } //======================================================================= //function : MakeWires //purpose : //======================================================================= void BRepFill_OffsetWire::MakeWires() { //-------------------------------------------------------- // creation d une liste unique des edges paralelles crees. //-------------------------------------------------------- TopTools_SequenceOfShape TheEdges; TopTools_ListOfShape TheWires; TopTools_ListIteratorOfListOfShape itl; //BRepFill_DataMapIteratorOfDataMapOfOrientedShapeListOfShape ite; TopTools_IndexedDataMapOfShapeListOfShape MVE; //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape MVEit; TopoDS_Vertex V1,V2,VF,CV; Standard_Integer i; for (i = 1; i <= myMap.Extent(); i++) { for (itl.Initialize(myMap(i)); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); TopExp::Vertices (E,V1,V2); if (V1.IsSame(V2) && IsSmallClosedEdge(E, V1)) continue; //remove small closed edges if (!MVE.Contains(V1)) { TopTools_ListOfShape empty; MVE.Add(V1,empty); } MVE.ChangeFromKey(V1).Append(E); if (!MVE.Contains(V2)) { TopTools_ListOfShape empty; MVE.Add(V2,empty); } MVE.ChangeFromKey(V2).Append(E); } } //-------------------------------------- // Creation des wires paralleles. //-------------------------------------- BRep_Builder B; // Standard_Integer NbEdges; // Standard_Boolean NewWire = Standard_True; // Standard_Boolean AddEdge = Standard_False; TopoDS_Wire NW; Standard_Boolean End; TopoDS_Edge CE; while (!MVE.IsEmpty()) { B.MakeWire(NW); //MVEit.Initialize(MVE); for (i = 1; i <= MVE.Extent(); i++) if(MVE(i).Extent() == 1) break; //if(!MVEit.More()) MVEit.Initialize(MVE); if (i > MVE.Extent()) i = 1; CV = VF = TopoDS::Vertex(MVE.FindKey(i)); CE = TopoDS::Edge(MVE(i).First()); End = Standard_False; MVE.ChangeFromKey(CV).RemoveFirst(); // Modified by Sergey KHROMOV - Thu Mar 14 11:29:59 2002 Begin Standard_Boolean isClosed = Standard_False; // Modified by Sergey KHROMOV - Thu Mar 14 11:30:00 2002 End while(!End) { //------------------------------- // Construction d un wire. //------------------------------- TopExp::Vertices(CE,V1,V2); if (!CV.IsSame(V1)) CV = V1; else CV = V2; B.Add (NW,CE); if (VF.IsSame(CV) || !MVE.Contains(CV)) { // Modified by Sergey KHROMOV - Thu Mar 14 11:30:14 2002 Begin isClosed = VF.IsSame(CV); // Modified by Sergey KHROMOV - Thu Mar 14 11:30:15 2002 End End = Standard_True; //MVE.UnBind(VF); TopoDS_Shape LastShape = MVE.FindKey(MVE.Extent()); TopTools_ListOfShape LastList; LastList.Append(MVE(MVE.Extent())); MVE.RemoveLast(); if (MVE.FindIndex(VF) != 0) MVE.Substitute(MVE.FindIndex(VF), LastShape, LastList); } if (!End) { if (MVE.FindFromKey(CV).Extent() > 2) { //cout <<"vertex sur plus de 2 edges dans une face."< MaxTol) MaxTol = Tol; } MaxTol *= 100.; Explo.Init( myShape, TopAbs_WIRE ); for (; Explo.More(); Explo.Next()) { TopoDS_Shape aWire = Explo.Current(); // Remove duplicated edges TopTools_DataMapOfShapeListOfShape EEmap; TopoDS_Iterator it( aWire ); for (; it.More(); it.Next()) { const TopoDS_Shape& anEdge = it.Value(); if (! EEmap.IsBound( anEdge )) { TopTools_ListOfShape LE; EEmap.Bind( anEdge, LE ); } else EEmap(anEdge).Append( anEdge ); } aWire.Free( Standard_True ); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape mapit( EEmap ); for (; mapit.More(); mapit.Next()) { const TopTools_ListOfShape& LE = mapit.Value(); TopTools_ListIteratorOfListOfShape itl( LE ); for (; itl.More(); itl.Next()) BB.Remove( aWire, itl.Value() ); } // Sorting if (aWire.Closed()) ClosedWires.Append( aWire ); else UnclosedWires.Append( aWire ); } while (!UnclosedWires.IsEmpty()) { TopoDS_Wire& Base = TopoDS::Wire( UnclosedWires(1) ); TopoDS_Vertex Vf, Vl; TopExp::Vertices( Base, Vf, Vl ); gp_Pnt Pf, Pl; Pf = BRep_Tool::Pnt(Vf); Pl = BRep_Tool::Pnt(Vl); Standard_Real DistF = RealLast(), DistL = RealLast(); Standard_Integer IndexF = 0, IndexL = 0; Standard_Boolean IsFirstF = Standard_False, IsFirstL = Standard_False; for (Standard_Integer i = 2; i <= UnclosedWires.Length(); i++) { TopoDS_Wire aWire = TopoDS::Wire( UnclosedWires(i) ); TopoDS_Vertex V1, V2; TopExp::Vertices( aWire, V1, V2 ); gp_Pnt P1, P2; P1 = BRep_Tool::Pnt(V1); P2 = BRep_Tool::Pnt(V2); Standard_Real dist = Pf.Distance( P1 ); if (dist < DistF) { DistF = dist; IndexF = i; IsFirstF = Standard_True; } dist = Pf.Distance( P2 ); if (dist < DistF) { DistF = dist; IndexF = i; IsFirstF = Standard_False; } dist = Pl.Distance( P1 ); if (dist < DistL) { DistL = dist; IndexL = i; IsFirstL = Standard_True; } dist = Pl.Distance( P2 ); if (dist < DistL) { DistL = dist; IndexL = i; IsFirstL = Standard_False; } } TopoDS_Wire theWire; TopoDS_Edge theEdge; TopoDS_Vertex theVertex; Standard_Real CommonTol; Standard_Boolean TryToClose = Standard_True; if (DistF <= MaxTol && DistL <= MaxTol && IndexF == IndexL && IsFirstF == IsFirstL) { if (DistF < DistL) { DistL = RealLast(); IndexL++; } else { DistF = RealLast(); IndexF++; } TryToClose = Standard_False; } if (DistF <= MaxTol) { theWire = TopoDS::Wire( UnclosedWires(IndexF) ); TopoDS_Vertex V1, V2; TopExp::Vertices( theWire, V1, V2 ); TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors( theWire, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); theEdge = (IsFirstF)? TopoDS::Edge(VEmap.FindFromKey( V1 ).First()) : TopoDS::Edge(VEmap.FindFromKey( V2 ).First()); TopoDS_Iterator it( theWire ); for (; it.More(); it.Next()) { TopoDS_Edge anEdge = TopoDS::Edge( it.Value() ); if (IsFirstF) anEdge.Reverse(); if (!anEdge.IsSame( theEdge )) BB.Add( Base, anEdge ); } theVertex = (IsFirstF)? V1 : V2; CommonTol = Max( BRep_Tool::Tolerance(Vf), BRep_Tool::Tolerance(theVertex) ); if (DistF <= CommonTol) { theEdge.Free( Standard_True ); Vf.Orientation( theVertex.Orientation() ); BB.Remove( theEdge, theVertex ); BB.Add( theEdge, Vf ); BB.UpdateVertex( Vf, CommonTol ); if (IsFirstF) theEdge.Reverse(); BB.Add( Base, theEdge ); } else { if (IsFirstF) theEdge.Reverse(); BB.Add( Base, theEdge ); // Creating new edge from theVertex to Vf TopoDS_Edge NewEdge = (TopoDS_Edge) BRepLib_MakeEdge( theVertex, Vf ); BB.Add( Base, NewEdge ); } } if (DistL <= MaxTol && IndexL != IndexF) { theWire = TopoDS::Wire( UnclosedWires(IndexL) ); TopoDS_Vertex V1, V2; TopExp::Vertices( theWire, V1, V2 ); TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors( theWire, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); theEdge = (IsFirstL)? TopoDS::Edge(VEmap.FindFromKey( V1 ).First()) : TopoDS::Edge(VEmap.FindFromKey( V2 ).First()); TopoDS_Iterator it( theWire ); for (; it.More(); it.Next()) { TopoDS_Edge anEdge = TopoDS::Edge( it.Value() ); if (!IsFirstL) anEdge.Reverse(); if (!anEdge.IsSame( theEdge )) BB.Add( Base, anEdge ); } theVertex = (IsFirstL)? V1 : V2; CommonTol = Max( BRep_Tool::Tolerance(Vl), BRep_Tool::Tolerance(theVertex) ); if (DistL <= CommonTol) { theEdge.Free( Standard_True ); Vl.Orientation( theVertex.Orientation() ); BB.Remove( theEdge, theVertex ); BB.Add( theEdge, Vl ); BB.UpdateVertex( Vl, CommonTol ); if (!IsFirstL) theEdge.Reverse(); BB.Add( Base, theEdge ); } else { if (!IsFirstL) theEdge.Reverse(); BB.Add( Base, theEdge ); // Creating new edge from Vl to theVertex TopoDS_Edge NewEdge = (TopoDS_Edge) BRepLib_MakeEdge( Vl, theVertex ); BB.Add( Base, NewEdge ); } } // Check if it is possible to close resulting wire if (TryToClose) { TopExp::Vertices( Base, Vf, Vl ); CommonTol = Max( BRep_Tool::Tolerance(Vf), BRep_Tool::Tolerance(Vl) ); TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors( Base, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); TopoDS_Edge Efirst, Elast; Efirst = TopoDS::Edge(VEmap.FindFromKey( Vf ).First()); Elast = TopoDS::Edge(VEmap.FindFromKey( Vl ).First()); Pf = BRep_Tool::Pnt(Vf); Pl = BRep_Tool::Pnt(Vl); Standard_Real Dist = Pf.Distance(Pl); if (Dist <= CommonTol) { Elast.Free( Standard_True ); Vf.Orientation( Vl.Orientation() ); BB.Remove( Elast, Vl ); BB.Add( Elast, Vf ); BB.UpdateVertex( Vf, CommonTol ); Base.Closed( Standard_True ); } else if (Dist <= MaxTol) { // Creating new edge from Vl to Vf TopoDS_Edge NewEdge = (TopoDS_Edge) BRepLib_MakeEdge( Vf, Vl ); BB.Add( Base, NewEdge ); Base.Closed( Standard_True ); } } // Updating sequences ClosedWires and UnclosedWires if (DistF <= MaxTol) UnclosedWires.Remove( IndexF ); if (DistL <= MaxTol && IndexL != IndexF) { if (DistF <= MaxTol && IndexL > IndexF) IndexL--; UnclosedWires.Remove( IndexL ); } if (Base.Closed()) { ClosedWires.Append( Base ); UnclosedWires.Remove( 1 ); } else if (DistF > MaxTol && DistL > MaxTol) { IsolatedWires.Append( Base ); UnclosedWires.Remove( 1 ); } } // Updating myShape if (ClosedWires.Length() + IsolatedWires.Length() == 1) { if (!ClosedWires.IsEmpty()) myShape = ClosedWires.First(); else myShape = IsolatedWires.First(); } else { TopoDS_Compound R; BB.MakeCompound( R ); for (i = 1; i <= ClosedWires.Length(); i++) BB.Add( R, ClosedWires(i) ); for (i = 1; i <= IsolatedWires.Length(); i++) BB.Add( R, IsolatedWires(i) ); myShape = R; } } //======================================================================= //function : CutEdge //purpose : Decoupe d une edge aux extrema de courbures et aux points // d inflexion. // Les cercles fermes sont aussi decoupes en deux. // Si est vide l edge n est pas modifie. // Le premier et le dernier vertex de l edge originale // appartiennent respectivement a la premiere et derniere // portions. //======================================================================= Standard_Integer CutEdge (const TopoDS_Edge& E, const TopoDS_Face& F, Standard_Integer ForceCut, TopTools_ListOfShape& Cuts) { Cuts.Clear(); MAT2d_CutCurve Cuter; TColGeom2d_SequenceOfCurve theCurves; Standard_Real f,l; Handle(Geom2d_Curve) C2d; Handle(Geom2d_TrimmedCurve) CT2d; // Modified by Sergey KHROMOV - Wed Mar 6 17:36:25 2002 Begin Standard_Real aTol = BRep_Tool::Tolerance(E); Handle(Geom_Curve) aC; // Modified by Sergey KHROMOV - Wed Mar 6 17:36:25 2002 End TopoDS_Vertex V1,V2,VF,VL; TopExp::Vertices (E,V1,V2); BRep_Builder B; C2d = BRep_Tool::CurveOnSurface (E,F,f,l); // Modified by Sergey KHROMOV - Wed Mar 6 17:36:54 2002 Begin aC = BRep_Tool::Curve(E,f,l); // Modified by Sergey KHROMOV - Wed Mar 6 17:36:54 2002 End CT2d = new Geom2d_TrimmedCurve(C2d,f,l); //if (E.Orientation() == TopAbs_REVERSED) CT2d->Reverse(); if (CT2d->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Circle)) && ( Abs(f-l) >= PI) ) { return 0; // @todo check here possible bug or really workaround? //--------------------------- // Decoupe cercle ferme. //--------------------------- #if 0 // Eventually re-enable here Standard_Real m = (f + l)*0.5; // Modified by Sergey KHROMOV - Wed Mar 6 17:37:28 2002 Begin gp_Pnt P = aC->Value(m); VL = BRepLib_MakeVertex(P); B.UpdateVertex(VL, aTol); // Modified by Sergey KHROMOV - Wed Mar 6 17:37:30 2002 End TopoDS_Shape aLocalShape = E.EmptyCopied(); TopoDS_Edge FE = TopoDS::Edge(aLocalShape); TopoDS_Edge LE = TopoDS::Edge(aLocalShape); // TopoDS_Edge FE = TopoDS::Edge(E.EmptyCopied()); // TopoDS_Edge LE = TopoDS::Edge(E.EmptyCopied()); FE.Orientation(TopAbs_FORWARD); LE.Orientation(TopAbs_FORWARD); B.Add (FE,V1); B.Add (FE,VL.Oriented(TopAbs_REVERSED)); B.Range(FE, f, m); B.Add (LE,V2); B.Add (LE,VL.Oriented(TopAbs_FORWARD)); B.Range(LE, m, l); Cuts.Append(FE.Oriented(E.Orientation())); Cuts.Append(LE.Oriented(E.Orientation())); //-------- // Retour. //-------- return 2; #endif } //------------------------- // Decoupe de la courbe. //------------------------- Cuter.Perform(CT2d); // Modified by Sergey KHROMOV - Thu Nov 16 17:28:29 2000 Begin if (ForceCut == 0) { if (Cuter.UnModified()) { //----------------------------- // edge non modifiee => retour. //----------------------------- return 0; } else { for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++) theCurves.Append(Cuter.Value(k)); } } else if (ForceCut == 1) { if (Cuter.UnModified()) { CutCurve (CT2d, 2, theCurves); } else { for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++) theCurves.Append(Cuter.Value(k)); } } else if (ForceCut == 2) { if (Cuter.UnModified()) { CutCurve (CT2d, 3, theCurves); } else { if (Cuter.NbCurves() == 2) { Handle(Geom2d_TrimmedCurve)CC = Cuter.Value(1); if (CC->LastParameter() > (l+f)/2.) { CutCurve (CC, 2, theCurves); theCurves.Append(Cuter.Value(2)); } else { theCurves.Append(CC); CutCurve (Cuter.Value(2), 2, theCurves); } } else { for (Standard_Integer k = 1; k <= Cuter.NbCurves(); k++) theCurves.Append(Cuter.Value(k)); } } } // Modified by Sergey KHROMOV - Thu Nov 16 17:28:37 2000 End //-------------------------------------- // Creation des edges decoupees. //-------------------------------------- VF = V1; for (Standard_Integer k = 1; k <= theCurves.Length(); k++) { Handle(Geom2d_TrimmedCurve)CC = Handle(Geom2d_TrimmedCurve)::DownCast(theCurves.Value(k)); if (k == theCurves.Length()) {VL = V2;} else { // Modified by Sergey KHROMOV - Wed Mar 6 17:38:02 2002 Begin gp_Pnt P = aC->Value(CC->LastParameter()); VL = BRepLib_MakeVertex(P); B.UpdateVertex(VL, aTol); // Modified by Sergey KHROMOV - Wed Mar 6 17:38:05 2002 End } TopoDS_Shape aLocalShape = E.EmptyCopied(); TopoDS_Edge NE = TopoDS::Edge(aLocalShape); // TopoDS_Edge NE = TopoDS::Edge(E.EmptyCopied()); NE.Orientation(TopAbs_FORWARD); B.Add (NE,VF.Oriented(TopAbs_FORWARD)); B.Add (NE,VL.Oriented(TopAbs_REVERSED)); B.Range(NE,CC->FirstParameter(),CC->LastParameter()); Cuts.Append(NE.Oriented(E.Orientation())); VF = VL; } return theCurves.Length(); } // Modified by Sergey KHROMOV - Thu Nov 16 17:27:56 2000 Begin //======================================================================= //function : CutCurve //purpose : //======================================================================= void CutCurve (const Handle(Geom2d_TrimmedCurve)& C, const Standard_Integer nbParts, TColGeom2d_SequenceOfCurve& theCurves) { Handle(Geom2d_TrimmedCurve) TrimC; Standard_Real UF,UL,UC; Standard_Real Step; gp_Pnt2d PF,PL,PC; Standard_Real PTol = Precision::PConfusion()*10; Standard_Real Tol = Precision::Confusion()*10; Standard_Boolean YaCut = Standard_False; UF = C->FirstParameter(); UL = C->LastParameter (); PF = C->Value(UF); PL = C->Value(UL); Step = (UL - UF)/nbParts; for (Standard_Integer i = 1; i < nbParts; i++) { UC = UF + i*Step; PC = C->Value(UC); if (UC - UF > PTol && PC.Distance(PF) > Tol) { if ( UL - UC < PTol || PL.Distance(PC) < Tol) continue; TrimC = new Geom2d_TrimmedCurve(C,UF,UC); theCurves.Append(TrimC); UF = UC; PF = PC; YaCut = Standard_True; } } if (YaCut) { TrimC = new Geom2d_TrimmedCurve(C,UF,UL); theCurves.Append(TrimC); } else theCurves.Append(C); } // Modified by Sergey KHROMOV - Thu Nov 16 17:28:13 2000 End //======================================================================= //function : MakeCircle //purpose : //======================================================================= void MakeCircle (const TopoDS_Edge& E, const TopoDS_Vertex& V, const TopoDS_Face& F, const Standard_Real Offset, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map, const Handle(Geom_Plane)& RefPlane) { // eval the Axis of the Circle. Standard_Real f,l; Handle(Geom2d_Curve) GC = BRep_Tool::CurveOnSurface(E,F,f,l); gp_Vec2d DX; gp_Pnt2d P; if (E.Orientation() == TopAbs_FORWARD) { GC->D1(l,P,DX); DX.Reverse(); } else GC->D1(f,P,DX); gp_Ax2d Axis(P,gp_Dir2d(DX)); Handle(Geom2d_Circle) Circ = new Geom2d_Circle(Axis, Abs(Offset), Offset < 0.); // Bind the edges in my Map. TopoDS_Edge OE = (TopoDS_Edge) BRepLib_MakeEdge(Circ, RefPlane); TopTools_ListOfShape LL; LL.Append(OE); Map.Add(V,LL); #ifdef DRAW if ( AffichGeom && !OE.IsNull()) { sprintf(name,"OFFSET_%d",++NbOFFSET); DBRep::Set(name,OE); } #endif } //======================================================================= //function : MakeOffset //purpose : //======================================================================= void MakeOffset (const TopoDS_Edge& E, const TopoDS_Face& F, const Standard_Real Offset, BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map, const Handle(Geom_Plane)& RefPlane) { Standard_Real f,l; Standard_Real anOffset = Offset; if (E.Orientation() == TopAbs_REVERSED) anOffset *= -1; Handle(Geom2d_Curve) G2d = BRep_Tool::CurveOnSurface(E,F,f,l); Handle(Geom2d_Curve) G2dOC; Geom2dAdaptor_Curve AC(G2d,f,l); if ( AC.GetType() == GeomAbs_Circle) { // si l offset est superieur ou egal au rayon et du cote de la // concavite du cercle => edge null. gp_Circ2d C1(AC.Circle()); gp_Ax22d axes( C1.Axis()); gp_Dir2d Xd = axes.XDirection(); gp_Dir2d Yd = axes.YDirection(); Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X(); Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.; if (anOffset*Signe < AC.Circle().Radius()) { // -anOffset vient d une Etrangete adaptoresque! Handle(Geom2dAdaptor_HCurve) AHC = new Geom2dAdaptor_HCurve(G2d); Adaptor3d_OffsetCurve Off(AHC,-anOffset); Handle(Geom2d_Circle) CC = new Geom2d_Circle(Off.Circle()); Standard_Real Delta = 2*PI - l + f; f -= 0.2*Delta; l += 0.2*Delta; G2dOC = new Geom2d_TrimmedCurve(CC,f,l); } } else if (AC.GetType() == GeomAbs_Line) { Handle(Geom2dAdaptor_HCurve) AHC = new Geom2dAdaptor_HCurve(G2d); Adaptor3d_OffsetCurve Off(AHC,anOffset); Handle(Geom2d_Line) CC = new Geom2d_Line(Off.Line()); Standard_Real Delta = (l - f); f -= Delta; l += Delta; G2dOC = new Geom2d_TrimmedCurve(CC,f,l); } else { anOffset = -anOffset; Handle(Geom2d_TrimmedCurve) G2dT = new Geom2d_TrimmedCurve(G2d,f,l); G2dOC = new Geom2d_OffsetCurve( G2dT, anOffset); } // Bind the edges in my Map. if (!G2dOC.IsNull()) { TopoDS_Edge OE = (TopoDS_Edge) BRepLib_MakeEdge(G2dOC, RefPlane); OE.Orientation(E.Orientation()); TopTools_ListOfShape LL; LL.Append(OE); Map.Add(E,LL); #ifdef DRAW if (AffichGeom && !OE.IsNull()) { sprintf(name,"OFFSET_%d",++NbOFFSET); DBRep::Set(name,OE); Standard_Real ii = 0; } #endif } } //======================================================================= //function : UpdateDetromp //purpose : Pour chaque interval sur la bissectrice defini par params // test si le point milieu est a une distance > offset // dans ce cas les vertex correspondants aux extremites de l interval // sont ranges dans le detrompeur. // => Si un meme vertex apparait deux fois dans le detrompeur la // frontiere de la zone de proximitee est tangente a l offset . //======================================================================= void UpdateDetromp (TopTools_ListOfShape& Detromp1, TopTools_ListOfShape& Detromp2, const TopTools_SequenceOfShape& Vertices, const TColgp_SequenceOfPnt& Params, const Bisector_Bisec& Bisec, const Standard_Boolean SOnE, const Standard_Boolean EOnE, const BRepFill_TrimEdgeTool& Trim) { Standard_Integer ii = 1; Standard_Real U1,U2; TopoDS_Vertex V1,V2; Handle(Geom2d_Curve) Bis = Bisec.Value(); U1 = Bis->FirstParameter(); if (SOnE) { // le premier point de la bissectrice est sur l offset V1 = TopoDS::Vertex(Vertices.Value(ii)); ii++; } while (ii <= Vertices.Length()) { U2 = Params.Value(ii).X(); V2 = TopoDS::Vertex(Vertices.Value(ii)); gp_Pnt2d P = Bis->Value((U2 + U1)*0.5); if (!Trim.IsInside(P)) { if (!V1.IsNull()) { Detromp1.Append(V1); Detromp2.Append(V1); } Detromp1.Append(V2); Detromp2.Append(V2); } U1 = U2; V1 = V2; ii ++; } // test point milieu entre le dernier params et la fin de la bissectrice. U2 = Bis->LastParameter(); if (!EOnE) { if (!Precision::IsInfinite(U2)) { gp_Pnt2d P = Bis->Value((U2 + U1)*0.5); if (!Trim.IsInside(P)) { if (!V1.IsNull()) { Detromp1.Append(V1); Detromp2.Append(V1); } } } else { if (!V1.IsNull()) { Detromp1.Append(V1); Detromp2.Append(V1); } } } } //======================================================================= //function : VertexFromNode //purpose : //======================================================================= Standard_Boolean VertexFromNode (const Handle(MAT_Node)& aNode, const Standard_Real Offset, gp_Pnt2d& PN, BRepFill_DataMapOfNodeShape& MapNodeVertex, TopoDS_Vertex& VN) { Standard_Boolean Status; Standard_Real Tol = Precision::Confusion(); BRep_Builder B; if (!aNode->Infinite() && Abs(aNode->Distance()-Offset) < Tol) { //------------------------------------------------ // le Noeud donne un vertex sur l offset //------------------------------------------------ if (MapNodeVertex.IsBound(aNode)) { VN = TopoDS::Vertex(MapNodeVertex(aNode)); } else { gp_Pnt P(PN.X(),PN.Y(),0.); B.MakeVertex (VN); B.UpdateVertex(VN,P, Precision::Confusion()); MapNodeVertex.Bind(aNode,VN); } Status = Standard_True; } else Status = Standard_False; return Status; } //======================================================================= //function : StoreInMap //purpose : //======================================================================= void StoreInMap (const TopoDS_Shape& V1, const TopoDS_Shape& V2, TopTools_IndexedDataMapOfShapeShape& MapVV) { TopoDS_Shape OldV = V1, NewV = V2; Standard_Integer i; if (MapVV.Contains(V2)) NewV = MapVV.FindFromKey(V2); if (MapVV.Contains(V1)) MapVV.ChangeFromKey(V1) = NewV; for (i = 1; i <= MapVV.Extent(); i++) if (MapVV(i).IsSame(V1)) MapVV(i) = NewV; MapVV.Add(V1, NewV); } //======================================================================= //function : TrimEdge //purpose : //======================================================================= void TrimEdge (const TopoDS_Edge& E, const TopTools_ListOfShape& Detromp, TopTools_SequenceOfShape& TheVer, TColStd_SequenceOfReal& ThePar, TopTools_SequenceOfShape& S, TopTools_IndexedDataMapOfShapeShape& MapVV) { Standard_Boolean Change = Standard_True; BRep_Builder TheBuilder; S.Clear(); //----------------------------------------------------------- // Tri des deux sequences en fonction du parametre sur l edge. //----------------------------------------------------------- while (Change) { Change = Standard_False; for (Standard_Integer i = 1; i < ThePar.Length(); i++) { if (ThePar.Value(i) > ThePar.Value(i+1)) { ThePar.Exchange(i,i+1); TheVer.Exchange(i,i+1); Change = Standard_True; } } } //---------------------------------------------------------- // Si un vertex n est pas dans le detrompeur il est elimine. //---------------------------------------------------------- if (!BRep_Tool::Degenerated(E)) { for (Standard_Integer k = 1; k <= TheVer.Length(); k ++) { if ( DoubleOrNotInside (Detromp, TopoDS::Vertex(TheVer.Value(k)))) { TheVer.Remove(k); ThePar.Remove(k); k--; } } } //---------------------------------------------------------- // Si un vertex_double apparait deux fois dans le detrompeur // le vertex est elimine . // sinon on garde une seule de ces representations. //---------------------------------------------------------- if (!BRep_Tool::Degenerated(E)) { for (Standard_Integer k = 1; k < TheVer.Length(); k ++) { if (TheVer.Value(k).IsSame(TheVer.Value(k+1)) || Abs(ThePar.Value(k)-ThePar.Value(k+1)) <= Precision::PConfusion()) { if(k+1 == TheVer.Length()) { StoreInMap(TheVer(k), TheVer(k+1), MapVV); TheVer.Remove(k); ThePar.Remove(k); } else { StoreInMap(TheVer(k+1), TheVer(k), MapVV); TheVer.Remove(k+1); ThePar.Remove(k+1); } /* if ( DoubleOrNotInside (Detromp, TopoDS::Vertex(TheVer.Value(k)))) { TheVer.Remove(k); ThePar.Remove(k); k--; } */ k--; } } } //----------------------------------------------------------- // Creation des edges. // le nombre de vertex doit etre pair les edges a creer vont // d un vertex d indice impair i au vertex i+1; //----------------------------------------------------------- for (Standard_Integer k = 1; k < TheVer.Length(); k = k+2) { TopoDS_Shape aLocalShape = E.EmptyCopied(); TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape); // TopoDS_Edge NewEdge = TopoDS::Edge(E.EmptyCopied()); if (NewEdge.Orientation() == TopAbs_REVERSED) { TheBuilder.Add (NewEdge,TheVer.Value(k) .Oriented(TopAbs_REVERSED)); TheBuilder.Add (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_FORWARD)); } else { TheBuilder.Add (NewEdge,TheVer.Value(k) .Oriented(TopAbs_FORWARD)); TheBuilder.Add (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_REVERSED)); } TheBuilder.Range(NewEdge,ThePar.Value(k),ThePar.Value(k+1)); #ifdef DRAW if ( AffichEdge) { sprintf(name,"TRIMEDGE_%d",NbTRIMEDGES); DBRep::Set(name,NewEdge); } if (Affich2d) { TopLoc_Location L; Standard_Real f,l; Handle(Geom_Surface) Surf; Handle(Geom2d_Curve) C; BRep_Tool::CurveOnSurface(NewEdge,C,Surf,L,f,l); sprintf(name,"OFFSET2d_%d",NbTRIMEDGES++); Handle(Geom2d_TrimmedCurve) C2d = new Geom2d_TrimmedCurve(C,f,l); Handle(DrawTrSurf_Curve2d) dr = new DrawTrSurf_Curve2d(C2d,Standard_False); dr->SetColor(Draw_bleu); Draw::Set(name,dr); } #endif S.Append(NewEdge); } } //======================================================================= //function : DoubleOrNotInside //purpose : return True si V apparait 2 fois dans LV ou n est pas dedans. //======================================================================= Standard_Boolean DoubleOrNotInside (const TopTools_ListOfShape& LV, const TopoDS_Vertex& V) { Standard_Boolean Vu = Standard_False; TopTools_ListIteratorOfListOfShape it(LV); for ( ; it.More(); it.Next()) { if (V.IsSame(it.Value())) { if (Vu) return Standard_True; else Vu = Standard_True; } } if (Vu) return Standard_False; else return Standard_True; } Standard_Boolean IsSmallClosedEdge(const TopoDS_Edge& anEdge, const TopoDS_Vertex& aVertex) { gp_Pnt PV = BRep_Tool::Pnt(aVertex); gp_Pnt2d PV2d, Pfirst, Plast, Pmid; PV2d.SetCoord( PV.X(), PV.Y() ); Handle(Geom2d_Curve) PCurve; Handle( BRep_CurveRepresentation ) CurveRep = ((Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->Curves()).First(); PCurve = CurveRep->PCurve(); Standard_Real fpar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First(); Standard_Real lpar = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last(); Pfirst = PCurve->Value(fpar); Plast = PCurve->Value(lpar); Pmid = PCurve->Value((fpar + lpar)*0.5); Standard_Real theTol = BRep_Tool::Tolerance(aVertex); theTol *= 1.5; Standard_Real dist1 = Pfirst.Distance(PV2d); Standard_Real dist2 = Plast.Distance(PV2d); Standard_Real dist3 = Pmid.Distance(PV2d); if (dist1 <= theTol && dist2 <= theTol && dist3 <= theTol) return Standard_True; return Standard_False; } static void CheckBadEdges(const TopoDS_Face& Spine, const Standard_Real Offset, const BRepMAT2d_BisectingLocus& Locus, const BRepMAT2d_LinkTopoBilo& Link, TopTools_ListOfShape& BadEdges) { TopoDS_Face F = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD)); Standard_Real eps = Precision::Confusion(); Standard_Real LimCurv = 1./Offset; TopTools_MapOfShape aMap; for (Standard_Integer ic = 1; ic <= Locus.NumberOfContours(); ic++) { for (Standard_Integer ie = 1; ie <= Locus.NumberOfElts(ic); ie++) { const TopoDS_Shape& SE = Link.GeneratingShape(Locus.BasicElt(ic,ie)); if (SE.ShapeType() == TopAbs_EDGE) { if (aMap.Contains(SE)) { //cout << "Edge is treated second time" << endl; continue; } TopoDS_Edge E = TopoDS::Edge(SE); Standard_Real f,l; Handle(Geom2d_Curve) G2d = BRep_Tool::CurveOnSurface(E,F,f,l); Geom2dAdaptor_Curve AC(G2d,f,l); GeomAbs_CurveType aCType = AC.GetType(); if(aCType != GeomAbs_Line && aCType != GeomAbs_Circle) { Standard_Boolean reverse = Standard_False; if (E.Orientation() == TopAbs_FORWARD) reverse = Standard_True; gp_Pnt2d P, Pc; gp_Dir2d N; Geom2dLProp_CLProps2d aCLProps(G2d, 2, eps); aCLProps.SetParameter(f); if(!aCLProps.IsTangentDefined()) { BadEdges.Append(SE); aMap.Add(SE); continue; } P = aCLProps.Value(); Standard_Real Crv = aCLProps.Curvature(); if(Crv >= eps) { aCLProps.Tangent(N); Standard_Real x = N.Y(), y = -N.X(); N.SetCoord(x, y); if (reverse) N.Reverse(); aCLProps.CentreOfCurvature(Pc); gp_Vec2d Dir( P, Pc ); if (N.Dot(Dir) > 0.) { if (LimCurv <= Crv + eps) { BadEdges.Append(SE); aMap.Add(SE); continue; } } } aCLProps.SetParameter(l); if(!aCLProps.IsTangentDefined()) { BadEdges.Append(SE); aMap.Add(SE); continue; } P = aCLProps.Value(); Crv = aCLProps.Curvature(); if(Crv >= eps) { aCLProps.Tangent(N); Standard_Real x = N.Y(), y = -N.X(); N.SetCoord(x, y); if (reverse) N.Reverse(); aCLProps.CentreOfCurvature(Pc); gp_Vec2d Dir( P, Pc ); if (N.Dot(Dir) > 0.) { if (LimCurv <= Crv + eps) { BadEdges.Append(SE); aMap.Add(SE); continue; } } } } } } } } //======================================================================= //function : QuasiFleche //purpose : //======================================================================= static void QuasiFleche(const Adaptor3d_Curve& C, const Standard_Real Deflection2, const Standard_Real Udeb, const gp_Pnt& Pdeb, const gp_Vec& Vdeb, const Standard_Real Ufin, const gp_Pnt& Pfin, const gp_Vec& Vfin, const Standard_Integer Nbmin, const Standard_Real Eps, TColStd_SequenceOfReal& Parameters, TColgp_SequenceOfPnt& Points) { Standard_Integer Ptslength = Points.Length(); Standard_Real Udelta = Ufin-Udeb; gp_Pnt Pdelta; gp_Vec Vdelta; if (Nbmin > 2) { Udelta /=(Nbmin-1); C.D1(Udeb+Udelta,Pdelta,Vdelta); } else { Pdelta = Pfin; Vdelta = Vfin; } Standard_Real Norme = gp_Vec(Pdeb,Pdelta).SquareMagnitude(); Standard_Real theFleche=0; Standard_Boolean flecheok = Standard_False; if (Norme > Eps) { // Evaluation de la fleche par interpolation . Voir IntWalk_IWalking_5.gxx Standard_Real N1 = Vdeb.SquareMagnitude(); Standard_Real N2 = Vdelta.SquareMagnitude(); if (N1 > Eps && N2 > Eps) { Standard_Real Normediff = (Vdeb.Normalized().XYZ()-Vdelta.Normalized().XYZ()).SquareModulus(); if (Normediff > Eps) { theFleche = Normediff*Norme/64.; flecheok = Standard_True; } } } if (!flecheok) { gp_Pnt Pmid((Pdeb.XYZ()+Pdelta.XYZ())/2.); gp_Pnt Pverif(C.Value(Udeb+Udelta/2.)); theFleche = Pmid.SquareDistance(Pverif); } if (theFleche < Deflection2) { Parameters.Append(Udeb+Udelta); Points.Append(Pdelta); } else { QuasiFleche(C,Deflection2,Udeb,Pdeb, Vdeb, Udeb+Udelta,Pdelta, Vdelta, 3, Eps, Parameters,Points); } if (Nbmin > 2) { QuasiFleche(C,Deflection2,Udeb+Udelta,Pdelta, Vdelta, Ufin,Pfin, Vfin, Nbmin-(Points.Length()-Ptslength), Eps, Parameters,Points); } } //======================================================================= //function : PerformCurve //purpose : //======================================================================= static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters, TColgp_SequenceOfPnt& Points, const Adaptor3d_Curve& C, const Standard_Real Deflection, const Standard_Real U1, const Standard_Real U2, const Standard_Real EPSILON, const Standard_Integer Nbmin) { Standard_Real UU1 = Min(U1, U2); Standard_Real UU2 = Max(U1, U2); gp_Pnt Pdeb, Pfin; gp_Vec Ddeb,Dfin; C.D1(UU1,Pdeb,Ddeb); Parameters.Append(UU1); Points.Append(Pdeb); C.D1(UU2,Pfin,Dfin); QuasiFleche(C,Deflection*Deflection, UU1,Pdeb, Ddeb, UU2,Pfin, Dfin, Nbmin, EPSILON*EPSILON, Parameters,Points); return Standard_True; }