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 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.
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 <BRepFill_DataMapOfShapeHArray2OfShape.hxx>
46 #include <TColStd_HArray1OfReal.hxx>
48 #include <GeomFill_TrihedronLaw.hxx>
49 #include <GeomFill_CorrectedFrenet.hxx>
50 #include <GeomFill_Frenet.hxx>
51 #include <GeomFill_DiscreteTrihedron.hxx>
52 #include <GeomFill_Fixed.hxx>
53 #include <GeomFill_ConstantBiNormal.hxx>
54 #include <GeomFill_SectionLaw.hxx>
55 #include <GeomFill_CurveAndTrihedron.hxx>
56 #include <GeomFill_GuideTrihedronAC.hxx>
57 #include <GeomFill_GuideTrihedronPlan.hxx>
58 #include <GeomFill_LocationGuide.hxx>
61 #include <GeomAdaptor_HCurve.hxx>
63 #include <gp_Trsf.hxx>
66 #include <Precision.hxx>
68 #include <Standard_NotImplemented.hxx>
69 #include <Standard_ConstructionError.hxx>
70 #include <StdFail_NotDone.hxx>
72 #include <BRepBuilderAPI_Copy.hxx>
73 #include <BRepBuilderAPI_Transform.hxx>
75 #include <GProp_GProps.hxx>
76 #include <BRepGProp.hxx>
77 #include <GeomAdaptor_HSurface.hxx>
78 #include <IntCurveSurface_HInter.hxx>
79 #include <IntCurveSurface_IntersectionPoint.hxx>
80 #include <TColgp_HArray1OfPnt2d.hxx>
81 #include <Law_Interpol.hxx>
85 #include <DrawTrSurf.hxx>
87 static Standard_Boolean Affich = 0;
90 #include <TopTools_ListIteratorOfListOfShape.hxx>
91 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
92 #include <TopoDS_Compound.hxx>
94 static Standard_Boolean UpdateMap(const TopoDS_Shape& theKey,
95 const TopoDS_Shape& theValue,
96 TopTools_DataMapOfShapeListOfShape& theMap);
98 static Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
99 const Handle(BRepFill_SectionLaw)& theSection,
100 TopoDS_Shape& theBottom,
101 TopoDS_Shape& theTop);
103 //=======================================================================
104 //function : ComputeSection
105 //purpose : Construct an intermediary section
106 //=======================================================================
108 static Standard_Boolean ComputeSection(const TopoDS_Wire& W1,
109 const TopoDS_Wire& W2,
110 const Standard_Real p1,
111 const Standard_Real p2,
114 TColStd_SequenceOfReal SR;
115 TopTools_SequenceOfShape SSh;
122 BRepFill_CompatibleWires CW(SSh);
125 if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
126 GeomFill_SequenceOfTrsf EmptyTrsfs;
127 Handle(BRepFill_NSections) SL = new (BRepFill_NSections) (CW.Shape(),EmptyTrsfs,SR,0.,1.);
128 Standard_Real US = p1/(p1+p2);
130 return Standard_True;
135 //=======================================================================
136 //function : PerformTransition
137 //purpose : Modify a law of location depending on Transition
138 //=======================================================================
140 static void PerformTransition(const BRepFill_TransitionStyle Mode,
141 Handle(BRepFill_LocationLaw)& Loc,
142 const Standard_Real angmin)
145 Loc->DeleteTransform();
146 if (Mode == BRepFill_Modified) Loc->TransformInG0Law();
147 else Loc->TransformInCompatibleLaw(angmin);
150 //=======================================================================
151 //function : PerformPlan
152 //purpose : Construct a plane of filling if exists
153 //=======================================================================
155 static Standard_Boolean PerformPlan(TopoDS_Shape& S)
157 Standard_Boolean isDegen = Standard_True;
158 TopExp_Explorer explo(S, TopAbs_EDGE);
159 for (; explo.More(); explo.Next())
161 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
162 if (!BRep_Tool::Degenerated(anEdge))
163 isDegen = Standard_False;
168 return Standard_True;
171 TopoDS_Wire W = TopoDS::Wire(S);
172 Standard_Boolean Ok = Standard_False;
174 BRepLib_MakeFace mkplan(W, Standard_True);
175 if (mkplan.IsDone()) {
183 //=============================================================================
184 //function : IsSameOriented
185 //purpose : Checks whether aFace is oriented to the same side as aShell or not
186 //=============================================================================
188 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
189 const TopoDS_Shape& aShell)
191 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
192 TopoDS_Shape anEdge = Explo.Current();
193 TopAbs_Orientation Or1 = anEdge.Orientation();
195 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
196 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
198 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
199 TopoDS_Shape theEdge;
200 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
202 theEdge = Explo.Current();
203 if (theEdge.IsSame(anEdge))
207 TopAbs_Orientation Or2 = theEdge.Orientation();
209 return Standard_False;
210 return Standard_True;
212 //=======================================================================
213 //function : BRepFill_PipeShell
215 //=======================================================================
216 BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
218 myForceApproxC1(Standard_False),
219 myIsAutomaticLaw(Standard_False),
220 myTrihedron(GeomFill_IsCorrectedFrenet),
221 myTransition(BRepFill_Modified),
222 myStatus(GeomFill_PipeOk)
224 myLocation.Nullify();
229 // Attention to closed non-declared wire !
230 if (!mySpine.Closed()) {
231 TopoDS_Vertex Vf, Vl;
232 TopExp::Vertices(mySpine, Vf, Vl);
233 if (Vf.IsSame(Vl)) mySpine.Closed(Standard_True);
237 //=======================================================================
239 //purpose : Define a law of Frenet (Correct)
240 //=======================================================================
241 void BRepFill_PipeShell::Set(const Standard_Boolean IsFrenet)
243 Handle(GeomFill_TrihedronLaw) TLaw;
245 myTrihedron = GeomFill_IsFrenet;
246 TLaw = new (GeomFill_Frenet) ();
249 myTrihedron = GeomFill_IsFrenet;
250 TLaw = new (GeomFill_CorrectedFrenet) ();
252 Handle(GeomFill_CurveAndTrihedron) Loc =
253 new (GeomFill_CurveAndTrihedron) (TLaw);
254 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
255 mySection.Nullify(); //It is required to relocalize sections.
258 //=======================================================================
259 //function : SetDiscrete
260 //purpose : Define a law of Discrete Trihedron
261 //=======================================================================
262 void BRepFill_PipeShell::SetDiscrete()
264 Handle(GeomFill_TrihedronLaw) TLaw;
266 myTrihedron = GeomFill_IsDiscreteTrihedron;
267 TLaw = new (GeomFill_DiscreteTrihedron) ();
269 Handle(GeomFill_CurveAndTrihedron) Loc =
270 new (GeomFill_CurveAndTrihedron) (TLaw);
271 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
272 mySection.Nullify(); //It is required to relocalize sections.
275 //=======================================================================
277 //purpose : Define a law Constant
278 //=======================================================================
279 void BRepFill_PipeShell::Set(const gp_Ax2& Axe)
281 myTrihedron = GeomFill_IsFixed;
283 V1.SetXYZ(Axe.Direction().XYZ());
284 V2.SetXYZ(Axe.XDirection().XYZ());
285 Handle(GeomFill_Fixed) TLaw = new (GeomFill_Fixed) (V1, V2);
286 Handle(GeomFill_CurveAndTrihedron) Loc =
287 new (GeomFill_CurveAndTrihedron) (TLaw);
288 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
289 mySection.Nullify(); //It is required to relocalize sections.
292 //=======================================================================
294 //purpose : Construct a law of location of binormal fixed type
295 //=======================================================================
296 void BRepFill_PipeShell::Set(const gp_Dir& BiNormal)
298 myTrihedron = GeomFill_IsConstantNormal;
300 Handle(GeomFill_ConstantBiNormal) TLaw =
301 new (GeomFill_ConstantBiNormal) (BiNormal);
302 Handle(GeomFill_CurveAndTrihedron) Loc =
303 new (GeomFill_CurveAndTrihedron) (TLaw);
304 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
305 mySection.Nullify(); //Il faut relocaliser les sections.
308 //=======================================================================
310 //purpose : Construct a law of location of Darboux type
311 //=======================================================================
312 Standard_Boolean BRepFill_PipeShell::Set(const TopoDS_Shape& SpineSupport)
316 // A special law of location is required
317 Handle(BRepFill_EdgeOnSurfLaw) loc =
318 new (BRepFill_EdgeOnSurfLaw) (mySpine, SpineSupport);
319 B = loc->HasResult();
322 myTrihedron = GeomFill_IsDarboux;
323 mySection.Nullify(); //It is required to relocalize the sections.
328 //=======================================================================
330 //purpose : Defines a lawv with help of a guided contour
331 //=======================================================================
332 void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine,
333 const Standard_Boolean CurvilinearEquivalence,
334 const BRepFill_TypeOfContact KeepContact)
336 // Reorganization of the guide (pb of orientation and origin)
337 TopoDS_Wire TheGuide;
338 TheGuide = AuxiliarySpine;
339 Standard_Boolean SpClose = mySpine.Closed(),
340 GuideClose = AuxiliarySpine.Closed();
342 if (KeepContact == BRepFill_ContactOnBorder)
343 myIsAutomaticLaw = Standard_True;
345 if (!SpClose && !GuideClose) {
346 // Case open reorientation of the guide
347 TopoDS_Wire sp = mySpine;
348 TopTools_SequenceOfShape Seq;
350 Seq.Append(TheGuide);
351 BRepFill_CompatibleWires CW(Seq);
354 if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
355 TheGuide = TopoDS::Wire(CW.Shape().Value(2));
357 else if (GuideClose) {
358 // Case guide closed : Determination of the origin
359 // & reorientation of the guide
363 TopoDS_Vertex Vf, Vl;
365 TopExp::Vertices(mySpine, Vf, Vl);
366 SpOr = BRep_Tool::Pnt(Vf);
367 P = BRep_Tool::Pnt(Vl);
369 SpOr.BaryCenter(0.5, P, 0.5);
373 BRepAdaptor_CompCurve BC(mySpine);
376 BRepFill::SearchOrigin(TheGuide, SpOr, Dir, 100*myTol3d);
381 DBRep::Set("theguide", TheGuide);
383 // transform the guide in a single curve (periodic if posssible)
384 Handle(BRepAdaptor_HCompCurve) Guide =
385 new (BRepAdaptor_HCompCurve) (TheGuide);
386 Guide->ChangeCurve().SetPeriodic(Standard_True);
388 if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa
389 if (KeepContact == BRepFill_Contact ||
390 KeepContact == BRepFill_ContactOnBorder)
391 myTrihedron = GeomFill_IsGuideACWithContact; // with rotation
393 myTrihedron = GeomFill_IsGuideAC; // without rotation
395 Handle(GeomFill_GuideTrihedronAC) TLaw
396 = new (GeomFill_GuideTrihedronAC) (Guide);
397 Handle(GeomFill_LocationGuide) Loc =
398 new (GeomFill_LocationGuide) (TLaw);
399 myLocation = new (BRepFill_ACRLaw) (mySpine, Loc);
401 else {// trihedron by plane
402 if (KeepContact == BRepFill_Contact ||
403 KeepContact == BRepFill_ContactOnBorder)
404 myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation
406 myTrihedron = GeomFill_IsGuidePlan; // without rotation
408 Handle(GeomFill_GuideTrihedronPlan) TLaw =
409 new (GeomFill_GuideTrihedronPlan) (Guide);
410 Handle(GeomFill_LocationGuide) Loc =
411 new (GeomFill_LocationGuide) (TLaw);
412 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
414 mySection.Nullify(); //It is required to relocalize the sections.
417 //=======================================================================
418 //function : SetForceApproxC1
419 //purpose : Set the flag that indicates attempt to approximate
420 // a C1-continuous surface if a swept surface proved
422 //=======================================================================
423 void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
425 myForceApproxC1 = ForceApproxC1;
428 //=======================================================================
430 //purpose : Add a Section
431 //=======================================================================
432 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
433 const Standard_Boolean WithContact,
434 const Standard_Boolean WithCorrection)
438 Add(Profile, V, WithContact, WithCorrection);
442 //=======================================================================
444 //purpose : Add a Section
445 //=======================================================================
446 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
447 const TopoDS_Vertex& Location,
448 const Standard_Boolean WithContact,
449 const Standard_Boolean WithCorrection)
451 Delete(Profile); // No duplication
452 if (myIsAutomaticLaw)
455 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
456 S.Set(Standard_True);
461 Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1));
462 Handle(TColgp_HArray1OfPnt2d) ParAndRad;
463 Loc->ComputeAutomaticLaw(ParAndRad);
465 //Compuite initial width of section (this will be 1.)
466 GProp_GProps GlobalProps;
467 BRepGProp::LinearProperties(Profile, GlobalProps);
468 gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
470 TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane
471 Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace);
472 Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane);
473 IntCurveSurface_HInter Intersector;
474 Handle(Adaptor3d_HCurve) aHCurve [2];
475 aHCurve[0] = Loc->GetCurve();
476 aHCurve[1] = Loc->Guide();
477 gp_Pnt PointsOnSpines [2];
478 Standard_Integer i, j;
480 for (i = 0; i < 2; i++)
482 Intersector.Perform(aHCurve[i], GAHplane);
483 Standard_Real MinDist = RealLast();
484 for (j = 1; j <= Intersector.NbPoints(); j++)
486 gp_Pnt aPint = Intersector.Point(j).Pnt();
487 Standard_Real aDist = BaryCenter.Distance(aPint);
491 PointsOnSpines[i] = aPint;
496 //Correct <ParAndRad> according to <InitialWidth>
497 Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]);
498 Standard_Integer NbParRad = ParAndRad->Upper();
499 for (i = 1; i <= NbParRad; i++)
501 gp_Pnt2d aParRad = ParAndRad->Value(i);
502 aParRad.SetY( aParRad.Y() / InitialWidth );
503 ParAndRad->SetValue(i, aParRad);
506 myLaw = new Law_Interpol();
508 Standard_Boolean IsPeriodic =
509 (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion());
511 (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic);
515 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
522 //=======================================================================
524 //purpose : Section + law of homothety
525 //=======================================================================
526 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
527 const Handle(Law_Function)& L,
528 const Standard_Boolean WithContact,
529 const Standard_Boolean WithCorrection)
533 SetLaw( Profile, L, V, WithContact, WithCorrection);
537 //=======================================================================
539 //purpose : Section + Law of homothety
540 //=======================================================================
541 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
542 const Handle(Law_Function)& L,
543 const TopoDS_Vertex& Location,
544 const Standard_Boolean WithContact,
545 const Standard_Boolean WithCorrection)
548 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
549 S.Set(Standard_True);
556 //=======================================================================
558 //purpose : Delete a section
559 //=======================================================================
560 void BRepFill_PipeShell::Delete(const TopoDS_Shape& Profile)
562 Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX);
564 Standard_Boolean Trouve=Standard_False;
566 for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
567 Standard_Boolean found = Standard_False;
568 const TopoDS_Wire& aWire = mySeq.Value(ii).Wire();
571 TopExp_Explorer Explo(aWire, TopAbs_VERTEX);
572 for (; Explo.More(); Explo.Next())
573 if (Profile.IsSame(Explo.Current()))
574 found = Standard_True;
576 else if (Profile.IsSame(aWire))
577 found = Standard_True;
581 Trouve = Standard_True;
586 if (Trouve) mySection.Nullify();
591 //=======================================================================
594 //=======================================================================
595 Standard_Boolean BRepFill_PipeShell::IsReady() const
597 return (mySeq.Length() != 0);
599 //=======================================================================
600 //function : GetStatus
602 //=======================================================================
603 GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
609 //=======================================================================
610 //function : SetTolerance
612 //=======================================================================
613 void BRepFill_PipeShell::SetTolerance(const Standard_Real Tol3d ,
614 const Standard_Real BoundTol,
615 const Standard_Real TolAngular)
618 myBoundTol = BoundTol;
619 myTolAngular = TolAngular;
622 //=======================================================================
623 //function : SetTransition
624 //purpose : Defines the mode of processing of corners
625 //=======================================================================
626 void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
627 const Standard_Real Angmin,
628 const Standard_Real Angmax)
630 if (myTransition != Mode)
631 mySection.Nullify(); //It is required to relocalize the sections.
637 //=======================================================================
638 //function : Simulate
639 //purpose : Calculate N Sections
640 //=======================================================================
641 void BRepFill_PipeShell::Simulate(const Standard_Integer N,
642 TopTools_ListOfShape& List)
648 Standard_Real First, Last, Length, Delta, U,
650 Standard_Integer ii, NbL = myLocation->NbLaw();
651 Standard_Boolean Finis=Standard_False;
654 // Calculate the parameters of digitalization
655 mySection->Law(1)->GetDomain(FirstS, Last);
656 DeltaS = Last - FirstS;
657 myLocation->CurvilinearBounds(NbL,First, Length);
659 if (N>1) Delta /= (N-1);
661 myLocation->CurvilinearBounds(1,First, Last); // Initiation of Last
662 for (U=0.0, ii=1; !Finis ; U+=Delta) {
665 Finis = Standard_True;
668 if (ii < NbL) myLocation->CurvilinearBounds(NbL,First, Last);
669 if (U > Last) U = (Last+First)/2; // The edge is not skipped
672 US = FirstS + (U/Length)*DeltaS;
673 // Calcul d'une section
674 mySection->D0(US, W);
675 myLocation->D0(U, W);
680 //=======================================================================
682 //purpose : Construct the Shell and the history
683 //=======================================================================
684 Standard_Boolean BRepFill_PipeShell::Build()
687 Standard_Real FirstS, LastS;
691 if (myStatus != GeomFill_PipeOk) {
695 myShape = Sh; // Nullify
696 return Standard_False;
699 // 2) Calculate myFirst and myLast
700 mySection->Law(1)->GetDomain(FirstS, LastS);
701 mySection->D0(FirstS, myFirst);
702 myLocation->D0(0, myFirst);
703 if (mySection->IsVClosed() && myLocation->IsClosed()) {
704 if (myLocation->IsG1(0)>=0)
712 Standard_Real Length;
713 myLocation->CurvilinearBounds(myLocation->NbLaw(),
715 mySection->D0(LastS, myLast);
716 myLocation->D0(Length, myLast);
717 // eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
718 // tolerances of shapes built on them may be quite different
719 if (myFirst.IsPartner( myLast )) {
720 BRepBuilderAPI_Copy copy(myLast);
722 myLast = copy.Shape();
724 // eap 5 Jun 2002 occ332, end modif
728 DBRep::Set("PipeFirst", myFirst);
729 DBRep::Set("PipeLast", myLast);
734 BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
735 MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
736 MkSw.SetAngularControl(angmin, angmax);
737 MkSw.SetForceApproxC1(myForceApproxC1);
738 MkSw.SetBounds(TopoDS::Wire(myFirst),
739 TopoDS::Wire(myLast));
740 GeomAbs_Shape theContinuity = GeomAbs_C2;
741 if (myTrihedron == GeomFill_IsDiscreteTrihedron)
742 theContinuity = GeomAbs_C0;
743 TopTools_MapOfShape Dummy;
744 BRepFill_DataMapOfShapeHArray2OfShape Dummy2;
745 BRepFill_DataMapOfShapeHArray2OfShape Dummy3;
746 MkSw.Build(Dummy, Dummy2, Dummy3, myTransition, theContinuity);
748 myStatus = myLocation->GetStatus();
749 Ok = (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
752 myShape = MkSw.Shape();
754 TopoDS_Shape aBottomWire = myFirst;
755 TopoDS_Shape aTopWire = myLast;
757 if(BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire)) {
758 myFirst = aBottomWire;
762 if (mySection->IsUClosed())
764 TopExp_Explorer explo;
765 Standard_Boolean DegenFirst = Standard_True, DegenLast = Standard_True;
767 for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
769 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
770 DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
773 for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
775 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
776 DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
779 if (DegenFirst && DegenLast)
780 myShape.Closed(Standard_True);
789 myShape = Sh; // Nullify
790 if (myStatus == GeomFill_PipeOk) myStatus = GeomFill_PipeNotOk;
795 //=======================================================================
796 //function : MakeSolid
798 //=======================================================================
799 Standard_Boolean BRepFill_PipeShell::MakeSolid()
801 if (myShape.IsNull())
802 StdFail_NotDone::Raise("PipeShell is not built");
803 Standard_Boolean B = myShape.Closed();
808 if(!myFirst.IsNull() && !myLast.IsNull()) {
809 B = (myFirst.Closed() && myLast.Closed());
812 // It is necessary to block the extremities
813 B = PerformPlan(myFirst);
815 B = PerformPlan(myLast);
817 if (!myFirst.IsNull() && !IsSameOriented( myFirst, myShape ))
819 if (!myLast.IsNull() && !IsSameOriented( myLast, myShape ))
822 if (!myFirst.IsNull())
823 BS.Add(myShape, TopoDS::Face(myFirst));
824 if (!myLast.IsNull())
825 BS.Add(myShape, TopoDS::Face(myLast));
827 myShape.Closed(Standard_True);
836 BS.Add(solid,TopoDS::Shell(myShape));
837 BRepClass3d_SolidClassifier SC(solid);
838 SC.PerformInfinitePoint(Precision::Confusion());
839 if ( SC.State() == TopAbs_IN) {
842 BS.Add(solid,TopoDS::Shell(myShape));
845 myShape.Closed(Standard_True);
850 //=======================================================================
852 //purpose : Return the result
853 //=======================================================================
854 const TopoDS_Shape& BRepFill_PipeShell::Shape() const
859 //=======================================================================
860 //function : FirstShape
861 //purpose : Return the start section
862 //=======================================================================
863 const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
868 //=======================================================================
869 //function : LastShape
870 //purpose : Return the end section
871 //=======================================================================
872 const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
877 //=======================================================================
878 //function : Generated
880 //=======================================================================
881 // void BRepFill_PipeShell::Generated(const TopoDS_Shape& ,
882 // TopTools_ListOfShape& )
883 void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape,
884 TopTools_ListOfShape& theList)
886 // Standard_NotImplemented::Raise("Generated:Pas Fait");
889 if(myGenMap.IsBound(theShape)) {
890 theList = myGenMap.Find(theShape);
894 //=======================================================================
896 //purpose : - Check that everything is ready
897 // - Construct the law of section
898 // - Construct the law of location if required
899 // - Calculate First & Last
900 //=======================================================================
901 void BRepFill_PipeShell::Prepare()
904 if (!IsReady()) StdFail_NotDone::Raise("PipeShell");
905 if (!myLocation.IsNull() && !mySection.IsNull()) return; // It is ready
907 //Check set of section for right configuration of punctual sections
909 TopoDS_Iterator iter;;
910 for (i = 2; i <= mySeq.Length()-1; i++)
912 Standard_Boolean wdeg = Standard_True;
913 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
915 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
916 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
919 Standard_Failure::Raise("Wrong usage of punctual sections");
921 if (mySeq.Length() <= 2)
923 Standard_Boolean wdeg = Standard_True;
924 for (i = 1; i <= mySeq.Length(); i++)
925 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
927 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
928 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
931 Standard_Failure::Raise("Wrong usage of punctual sections");
934 // Construction of the law of location
935 if(myLocation.IsNull())
939 case GeomFill_IsCorrectedFrenet :
941 Handle(GeomFill_TrihedronLaw) TLaw =
942 new (GeomFill_CorrectedFrenet) ();
943 Handle(GeomFill_CurveAndTrihedron) Loc =
944 new (GeomFill_CurveAndTrihedron) (TLaw);
945 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
950 Standard_ConstructionError::Raise("PipeShell");
955 //Transformation of the law (Transition Management)
956 PerformTransition(myTransition, myLocation, angmin);
959 // Construction of the section law
960 if (mySeq.Length() == 1) {
963 Place(mySeq(1), theSect, aTrsf, p1);
964 TopoDS_Wire aLocalShape = theSect;
965 if (mySeq(1).IsLaw())
966 mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
967 // mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
969 mySection = new BRepFill_ShapeLaw(aLocalShape);
970 // mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
974 TColStd_SequenceOfReal Param;
975 TopTools_SequenceOfShape WSeq;
976 GeomFill_SequenceOfTrsf Transformations;
979 Standard_Integer NbL = myLocation->NbLaw();
981 Standard_Real V1, V2, param;
982 myLocation->CurvilinearBounds(NbL, V1, V2);
984 Standard_Integer ideb = 0, ifin = 0;
985 // for (Standard_Integer iseq=1;iseq<=mySeq.Length();iseq++) {
986 Standard_Integer iseq;
987 for (iseq=1;iseq<=mySeq.Length();iseq++) {
988 Place(mySeq(iseq), theSect, aTrsf, param);
990 WSeq.Append(theSect);
991 // WSeq.Append(TopoDS::Wire(theSect));
992 Transformations.Append(aTrsf);
993 if (param==V1) ideb = iseq;
994 if (param==V2) ifin = iseq;
998 // looping sections ?
999 if (myLocation->IsClosed()) {
1001 // place the initial section at the final position
1003 WSeq.Append(WSeq(ideb));
1006 // place the final section at the initial position
1008 WSeq.Append(WSeq(ifin));
1011 // it is necessary to find a medium section to impose by V1 and by V2
1012 Standard_Real pmin = Param.Value(1), pmax = Param.Value(1);
1013 TopoDS_Wire Wmin = TopoDS::Wire(WSeq.Value(1)), Wmax;
1014 for (iseq=2;iseq<=WSeq.Length();iseq++) {
1015 if (Param.Value(iseq)<pmin) {
1016 pmin = Param.Value(iseq);
1017 Wmin = TopoDS::Wire(WSeq.Value(iseq));
1019 if (Param.Value(iseq)>pmax) {
1020 pmax = Param.Value(iseq);
1021 Wmax = TopoDS::Wire(WSeq.Value(iseq));
1024 // medium section between Wmin and Wmax
1026 Standard_Real dmin = Abs(pmin-V1);
1027 Standard_Real dmax = Abs(pmax-V2);
1028 if (ComputeSection(Wmin,Wmax,dmin,dmax,Wres)) {
1029 // impose section Wres at the beginning and the end
1040 // parse sections by increasing parameter
1041 Standard_Boolean play_again = Standard_True;
1042 while (play_again) {
1043 play_again = Standard_False;
1044 for (iseq=1;iseq<=WSeq.Length();iseq++) {
1045 for (Standard_Integer jseq=iseq+1;jseq<=WSeq.Length();jseq++) {
1046 if (Param.Value(iseq)>Param.Value(jseq)) {
1047 Param.Exchange(iseq,jseq);
1048 WSeq.Exchange(iseq,jseq);
1049 play_again = Standard_True;
1057 char* name = new char[100];
1058 Standard_Integer NBSECT = 0;
1059 for (Standard_Integer i=1;i<=WSeq.Length();i++) {
1061 sprintf(name,"WSeq_%d",NBSECT);
1062 DBRep::Set(name,TopoDS::Wire(WSeq.Value(i)));
1069 // Calculate work sections
1070 TopTools_SequenceOfShape WorkingSections;
1071 WorkingSections.Clear();
1072 TopTools_DataMapOfShapeListOfShape WorkingMap;
1074 BRepFill_CompatibleWires Georges(WSeq);
1075 Georges.SetPercent(0.1);
1076 Georges.Perform(Standard_False);
1077 if (Georges.IsDone()) {
1078 WorkingSections = Georges.Shape();
1079 WorkingMap = Georges.Generated();
1082 Standard_ConstructionError::Raise("PipeShell : uncompatible wires");
1084 mySection = new (BRepFill_NSections) (WorkingSections,Transformations,Param,V1,V2);
1088 // modify the law of location if contact
1089 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1090 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1091 Standard_Real fs, f, l, Delta, Length;
1092 Handle(GeomFill_LocationGuide) Loc;
1093 Handle(GeomFill_SectionLaw) Sec = mySection->ConcatenedLaw();
1094 myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
1095 Sec->GetDomain(fs,l);
1096 Delta = (l-fs)/Length;
1098 Standard_Real angle, old_angle = 0;
1099 for (Standard_Integer ipath=1; ipath<=myLocation->NbLaw(); ipath++) {
1100 myLocation->CurvilinearBounds(ipath, f, l);
1101 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(ipath));
1102 Loc->Set(Sec, Standard_True, fs + f*Delta, fs + l*Delta,
1103 old_angle, angle); // force the rotation
1108 myStatus = myLocation->GetStatus();
1111 //=======================================================================
1113 //purpose : Implement a Section in the local refernce frame
1114 // and return its parameter on the trajectory
1115 //=======================================================================
1116 void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
1119 Standard_Real& param)
1121 BRepFill_SectionPlacement Place(myLocation,
1125 Sec.WithCorrection());
1126 TopoDS_Wire TmpWire = Sec.Wire();
1127 aTrsf = Place.Transformation();
1128 //TopLoc_Location Loc2(Place.Transformation()), Loc1;
1129 //Loc1 = TmpWire.Location();
1130 //W.Location(Loc2.Multiplied(Loc1));
1131 //Transform the copy
1132 W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, Standard_True));
1133 ////////////////////////////////////
1134 param = Place.AbscissaOnPath();
1138 //=======================================================================
1139 //function : ResetLoc
1140 //purpose : Remove references to the sections in the laws of location
1141 //=======================================================================
1142 void BRepFill_PipeShell::ResetLoc()
1144 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1145 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1146 Handle(GeomFill_LocationGuide) Loc;
1147 for (Standard_Integer isec=1; isec<=myLocation->NbLaw(); isec++) {
1148 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(isec));
1149 Loc->EraseRotation();// remove the rotation
1154 //=======================================================================
1155 //function : BuildHistory
1156 //purpose : Builds history for edges of spine,
1157 // for built bottom shape of sweep,
1158 // for boundary vertices of bottom shape of sweep,
1159 // for boundary profiles
1160 //=======================================================================
1161 void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
1163 Handle(TopTools_HArray2OfShape) aFaces = theSweep.SubShape();
1164 Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1165 Handle(TopTools_HArray2OfShape) aUEdges = theSweep.InterFaces();
1166 Standard_Integer i = 0, j = 0;
1167 Standard_Boolean bPrevModified = Standard_False;
1169 for(i = 1; i <= mySection->NbLaw(); i++) {
1170 if((!aVEdges->Value(i, 1).IsNull()) && (aVEdges->Value(i, 1).ShapeType() == TopAbs_FACE)) {
1171 bPrevModified = Standard_True;
1176 for(j = myLocation->NbLaw(); j >= 1; j--) {
1177 TopTools_ListOfShape aListOfFace;
1180 for(i = 1; i <= mySection->NbLaw(); i++) {
1181 Standard_Integer lessindex = j + 1;
1182 lessindex = (lessindex > myLocation->NbLaw()) ? 1 : lessindex;
1184 if((!aVEdges->Value(i, lessindex).IsNull()) && (aVEdges->Value(i, lessindex).ShapeType() == TopAbs_FACE)) {
1185 aListOfFace.Append(aVEdges->Value(i, lessindex));
1186 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1188 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1189 UpdateMap(aBottomEdge, aVEdges->Value(i, lessindex), myGenMap);
1194 bPrevModified = Standard_False;
1196 for(i = 1; i <= mySection->NbLaw(); i++) {
1197 if((!aVEdges->Value(i, j).IsNull()) && (aVEdges->Value(i, j).ShapeType() == TopAbs_FACE)) {
1198 aListOfFace.Append(aVEdges->Value(i, j));
1199 bPrevModified = Standard_True;
1201 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1203 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1204 UpdateMap(aBottomEdge, aVEdges->Value(i, j), myGenMap);
1208 if(aFaces->Value(i, j).ShapeType() == TopAbs_FACE) {
1209 aListOfFace.Append(aFaces->Value(i, j));
1210 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1212 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1213 UpdateMap(aBottomEdge, aFaces->Value(i, j), myGenMap);
1218 if(!myGenMap.IsBound(myLocation->Edge(j)))
1219 myGenMap.Bind(myLocation->Edge(j), aListOfFace);
1221 myGenMap.ChangeFind(myLocation->Edge(j)).Append(aListOfFace);
1223 // build history for free booundaries.begin
1224 if(!mySection->IsUClosed()) {
1225 TopoDS_Compound aFaceComp;
1227 aB.MakeCompound(aFaceComp);
1228 TopTools_ListIteratorOfListOfShape anIt(aListOfFace);
1230 for(; anIt.More(); anIt.Next()) {
1231 aB.Add(aFaceComp, anIt.Value());
1233 TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1234 TopExp::MapShapesAndAncestors(aFaceComp, TopAbs_EDGE, TopAbs_FACE, aMapEF);
1235 Standard_Integer eit = 0;
1237 for(eit = aUEdges->LowerRow(); eit <= aUEdges->UpperRow(); eit++) {
1238 const TopoDS_Shape& aShape = aUEdges->Value(eit, j);
1240 if(aMapEF.Contains(aShape)) {
1241 const TopTools_ListOfShape& aList = aMapEF.FindFromKey(aShape);
1243 if(aList.Extent() < 2) {
1244 UpdateMap(myLocation->Edge(j), aShape, myGenMap);
1246 TopoDS_Shape aGenVertex;
1247 TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
1249 for(i = 1; i <= mySection->NbLaw(); i++) {
1250 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1252 if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1253 TopExp::MapShapesAndAncestors(aBottomEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1256 const TopoDS_Shape& aFreeEdge = aUEdges->Value(eit, aUEdges->LowerCol());
1257 TopExp::MapShapesAndAncestors(aFreeEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1258 TopExp_Explorer anExpV(aFreeEdge, TopAbs_VERTEX);
1260 for(; anExpV.More(); anExpV.Next()) {
1261 if(aMapVE.Contains(anExpV.Current())) {
1262 const TopTools_ListOfShape& aListOfV = aMapVE.FindFromKey(anExpV.Current());
1264 if(aListOfV.Extent() >= 2) {
1265 aGenVertex = anExpV.Current();
1270 if(!aGenVertex.IsNull()) {
1271 UpdateMap(aGenVertex, aShape, myGenMap);
1276 // end for(eit = aUEdges->LowerRow...
1278 // build history for free booundaries.end
1281 // build history for boundary section wires. begin
1283 if(!mySeq.IsEmpty()) {
1284 Standard_Integer iseq;
1287 Standard_Real param = 0., aparmin = RealLast(), aparmax = -RealLast();
1288 Standard_Integer ideb = 1, ifin = mySeq.Length();
1290 for (iseq = 1;iseq <= mySeq.Length(); iseq++) {
1291 Place(mySeq(iseq), aSect, aTrsf, param);
1293 if(param < aparmin) {
1298 if(param > aparmax) {
1304 UpdateMap(mySeq(ideb).Wire(), myFirst, myGenMap);
1305 UpdateMap(mySeq(ifin).Wire(), myLast, myGenMap);
1307 // build history for boundary section wires. end
1310 // ---------------------------------------------------------------------------------
1311 // static function: UpdateMap
1313 // ---------------------------------------------------------------------------------
1314 Standard_Boolean UpdateMap(const TopoDS_Shape& theKey,
1315 const TopoDS_Shape& theValue,
1316 TopTools_DataMapOfShapeListOfShape& theMap) {
1318 if(!theMap.IsBound(theKey)) {
1319 TopTools_ListOfShape thelist;
1320 theMap.Bind(theKey, thelist);
1322 TopTools_ListOfShape& aList = theMap.ChangeFind(theKey);
1323 TopTools_ListIteratorOfListOfShape anIt(aList);
1324 Standard_Boolean found = Standard_False;
1326 for(; anIt.More(); anIt.Next()) {
1327 if(theValue.IsSame(anIt.Value())) {
1328 found = Standard_True;
1334 aList.Append(theValue);
1338 // ---------------------------------------------------------------------------------
1339 // static function: BuildBoundaries
1341 // ---------------------------------------------------------------------------------
1342 Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
1343 const Handle(BRepFill_SectionLaw)& theSection,
1344 TopoDS_Shape& theBottom,
1345 TopoDS_Shape& theTop) {
1347 TopoDS_Wire aBottomWire;
1348 TopoDS_Wire aTopWire;
1350 aB.MakeWire(aBottomWire);
1351 aB.MakeWire(aTopWire);
1352 Standard_Boolean bfoundbottom = Standard_False;
1353 Standard_Boolean bfoundtop = Standard_False;
1354 Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1355 Standard_Integer i = 0;
1356 Standard_Boolean bAllSame = Standard_True;
1358 for(i = 1; i <= theSection->NbLaw(); i++) {
1359 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1361 if(!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1362 aB.Add(aBottomWire, aBottomEdge);
1363 bfoundbottom = Standard_True;
1365 const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
1367 if(!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE)) {
1368 aB.Add(aTopWire, aTopEdge);
1369 bfoundtop = Standard_True;
1372 if(!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
1373 bAllSame = Standard_False;
1376 if(theSection->IsUClosed()) {
1377 aBottomWire.Closed(Standard_True);
1378 aTopWire.Closed(Standard_True);
1382 theBottom = aBottomWire;
1389 if(bAllSame && bfoundbottom && bfoundtop)
1392 return bfoundbottom || bfoundtop;