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 // Calculate approximate barycenter
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();
104 // Calculate the Transformation
106 Tf.SetTransformation(N);
107 BRepAdaptor_Curve AC;
108 // BndLib_Add3dCurve BC;
110 // transformation to the wire
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 //=======================================================================
128 //======================================================================
129 static Standard_Real Longueur(const Bnd_Box& WBox,
134 // face of the box most remoted from the face input in
135 // the direction of skin
136 Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,WZmin,WZmax,L;
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 // Skin in the wrong direction. Invert...
158 //=======================================================================
159 //function : GoodOrientation
160 //purpose : Check if the law is oriented to have an exterior skin
161 //======================================================================
162 static Standard_Boolean GoodOrientation(const Bnd_Box& B,
163 const Handle(BRepFill_LocationLaw)& Law,
166 Standard_Real f, l, r, t;
167 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
169 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
170 gp_Pnt P1(aXmin, aYmin, aZmin), P2(aXmax, aYmax, aZmax);
173 Law->CurvilinearBounds(Law->NbLaw(), f, l);
176 Standard_Integer ii, Ind;
178 Standard_Integer Nb = (Standard_Integer) (4+(10*r));
180 // Standard_Integer Nb = 4+(10*r);
184 Nb++; // Number of points
186 TColgp_Array1OfPnt Pnts(1, Nb);
187 Handle(Adaptor3d_HCurve) AC;
188 gp_XYZ Bary(0.,0.,0.);
190 for (ii=1; ii<=Nb; ii++) {
191 Law->Parameter((ii-1)*r, Ind, t);
192 AC = Law->Law(Ind)->GetCurve();
194 Bary+= Pnts(ii).XYZ();
199 gp_Vec Normal(D.XYZ());
200 Standard_Real Angle = 0;
201 gp_Vec Ref(Centre, Pnts(1));
203 for (ii=2; ii<=Nb; ii++) {
204 gp_Vec R(Centre, Pnts(ii));
205 Angle += Ref.AngleWithRef(R, Normal);
212 //=======================================================================
213 //function : Constructeur
215 //======================================================================
216 BRepFill_Draft::BRepFill_Draft(const TopoDS_Shape& S,
218 const Standard_Real Angle)
223 mySections.Nullify();
225 switch (S.ShapeType()) {
228 myWire = TopoDS::Wire(S);
233 TopoDS_Iterator Exp (S);
234 myWire = TopoDS::Wire(Exp.Value());
239 TopTools_ListOfShape List;
240 TopTools_IndexedDataMapOfShapeListOfShape edgemap;
241 TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,edgemap);
242 Standard_Integer iedge, nbf;
243 for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
244 const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
245 // skip degenerated edges
246 if (!BRep_Tool::Degenerated(theEdge)) {
247 nbf = edgemap(iedge).Extent();
248 if (nbf==1) List.Append(theEdge);
252 if( List.Extent()>0) {
255 BRepLib_WireError Err = MW.Error();
256 if (Err == BRepLib_WireDone) {
261 cout << "Error in MakeWire" << endl;
263 Standard_ConstructionError::Raise("BRepFill_Draft");
268 cout << "No Free Borders !" << endl;
270 Standard_ConstructionError::Raise("BRepFill_Draft");
275 Standard_ConstructionError::Raise("BRepFill_Draft");
278 // Attention to closed non declared wires !
279 if (!myWire.Closed()) {
280 TopoDS_Vertex Vf, Vl;
281 TopExp::Vertices(myWire, Vf, Vl);
282 if (Vf.IsSame(Vl)) myWire.Closed(Standard_True);
286 DBRep::Set("TheWire", myWire);
290 myAngle = Abs(Angle);
293 myDone = Standard_False;
300 //=======================================================================
301 //function :SetOptions
302 //purpose : Defines the style
303 //======================================================================
304 void BRepFill_Draft::SetOptions(const BRepFill_TransitionStyle Style,
305 const Standard_Real Min,
306 const Standard_Real Max)
313 //=======================================================================
316 //======================================================================
317 void BRepFill_Draft::SetDraft(const Standard_Boolean Internal)
319 IsInternal = Internal;
323 //=======================================================================
325 //purpose : calculate a surface of skinning
326 //======================================================================
327 void BRepFill_Draft::Perform(const Standard_Real LengthMax)
329 Handle(Geom_Surface) S;
331 Bnd_Box WBox;//, SBox;
335 ComputeTrsf(myWire, myDir, WBox, Trsf);
336 Init(S, LengthMax, WBox);
341 //=======================================================================
343 //purpose : calculate a surface of skinning
344 //======================================================================
345 void BRepFill_Draft::Perform(const Handle(Geom_Surface)& Surface,
346 const Standard_Boolean KeepInsideSurface)
353 ComputeTrsf(myWire, myDir, WBox, Trsf);
355 // box with bounds of the stop surface
356 Handle(Geom_Surface) Surf;
357 Surf = Handle(Geom_Surface)::DownCast(Surface->Transformed(Trsf));
358 GeomAdaptor_Surface S1 (Surf);
359 // BndLib_AddSurface AS;
360 // AS.Add(S1, 0.1, SBox);
361 BndLib_AddSurface::Add(S1, 0.1, SBox);
363 // calculate the maximum length of the rule.
364 L = Longueur(WBox, SBox, myDir, Pt);
365 L /= Abs(Cos(myAngle));
368 Init(Surface, L, WBox);
369 BuildShell(Surface, !KeepInsideSurface);
373 //================================================================
375 //purpose : calculate the surface of skinning, stopped by a shape
376 //================================================================
377 void BRepFill_Draft::Perform(const TopoDS_Shape& StopShape,
378 const Standard_Boolean KeepOutSide)
385 ComputeTrsf(myWire, myDir, WBox, Trsf);
387 // bounding box of the stop shape
388 Bnd_Box BSurf;//, TheBox;
389 Standard_Real Umin, Umax, Vmin, Vmax;
391 Standard_Real Tol = Precision::Confusion()/10;
395 Handle(Geom_Surface) Surf;
397 // BndLib_AddSurface AS;
399 TopExp_Explorer Ex (StopShape, TopAbs_FACE);
402 while (Ex.More()) { // parse faces of the stop shape
403 // B.UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
404 BRepTools::UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
405 Surf = Handle(Geom_Surface)::DownCast(
406 // BT.Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
407 BRep_Tool::Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
408 GeomAdaptor_Surface S1 (Surf);
409 // bounding box of the current face
410 // AS.Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
411 BndLib_AddSurface::Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
412 SBox.Add(BSurf); // group boxes
416 // calculate the maximum length of the rule.
417 L = Longueur(WBox, SBox, myDir, Pt);
418 L /= Abs(Cos(myAngle));
422 Inv = Trsf.Inverted(); // inverted transformation
423 Pt.Transform(Inv); // coordinate in the absolute reference
424 Handle(Geom_Plane) Plan = new (Geom_Plane)(Pt, myDir);
425 Surf = new (Geom_RectangularTrimmedSurface) (Plan,-L, L, -L, L);
429 char* Temp = "ThePlan" ;
430 DrawTrSurf::Set(Temp, Surf);
431 // DrawTrSurf::Set("ThePlan", Surf);
435 // Sweeping and restriction
436 Init(Plan, L*1.01, WBox);
437 BuildShell(Surf, Standard_False);
438 Fuse(StopShape, KeepOutSide);
442 //=======================================================================
444 //purpose : Construction of laws.
445 //======================================================================
446 void BRepFill_Draft::Init(const Handle(Geom_Surface)& ,
447 const Standard_Real Length,
452 // law of positioning
453 Handle(GeomFill_LocationDraft) Loc
454 = new (GeomFill_LocationDraft) (myDir, myAngle);
455 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
457 B = GoodOrientation(Box, myLoc, myDir);
459 if (IsInternal ^ (!B) ) {
461 Loc->SetAngle(myAngle);
462 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
465 myLoc->CleanLaw(angmin); // Clean small discontinuities.
468 // generating line is straight and parallel to binormal.
470 gp_Vec D (0., 1., 0.);
472 // Control of the orientation
474 myLoc->Law(1)->GetDomain(f,l);
478 myLoc->Law(1)->D0( (f+l)/2, M, Bid);
479 gp_Dir BN(M.Column(2));
481 Standard_Real ang = myDir.Angle(BN);
482 if (ang > M_PI/2) D.Reverse();
483 Handle(Geom_Line) L = new (Geom_Line) (P, D);
485 Handle(Geom_Curve) TC = new (Geom_TrimmedCurve) (L, 0, Length);
490 TC = new (Geom_Circle) (gp::XOY(), Length);
494 BRepLib_MakeEdge ME(TC);
495 TopoDS_Edge EG = ME.Edge();
497 BRepLib_MakeWire MW(EG);
498 TopoDS_Wire G = MW.Wire();
500 mySec = new (BRepFill_ShapeLaw) (G, Standard_True);
504 //=======================================================================
505 //function : BuildShell
506 //purpose : Construction of the skinning surface
507 //======================================================================
508 void BRepFill_Draft::BuildShell(const Handle(Geom_Surface)& Surf,
509 const Standard_Boolean KeepOutSide)
511 // construction of the surface
512 BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
513 Sweep.SetTolerance(myTol);
514 Sweep.SetAngularControl(angmin, angmax);
515 Sweep.Build(myStyle, GeomFill_Location, myCont);
516 if (Sweep.IsDone()) {
517 myShape = Sweep.Shape();
518 myShell = TopoDS::Shell(myShape);
519 myFaces = Sweep.SubShape();
520 mySections = Sweep.Sections();
521 myDone = Standard_True;
522 // Control of the orientation
523 Standard_Boolean out=Standard_True;
524 TopExp_Explorer ex(myShell,TopAbs_FACE);
526 F = TopoDS::Face(ex.Current());
527 BRepAdaptor_Surface SF(F);
531 u = SF.FirstUParameter();
532 v = SF.FirstVParameter();
535 if (F.Orientation() == TopAbs_REVERSED) V.Reverse();
536 if (V.Magnitude() > 1.e-10) {
537 out = myDir.Angle(V) > M_PI/2;
539 if (out == IsInternal) {
545 myDone = Standard_False;
549 if (!Surf.IsNull()) { // Add the face at end
551 // Waiting the use of traces & retriction in BRepFill_Sweep
553 BRepLib_MakeFace MkF;
554 MkF.Init(Surf, Standard_True, Precision::Confusion());
555 Fuse(MkF.Face(), KeepOutSide);
560 //=======================================================================
562 //purpose : Boolean operation between the skin and the
564 //======================================================================
565 Standard_Boolean BRepFill_Draft::Fuse(const TopoDS_Shape& StopShape,
566 const Standard_Boolean KeepOutSide)
569 Standard_Boolean issolid = Standard_False;
570 TopoDS_Solid Sol1, Sol2;
571 TopAbs_State State1 = TopAbs_OUT, State2 = TopAbs_OUT;
574 if (myShape.ShapeType()==TopAbs_SOLID) {
575 Sol1 = TopoDS::Solid(myShape);
576 issolid = Standard_True;
580 B.Add(Sol1, myShape); // shell => solid (for fusion)
584 switch (StopShape.ShapeType()) {
585 case TopAbs_COMPOUND :
587 TopoDS_Iterator It(StopShape);
588 return Fuse(It.Value(), KeepOutSide);
592 Sol2 = TopoDS::Solid(StopShape);
598 B.Add(Sol2, StopShape); // shell => solid (for fusion)
608 B.Add(Sol2, S); // shell => solid (for fusion)
614 return Standard_False; // Impossible to do
618 BRepAlgo_DSAccess DSA;
619 DSA.Load(Sol1, Sol2);
620 DSA.Intersect(Sol1, Sol2); // intersection of 2 solids
622 // removal of edges corresponding to "unused" intersections
623 Standard_Integer NbPaquet;
626 TopTools_ListOfShape List;
627 List = DSA.GetSectionEdgeSet();// list of edges
629 NbPaquet = List.Extent();
633 cout << "No fusion" << endl;
634 DBRep::Set("DepPart", Sol1);
635 DBRep::Set("StopPart", Sol2);
637 return Standard_False;
641 // It is required to select packs.
642 TColStd_Array1OfReal Dist(1, NbPaquet);
643 TopTools_ListIteratorOfListOfShape it(List);
644 Standard_Real D, Dmin = 1.e10;
647 //Classify the packs by distance.
648 BRepExtrema_DistShapeShape Dist2;
649 Dist2.LoadS1( myWire );
650 for (ii=1; it.More();it.Next(),ii++){
651 Dist2.LoadS2( it.Value() );
653 if (Dist2.IsDone()) {
656 if (D < Dmin) Dmin = D;
662 // remove edges "farther" than Dmin
663 for (ii=1, it.Initialize(List); it.More();it.Next(), ii++){
664 if (Dist(ii) > Dmin) {
665 DSA.SuppressEdgeSet(it.Value());
669 DBRep::Set("KeepEdges", it.Value());
675 if (StopShape.ShapeType() != TopAbs_SOLID) {
676 // It is required to choose the state by the geometry
678 //(1) Return an edge of section
679 List = DSA.GetSectionEdgeSet();// list of edges
680 TopTools_ListIteratorOfListOfShape it(List);
681 TopoDS_Iterator iter(it.Value());
682 TopoDS_Edge E = TopoDS::Edge(iter.Value());
684 //(2) Return geometry on StopShape
685 // Class BRep_Tool without fields and without Constructor :
687 Handle(Geom_Surface) S;
688 Handle(Geom2d_Curve) C2d;
692 // BT.CurveOnSurface(E, C2d, S, L, f, l, 2);
693 BRep_Tool::CurveOnSurface(E, C2d, S, L, f, l, 2);
696 C2d->D0((f+l)/2,P2d);
697 GeomLProp_SLProps SP(S, P2d.X(), P2d.Y(), 1, 1.e-12);
698 if (! SP.IsNormalDefined()) {
699 C2d->D0((3*f+l)/4,P2d);
700 SP.SetParameters(P2d.X(), P2d.Y());
701 if ( !SP.IsNormalDefined()) {
702 C2d->D0((f+3*l)/4,P2d);
703 SP.SetParameters(P2d.X(), P2d.Y());
708 if (myDir.Angle(SP.Normal()) < M_PI/2) State1 = TopAbs_IN;
709 else State1 = TopAbs_OUT;
712 if (! KeepOutSide) { // Invert State2;
713 if (State2 == TopAbs_IN) State2 = TopAbs_OUT;
714 else State2 = TopAbs_IN;
717 //recalculate the final shape
718 TopoDS_Shape result = DSA.Merge(State1, State2);
720 if (issolid) myShape = result;
723 Exp.Init(result, TopAbs_SHELL);
724 if (Exp.More()) myShape = Exp.Current();
727 // Update the History
729 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
730 const TopTools_ListOfShape& L = DSA.Modified(myFaces->Value(1,ii));
732 myFaces->SetValue(1, ii, L.First());
734 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
735 const TopTools_ListOfShape& L = DSA.Modified(mySections->Value(1,ii));
737 mySections->SetValue(1, ii, L.First());
740 return Standard_True;
743 //=======================================================================
745 //purpose : Assemble the skin with the above face
746 //======================================================================
747 Standard_Boolean BRepFill_Draft::Sewing()
749 Standard_Boolean ToAss;
750 Standard_Boolean Ok = Standard_False;
751 ToAss = (myTop.ShapeType() != TopAbs_WIRE);
753 if ((!ToAss) || (!myDone)) return Standard_False;
755 // Assembly make a shell from the faces of the shape + the input shape
756 Handle(BRepBuilderAPI_Sewing) Ass = new BRepBuilderAPI_Sewing(5*myTol, Standard_True,
757 Standard_True, Standard_False);
760 ToAss = Standard_True;
763 Standard_Integer NbCE;
766 // Check if the assembly is real.
767 NbCE = Ass->NbContigousEdges();
771 res = Ass->SewedShape();
772 if ((res.ShapeType() == TopAbs_SHELL)||
773 (res.ShapeType() == TopAbs_SOLID)) {
777 else if (res.ShapeType() == TopAbs_COMPOUND) {
778 TopoDS_Iterator It(res);
781 if (!It.More()) {//Only one part => this is correct
789 // Update the History
791 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
792 if (Ass->IsModified(myFaces->Value(1,ii)))
793 myFaces->SetValue(1, ii,
794 Ass->Modified(myFaces->Value(1,ii)));
796 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
797 if (Ass->IsModified(mySections->Value(1,ii)))
798 mySections->SetValue(1, ii,
799 Ass->Modified(mySections->Value(1,ii)));
802 if (myShape.Closed()) { // Make a Solid
806 BS.Add(solid,TopoDS::Shell(myShape));
808 BRepClass3d_SolidClassifier SC(solid);
809 SC.PerformInfinitePoint(Precision::Confusion());
810 if ( SC.State() == TopAbs_IN) {
813 BS.Add(solid,TopoDS::Shell(myShape));
819 else cout << "Draft : No assembly !" << endl;
824 //=======================================================================
825 //function : Generated
826 //purpose : return a sub-part generated by sweeping
827 //======================================================================
828 const TopTools_ListOfShape&
829 BRepFill_Draft::Generated(const TopoDS_Shape& S)
836 for (ii=0; ii<=myLoc->NbLaw(); ii++)
837 if (E.IsSame(myLoc->Vertex(ii))) {
838 myGenerated.Append(mySections->Value(1, ii+1));
843 for (ii=1; ii<=myLoc->NbLaw(); ii++)
844 if (E.IsSame(myLoc->Edge(ii))) {
845 myGenerated.Append(myFaces->Value(1, ii));
853 //=======================================================================
855 //purpose : return the complete shape
856 //======================================================================
857 TopoDS_Shape BRepFill_Draft::Shape()const
862 //=====================================================================
864 //purpose : surface of skinning with the input face (=>shell)
865 //=====================================================================
866 TopoDS_Shell BRepFill_Draft::Shell()const
871 //=======================================================================
874 //======================================================================
875 Standard_Boolean BRepFill_Draft::IsDone()const