1 // Created on: 1998-06-08
2 // Created by: Stephanie HUMEAU
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRepFill_Draft.ixx>
20 #include <BRepFill_DraftLaw.hxx>
21 #include <BRepFill_ShapeLaw.hxx>
22 #include <BRepFill_Sweep.hxx>
23 #include <BRepFill_DataMapOfShapeHArray2OfShape.hxx>
25 #include <BndLib_Add3dCurve.hxx>
26 #include <BndLib_AddSurface.hxx>
27 #include <Bnd_Box.hxx>
30 #include <gp_Trsf.hxx>
34 #include <TColgp_Array1OfPnt.hxx>
36 #include <GeomAdaptor_Surface.hxx>
37 #include <BRepAdaptor_Surface.hxx>
38 #include <Adaptor3d_HCurve.hxx>
40 #include <GeomLProp_SLProps.hxx>
41 #include <Geom_Surface.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_TrimmedCurve.hxx>
44 #include <Geom_Geometry.hxx>
45 #include <Geom_Plane.hxx>
46 #include <Geom_RectangularTrimmedSurface.hxx>
48 #include <GeomAdaptor_HSurface.hxx>
49 #include <Adaptor3d_Surface.hxx>
50 #include <BRepAdaptor_Curve.hxx>
52 #include <GeomFill_LocationDraft.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Wire.hxx>
57 #include <TopoDS_Shell.hxx>
58 #include <TopoDS_Solid.hxx>
59 #include <TopoDS_Iterator.hxx>
60 #include <TopExp_Explorer.hxx>
63 #include <BRepLib_MakeWire.hxx>
64 #include <BRepLib_MakeEdge.hxx>
65 #include <BRepLib_MakeFace.hxx>
66 #include <BRepLib_FindSurface.hxx>
67 #include <BRep_Builder.hxx>
69 #include <BRep_Tool.hxx>
70 #include <BRepTools.hxx>
71 #include <BRepAlgo_DSAccess.hxx>
72 #include <BRepBuilderAPI_Sewing.hxx>
73 #include <BRepClass3d_SolidClassifier.hxx>
75 #include <TopTools_ListIteratorOfListOfShape.hxx>
76 #include <TopTools_ListOfShape.hxx>
77 #include <BRepExtrema_DistShapeShape.hxx>
79 #include <Precision.hxx>
80 #include <TColStd_Array1OfReal.hxx>
82 #include <Standard_NoSuchObject.hxx>
83 #include <StdFail_NotDone.hxx>
86 #include <Geom_Circle.hxx>
89 #include <DrawTrSurf.hxx>
90 static Standard_Boolean Affich = 0;
93 //=======================================================================
96 //======================================================================
97 static void ComputeTrsf(const TopoDS_Wire& W,
102 // Calculate approximate barycenter
103 BRepTools_WireExplorer Exp(W);
104 // Class BRep_Tool without fields and without Constructor :
106 gp_XYZ Bary(0.,0.,0.);
109 for (nb=0; Exp.More(); Exp.Next()) {
110 // Bary += BT.Pnt(Exp.CurrentVertex()).XYZ();
111 Bary += BRep_Tool::Pnt(Exp.CurrentVertex()).XYZ();
116 // Calculate the Transformation
118 Tf.SetTransformation(N);
119 BRepAdaptor_Curve AC;
120 // BndLib_Add3dCurve BC;
122 // transformation to the wire
123 TopoDS_Wire TheW = W;
124 TopLoc_Location Loc(Tf);
130 for (Exp.Init(TheW); Exp.More(); Exp.Next()) {
131 AC.Initialize(Exp.Current());
132 // BC.Add(AC, 0.1, Box);
133 BndLib_Add3dCurve::Add(AC, 0.1, Box);
137 //=======================================================================
140 //======================================================================
141 static Standard_Real Longueur(const Bnd_Box& WBox,
146 // face of the box most remoted from the face input in
147 // the direction of skin
148 Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,WZmin,WZmax,L;
151 WBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
155 SBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
156 P.SetCoord( (Xmin+Xmax)/2, (Ymin+Ymax)/2, Zmax);
159 // Skin in the wrong direction. Invert...
170 //=======================================================================
171 //function : GoodOrientation
172 //purpose : Check if the law is oriented to have an exterior skin
173 //======================================================================
174 static Standard_Boolean GoodOrientation(const Bnd_Box& B,
175 const Handle(BRepFill_LocationLaw)& Law,
178 Standard_Real f, l, r, t;
179 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
181 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
182 gp_Pnt P1(aXmin, aYmin, aZmin), P2(aXmax, aYmax, aZmax);
185 Law->CurvilinearBounds(Law->NbLaw(), f, l);
188 Standard_Integer ii, Ind;
190 Standard_Integer Nb = (Standard_Integer) (4+(10*r));
192 // Standard_Integer Nb = 4+(10*r);
196 Nb++; // Number of points
198 TColgp_Array1OfPnt Pnts(1, Nb);
199 Handle(Adaptor3d_HCurve) AC;
200 gp_XYZ Bary(0.,0.,0.);
202 for (ii=1; ii<=Nb; ii++) {
203 Law->Parameter((ii-1)*r, Ind, t);
204 AC = Law->Law(Ind)->GetCurve();
206 Bary+= Pnts(ii).XYZ();
211 gp_Vec Normal(D.XYZ());
212 Standard_Real Angle = 0;
213 gp_Vec Ref(Centre, Pnts(1));
215 for (ii=2; ii<=Nb; ii++) {
216 gp_Vec R(Centre, Pnts(ii));
217 Angle += Ref.AngleWithRef(R, Normal);
224 //=======================================================================
225 //function : Constructeur
227 //======================================================================
228 BRepFill_Draft::BRepFill_Draft(const TopoDS_Shape& S,
230 const Standard_Real Angle)
235 mySections.Nullify();
237 switch (S.ShapeType()) {
240 myWire = TopoDS::Wire(S);
245 TopoDS_Iterator Exp (S);
246 myWire = TopoDS::Wire(Exp.Value());
251 TopTools_ListOfShape List;
252 TopTools_IndexedDataMapOfShapeListOfShape edgemap;
253 TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,edgemap);
254 Standard_Integer iedge, nbf;
255 for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
256 const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
257 // skip degenerated edges
258 if (!BRep_Tool::Degenerated(theEdge)) {
259 nbf = edgemap(iedge).Extent();
260 if (nbf==1) List.Append(theEdge);
264 if( List.Extent()>0) {
267 BRepLib_WireError Err = MW.Error();
268 if (Err == BRepLib_WireDone) {
273 cout << "Error in MakeWire" << endl;
275 Standard_ConstructionError::Raise("BRepFill_Draft");
280 cout << "No Free Borders !" << endl;
282 Standard_ConstructionError::Raise("BRepFill_Draft");
287 Standard_ConstructionError::Raise("BRepFill_Draft");
290 // Attention to closed non declared wires !
291 if (!myWire.Closed()) {
292 TopoDS_Vertex Vf, Vl;
293 TopExp::Vertices(myWire, Vf, Vl);
294 if (Vf.IsSame(Vl)) myWire.Closed(Standard_True);
298 DBRep::Set("TheWire", myWire);
302 myAngle = Abs(Angle);
305 myDone = Standard_False;
312 //=======================================================================
313 //function :SetOptions
314 //purpose : Defines the style
315 //======================================================================
316 void BRepFill_Draft::SetOptions(const BRepFill_TransitionStyle Style,
317 const Standard_Real Min,
318 const Standard_Real Max)
325 //=======================================================================
328 //======================================================================
329 void BRepFill_Draft::SetDraft(const Standard_Boolean Internal)
331 IsInternal = Internal;
335 //=======================================================================
337 //purpose : calculate a surface of skinning
338 //======================================================================
339 void BRepFill_Draft::Perform(const Standard_Real LengthMax)
341 Handle(Geom_Surface) S;
343 Bnd_Box WBox;//, SBox;
347 ComputeTrsf(myWire, myDir, WBox, Trsf);
348 Init(S, LengthMax, WBox);
353 //=======================================================================
355 //purpose : calculate a surface of skinning
356 //======================================================================
357 void BRepFill_Draft::Perform(const Handle(Geom_Surface)& Surface,
358 const Standard_Boolean KeepInsideSurface)
365 ComputeTrsf(myWire, myDir, WBox, Trsf);
367 // box with bounds of the stop surface
368 Handle(Geom_Surface) Surf;
369 Surf = Handle(Geom_Surface)::DownCast(Surface->Transformed(Trsf));
370 GeomAdaptor_Surface S1 (Surf);
371 // BndLib_AddSurface AS;
372 // AS.Add(S1, 0.1, SBox);
373 BndLib_AddSurface::Add(S1, 0.1, SBox);
375 // calculate the maximum length of the rule.
376 L = Longueur(WBox, SBox, myDir, Pt);
377 L /= Abs(Cos(myAngle));
380 Init(Surface, L, WBox);
381 BuildShell(Surface, !KeepInsideSurface);
385 //================================================================
387 //purpose : calculate the surface of skinning, stopped by a shape
388 //================================================================
389 void BRepFill_Draft::Perform(const TopoDS_Shape& StopShape,
390 const Standard_Boolean KeepOutSide)
397 ComputeTrsf(myWire, myDir, WBox, Trsf);
399 // bounding box of the stop shape
400 Bnd_Box BSurf;//, TheBox;
401 Standard_Real Umin, Umax, Vmin, Vmax;
404 Handle(Geom_Surface) Surf;
406 // BndLib_AddSurface AS;
408 TopExp_Explorer Ex (StopShape, TopAbs_FACE);
411 while (Ex.More()) { // parse faces of the stop shape
412 // B.UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
413 BRepTools::UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax);
414 Surf = Handle(Geom_Surface)::DownCast(
415 // BT.Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
416 BRep_Tool::Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) );
417 GeomAdaptor_Surface S1 (Surf);
418 // bounding box of the current face
419 // AS.Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
420 BndLib_AddSurface::Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
421 SBox.Add(BSurf); // group boxes
425 // calculate the maximum length of the rule.
426 L = Longueur(WBox, SBox, myDir, Pt);
427 L /= Abs(Cos(myAngle));
431 Inv = Trsf.Inverted(); // inverted transformation
432 Pt.Transform(Inv); // coordinate in the absolute reference
433 Handle(Geom_Plane) Plan = new (Geom_Plane)(Pt, myDir);
434 Surf = new (Geom_RectangularTrimmedSurface) (Plan,-L, L, -L, L);
438 char* Temp = "ThePlan" ;
439 DrawTrSurf::Set(Temp, Surf);
440 // DrawTrSurf::Set("ThePlan", Surf);
444 // Sweeping and restriction
445 Init(Plan, L*1.01, WBox);
446 BuildShell(Surf, Standard_False);
447 Fuse(StopShape, KeepOutSide);
451 //=======================================================================
453 //purpose : Construction of laws.
454 //======================================================================
455 void BRepFill_Draft::Init(const Handle(Geom_Surface)& ,
456 const Standard_Real Length,
461 // law of positioning
462 Handle(GeomFill_LocationDraft) Loc
463 = new (GeomFill_LocationDraft) (myDir, myAngle);
464 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
466 B = GoodOrientation(Box, myLoc, myDir);
468 if (IsInternal ^ (!B) ) {
470 Loc->SetAngle(myAngle);
471 myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
474 myLoc->CleanLaw(angmin); // Clean small discontinuities.
477 // generating line is straight and parallel to binormal.
479 gp_Vec D (0., 1., 0.);
481 // Control of the orientation
483 myLoc->Law(1)->GetDomain(f,l);
487 myLoc->Law(1)->D0( (f+l)/2, M, Bid);
488 gp_Dir BN(M.Column(2));
490 Standard_Real ang = myDir.Angle(BN);
491 if (ang > M_PI/2) D.Reverse();
492 Handle(Geom_Line) L = new (Geom_Line) (P, D);
494 Handle(Geom_Curve) TC = new (Geom_TrimmedCurve) (L, 0, Length);
499 TC = new (Geom_Circle) (gp::XOY(), Length);
503 BRepLib_MakeEdge ME(TC);
504 TopoDS_Edge EG = ME.Edge();
506 BRepLib_MakeWire MW(EG);
507 TopoDS_Wire G = MW.Wire();
509 mySec = new (BRepFill_ShapeLaw) (G, Standard_True);
513 //=======================================================================
514 //function : BuildShell
515 //purpose : Construction of the skinning surface
516 //======================================================================
517 void BRepFill_Draft::BuildShell(const Handle(Geom_Surface)& Surf,
518 const Standard_Boolean KeepOutSide)
520 // construction of the surface
521 BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
522 Sweep.SetTolerance(myTol);
523 Sweep.SetAngularControl(angmin, angmax);
524 TopTools_MapOfShape Dummy;
525 BRepFill_DataMapOfShapeHArray2OfShape Dummy2;
526 BRepFill_DataMapOfShapeHArray2OfShape Dummy3;
527 Sweep.Build(Dummy, Dummy2, Dummy3, myStyle, myCont);
528 if (Sweep.IsDone()) {
529 myShape = Sweep.Shape();
530 myShell = TopoDS::Shell(myShape);
531 myFaces = Sweep.SubShape();
532 mySections = Sweep.Sections();
533 myDone = Standard_True;
534 // Control of the orientation
535 Standard_Boolean out=Standard_True;
536 TopExp_Explorer ex(myShell,TopAbs_FACE);
538 F = TopoDS::Face(ex.Current());
539 BRepAdaptor_Surface SF(F);
543 u = SF.FirstUParameter();
544 v = SF.FirstVParameter();
547 if (F.Orientation() == TopAbs_REVERSED) V.Reverse();
548 if (V.Magnitude() > 1.e-10) {
549 out = myDir.Angle(V) > M_PI/2;
551 if (out == IsInternal) {
557 myDone = Standard_False;
561 if (!Surf.IsNull()) { // Add the face at end
563 // Waiting the use of traces & retriction in BRepFill_Sweep
565 BRepLib_MakeFace MkF;
566 MkF.Init(Surf, Standard_True, Precision::Confusion());
567 Fuse(MkF.Face(), KeepOutSide);
572 //=======================================================================
574 //purpose : Boolean operation between the skin and the
576 //======================================================================
577 Standard_Boolean BRepFill_Draft::Fuse(const TopoDS_Shape& StopShape,
578 const Standard_Boolean KeepOutSide)
581 Standard_Boolean issolid = Standard_False;
582 TopoDS_Solid Sol1, Sol2;
583 TopAbs_State State1 = TopAbs_OUT, State2 = TopAbs_OUT;
586 if (myShape.ShapeType()==TopAbs_SOLID) {
587 Sol1 = TopoDS::Solid(myShape);
588 issolid = Standard_True;
592 B.Add(Sol1, myShape); // shell => solid (for fusion)
596 switch (StopShape.ShapeType()) {
597 case TopAbs_COMPOUND :
599 TopoDS_Iterator It(StopShape);
600 return Fuse(It.Value(), KeepOutSide);
604 Sol2 = TopoDS::Solid(StopShape);
610 B.Add(Sol2, StopShape); // shell => solid (for fusion)
619 S.Closed (BRep_Tool::IsClosed (S));
621 B.Add(Sol2, S); // shell => solid (for fusion)
627 return Standard_False; // Impossible to do
631 BRepAlgo_DSAccess DSA;
632 DSA.Load(Sol1, Sol2);
633 DSA.Intersect(Sol1, Sol2); // intersection of 2 solids
635 // removal of edges corresponding to "unused" intersections
636 Standard_Integer NbPaquet;
639 TopTools_ListOfShape List;
640 List = DSA.GetSectionEdgeSet();// list of edges
642 NbPaquet = List.Extent();
646 cout << "No fusion" << endl;
647 DBRep::Set("DepPart", Sol1);
648 DBRep::Set("StopPart", Sol2);
650 return Standard_False;
654 // It is required to select packs.
655 TColStd_Array1OfReal Dist(1, NbPaquet);
656 TopTools_ListIteratorOfListOfShape it(List);
657 Standard_Real D, Dmin = 1.e10;
660 //Classify the packs by distance.
661 BRepExtrema_DistShapeShape Dist2;
662 Dist2.LoadS1( myWire );
663 for (ii=1; it.More();it.Next(),ii++){
664 Dist2.LoadS2( it.Value() );
666 if (Dist2.IsDone()) {
669 if (D < Dmin) Dmin = D;
675 // remove edges "farther" than Dmin
676 for (ii=1, it.Initialize(List); it.More();it.Next(), ii++){
677 if (Dist(ii) > Dmin) {
678 DSA.SuppressEdgeSet(it.Value());
682 DBRep::Set("KeepEdges", it.Value());
688 if (StopShape.ShapeType() != TopAbs_SOLID) {
689 // It is required to choose the state by the geometry
691 //(1) Return an edge of section
692 List = DSA.GetSectionEdgeSet();// list of edges
693 TopTools_ListIteratorOfListOfShape it(List);
694 TopoDS_Iterator iter(it.Value());
695 TopoDS_Edge E = TopoDS::Edge(iter.Value());
697 //(2) Return geometry on StopShape
698 // Class BRep_Tool without fields and without Constructor :
700 Handle(Geom_Surface) S;
701 Handle(Geom2d_Curve) C2d;
705 // BT.CurveOnSurface(E, C2d, S, L, f, l, 2);
706 BRep_Tool::CurveOnSurface(E, C2d, S, L, f, l, 2);
709 C2d->D0((f+l)/2,P2d);
710 GeomLProp_SLProps SP(S, P2d.X(), P2d.Y(), 1, 1.e-12);
711 if (! SP.IsNormalDefined()) {
712 C2d->D0((3*f+l)/4,P2d);
713 SP.SetParameters(P2d.X(), P2d.Y());
714 if ( !SP.IsNormalDefined()) {
715 C2d->D0((f+3*l)/4,P2d);
716 SP.SetParameters(P2d.X(), P2d.Y());
721 if (myDir.Angle(SP.Normal()) < M_PI/2) State1 = TopAbs_IN;
722 else State1 = TopAbs_OUT;
725 if (! KeepOutSide) { // Invert State2;
726 if (State2 == TopAbs_IN) State2 = TopAbs_OUT;
727 else State2 = TopAbs_IN;
730 //recalculate the final shape
731 TopoDS_Shape result = DSA.Merge(State1, State2);
733 if (issolid) myShape = result;
736 Exp.Init(result, TopAbs_SHELL);
737 if (Exp.More()) myShape = Exp.Current();
740 // Update the History
742 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
743 const TopTools_ListOfShape& L = DSA.Modified(myFaces->Value(1,ii));
745 myFaces->SetValue(1, ii, L.First());
747 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
748 const TopTools_ListOfShape& L = DSA.Modified(mySections->Value(1,ii));
750 mySections->SetValue(1, ii, L.First());
753 return Standard_True;
756 //=======================================================================
758 //purpose : Assemble the skin with the above face
759 //======================================================================
760 Standard_Boolean BRepFill_Draft::Sewing()
762 Standard_Boolean ToAss;
763 Standard_Boolean Ok = Standard_False;
764 ToAss = (myTop.ShapeType() != TopAbs_WIRE);
766 if ((!ToAss) || (!myDone)) return Standard_False;
768 // Assembly make a shell from the faces of the shape + the input shape
769 Handle(BRepBuilderAPI_Sewing) Ass = new BRepBuilderAPI_Sewing(5*myTol, Standard_True,
770 Standard_True, Standard_False);
773 ToAss = Standard_True;
776 Standard_Integer NbCE;
779 // Check if the assembly is real.
780 NbCE = Ass->NbContigousEdges();
784 res = Ass->SewedShape();
785 if ((res.ShapeType() == TopAbs_SHELL)||
786 (res.ShapeType() == TopAbs_SOLID)) {
790 else if (res.ShapeType() == TopAbs_COMPOUND) {
791 TopoDS_Iterator It(res);
794 if (!It.More()) {//Only one part => this is correct
802 // Update the History
804 for (ii=1; ii<=myLoc->NbLaw(); ii++) {
805 if (Ass->IsModified(myFaces->Value(1,ii)))
806 myFaces->SetValue(1, ii,
807 Ass->Modified(myFaces->Value(1,ii)));
809 for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
810 if (Ass->IsModified(mySections->Value(1,ii)))
811 mySections->SetValue(1, ii,
812 Ass->Modified(mySections->Value(1,ii)));
815 if (myShape.Closed()) { // Make a Solid
819 BS.Add(solid,TopoDS::Shell(myShape));
821 BRepClass3d_SolidClassifier SC(solid);
822 SC.PerformInfinitePoint(Precision::Confusion());
823 if ( SC.State() == TopAbs_IN) {
826 BS.Add(solid,TopoDS::Shell(myShape));
832 else cout << "Draft : No assembly !" << endl;
837 //=======================================================================
838 //function : Generated
839 //purpose : return a sub-part generated by sweeping
840 //======================================================================
841 const TopTools_ListOfShape&
842 BRepFill_Draft::Generated(const TopoDS_Shape& S)
849 for (ii=0; ii<=myLoc->NbLaw(); ii++)
850 if (E.IsSame(myLoc->Vertex(ii))) {
851 myGenerated.Append(mySections->Value(1, ii+1));
856 for (ii=1; ii<=myLoc->NbLaw(); ii++)
857 if (E.IsSame(myLoc->Edge(ii))) {
858 myGenerated.Append(myFaces->Value(1, ii));
866 //=======================================================================
868 //purpose : return the complete shape
869 //======================================================================
870 TopoDS_Shape BRepFill_Draft::Shape()const
875 //=====================================================================
877 //purpose : surface of skinning with the input face (=>shell)
878 //=====================================================================
879 TopoDS_Shell BRepFill_Draft::Shell()const
884 //=======================================================================
887 //======================================================================
888 Standard_Boolean BRepFill_Draft::IsDone()const