// File: BRepOffset_Analyse.cxx // Created: Fri Oct 20 18:19:36 1995 // Author: Yves FRICAUD // #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 //======================================================================= //function : BRepOffset_Analyse //purpose : //======================================================================= BRepOffset_Analyse::BRepOffset_Analyse() :myDone(Standard_False) { } //======================================================================= //function : BRepOffset_Analyse //purpose : //======================================================================= BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S, const Standard_Real Angle) :myDone(Standard_False) { Perform( S, Angle); } //======================================================================= //function : EdgeAnlyse //purpose : //======================================================================= static void EdgeAnalyse(const TopoDS_Edge& E, const TopoDS_Face& F1, const TopoDS_Face& F2, const Standard_Real SinTol, BRepOffset_ListOfInterval& LI) { TopLoc_Location L; Standard_Real f,l; Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1); Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2); Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l); Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l); BRepAdaptor_Curve C(E); f = C.FirstParameter(); l = C.LastParameter(); // Tangent si la regularite estaum moins G1. if (BRep_Tool::HasContinuity(E,F1,F2)) { if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) { BRepOffset_Interval I; I.First(f); I.Last(l); I.Type(BRepOffset_Tangent); LI.Append(I); return; } } // Premiere etape : Type determine par un des bout. // Calcul des normales et tangentes sur les courbes et surface. // normales sont dirigees vers l exterieur. Standard_Real ParOnC = 0.5*(f+l); gp_Vec T1 = C.DN(ParOnC,1).Transformed(L.Transformation()); if (T1.SquareMagnitude() > gp::Resolution()) { T1.Normalize(); } if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) { T1.Reverse(); } if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse(); gp_Pnt2d P = C1->Value(ParOnC); gp_Pnt P3; gp_Vec D1U,D1V; S1->D1(P.X(),P.Y(),P3,D1U,D1V); gp_Vec DN1(D1U^D1V); if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse(); P = C2->Value(ParOnC); S2->D1(P.X(),P.Y(),P3,D1U,D1V); gp_Vec DN2(D1U^D1V); if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse(); DN1.Normalize(); DN2.Normalize(); gp_Vec ProVec = DN1^DN2; Standard_Real NormProVec = ProVec.Magnitude(); BRepOffset_Interval I; I.First(f); I.Last(l); if (Abs(NormProVec) < SinTol) { // plat if (DN1.Dot(DN2) > 0) { //Tangent I.Type(BRepOffset_Tangent); } else { //Confondu pas fini! #ifdef DEB cout <<" face localement confondues"< gp::Resolution()) ProVec.Normalize(); Standard_Real Prod = T1.Dot(DN1^DN2); if (Prod > 0.) { //Saillant I.Type(BRepOffset_Convex); } else { //rentrant I.Type(BRepOffset_Concave); } } LI.Append(I); } //======================================================================= //function : BuildAncestors //purpose : //======================================================================= static void BuildAncestors (const TopoDS_Shape& S, TopTools_IndexedDataMapOfShapeListOfShape& MA) { MA.Clear(); TopExp::MapShapesAndAncestors(S,TopAbs_VERTEX,TopAbs_EDGE,MA); TopExp::MapShapesAndAncestors(S,TopAbs_EDGE ,TopAbs_FACE,MA); // Purge des ancetres. TopTools_MapOfShape Map; for (Standard_Integer i = 1; i <= MA.Extent(); i++) { Map.Clear(); TopTools_ListOfShape& L = MA(i); TopTools_ListIteratorOfListOfShape it(L); while (it.More()) { if (!Map.Add(it.Value())) { L.Remove(it); } else { it.Next(); } } } } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean BRepOffset_Analyse::IsDone() const { return myDone; } //======================================================================= //function : Perform //purpose : //======================================================================= void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, const Standard_Real Angle) { myShape = S; angle = Angle; Standard_Real SinTol = sin(Angle); // Build ancestors. BuildAncestors (S,ancestors); TopExp_Explorer Exp(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); for ( ; Exp.More(); Exp.Next()) { const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); if (!mapEdgeType.IsBound(E)) { BRepOffset_ListOfInterval LI; mapEdgeType.Bind(E,LI); const TopTools_ListOfShape& L = Ancestors(E); if ( L.IsEmpty()) continue; if (L.Extent() == 2) { const TopoDS_Face& F1 = TopoDS::Face(L.First()); const TopoDS_Face& F2 = TopoDS::Face(L.Last ()); EdgeAnalyse(E,F1,F2,SinTol,mapEdgeType(E)); } else if (L.Extent() == 1) { Standard_Real U1,U2; const TopoDS_Face& F = TopoDS::Face(L.First()); BRep_Tool::Range(E,F,U1,U2); BRepOffset_Interval Inter(U1,U2,BRepOffset_Other); if (! BRepTools::IsReallyClosed(E,F)) { Inter.Type(BRepOffset_FreeBoundary); } mapEdgeType(E).Append(Inter); } else { #ifdef DEB cout <<"edge shared by more than two faces"< AddFaces(Face,Co,Map,T); List.Append(Co); } } } //======================================================================= //function : Explode //purpose : //======================================================================= void BRepOffset_Analyse::Explode( TopTools_ListOfShape& List, const BRepOffset_Type T1, const BRepOffset_Type T2) const { List.Clear(); BRep_Builder B; TopTools_MapOfShape Map; TopExp_Explorer Fexp; for (Fexp.Init(myShape,TopAbs_FACE); Fexp.More(); Fexp.Next()) { if ( Map.Add(Fexp.Current())) { TopoDS_Face Face = TopoDS::Face(Fexp.Current()); TopoDS_Compound Co; B.MakeCompound(Co); B.Add(Co,Face); // on ajoute a Co toutes les faces constituant la nappe de faces // G1 creee a partir de AddFaces(Face,Co,Map,T1,T2); List.Append(Co); } } } //======================================================================= //function : AddFaces //purpose : //======================================================================= void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, TopoDS_Compound& Co, TopTools_MapOfShape& Map, const BRepOffset_Type T) const { BRep_Builder B; TopExp_Explorer exp(Face,TopAbs_EDGE); for ( ; exp.More(); exp.Next()) { const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); const BRepOffset_ListOfInterval& LI = Type(E); if (!LI.IsEmpty() && LI.First().Type() == T) { // alors ca y est est raccordee G1 a const TopTools_ListOfShape& L = Ancestors(E); if (L.Extent() == 2) { TopoDS_Face F1 = TopoDS::Face(L.First()); if ( F1.IsSame(Face)) F1 = TopoDS::Face(L.Last ()); if ( Map.Add(F1)) { B.Add(Co,F1); AddFaces(F1,Co,Map,T); } } } } } //======================================================================= //function : AddFaces //purpose : //======================================================================= void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face, TopoDS_Compound& Co, TopTools_MapOfShape& Map, const BRepOffset_Type T1, const BRepOffset_Type T2) const { BRep_Builder B; TopExp_Explorer exp(Face,TopAbs_EDGE); for ( ; exp.More(); exp.Next()) { const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); const BRepOffset_ListOfInterval& LI = Type(E); if (!LI.IsEmpty() && (LI.First().Type() == T1 || LI.First().Type() == T2)) { // alors ca y est est raccordee G1 a const TopTools_ListOfShape& L = Ancestors(E); if (L.Extent() == 2) { TopoDS_Face F1 = TopoDS::Face(L.First()); if ( F1.IsSame(Face)) F1 = TopoDS::Face(L.Last ()); if ( Map.Add(F1)) { B.Add(Co,F1); AddFaces(F1,Co,Map,T1,T2); } } } } }