1 // File: BRepFill_Draft.cxx
2 // Created: Mon Jun 8 15:13:03 1998
3 // Author: Stephanie HUMEAU
7 #include <BRepFill_Draft.ixx>
9 #include <BRepFill_DraftLaw.hxx>
10 #include <BRepFill_ShapeLaw.hxx>
11 #include <BRepFill_Sweep.hxx>
13 #include <BndLib_Add3dCurve.hxx>
14 #include <BndLib_AddSurface.hxx>
15 #include <Bnd_Box.hxx>
18 #include <gp_Trsf.hxx>
22 #include <TColgp_Array1OfPnt.hxx>
24 #include <GeomAdaptor_Surface.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <Adaptor3d_HCurve.hxx>
28 #include <GeomLProp_SLProps.hxx>
29 #include <Geom_Surface.hxx>
30 #include <Geom_Line.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Geom_Geometry.hxx>
33 #include <Geom_Plane.hxx>
34 #include <Geom_RectangularTrimmedSurface.hxx>
36 #include <GeomAdaptor_HSurface.hxx>
37 #include <Adaptor3d_Surface.hxx>
38 #include <BRepAdaptor_Curve.hxx>
40 #include <GeomFill_LocationDraft.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Wire.hxx>
45 #include <TopoDS_Shell.hxx>
46 #include <TopoDS_Solid.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopExp_Explorer.hxx>
51 #include <BRepLib_MakeWire.hxx>
52 #include <BRepLib_MakeEdge.hxx>
53 #include <BRepLib_MakeFace.hxx>
54 #include <BRepLib_FindSurface.hxx>
55 #include <BRep_Builder.hxx>
57 #include <BRep_Tool.hxx>
58 #include <BRepTools.hxx>
59 #include <BRepAlgo_DSAccess.hxx>
60 #include <BRepBuilderAPI_Sewing.hxx>
61 #include <BRepClass3d_SolidClassifier.hxx>
63 #include <TopTools_ListIteratorOfListOfShape.hxx>
64 #include <TopTools_ListOfShape.hxx>
65 #include <BRepExtrema_DistShapeShape.hxx>
67 #include <Precision.hxx>
68 #include <TColStd_Array1OfReal.hxx>
70 #include <Standard_NoSuchObject.hxx>
71 #include <StdFail_NotDone.hxx>
74 #include <Geom_Circle.hxx>
77 #include <DrawTrSurf.hxx>
78 static Standard_Boolean Affich = 0;
81 //=======================================================================
84 //======================================================================
85 static void ComputeTrsf(const TopoDS_Wire& W,
90 // Calcul d'un barycentre approximatif
91 BRepTools_WireExplorer Exp(W);
92 // Class BRep_Tool without fields and without Constructor :
94 gp_XYZ Bary(0.,0.,0.);
97 for (nb=0; Exp.More(); Exp.Next()) {
98 // Bary += BT.Pnt(Exp.CurrentVertex()).XYZ();
99 Bary += BRep_Tool::Pnt(Exp.CurrentVertex()).XYZ();
106 Tf.SetTransformation(N);
107 BRepAdaptor_Curve AC;
108 // BndLib_Add3dCurve BC;
111 TopoDS_Wire TheW = W;
112 TopLoc_Location Loc(Tf);
118 for (Exp.Init(TheW); Exp.More(); Exp.Next()) {
119 AC.Initialize(Exp.Current());
120 // BC.Add(AC, 0.1, Box);
121 BndLib_Add3dCurve::Add(AC, 0.1, Box);
125 //=======================================================================
126 //function : Longueur
128 //======================================================================
129 static Standard_Real Longueur(const Bnd_Box& WBox,
134 // face de la boite la plus eloignee de la face entree dans
135 //la direction de depouille
136 Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,WZmin,WZmax,L;
138 //"coord" de la boite
139 WBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
143 SBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
144 P.SetCoord( (Xmin+Xmax)/2, (Ymin+Ymax)/2, Zmax);
147 // Depouille dans le mauvais sens. On inverse...
158 //=======================================================================
159 //function : GoodOrientation
160 //purpose : Regarde si la loi est oriente de maniere a avoir une depouille
162 //======================================================================
163 static Standard_Boolean GoodOrientation(const Bnd_Box& B,
164 const Handle(BRepFill_LocationLaw)& Law,
167 Standard_Real f, l, r, t;
168 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
170 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
171 gp_Pnt P1(aXmin, aYmin, aZmin), P2(aXmax, aYmax, aZmax);
174 Law->CurvilinearBounds(Law->NbLaw(), f, l);
177 Standard_Integer ii, Ind;
179 Standard_Integer Nb = (Standard_Integer) (4+(10*r));
181 // Standard_Integer Nb = 4+(10*r);
185 Nb++; // Nombre de points
187 TColgp_Array1OfPnt Pnts(1, Nb);
188 Handle(Adaptor3d_HCurve) AC;
189 gp_XYZ Bary(0.,0.,0.);
191 for (ii=1; ii<=Nb; ii++) {
192 Law->Parameter((ii-1)*r, Ind, t);
193 AC = Law->Law(Ind)->GetCurve();
195 Bary+= Pnts(ii).XYZ();
200 gp_Vec Normal(D.XYZ());
201 Standard_Real Angle = 0;
202 gp_Vec Ref(Centre, Pnts(1));
204 for (ii=2; ii<=Nb; ii++) {
205 gp_Vec R(Centre, Pnts(ii));
206 Angle += Ref.AngleWithRef(R, Normal);
213 //=======================================================================
214 //function : Constructeur
216 //======================================================================
217 BRepFill_Draft::BRepFill_Draft(const TopoDS_Shape& S,
219 const Standard_Real Angle)
224 mySections.Nullify();
226 switch (S.ShapeType()) {
229 myWire = TopoDS::Wire(S);
234 TopoDS_Iterator Exp (S);
235 myWire = TopoDS::Wire(Exp.Value());
240 TopTools_ListOfShape List;
241 TopTools_IndexedDataMapOfShapeListOfShape edgemap;
242 TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,edgemap);
243 Standard_Integer iedge, nbf;
244 for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
245 const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
246 // skip degenerated edges
247 if (!BRep_Tool::Degenerated(theEdge)) {
248 nbf = edgemap(iedge).Extent();
249 if (nbf==1) List.Append(theEdge);
253 if( List.Extent()>0) {
256 BRepLib_WireError Err = MW.Error();
257 if (Err == BRepLib_WireDone) {
262 cout << "Error in MakeWire" << endl;
264 Standard_ConstructionError::Raise("BRepFill_Draft");
269 cout << "Pas de Bords Libre !" << endl;
271 Standard_ConstructionError::Raise("BRepFill_Draft");
276 Standard_ConstructionError::Raise("BRepFill_Draft");
279 // Attention aux wire closed non declare !
280 if (!myWire.Closed()) {
281 TopoDS_Vertex Vf, Vl;
282 TopExp::Vertices(myWire, Vf, Vl);
283 if (Vf.IsSame(Vl)) myWire.Closed(Standard_True);
287 DBRep::Set("TheWire", myWire);
291 myAngle = Abs(Angle);
294 myDone = Standard_False;
301 //=======================================================================
302 //function :SetOptions
303 //purpose : Definit le style
304 //======================================================================
305 void BRepFill_Draft::SetOptions(const BRepFill_TransitionStyle Style,
306 const Standard_Real Min,
307 const Standard_Real Max)
314 //=======================================================================
317 //======================================================================
318 void BRepFill_Draft::SetDraft(const Standard_Boolean Internal)
320 IsInternal = Internal;
324 //=======================================================================
326 //purpose : calcul d'une surface de depouille
327 //======================================================================
328 void BRepFill_Draft::Perform(const Standard_Real LengthMax)
330 Handle(Geom_Surface) S;
332 Bnd_Box WBox;//, SBox;
336 ComputeTrsf(myWire, myDir, WBox, Trsf);
337 Init(S, LengthMax, WBox);
342 //=======================================================================
344 //purpose : calcul d'une surface de depouille
345 //======================================================================
346 void BRepFill_Draft::Perform(const Handle(Geom_Surface)& Surface,
347 const Standard_Boolean KeepInsideSurface)
354 ComputeTrsf(myWire, myDir, WBox, Trsf);
356 // boite englobant la surface d'arret
357 Handle(Geom_Surface) Surf;
358 Surf = Handle(Geom_Surface)::DownCast(Surface->Transformed(Trsf));
359 GeomAdaptor_Surface S1 (Surf);
360 // BndLib_AddSurface AS;
361 // AS.Add(S1, 0.1, SBox);
362 BndLib_AddSurface::Add(S1, 0.1, SBox);
364 // on calcule la longueur maximum de la regle.
365 L = Longueur(WBox, SBox, myDir, Pt);
366 L /= Abs(Cos(myAngle));
369 Init(Surface, L, WBox);
370 BuildShell(Surface, !KeepInsideSurface);
374 //=======================================================================
376 //purpose : calcul de la surface de depouille, arretee par une shape
377 //======================================================================
378 void BRepFill_Draft::Perform(const TopoDS_Shape& StopShape,
379 const Standard_Boolean KeepOutSide)
386 ComputeTrsf(myWire, myDir, WBox, Trsf);
388 // boite englobant la shape d'arret
389 Bnd_Box BSurf;//, TheBox;
390 Standard_Real Umin, Umax, Vmin, Vmax;
392 Standard_Real Tol = Precision::Confusion()/10;
396 Handle(Geom_Surface) Surf;
398 // BndLib_AddSurface AS;
400 TopExp_Explorer Ex (StopShape, TopAbs_FACE);
403 while (Ex.More()) { // on parcourt les faces de la shape d'arret
404 // B.UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
405 BRepTools::UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
406 Surf = Handle(Geom_Surface)::DownCast(
407 // BT.Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
408 BRep_Tool::Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
409 GeomAdaptor_Surface S1 (Surf);
410 // boite englobant la face courante
411 // AS.Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
412 BndLib_AddSurface::Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
413 SBox.Add(BSurf); // on regroupe les boites
417 // on calcule la longueur maximum de la regle.
418 L = Longueur(WBox, SBox, myDir, Pt);
419 L /= Abs(Cos(myAngle));
423 Inv = Trsf.Inverted(); // transfo inverse
424 Pt.Transform(Inv); // coord dans le repere absolu
425 Handle(Geom_Plane) Plan = new (Geom_Plane)(Pt, myDir);
426 Surf = new (Geom_RectangularTrimmedSurface) (Plan,-L, L, -L, L);
430 char* Temp = "ThePlan" ;
431 DrawTrSurf::Set(Temp, Surf);
432 // DrawTrSurf::Set("ThePlan", Surf);
436 // Balayage et restriction
437 Init(Plan, L*1.01, WBox);
438 BuildShell(Surf, Standard_False);
439 Fuse(StopShape, KeepOutSide);
443 //=======================================================================
445 //purpose : Construction des lois.
446 //======================================================================
447 void BRepFill_Draft::Init(const Handle(Geom_Surface)& ,
448 const Standard_Real Length,
453 // loi de positionnement
454 Handle(GeomFill_LocationDraft) Loc
455 = new (GeomFill_LocationDraft) (myDir, myAngle);
456 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
458 B = GoodOrientation(Box, myLoc, myDir);
460 if (IsInternal ^ (!B) ) {
462 Loc->SetAngle(myAngle);
463 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
466 myLoc->CleanLaw(angmin); // Nettoie les petites discontinuites.
469 // generatrice est une droite // a la binormal.
471 gp_Vec D (0., 1., 0.);
473 // Controle de l'orientation
475 myLoc->Law(1)->GetDomain(f,l);
479 myLoc->Law(1)->D0( (f+l)/2, M, Bid);
480 gp_Dir BN(M.Column(2));
482 Standard_Real ang = myDir.Angle(BN);
483 if (ang > PI/2) D.Reverse();
484 Handle(Geom_Line) L = new (Geom_Line) (P, D);
486 Handle(Geom_Curve) TC = new (Geom_TrimmedCurve) (L, 0, Length);
491 TC = new (Geom_Circle) (gp::XOY(), Length);
495 BRepLib_MakeEdge ME(TC);
496 TopoDS_Edge EG = ME.Edge();
498 BRepLib_MakeWire MW(EG);
499 TopoDS_Wire G = MW.Wire();
501 mySec = new (BRepFill_ShapeLaw) (G, Standard_True);
505 //=======================================================================
506 //function : BuildShell
507 //purpose : Construction de la surface de depouille
508 //======================================================================
509 void BRepFill_Draft::BuildShell(const Handle(Geom_Surface)& Surf,
510 const Standard_Boolean KeepOutSide)
512 // construction de la surface
513 BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
514 Sweep.SetTolerance(myTol);
515 Sweep.SetAngularControl(angmin, angmax);
516 Sweep.Build(myStyle, GeomFill_Location, myCont);
517 if (Sweep.IsDone()) {
518 myShape = Sweep.Shape();
519 myShell = TopoDS::Shell(myShape);
520 myFaces = Sweep.SubShape();
521 mySections = Sweep.Sections();
522 myDone = Standard_True;
523 // Controle de l'orientation
524 Standard_Boolean out=Standard_True;
525 TopExp_Explorer ex(myShell,TopAbs_FACE);
527 F = TopoDS::Face(ex.Current());
528 BRepAdaptor_Surface SF(F);
532 u = SF.FirstUParameter();
533 v = SF.FirstVParameter();
536 if (F.Orientation() == TopAbs_REVERSED) V.Reverse();
537 if (V.Magnitude() > 1.e-10) {
538 out = myDir.Angle(V) > PI/2;
540 if (out == IsInternal) {
546 myDone = Standard_False;
550 if (!Surf.IsNull()) { // On ajoute la face en bout
552 // En attendant une utilisation des traces & retriction dans BRepFill_Sweep
554 BRepLib_MakeFace MkF;
555 MkF.Init(Surf, Standard_True, Precision::Confusion());
556 Fuse(MkF.Face(), KeepOutSide);
561 //=======================================================================
563 //purpose : Operation booleenne entre la depouille et
565 //======================================================================
566 Standard_Boolean BRepFill_Draft::Fuse(const TopoDS_Shape& StopShape,
567 const Standard_Boolean KeepOutSide)
570 Standard_Boolean issolid = Standard_False;
571 TopoDS_Solid Sol1, Sol2;
572 TopAbs_State State1 = TopAbs_OUT, State2 = TopAbs_OUT;
575 if (myShape.ShapeType()==TopAbs_SOLID) {
576 Sol1 = TopoDS::Solid(myShape);
577 issolid = Standard_True;
581 B.Add(Sol1, myShape); // shell => solid (pour fusion)
585 switch (StopShape.ShapeType()) {
586 case TopAbs_COMPOUND :
588 TopoDS_Iterator It(StopShape);
589 return Fuse(It.Value(), KeepOutSide);
593 Sol2 = TopoDS::Solid(StopShape);
599 B.Add(Sol2, StopShape); // shell => solid (pour fusion)
609 B.Add(Sol2, S); // shell => solid (pour fusion)
615 return Standard_False; // On ne sait pas faire
619 BRepAlgo_DSAccess DSA;
620 DSA.Load(Sol1, Sol2);
621 DSA.Intersect(Sol1, Sol2); // intersection des 2 solids
623 // suppression des aretes correspondant aux intersections "inutiles"
624 Standard_Integer NbPaquet;
627 TopTools_ListOfShape List;
628 List = DSA.GetSectionEdgeSet();// liste des aretes
630 NbPaquet = List.Extent();
634 cout << "Pas de fusion" << endl;
635 DBRep::Set("DepPart", Sol1);
636 DBRep::Set("StopPart", Sol2);
638 return Standard_False;
642 // Il faut selectioner les paquets.
643 TColStd_Array1OfReal Dist(1, NbPaquet);
644 TopTools_ListIteratorOfListOfShape it(List);
645 Standard_Real D, Dmin = 1.e10;
648 //On classe les paquets par eloignement.
649 BRepExtrema_DistShapeShape Dist2;
650 Dist2.LoadS1( myWire );
651 for (ii=1; it.More();it.Next(),ii++){
652 Dist2.LoadS2( it.Value() );
654 if (Dist2.IsDone()) {
657 if (D < Dmin) Dmin = D;
663 // on supprime les edges "plus loin" que Dmin
664 for (ii=1, it.Initialize(List); it.More();it.Next(), ii++){
665 if (Dist(ii) > Dmin) {
666 DSA.SuppressEdgeSet(it.Value());
670 DBRep::Set("KeepEdges", it.Value());
676 if (StopShape.ShapeType() != TopAbs_SOLID) {
677 // Il faut choisir le state par la geometrie
679 //(1) On recupere une edge de section
680 List = DSA.GetSectionEdgeSet();// liste des aretes
681 TopTools_ListIteratorOfListOfShape it(List);
682 TopoDS_Iterator iter(it.Value());
683 TopoDS_Edge E = TopoDS::Edge(iter.Value());
685 // (2) On recupere sa geometrie sur StopShape
686 // Class BRep_Tool without fields and without Constructor :
688 Handle(Geom_Surface) S;
689 Handle(Geom2d_Curve) C2d;
693 // BT.CurveOnSurface(E, C2d, S, L, f, l, 2);
694 BRep_Tool::CurveOnSurface(E, C2d, S, L, f, l, 2);
696 // On Trouve une normale.
697 C2d->D0((f+l)/2,P2d);
698 GeomLProp_SLProps SP(S, P2d.X(), P2d.Y(), 1, 1.e-12);
699 if (! SP.IsNormalDefined()) {
700 C2d->D0((3*f+l)/4,P2d);
701 SP.SetParameters(P2d.X(), P2d.Y());
702 if ( !SP.IsNormalDefined()) {
703 C2d->D0((f+3*l)/4,P2d);
704 SP.SetParameters(P2d.X(), P2d.Y());
708 // On en deduit State1
709 if (myDir.Angle(SP.Normal()) < PI/2) State1 = TopAbs_IN;
710 else State1 = TopAbs_OUT;
713 if (! KeepOutSide) { // On inverse State2;
714 if (State2 == TopAbs_IN) State2 = TopAbs_OUT;
715 else State2 = TopAbs_IN;
718 //recalcul de la shape finale
719 TopoDS_Shape result = DSA.Merge(State1, State2);
721 if (issolid) myShape = result;
724 Exp.Init(result, TopAbs_SHELL);
725 if (Exp.More()) myShape = Exp.Current();
728 // Mise a jour de l'Historique
730 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
731 const TopTools_ListOfShape& L = DSA.Modified(myFaces->Value(1,ii));
733 myFaces->SetValue(1, ii, L.First());
735 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
736 const TopTools_ListOfShape& L = DSA.Modified(mySections->Value(1,ii));
738 mySections->SetValue(1, ii, L.First());
741 return Standard_True;
744 //=======================================================================
746 //purpose : Assemble la depouille avec la face du dessus
747 //======================================================================
748 Standard_Boolean BRepFill_Draft::Sewing()
750 Standard_Boolean ToAss;
751 Standard_Boolean Ok = Standard_False;
752 ToAss = (myTop.ShapeType() != TopAbs_WIRE);
754 if ((!ToAss) || (!myDone)) return Standard_False;
757 // on fait un shell a partir des faces de la shape + la shape en entree
758 Handle(BRepBuilderAPI_Sewing) Ass = new BRepBuilderAPI_Sewing(5*myTol, Standard_True,
759 Standard_True, Standard_False);
762 ToAss = Standard_True;
765 Standard_Integer NbCE;
768 // On verifie que l'assemblage est effectif.
769 NbCE = Ass->NbContigousEdges();
773 res = Ass->SewedShape();
774 if ((res.ShapeType() == TopAbs_SHELL)||
775 (res.ShapeType() == TopAbs_SOLID)) {
779 else if (res.ShapeType() == TopAbs_COMPOUND) {
780 TopoDS_Iterator It(res);
783 if (!It.More()) {//Une seule partie => c'est bon
791 // Mise a jour de l'Historique
793 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
794 if (Ass->IsModified(myFaces->Value(1,ii)))
795 myFaces->SetValue(1, ii,
796 Ass->Modified(myFaces->Value(1,ii)));
798 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
799 if (Ass->IsModified(mySections->Value(1,ii)))
800 mySections->SetValue(1, ii,
801 Ass->Modified(mySections->Value(1,ii)));
804 if (myShape.Closed()) { // On fait un Solid
808 BS.Add(solid,TopoDS::Shell(myShape));
810 BRepClass3d_SolidClassifier SC(solid);
811 SC.PerformInfinitePoint(Precision::Confusion());
812 if ( SC.State() == TopAbs_IN) {
815 BS.Add(solid,TopoDS::Shell(myShape));
821 else cout << "Draft : Pas d'assemblage !" << endl;
826 //=======================================================================
827 //function : Generated
828 //purpose : retourne une sous partie partie generes par balayage
829 //======================================================================
830 const TopTools_ListOfShape&
831 BRepFill_Draft::Generated(const TopoDS_Shape& S)
838 for (ii=0; ii<=myLoc->NbLaw(); ii++)
839 if (E.IsSame(myLoc->Vertex(ii))) {
840 myGenerated.Append(mySections->Value(1, ii+1));
845 for (ii=1; ii<=myLoc->NbLaw(); ii++)
846 if (E.IsSame(myLoc->Edge(ii))) {
847 myGenerated.Append(myFaces->Value(1, ii));
855 //=======================================================================
857 //purpose : retourne la shape complete
858 //======================================================================
859 TopoDS_Shape BRepFill_Draft::Shape()const
864 //=======================================================================
866 //purpose : surface de depouille avec la face entree (=>shell)
867 //======================================================================
868 TopoDS_Shell BRepFill_Draft::Shell()const
873 //=======================================================================
876 //======================================================================
877 Standard_Boolean BRepFill_Draft::IsDone()const