1 // Created on: 1998-07-22
2 // Created by: Philippe MANGIN
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
9 // under the terms of the GNU Lesser General Public 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.
19 #include <BRepFill_PipeShell.ixx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
24 #include <TopTools_SequenceOfShape.hxx>
26 #include <TopoDS_Shell.hxx>
27 #include <TopoDS_Solid.hxx>
28 #include <TopoDS_Iterator.hxx>
29 #include <TopLoc_Location.hxx>
31 #include <BRepLib_MakeEdge.hxx>
32 #include <BRepLib_MakeFace.hxx>
33 #include <BRepAdaptor_HCompCurve.hxx>
34 #include <BRepClass3d_SolidClassifier.hxx>
36 #include <BRepFill.hxx>
37 #include <BRepFill_Sweep.hxx>
38 #include <BRepFill_SectionPlacement.hxx>
39 #include <BRepFill_Edge3DLaw.hxx>
40 #include <BRepFill_ACRLaw.hxx>
41 #include <BRepFill_EdgeOnSurfLaw.hxx>
42 #include <BRepFill_ShapeLaw.hxx>
43 #include <BRepFill_CompatibleWires.hxx>
44 #include <BRepFill_NSections.hxx>
45 #include <TColStd_HArray1OfReal.hxx>
47 #include <GeomFill_TrihedronLaw.hxx>
48 #include <GeomFill_CorrectedFrenet.hxx>
49 #include <GeomFill_Frenet.hxx>
50 #include <GeomFill_DiscreteTrihedron.hxx>
51 #include <GeomFill_Fixed.hxx>
52 #include <GeomFill_ConstantBiNormal.hxx>
53 #include <GeomFill_SectionLaw.hxx>
54 #include <GeomFill_CurveAndTrihedron.hxx>
55 #include <GeomFill_GuideTrihedronAC.hxx>
56 #include <GeomFill_GuideTrihedronPlan.hxx>
57 #include <GeomFill_LocationGuide.hxx>
60 #include <GeomAdaptor_HCurve.hxx>
62 #include <gp_Trsf.hxx>
65 #include <Precision.hxx>
67 #include <Standard_NotImplemented.hxx>
68 #include <Standard_ConstructionError.hxx>
69 #include <StdFail_NotDone.hxx>
71 #include <BRepBuilderAPI_Copy.hxx>
73 #include <GProp_GProps.hxx>
74 #include <BRepGProp.hxx>
75 #include <GeomAdaptor_HSurface.hxx>
76 #include <IntCurveSurface_HInter.hxx>
77 #include <IntCurveSurface_IntersectionPoint.hxx>
78 #include <TColgp_HArray1OfPnt2d.hxx>
79 #include <Law_Interpol.hxx>
83 #include <DrawTrSurf.hxx>
85 static Standard_Boolean Affich = 0;
88 #include <TopTools_ListIteratorOfListOfShape.hxx>
89 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
90 #include <TopoDS_Compound.hxx>
92 static Standard_Boolean UpdateMap(const TopoDS_Shape& theKey,
93 const TopoDS_Shape& theValue,
94 TopTools_DataMapOfShapeListOfShape& theMap);
96 static Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
97 const Handle(BRepFill_SectionLaw)& theSection,
98 TopoDS_Shape& theBottom,
99 TopoDS_Shape& theTop);
101 //=======================================================================
102 //function : ComputeSection
103 //purpose : Construct an intermediary section
104 //=======================================================================
106 static Standard_Boolean ComputeSection(const TopoDS_Wire& W1,
107 const TopoDS_Wire& W2,
108 const Standard_Real p1,
109 const Standard_Real p2,
112 TColStd_SequenceOfReal SR;
113 TopTools_SequenceOfShape SSh;
120 BRepFill_CompatibleWires CW(SSh);
123 if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
124 GeomFill_SequenceOfTrsf EmptyTrsfs;
125 Handle(BRepFill_NSections) SL = new (BRepFill_NSections) (CW.Shape(),EmptyTrsfs,SR,0.,1.);
126 Standard_Real US = p1/(p1+p2);
128 return Standard_True;
133 //=======================================================================
134 //function : PerformTransition
135 //purpose : Modify a law of location depending on Transition
136 //=======================================================================
138 static void PerformTransition(const BRepFill_TransitionStyle Mode,
139 Handle(BRepFill_LocationLaw)& Loc,
140 const Standard_Real angmin)
143 Loc->DeleteTransform();
144 if (Mode == BRepFill_Modified) Loc->TransformInG0Law();
145 else Loc->TransformInCompatibleLaw(angmin);
148 //=======================================================================
149 //function : PerformPlan
150 //purpose : Construct a plane of filling if exists
151 //=======================================================================
153 static Standard_Boolean PerformPlan(TopoDS_Shape& S)
155 Standard_Boolean isDegen = Standard_True;
156 TopExp_Explorer explo(S, TopAbs_EDGE);
157 for (; explo.More(); explo.Next())
159 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
160 if (!BRep_Tool::Degenerated(anEdge))
161 isDegen = Standard_False;
166 return Standard_True;
169 TopoDS_Wire W = TopoDS::Wire(S);
170 Standard_Boolean Ok = Standard_False;
172 BRepLib_MakeFace mkplan(W, Standard_True);
173 if (mkplan.IsDone()) {
181 //=============================================================================
182 //function : IsSameOriented
183 //purpose : Checks whether aFace is oriented to the same side as aShell or not
184 //=============================================================================
186 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
187 const TopoDS_Shape& aShell)
189 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
190 TopoDS_Shape anEdge = Explo.Current();
191 TopAbs_Orientation Or1 = anEdge.Orientation();
193 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
194 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
196 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
197 TopoDS_Shape theEdge;
198 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
200 theEdge = Explo.Current();
201 if (theEdge.IsSame(anEdge))
205 TopAbs_Orientation Or2 = theEdge.Orientation();
207 return Standard_False;
208 return Standard_True;
210 //=======================================================================
211 //function : BRepFill_PipeShell
213 //=======================================================================
214 BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
216 myForceApproxC1(Standard_False),
217 myIsAutomaticLaw(Standard_False),
218 myTrihedron(GeomFill_IsCorrectedFrenet),
219 myTransition(BRepFill_Modified),
220 myStatus(GeomFill_PipeOk)
222 myLocation.Nullify();
227 // Attention to closed non-declared wire !
228 if (!mySpine.Closed()) {
229 TopoDS_Vertex Vf, Vl;
230 TopExp::Vertices(mySpine, Vf, Vl);
231 if (Vf.IsSame(Vl)) mySpine.Closed(Standard_True);
235 //=======================================================================
237 //purpose : Define a law of Frenet (Correct)
238 //=======================================================================
239 void BRepFill_PipeShell::Set(const Standard_Boolean IsFrenet)
241 Handle(GeomFill_TrihedronLaw) TLaw;
243 myTrihedron = GeomFill_IsFrenet;
244 TLaw = new (GeomFill_Frenet) ();
247 myTrihedron = GeomFill_IsFrenet;
248 TLaw = new (GeomFill_CorrectedFrenet) ();
250 Handle(GeomFill_CurveAndTrihedron) Loc =
251 new (GeomFill_CurveAndTrihedron) (TLaw);
252 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
253 mySection.Nullify(); //It is required to relocalize sections.
256 //=======================================================================
257 //function : SetDiscrete
258 //purpose : Define a law of Discrete Trihedron
259 //=======================================================================
260 void BRepFill_PipeShell::SetDiscrete()
262 Handle(GeomFill_TrihedronLaw) TLaw;
264 myTrihedron = GeomFill_IsDiscreteTrihedron;
265 TLaw = new (GeomFill_DiscreteTrihedron) ();
267 Handle(GeomFill_CurveAndTrihedron) Loc =
268 new (GeomFill_CurveAndTrihedron) (TLaw);
269 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
270 mySection.Nullify(); //It is required to relocalize sections.
273 //=======================================================================
275 //purpose : Define a law Constant
276 //=======================================================================
277 void BRepFill_PipeShell::Set(const gp_Ax2& Axe)
279 myTrihedron = GeomFill_IsFixed;
281 V1.SetXYZ(Axe.Direction().XYZ());
282 V2.SetXYZ(Axe.XDirection().XYZ());
283 Handle(GeomFill_Fixed) TLaw = new (GeomFill_Fixed) (V1, V2);
284 Handle(GeomFill_CurveAndTrihedron) Loc =
285 new (GeomFill_CurveAndTrihedron) (TLaw);
286 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
287 mySection.Nullify(); //It is required to relocalize sections.
290 //=======================================================================
292 //purpose : Construct a law of location of binormal fixed type
293 //=======================================================================
294 void BRepFill_PipeShell::Set(const gp_Dir& BiNormal)
296 myTrihedron = GeomFill_IsConstantNormal;
298 Handle(GeomFill_ConstantBiNormal) TLaw =
299 new (GeomFill_ConstantBiNormal) (BiNormal);
300 Handle(GeomFill_CurveAndTrihedron) Loc =
301 new (GeomFill_CurveAndTrihedron) (TLaw);
302 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
303 mySection.Nullify(); //Il faut relocaliser les sections.
306 //=======================================================================
308 //purpose : Construct a law of location of Darboux type
309 //=======================================================================
310 Standard_Boolean BRepFill_PipeShell::Set(const TopoDS_Shape& SpineSupport)
314 // A special law of location is required
315 Handle(BRepFill_EdgeOnSurfLaw) loc =
316 new (BRepFill_EdgeOnSurfLaw) (mySpine, SpineSupport);
317 B = loc->HasResult();
320 myTrihedron = GeomFill_IsDarboux;
321 mySection.Nullify(); //It is required to relocalize the sections.
326 //=======================================================================
328 //purpose : Defines a lawv with help of a guided contour
329 //=======================================================================
330 void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine,
331 const Standard_Boolean CurvilinearEquivalence,
332 const BRepFill_TypeOfContact KeepContact)
334 // Reorganization of the guide (pb of orientation and origin)
335 TopoDS_Wire TheGuide;
336 TheGuide = AuxiliarySpine;
337 Standard_Boolean SpClose = mySpine.Closed(),
338 GuideClose = AuxiliarySpine.Closed();
340 if (KeepContact == BRepFill_ContactOnBorder)
341 myIsAutomaticLaw = Standard_True;
343 if (!SpClose && !GuideClose) {
344 // Case open reorientation of the guide
345 TopoDS_Wire sp = mySpine;
346 TopTools_SequenceOfShape Seq;
348 Seq.Append(TheGuide);
349 BRepFill_CompatibleWires CW(Seq);
352 if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
353 TheGuide = TopoDS::Wire(CW.Shape().Value(2));
355 else if (GuideClose) {
356 // Case guide closed : Determination of the origin
357 // & reorientation of the guide
361 TopoDS_Vertex Vf, Vl;
363 TopExp::Vertices(mySpine, Vf, Vl);
364 SpOr = BRep_Tool::Pnt(Vf);
365 P = BRep_Tool::Pnt(Vl);
367 SpOr.BaryCenter(0.5, P, 0.5);
371 BRepAdaptor_CompCurve BC(mySpine);
374 BRepFill::SearchOrigin(TheGuide, SpOr, Dir, 100*myTol3d);
379 DBRep::Set("theguide", TheGuide);
381 // transform the guide in a single curve (periodic if posssible)
382 Handle(BRepAdaptor_HCompCurve) Guide =
383 new (BRepAdaptor_HCompCurve) (TheGuide);
384 Guide->ChangeCurve().SetPeriodic(Standard_True);
386 if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa
387 if (KeepContact == BRepFill_Contact ||
388 KeepContact == BRepFill_ContactOnBorder)
389 myTrihedron = GeomFill_IsGuideACWithContact; // with rotation
391 myTrihedron = GeomFill_IsGuideAC; // without rotation
393 Handle(GeomFill_GuideTrihedronAC) TLaw
394 = new (GeomFill_GuideTrihedronAC) (Guide);
395 Handle(GeomFill_LocationGuide) Loc =
396 new (GeomFill_LocationGuide) (TLaw);
397 myLocation = new (BRepFill_ACRLaw) (mySpine, Loc);
399 else {// trihedron by plane
400 if (KeepContact == BRepFill_Contact ||
401 KeepContact == BRepFill_ContactOnBorder)
402 myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation
404 myTrihedron = GeomFill_IsGuidePlan; // without rotation
406 Handle(GeomFill_GuideTrihedronPlan) TLaw =
407 new (GeomFill_GuideTrihedronPlan) (Guide);
408 Handle(GeomFill_LocationGuide) Loc =
409 new (GeomFill_LocationGuide) (TLaw);
410 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
412 mySection.Nullify(); //It is required to relocalize the sections.
415 //=======================================================================
416 //function : SetForceApproxC1
417 //purpose : Set the flag that indicates attempt to approximate
418 // a C1-continuous surface if a swept surface proved
420 //=======================================================================
421 void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
423 myForceApproxC1 = ForceApproxC1;
426 //=======================================================================
428 //purpose : Add a Section
429 //=======================================================================
430 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
431 const Standard_Boolean WithContact,
432 const Standard_Boolean WithCorrection)
436 Add(Profile, V, WithContact, WithCorrection);
440 //=======================================================================
442 //purpose : Add a Section
443 //=======================================================================
444 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
445 const TopoDS_Vertex& Location,
446 const Standard_Boolean WithContact,
447 const Standard_Boolean WithCorrection)
449 Delete(Profile); // No duplication
450 if (myIsAutomaticLaw)
453 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
454 S.Set(Standard_True);
459 Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1));
460 Handle(TColgp_HArray1OfPnt2d) ParAndRad;
461 Loc->ComputeAutomaticLaw(ParAndRad);
463 //Compuite initial width of section (this will be 1.)
464 GProp_GProps GlobalProps;
465 BRepGProp::LinearProperties(Profile, GlobalProps);
466 gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
468 TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane
469 Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace);
470 Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane);
471 IntCurveSurface_HInter Intersector;
472 Handle(Adaptor3d_HCurve) aHCurve [2];
473 aHCurve[0] = Loc->GetCurve();
474 aHCurve[1] = Loc->Guide();
475 gp_Pnt PointsOnSpines [2];
476 Standard_Integer i, j;
478 for (i = 0; i < 2; i++)
480 Intersector.Perform(aHCurve[i], GAHplane);
481 Standard_Real MinDist = RealLast();
482 for (j = 1; j <= Intersector.NbPoints(); j++)
484 gp_Pnt aPint = Intersector.Point(j).Pnt();
485 Standard_Real aDist = BaryCenter.Distance(aPint);
489 PointsOnSpines[i] = aPint;
494 //Correct <ParAndRad> according to <InitialWidth>
495 Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]);
496 Standard_Integer NbParRad = ParAndRad->Upper();
497 for (i = 1; i <= NbParRad; i++)
499 gp_Pnt2d aParRad = ParAndRad->Value(i);
500 aParRad.SetY( aParRad.Y() / InitialWidth );
501 ParAndRad->SetValue(i, aParRad);
504 myLaw = new Law_Interpol();
506 Standard_Boolean IsPeriodic =
507 (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion());
509 (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic);
513 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
520 //=======================================================================
522 //purpose : Section + law of homothety
523 //=======================================================================
524 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
525 const Handle(Law_Function)& L,
526 const Standard_Boolean WithContact,
527 const Standard_Boolean WithCorrection)
531 SetLaw( Profile, L, V, WithContact, WithCorrection);
535 //=======================================================================
537 //purpose : Section + Law of homothety
538 //=======================================================================
539 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
540 const Handle(Law_Function)& L,
541 const TopoDS_Vertex& Location,
542 const Standard_Boolean WithContact,
543 const Standard_Boolean WithCorrection)
546 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
547 S.Set(Standard_True);
554 //=======================================================================
556 //purpose : Delete a section
557 //=======================================================================
558 void BRepFill_PipeShell::Delete(const TopoDS_Shape& Profile)
560 Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX);
562 Standard_Boolean Trouve=Standard_False;
564 for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
565 Standard_Boolean found = Standard_False;
566 const TopoDS_Wire& aWire = mySeq.Value(ii).Wire();
569 TopExp_Explorer Explo(aWire, TopAbs_VERTEX);
570 for (; Explo.More(); Explo.Next())
571 if (Profile.IsSame(Explo.Current()))
572 found = Standard_True;
574 else if (Profile.IsSame(aWire))
575 found = Standard_True;
579 Trouve = Standard_True;
584 if (Trouve) mySection.Nullify();
589 //=======================================================================
592 //=======================================================================
593 Standard_Boolean BRepFill_PipeShell::IsReady() const
595 return (mySeq.Length() != 0);
597 //=======================================================================
598 //function : GetStatus
600 //=======================================================================
601 GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
607 //=======================================================================
608 //function : SetTolerance
610 //=======================================================================
611 void BRepFill_PipeShell::SetTolerance(const Standard_Real Tol3d ,
612 const Standard_Real BoundTol,
613 const Standard_Real TolAngular)
616 myBoundTol = BoundTol;
617 myTolAngular = TolAngular;
620 //=======================================================================
621 //function : SetTransition
622 //purpose : Defines the mode of processing of corners
623 //=======================================================================
624 void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
625 const Standard_Real Angmin,
626 const Standard_Real Angmax)
628 if (myTransition != Mode)
629 mySection.Nullify(); //It is required to relocalize the sections.
635 //=======================================================================
636 //function : Simulate
637 //purpose : Calculate N Sections
638 //=======================================================================
639 void BRepFill_PipeShell::Simulate(const Standard_Integer N,
640 TopTools_ListOfShape& List)
646 Standard_Real First, Last, Length, Delta, U,
648 Standard_Integer ii, NbL = myLocation->NbLaw();
649 Standard_Boolean Finis=Standard_False;
652 // Calculate the parameters of digitalization
653 mySection->Law(1)->GetDomain(FirstS, Last);
654 DeltaS = Last - FirstS;
655 myLocation->CurvilinearBounds(NbL,First, Length);
657 if (N>1) Delta /= (N-1);
659 myLocation->CurvilinearBounds(1,First, Last); // Initiation of Last
660 for (U=0.0, ii=1; !Finis ; U+=Delta) {
663 Finis = Standard_True;
666 if (ii < NbL) myLocation->CurvilinearBounds(NbL,First, Last);
667 if (U > Last) U = (Last+First)/2; // The edge is not skipped
670 US = FirstS + (U/Length)*DeltaS;
671 // Calcul d'une section
672 mySection->D0(US, W);
673 myLocation->D0(U, W);
678 //=======================================================================
680 //purpose : Construct the Shell and the history
681 //=======================================================================
682 Standard_Boolean BRepFill_PipeShell::Build()
685 Standard_Real FirstS, LastS;
689 if (myStatus != GeomFill_PipeOk) {
693 myShape = Sh; // Nullify
694 return Standard_False;
697 // 2) Calculate myFirst and myLast
698 mySection->Law(1)->GetDomain(FirstS, LastS);
699 mySection->D0(FirstS, myFirst);
700 myLocation->D0(0, myFirst);
701 if (mySection->IsVClosed() && myLocation->IsClosed()) {
702 if (myLocation->IsG1(0)>=0)
710 Standard_Real Length;
711 myLocation->CurvilinearBounds(myLocation->NbLaw(),
713 mySection->D0(LastS, myLast);
714 myLocation->D0(Length, myLast);
715 // eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
716 // tolerances of shapes built on them may be quite different
717 if (myFirst.IsPartner( myLast )) {
718 BRepBuilderAPI_Copy copy(myLast);
720 myLast = copy.Shape();
722 // eap 5 Jun 2002 occ332, end modif
726 DBRep::Set("PipeFirst", myFirst);
727 DBRep::Set("PipeLast", myLast);
732 BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
733 MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
734 MkSw.SetAngularControl(angmin, angmax);
735 MkSw.SetForceApproxC1(myForceApproxC1);
736 MkSw.SetBounds(TopoDS::Wire(myFirst),
737 TopoDS::Wire(myLast));
738 GeomAbs_Shape theContinuity = GeomAbs_C2;
739 if (myTrihedron == GeomFill_IsDiscreteTrihedron)
740 theContinuity = GeomAbs_C0;
741 MkSw.Build(myTransition, theContinuity);
743 myStatus = myLocation->GetStatus();
744 Ok = (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
747 myShape = MkSw.Shape();
749 TopoDS_Shape aBottomWire = myFirst;
750 TopoDS_Shape aTopWire = myLast;
752 if(BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire)) {
753 myFirst = aBottomWire;
757 if (mySection->IsUClosed())
759 TopExp_Explorer explo;
760 Standard_Boolean DegenFirst = Standard_True, DegenLast = Standard_True;
762 for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
764 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
765 DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
768 for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
770 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
771 DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
774 if (DegenFirst && DegenLast)
775 myShape.Closed(Standard_True);
784 myShape = Sh; // Nullify
785 if (myStatus == GeomFill_PipeOk) myStatus = GeomFill_PipeNotOk;
790 //=======================================================================
791 //function : MakeSolid
793 //=======================================================================
794 Standard_Boolean BRepFill_PipeShell::MakeSolid()
796 if (myShape.IsNull())
797 StdFail_NotDone::Raise("PipeShell is not built");
798 Standard_Boolean B = myShape.Closed();
803 if(!myFirst.IsNull() && !myLast.IsNull()) {
804 B = (myFirst.Closed() && myLast.Closed());
807 // It is necessary to block the extremities
808 B = PerformPlan(myFirst);
810 B = PerformPlan(myLast);
812 if (!myFirst.IsNull() && !IsSameOriented( myFirst, myShape ))
814 if (!myLast.IsNull() && !IsSameOriented( myLast, myShape ))
817 if (!myFirst.IsNull())
818 BS.Add(myShape, TopoDS::Face(myFirst));
819 if (!myLast.IsNull())
820 BS.Add(myShape, TopoDS::Face(myLast));
822 myShape.Closed(Standard_True);
831 BS.Add(solid,TopoDS::Shell(myShape));
832 BRepClass3d_SolidClassifier SC(solid);
833 SC.PerformInfinitePoint(Precision::Confusion());
834 if ( SC.State() == TopAbs_IN) {
837 BS.Add(solid,TopoDS::Shell(myShape));
840 myShape.Closed(Standard_True);
845 //=======================================================================
847 //purpose : Return the result
848 //=======================================================================
849 const TopoDS_Shape& BRepFill_PipeShell::Shape() const
854 //=======================================================================
855 //function : FirstShape
856 //purpose : Return the start section
857 //=======================================================================
858 const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
863 //=======================================================================
864 //function : LastShape
865 //purpose : Return the end section
866 //=======================================================================
867 const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
872 //=======================================================================
873 //function : Generated
875 //=======================================================================
876 // void BRepFill_PipeShell::Generated(const TopoDS_Shape& ,
877 // TopTools_ListOfShape& )
878 void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape,
879 TopTools_ListOfShape& theList)
881 // Standard_NotImplemented::Raise("Generated:Pas Fait");
884 if(myGenMap.IsBound(theShape)) {
885 theList = myGenMap.Find(theShape);
889 //=======================================================================
891 //purpose : - Check that everything is ready
892 // - Construct the law of section
893 // - Construct the law of location if required
894 // - Calculate First & Last
895 //=======================================================================
896 void BRepFill_PipeShell::Prepare()
899 if (!IsReady()) StdFail_NotDone::Raise("PipeShell");
900 if (!myLocation.IsNull() && !mySection.IsNull()) return; // It is ready
902 //Check set of section for right configuration of punctual sections
904 TopoDS_Iterator iter;;
905 for (i = 2; i <= mySeq.Length()-1; i++)
907 Standard_Boolean wdeg = Standard_True;
908 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
910 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
911 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
914 Standard_Failure::Raise("Wrong usage of punctual sections");
916 if (mySeq.Length() <= 2)
918 Standard_Boolean wdeg = Standard_True;
919 for (i = 1; i <= mySeq.Length(); i++)
920 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
922 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
923 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
926 Standard_Failure::Raise("Wrong usage of punctual sections");
929 // Construction of the law of location
930 if(myLocation.IsNull())
934 case GeomFill_IsCorrectedFrenet :
936 Handle(GeomFill_TrihedronLaw) TLaw =
937 new (GeomFill_CorrectedFrenet) ();
938 Handle(GeomFill_CurveAndTrihedron) Loc =
939 new (GeomFill_CurveAndTrihedron) (TLaw);
940 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
945 Standard_ConstructionError::Raise("PipeShell");
950 //Transformation of the law (Transition Management)
951 PerformTransition(myTransition, myLocation, angmin);
954 // Construction of the section law
955 if (mySeq.Length() == 1) {
958 Place(mySeq(1), theSect, aTrsf, p1);
959 TopoDS_Wire aLocalShape = theSect;
960 if (mySeq(1).IsLaw())
961 mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
962 // mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
964 mySection = new BRepFill_ShapeLaw(aLocalShape);
965 // mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
969 TColStd_SequenceOfReal Param;
970 TopTools_SequenceOfShape WSeq;
971 GeomFill_SequenceOfTrsf Transformations;
974 Standard_Integer NbL = myLocation->NbLaw();
976 Standard_Real V1, V2, param;
977 myLocation->CurvilinearBounds(NbL, V1, V2);
979 Standard_Integer ideb = 0, ifin = 0;
980 // for (Standard_Integer iseq=1;iseq<=mySeq.Length();iseq++) {
981 Standard_Integer iseq;
982 for (iseq=1;iseq<=mySeq.Length();iseq++) {
983 Place(mySeq(iseq), theSect, aTrsf, param);
985 WSeq.Append(theSect);
986 // WSeq.Append(TopoDS::Wire(theSect));
987 Transformations.Append(aTrsf);
988 if (param==V1) ideb = iseq;
989 if (param==V2) ifin = iseq;
993 // looping sections ?
994 if (myLocation->IsClosed()) {
996 // place the initial section at the final position
998 WSeq.Append(WSeq(ideb));
1001 // place the final section at the initial position
1003 WSeq.Append(WSeq(ifin));
1006 // it is necessary to find a medium section to impose by V1 and by V2
1007 Standard_Real pmin = Param.Value(1), pmax = Param.Value(1);
1008 TopoDS_Wire Wmin = TopoDS::Wire(WSeq.Value(1)), Wmax;
1009 for (iseq=2;iseq<=WSeq.Length();iseq++) {
1010 if (Param.Value(iseq)<pmin) {
1011 pmin = Param.Value(iseq);
1012 Wmin = TopoDS::Wire(WSeq.Value(iseq));
1014 if (Param.Value(iseq)>pmax) {
1015 pmax = Param.Value(iseq);
1016 Wmax = TopoDS::Wire(WSeq.Value(iseq));
1019 // medium section between Wmin and Wmax
1021 Standard_Real dmin = Abs(pmin-V1);
1022 Standard_Real dmax = Abs(pmax-V2);
1023 if (ComputeSection(Wmin,Wmax,dmin,dmax,Wres)) {
1024 // impose section Wres at the beginning and the end
1035 // parse sections by increasing parameter
1036 Standard_Boolean play_again = Standard_True;
1037 while (play_again) {
1038 play_again = Standard_False;
1039 for (iseq=1;iseq<=WSeq.Length();iseq++) {
1040 for (Standard_Integer jseq=iseq+1;jseq<=WSeq.Length();jseq++) {
1041 if (Param.Value(iseq)>Param.Value(jseq)) {
1042 Param.Exchange(iseq,jseq);
1043 WSeq.Exchange(iseq,jseq);
1044 play_again = Standard_True;
1052 char* name = new char[100];
1053 Standard_Integer NBSECT = 0;
1054 for (Standard_Integer i=1;i<=WSeq.Length();i++) {
1056 sprintf(name,"WSeq_%d",NBSECT);
1057 DBRep::Set(name,TopoDS::Wire(WSeq.Value(i)));
1064 // Calculate work sections
1065 TopTools_SequenceOfShape WorkingSections;
1066 WorkingSections.Clear();
1067 TopTools_DataMapOfShapeListOfShape WorkingMap;
1069 BRepFill_CompatibleWires Georges(WSeq);
1070 Georges.SetPercent(0.1);
1071 Georges.Perform(Standard_False);
1072 if (Georges.IsDone()) {
1073 WorkingSections = Georges.Shape();
1074 WorkingMap = Georges.Generated();
1077 Standard_ConstructionError::Raise("PipeShell : uncompatible wires");
1079 mySection = new (BRepFill_NSections) (WorkingSections,Transformations,Param,V1,V2);
1083 // modify the law of location if contact
1084 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1085 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1086 Standard_Real fs, f, l, Delta, Length;
1087 Handle(GeomFill_LocationGuide) Loc;
1088 Handle(GeomFill_SectionLaw) Sec = mySection->ConcatenedLaw();
1089 myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
1090 Sec->GetDomain(fs,l);
1091 Delta = (l-fs)/Length;
1093 Standard_Real angle, old_angle = 0;
1094 for (Standard_Integer ipath=1; ipath<=myLocation->NbLaw(); ipath++) {
1095 myLocation->CurvilinearBounds(ipath, f, l);
1096 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(ipath));
1097 Loc->Set(Sec, Standard_True, fs + f*Delta, fs + l*Delta,
1098 old_angle, angle); // force the rotation
1103 myStatus = myLocation->GetStatus();
1106 //=======================================================================
1108 //purpose : Implement a Section in the local refernce frame
1109 // and return its parameter on the trajectory
1110 //=======================================================================
1111 void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
1114 Standard_Real& param)
1116 BRepFill_SectionPlacement Place(myLocation,
1120 Sec.WithCorrection());
1122 aTrsf = Place.Transformation();
1123 TopLoc_Location Loc2(Place.Transformation()), Loc1;
1124 Loc1 = W.Location();
1125 W.Location(Loc2.Multiplied(Loc1));
1126 param = Place.AbscissaOnPath();
1130 //=======================================================================
1131 //function : ResetLoc
1132 //purpose : Remove references to the sections in the laws of location
1133 //=======================================================================
1134 void BRepFill_PipeShell::ResetLoc()
1136 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1137 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1138 Handle(GeomFill_LocationGuide) Loc;
1139 for (Standard_Integer isec=1; isec<=myLocation->NbLaw(); isec++) {
1140 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(isec));
1141 Loc->EraseRotation();// remove the rotation
1146 //=======================================================================
1147 //function : BuildHistory
1148 //purpose : Builds history for edges of spine,
1149 // for built bottom shape of sweep,
1150 // for boundary vertices of bottom shape of sweep,
1151 // for boundary profiles
1152 //=======================================================================
1153 void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
1155 Handle(TopTools_HArray2OfShape) aFaces = theSweep.SubShape();
1156 Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1157 Handle(TopTools_HArray2OfShape) aUEdges = theSweep.InterFaces();
1158 Standard_Integer i = 0, j = 0;
1159 Standard_Boolean bPrevModified = Standard_False;
1161 for(i = 1; i <= mySection->NbLaw(); i++) {
1162 if((!aVEdges->Value(i, 1).IsNull()) && (aVEdges->Value(i, 1).ShapeType() == TopAbs_FACE)) {
1163 bPrevModified = Standard_True;
1168 for(j = myLocation->NbLaw(); j >= 1; j--) {
1169 TopTools_ListOfShape aListOfFace;
1172 for(i = 1; i <= mySection->NbLaw(); i++) {
1173 Standard_Integer lessindex = j + 1;
1174 lessindex = (lessindex > myLocation->NbLaw()) ? 1 : lessindex;
1176 if((!aVEdges->Value(i, lessindex).IsNull()) && (aVEdges->Value(i, lessindex).ShapeType() == TopAbs_FACE)) {
1177 aListOfFace.Append(aVEdges->Value(i, lessindex));
1178 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1180 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1181 UpdateMap(aBottomEdge, aVEdges->Value(i, lessindex), myGenMap);
1186 bPrevModified = Standard_False;
1188 for(i = 1; i <= mySection->NbLaw(); i++) {
1189 if((!aVEdges->Value(i, j).IsNull()) && (aVEdges->Value(i, j).ShapeType() == TopAbs_FACE)) {
1190 aListOfFace.Append(aVEdges->Value(i, j));
1191 bPrevModified = Standard_True;
1193 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1195 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1196 UpdateMap(aBottomEdge, aVEdges->Value(i, j), myGenMap);
1200 if(aFaces->Value(i, j).ShapeType() == TopAbs_FACE) {
1201 aListOfFace.Append(aFaces->Value(i, j));
1202 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1204 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1205 UpdateMap(aBottomEdge, aFaces->Value(i, j), myGenMap);
1210 if(!myGenMap.IsBound(myLocation->Edge(j)))
1211 myGenMap.Bind(myLocation->Edge(j), aListOfFace);
1213 myGenMap.ChangeFind(myLocation->Edge(j)).Append(aListOfFace);
1215 // build history for free booundaries.begin
1216 if(!mySection->IsUClosed()) {
1217 TopoDS_Compound aFaceComp;
1219 aB.MakeCompound(aFaceComp);
1220 TopTools_ListIteratorOfListOfShape anIt(aListOfFace);
1222 for(; anIt.More(); anIt.Next()) {
1223 aB.Add(aFaceComp, anIt.Value());
1225 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1226 TopExp::MapShapesAndAncestors(aFaceComp, TopAbs_EDGE, TopAbs_FACE, aMapEF);
1227 Standard_Integer eit = 0;
1229 for(eit = aUEdges->LowerRow(); eit <= aUEdges->UpperRow(); eit++) {
1230 const TopoDS_Shape& aShape = aUEdges->Value(eit, j);
1232 if(aMapEF.Contains(aShape)) {
1233 const TopTools_ListOfShape& aList = aMapEF.FindFromKey(aShape);
1235 if(aList.Extent() < 2) {
1236 UpdateMap(myLocation->Edge(j), aShape, myGenMap);
1238 TopoDS_Shape aGenVertex;
1239 TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
1241 for(i = 1; i <= mySection->NbLaw(); i++) {
1242 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1244 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1245 TopExp::MapShapesAndAncestors(aBottomEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1248 const TopoDS_Shape& aFreeEdge = aUEdges->Value(eit, aUEdges->LowerCol());
1249 TopExp::MapShapesAndAncestors(aFreeEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1250 TopExp_Explorer anExpV(aFreeEdge, TopAbs_VERTEX);
1252 for(; anExpV.More(); anExpV.Next()) {
1253 if(aMapVE.Contains(anExpV.Current())) {
1254 const TopTools_ListOfShape& aListOfV = aMapVE.FindFromKey(anExpV.Current());
1256 if(aListOfV.Extent() >= 2) {
1257 aGenVertex = anExpV.Current();
1262 if(!aGenVertex.IsNull()) {
1263 UpdateMap(aGenVertex, aShape, myGenMap);
1268 // end for(eit = aUEdges->LowerRow...
1270 // build history for free booundaries.end
1273 // build history for boundary section wires. begin
1275 if(!mySeq.IsEmpty()) {
1276 Standard_Integer iseq;
1279 Standard_Real param = 0., aparmin = RealLast(), aparmax = -RealLast();
1280 Standard_Integer ideb = 1, ifin = mySeq.Length();
1282 for (iseq = 1;iseq <= mySeq.Length(); iseq++) {
1283 Place(mySeq(iseq), aSect, aTrsf, param);
1285 if(param < aparmin) {
1290 if(param > aparmax) {
1296 UpdateMap(mySeq(ideb).Wire(), myFirst, myGenMap);
1297 UpdateMap(mySeq(ifin).Wire(), myLast, myGenMap);
1299 // build history for boundary section wires. end
1302 // ---------------------------------------------------------------------------------
1303 // static function: UpdateMap
1305 // ---------------------------------------------------------------------------------
1306 Standard_Boolean UpdateMap(const TopoDS_Shape& theKey,
1307 const TopoDS_Shape& theValue,
1308 TopTools_DataMapOfShapeListOfShape& theMap) {
1310 if(!theMap.IsBound(theKey)) {
1311 TopTools_ListOfShape thelist;
1312 theMap.Bind(theKey, thelist);
1314 TopTools_ListOfShape& aList = theMap.ChangeFind(theKey);
1315 TopTools_ListIteratorOfListOfShape anIt(aList);
1316 Standard_Boolean found = Standard_False;
1318 for(; anIt.More(); anIt.Next()) {
1319 if(theValue.IsSame(anIt.Value())) {
1320 found = Standard_True;
1326 aList.Append(theValue);
1330 // ---------------------------------------------------------------------------------
1331 // static function: BuildBoundaries
1333 // ---------------------------------------------------------------------------------
1334 Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
1335 const Handle(BRepFill_SectionLaw)& theSection,
1336 TopoDS_Shape& theBottom,
1337 TopoDS_Shape& theTop) {
1339 TopoDS_Wire aBottomWire;
1340 TopoDS_Wire aTopWire;
1342 aB.MakeWire(aBottomWire);
1343 aB.MakeWire(aTopWire);
1344 Standard_Boolean bfoundbottom = Standard_False;
1345 Standard_Boolean bfoundtop = Standard_False;
1346 Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1347 Standard_Integer i = 0;
1348 Standard_Boolean bAllSame = Standard_True;
1350 for(i = 1; i <= theSection->NbLaw(); i++) {
1351 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1353 if(!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1354 aB.Add(aBottomWire, aBottomEdge);
1355 bfoundbottom = Standard_True;
1357 const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
1359 if(!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE)) {
1360 aB.Add(aTopWire, aTopEdge);
1361 bfoundtop = Standard_True;
1364 if(!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
1365 bAllSame = Standard_False;
1368 if(theSection->IsUClosed()) {
1369 aBottomWire.Closed(Standard_True);
1370 aTopWire.Closed(Standard_True);
1374 theBottom = aBottomWire;
1381 if(bAllSame && bfoundbottom && bfoundtop)
1384 return bfoundbottom || bfoundtop;