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.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_HCompCurve.hxx>
21 #include <BRepBuilderAPI_Copy.hxx>
22 #include <BRepBuilderAPI_Transform.hxx>
23 #include <BRepClass3d_SolidClassifier.hxx>
24 #include <BRepFill.hxx>
25 #include <BRepFill_ACRLaw.hxx>
26 #include <BRepFill_CompatibleWires.hxx>
27 #include <BRepFill_DataMapOfShapeHArray2OfShape.hxx>
28 #include <BRepFill_Edge3DLaw.hxx>
29 #include <BRepFill_EdgeOnSurfLaw.hxx>
30 #include <BRepFill_LocationLaw.hxx>
31 #include <BRepFill_NSections.hxx>
32 #include <BRepFill_PipeShell.hxx>
33 #include <BRepFill_Section.hxx>
34 #include <BRepFill_SectionLaw.hxx>
35 #include <BRepFill_SectionPlacement.hxx>
36 #include <BRepFill_ShapeLaw.hxx>
37 #include <BRepFill_Sweep.hxx>
38 #include <BRepGProp.hxx>
39 #include <BRepLib_MakeEdge.hxx>
40 #include <BRepLib_MakeFace.hxx>
41 #include <GeomAdaptor_HCurve.hxx>
42 #include <GeomAdaptor_HSurface.hxx>
43 #include <GeomFill_ConstantBiNormal.hxx>
44 #include <GeomFill_CorrectedFrenet.hxx>
45 #include <GeomFill_CurveAndTrihedron.hxx>
46 #include <GeomFill_DiscreteTrihedron.hxx>
47 #include <GeomFill_Fixed.hxx>
48 #include <GeomFill_Frenet.hxx>
49 #include <GeomFill_GuideTrihedronAC.hxx>
50 #include <GeomFill_GuideTrihedronPlan.hxx>
51 #include <GeomFill_LocationGuide.hxx>
52 #include <GeomFill_SectionLaw.hxx>
53 #include <GeomFill_TrihedronLaw.hxx>
56 #include <gp_Trsf.hxx>
58 #include <GProp_GProps.hxx>
59 #include <IntCurveSurface_HInter.hxx>
60 #include <IntCurveSurface_IntersectionPoint.hxx>
61 #include <Law_Function.hxx>
62 #include <Law_Interpol.hxx>
63 #include <Precision.hxx>
64 #include <Standard_ConstructionError.hxx>
65 #include <Standard_DomainError.hxx>
66 #include <Standard_NotImplemented.hxx>
67 #include <Standard_Type.hxx>
68 #include <StdFail_NotDone.hxx>
69 #include <TColgp_HArray1OfPnt2d.hxx>
70 #include <TColStd_HArray1OfReal.hxx>
71 #include <TColStd_SequenceOfInteger.hxx>
73 #include <TopLoc_Location.hxx>
75 #include <TopoDS_Iterator.hxx>
76 #include <TopoDS_Shape.hxx>
77 #include <TopoDS_Shell.hxx>
78 #include <TopoDS_Solid.hxx>
79 #include <TopoDS_Vertex.hxx>
80 #include <TopoDS_Wire.hxx>
81 #include <TopTools_SequenceOfShape.hxx>
84 IMPLEMENT_STANDARD_RTTIEXT(BRepFill_PipeShell,MMgt_TShared)
89 #include <DrawTrSurf.hxx>
91 static Standard_Boolean Affich = 0;
94 #include <TopTools_ListIteratorOfListOfShape.hxx>
95 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
96 #include <TopTools_DataMapOfIntegerShape.hxx>
97 #include <TopoDS_Compound.hxx>
100 static Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
101 const Handle(BRepFill_SectionLaw)& theSection,
102 TopoDS_Shape& theBottom,
103 TopoDS_Shape& theTop);
105 //=======================================================================
106 //function : ComputeSection
107 //purpose : Construct an intermediary section
108 //=======================================================================
110 static Standard_Boolean ComputeSection(const TopoDS_Wire& W1,
111 const TopoDS_Wire& W2,
112 const Standard_Real p1,
113 const Standard_Real p2,
116 TColStd_SequenceOfReal SR;
117 TopTools_SequenceOfShape SSh;
124 BRepFill_CompatibleWires CW(SSh);
127 if (!CW.IsDone()) throw StdFail_NotDone("Uncompatible wires");
128 GeomFill_SequenceOfTrsf EmptyTrsfs;
129 Handle(BRepFill_NSections) SL = new (BRepFill_NSections) (CW.Shape(),EmptyTrsfs,SR,0.,1.);
130 Standard_Real US = p1/(p1+p2);
132 return Standard_True;
137 //=======================================================================
138 //function : PerformTransition
139 //purpose : Modify a law of location depending on Transition
140 //=======================================================================
142 static void PerformTransition(const BRepFill_TransitionStyle Mode,
143 Handle(BRepFill_LocationLaw)& Loc,
144 const Standard_Real angmin)
147 Loc->DeleteTransform();
148 if (Mode == BRepFill_Modified) Loc->TransformInG0Law();
149 else Loc->TransformInCompatibleLaw(angmin);
152 //=======================================================================
153 //function : PerformPlan
154 //purpose : Construct a plane of filling if exists
155 //=======================================================================
157 static Standard_Boolean PerformPlan(TopoDS_Shape& S)
159 Standard_Boolean isDegen = Standard_True;
160 TopExp_Explorer explo(S, TopAbs_EDGE);
161 for (; explo.More(); explo.Next())
163 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
164 if (!BRep_Tool::Degenerated(anEdge))
165 isDegen = Standard_False;
170 return Standard_True;
173 TopoDS_Wire W = TopoDS::Wire(S);
174 Standard_Boolean Ok = Standard_False;
176 BRepLib_MakeFace mkplan(W, Standard_True);
177 if (mkplan.IsDone()) {
185 //=============================================================================
186 //function : IsSameOriented
187 //purpose : Checks whether aFace is oriented to the same side as aShell or not
188 //=============================================================================
190 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
191 const TopoDS_Shape& aShell)
193 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
194 TopoDS_Shape anEdge = Explo.Current();
195 TopAbs_Orientation Or1 = anEdge.Orientation();
197 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
198 TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
200 const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
201 TopoDS_Shape theEdge;
202 for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
204 theEdge = Explo.Current();
205 if (theEdge.IsSame(anEdge))
209 TopAbs_Orientation Or2 = theEdge.Orientation();
211 return Standard_False;
212 return Standard_True;
214 //=======================================================================
215 //function : BRepFill_PipeShell
217 //=======================================================================
218 BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
220 myForceApproxC1(Standard_False),
221 myIsAutomaticLaw(Standard_False),
222 myTrihedron(GeomFill_IsCorrectedFrenet),
223 myTransition(BRepFill_Modified),
224 myStatus(GeomFill_PipeOk)
226 myLocation.Nullify();
234 // Attention to closed non-declared wire !
235 if (!mySpine.Closed()) {
236 TopoDS_Vertex Vf, Vl;
237 TopExp::Vertices(mySpine, Vf, Vl);
238 if (Vf.IsSame(Vl)) mySpine.Closed(Standard_True);
242 //=======================================================================
244 //purpose : Define a law of Frenet (Correct)
245 //=======================================================================
246 void BRepFill_PipeShell::Set(const Standard_Boolean IsFrenet)
248 Handle(GeomFill_TrihedronLaw) TLaw;
250 myTrihedron = GeomFill_IsFrenet;
251 TLaw = new (GeomFill_Frenet) ();
254 myTrihedron = GeomFill_IsFrenet;
255 TLaw = new (GeomFill_CorrectedFrenet) ();
257 Handle(GeomFill_CurveAndTrihedron) Loc =
258 new (GeomFill_CurveAndTrihedron) (TLaw);
259 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
260 mySection.Nullify(); //It is required to relocalize sections.
263 //=======================================================================
264 //function : SetDiscrete
265 //purpose : Define a law of Discrete Trihedron
266 //=======================================================================
267 void BRepFill_PipeShell::SetDiscrete()
269 Handle(GeomFill_TrihedronLaw) TLaw;
271 myTrihedron = GeomFill_IsDiscreteTrihedron;
272 TLaw = new (GeomFill_DiscreteTrihedron) ();
274 Handle(GeomFill_CurveAndTrihedron) Loc =
275 new (GeomFill_CurveAndTrihedron) (TLaw);
276 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
277 mySection.Nullify(); //It is required to relocalize sections.
280 //=======================================================================
282 //purpose : Define a law Constant
283 //=======================================================================
284 void BRepFill_PipeShell::Set(const gp_Ax2& Axe)
286 myTrihedron = GeomFill_IsFixed;
288 V1.SetXYZ(Axe.Direction().XYZ());
289 V2.SetXYZ(Axe.XDirection().XYZ());
290 Handle(GeomFill_Fixed) TLaw = new (GeomFill_Fixed) (V1, V2);
291 Handle(GeomFill_CurveAndTrihedron) Loc =
292 new (GeomFill_CurveAndTrihedron) (TLaw);
293 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
294 mySection.Nullify(); //It is required to relocalize sections.
297 //=======================================================================
299 //purpose : Construct a law of location of binormal fixed type
300 //=======================================================================
301 void BRepFill_PipeShell::Set(const gp_Dir& BiNormal)
303 myTrihedron = GeomFill_IsConstantNormal;
305 Handle(GeomFill_ConstantBiNormal) TLaw =
306 new (GeomFill_ConstantBiNormal) (BiNormal);
307 Handle(GeomFill_CurveAndTrihedron) Loc =
308 new (GeomFill_CurveAndTrihedron) (TLaw);
309 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
310 mySection.Nullify(); //Il faut relocaliser les sections.
313 //=======================================================================
315 //purpose : Construct a law of location of Darboux type
316 //=======================================================================
317 Standard_Boolean BRepFill_PipeShell::Set(const TopoDS_Shape& SpineSupport)
321 // A special law of location is required
322 Handle(BRepFill_EdgeOnSurfLaw) loc =
323 new (BRepFill_EdgeOnSurfLaw) (mySpine, SpineSupport);
324 B = loc->HasResult();
327 myTrihedron = GeomFill_IsDarboux;
328 mySection.Nullify(); //It is required to relocalize the sections.
333 //=======================================================================
335 //purpose : Defines a lawv with help of a guided contour
336 //=======================================================================
337 void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine,
338 const Standard_Boolean CurvilinearEquivalence,
339 const BRepFill_TypeOfContact KeepContact)
341 // Reorganization of the guide (pb of orientation and origin)
342 TopoDS_Wire TheGuide;
343 TheGuide = AuxiliarySpine;
344 Standard_Boolean SpClose = mySpine.Closed(),
345 GuideClose = AuxiliarySpine.Closed();
347 if (KeepContact == BRepFill_ContactOnBorder)
348 myIsAutomaticLaw = Standard_True;
350 if (!SpClose && !GuideClose) {
351 // Case open reorientation of the guide
352 TopoDS_Wire sp = mySpine;
353 TopTools_SequenceOfShape Seq;
355 Seq.Append(TheGuide);
356 BRepFill_CompatibleWires CW(Seq);
359 if (!CW.IsDone()) throw StdFail_NotDone("Uncompatible wires");
360 TheGuide = TopoDS::Wire(CW.Shape().Value(2));
362 else if (GuideClose) {
363 // Case guide closed : Determination of the origin
364 // & reorientation of the guide
368 TopoDS_Vertex Vf, Vl;
370 TopExp::Vertices(mySpine, Vf, Vl);
371 SpOr = BRep_Tool::Pnt(Vf);
372 P = BRep_Tool::Pnt(Vl);
374 SpOr.BaryCenter(0.5, P, 0.5);
378 BRepAdaptor_CompCurve BC(mySpine);
381 BRepFill::SearchOrigin(TheGuide, SpOr, Dir, 100*myTol3d);
386 DBRep::Set("theguide", TheGuide);
388 // transform the guide in a single curve (periodic if posssible)
389 Handle(BRepAdaptor_HCompCurve) Guide =
390 new (BRepAdaptor_HCompCurve) (TheGuide);
391 Guide->ChangeCurve().SetPeriodic(Standard_True);
393 if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa
394 if (KeepContact == BRepFill_Contact ||
395 KeepContact == BRepFill_ContactOnBorder)
396 myTrihedron = GeomFill_IsGuideACWithContact; // with rotation
398 myTrihedron = GeomFill_IsGuideAC; // without rotation
400 Handle(GeomFill_GuideTrihedronAC) TLaw
401 = new (GeomFill_GuideTrihedronAC) (Guide);
402 Handle(GeomFill_LocationGuide) Loc =
403 new (GeomFill_LocationGuide) (TLaw);
404 myLocation = new (BRepFill_ACRLaw) (mySpine, Loc);
406 else {// trihedron by plane
407 if (KeepContact == BRepFill_Contact ||
408 KeepContact == BRepFill_ContactOnBorder)
409 myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation
411 myTrihedron = GeomFill_IsGuidePlan; // without rotation
413 Handle(GeomFill_GuideTrihedronPlan) TLaw =
414 new (GeomFill_GuideTrihedronPlan) (Guide);
415 Handle(GeomFill_LocationGuide) Loc =
416 new (GeomFill_LocationGuide) (TLaw);
417 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
419 mySection.Nullify(); //It is required to relocalize the sections.
423 //=======================================================================
424 //function : SetMaxDegree
426 //=======================================================================
427 void BRepFill_PipeShell::SetMaxDegree(const Standard_Integer NewMaxDegree)
429 myMaxDegree = NewMaxDegree;
432 //=======================================================================
433 //function : SetMaxSegments
435 //=======================================================================
436 void BRepFill_PipeShell::SetMaxSegments(const Standard_Integer NewMaxSegments)
438 myMaxSegments = NewMaxSegments;
441 //=======================================================================
442 //function : SetForceApproxC1
443 //purpose : Set the flag that indicates attempt to approximate
444 // a C1-continuous surface if a swept surface proved
446 //=======================================================================
447 void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
449 myForceApproxC1 = ForceApproxC1;
452 //=======================================================================
454 //purpose : Add a Section
455 //=======================================================================
456 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
457 const Standard_Boolean WithContact,
458 const Standard_Boolean WithCorrection)
462 Add(Profile, V, WithContact, WithCorrection);
466 //=======================================================================
468 //purpose : Add a Section
469 //=======================================================================
470 void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
471 const TopoDS_Vertex& Location,
472 const Standard_Boolean WithContact,
473 const Standard_Boolean WithCorrection)
475 DeleteProfile(Profile); // No duplication
476 if (myIsAutomaticLaw)
479 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
480 S.Set(Standard_True);
485 Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1));
486 Handle(TColgp_HArray1OfPnt2d) ParAndRad;
487 Loc->ComputeAutomaticLaw(ParAndRad);
489 //Compuite initial width of section (this will be 1.)
490 GProp_GProps GlobalProps;
491 BRepGProp::LinearProperties(Profile, GlobalProps);
492 gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
494 TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane
495 Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace);
496 Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane);
497 IntCurveSurface_HInter Intersector;
498 Handle(Adaptor3d_HCurve) aHCurve [2];
499 aHCurve[0] = Loc->GetCurve();
500 aHCurve[1] = Loc->Guide();
501 gp_Pnt PointsOnSpines [2];
502 Standard_Integer i, j;
504 for (i = 0; i < 2; i++)
506 Intersector.Perform(aHCurve[i], GAHplane);
507 Standard_Real MinDist = RealLast();
508 for (j = 1; j <= Intersector.NbPoints(); j++)
510 gp_Pnt aPint = Intersector.Point(j).Pnt();
511 Standard_Real aDist = BaryCenter.Distance(aPint);
515 PointsOnSpines[i] = aPint;
520 //Correct <ParAndRad> according to <InitialWidth>
521 Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]);
522 Standard_Integer NbParRad = ParAndRad->Upper();
523 for (i = 1; i <= NbParRad; i++)
525 gp_Pnt2d aParRad = ParAndRad->Value(i);
526 aParRad.SetY( aParRad.Y() / InitialWidth );
527 ParAndRad->SetValue(i, aParRad);
530 myLaw = new Law_Interpol();
532 Standard_Boolean IsPeriodic =
533 (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion());
535 (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic);
539 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
546 //=======================================================================
548 //purpose : Section + law of homothety
549 //=======================================================================
550 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
551 const Handle(Law_Function)& L,
552 const Standard_Boolean WithContact,
553 const Standard_Boolean WithCorrection)
557 SetLaw( Profile, L, V, WithContact, WithCorrection);
561 //=======================================================================
563 //purpose : Section + Law of homothety
564 //=======================================================================
565 void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
566 const Handle(Law_Function)& L,
567 const TopoDS_Vertex& Location,
568 const Standard_Boolean WithContact,
569 const Standard_Boolean WithCorrection)
572 BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
573 S.Set(Standard_True);
580 //=======================================================================
582 //purpose : Delete a section
583 //=======================================================================
584 void BRepFill_PipeShell::DeleteProfile(const TopoDS_Shape& Profile)
586 Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX);
588 Standard_Boolean Trouve=Standard_False;
590 for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
591 Standard_Boolean found = Standard_False;
592 const TopoDS_Wire& aWire = mySeq.Value(ii).Wire();
595 TopExp_Explorer Explo(aWire, TopAbs_VERTEX);
596 for (; Explo.More(); Explo.Next())
597 if (Profile.IsSame(Explo.Current()))
598 found = Standard_True;
600 else if (Profile.IsSame(aWire))
601 found = Standard_True;
605 Trouve = Standard_True;
610 if (Trouve) mySection.Nullify();
615 //=======================================================================
618 //=======================================================================
619 Standard_Boolean BRepFill_PipeShell::IsReady() const
621 return (mySeq.Length() != 0);
623 //=======================================================================
624 //function : GetStatus
626 //=======================================================================
627 GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
633 //=======================================================================
634 //function : SetTolerance
636 //=======================================================================
637 void BRepFill_PipeShell::SetTolerance(const Standard_Real Tol3d ,
638 const Standard_Real BoundTol,
639 const Standard_Real TolAngular)
642 myBoundTol = BoundTol;
643 myTolAngular = TolAngular;
646 //=======================================================================
647 //function : SetTransition
648 //purpose : Defines the mode of processing of corners
649 //=======================================================================
650 void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
651 const Standard_Real Angmin,
652 const Standard_Real Angmax)
654 if (myTransition != Mode)
655 mySection.Nullify(); //It is required to relocalize the sections.
661 //=======================================================================
662 //function : Simulate
663 //purpose : Calculate N Sections
664 //=======================================================================
665 void BRepFill_PipeShell::Simulate(const Standard_Integer N,
666 TopTools_ListOfShape& List)
672 Standard_Real First, Last, Length, Delta, U,
674 Standard_Integer ii, NbL = myLocation->NbLaw();
675 Standard_Boolean Finis=Standard_False;
678 // Calculate the parameters of digitalization
679 mySection->Law(1)->GetDomain(FirstS, Last);
680 DeltaS = Last - FirstS;
681 myLocation->CurvilinearBounds(NbL,First, Length);
683 if (N>1) Delta /= (N-1);
685 myLocation->CurvilinearBounds(1,First, Last); // Initiation of Last
686 for (U=0.0, ii=1; !Finis ; U+=Delta) {
689 Finis = Standard_True;
692 if (ii < NbL) myLocation->CurvilinearBounds(NbL,First, Last);
693 if (U > Last) U = (Last+First)/2; // The edge is not skipped
696 US = FirstS + (U/Length)*DeltaS;
697 // Calcul d'une section
698 mySection->D0(US, W);
699 myLocation->D0(U, W);
704 //=======================================================================
706 //purpose : Construct the Shell and the history
707 //=======================================================================
708 Standard_Boolean BRepFill_PipeShell::Build()
711 Standard_Real FirstS, LastS;
715 if (myStatus != GeomFill_PipeOk) {
719 myShape = Sh; // Nullify
720 return Standard_False;
723 // 2) Calculate myFirst and myLast
724 mySection->Law(1)->GetDomain(FirstS, LastS);
725 mySection->D0(FirstS, myFirst);
726 myLocation->D0(0, myFirst);
727 if (mySection->IsVClosed() && myLocation->IsClosed()) {
728 if (myLocation->IsG1(0)>=0)
736 Standard_Real Length;
737 myLocation->CurvilinearBounds(myLocation->NbLaw(),
739 mySection->D0(LastS, myLast);
740 myLocation->D0(Length, myLast);
741 // eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
742 // tolerances of shapes built on them may be quite different
743 if (myFirst.IsPartner( myLast )) {
744 BRepBuilderAPI_Copy copy(myLast);
746 myLast = copy.Shape();
748 // eap 5 Jun 2002 occ332, end modif
752 DBRep::Set("PipeFirst", myFirst);
753 DBRep::Set("PipeLast", myLast);
758 BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
759 MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
760 MkSw.SetAngularControl(angmin, angmax);
761 MkSw.SetForceApproxC1(myForceApproxC1);
762 MkSw.SetBounds(TopoDS::Wire(myFirst),
763 TopoDS::Wire(myLast));
764 GeomAbs_Shape theContinuity = GeomAbs_C2;
765 if (myTrihedron == GeomFill_IsDiscreteTrihedron)
766 theContinuity = GeomAbs_C0;
767 TopTools_MapOfShape Dummy;
768 BRepFill_DataMapOfShapeHArray2OfShape Dummy2;
769 BRepFill_DataMapOfShapeHArray2OfShape Dummy3;
770 MkSw.Build(Dummy, Dummy2, Dummy3, myTransition, theContinuity,
771 GeomFill_Location, myMaxDegree, myMaxSegments);
773 myStatus = myLocation->GetStatus();
774 Ok = (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
777 myShape = MkSw.Shape();
778 myErrorOnSurf = MkSw.ErrorOnSurface();
780 TopoDS_Shape aBottomWire = myFirst;
781 TopoDS_Shape aTopWire = myLast;
783 if(BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire)) {
784 myFirst = aBottomWire;
788 if (mySection->IsUClosed())
790 TopExp_Explorer explo;
791 Standard_Boolean DegenFirst = Standard_True, DegenLast = Standard_True;
793 for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
795 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
796 DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
799 for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
801 const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
802 DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
805 if (DegenFirst && DegenLast)
806 myShape.Closed(Standard_True);
815 myShape = Sh; // Nullify
816 if (myStatus == GeomFill_PipeOk) myStatus = GeomFill_PipeNotOk;
821 //=======================================================================
822 //function : MakeSolid
824 //=======================================================================
825 Standard_Boolean BRepFill_PipeShell::MakeSolid()
827 if (myShape.IsNull())
828 throw StdFail_NotDone("PipeShell is not built");
829 Standard_Boolean B = myShape.Closed();
834 if(!myFirst.IsNull() && !myLast.IsNull()) {
835 B = (myFirst.Closed() && myLast.Closed());
838 // It is necessary to block the extremities
839 B = PerformPlan(myFirst);
841 B = PerformPlan(myLast);
843 if (!myFirst.IsNull() && !IsSameOriented( myFirst, myShape ))
845 if (!myLast.IsNull() && !IsSameOriented( myLast, myShape ))
848 if (!myFirst.IsNull())
849 BS.Add(myShape, TopoDS::Face(myFirst));
850 if (!myLast.IsNull())
851 BS.Add(myShape, TopoDS::Face(myLast));
853 myShape.Closed(Standard_True);
862 BS.Add(solid,TopoDS::Shell(myShape));
863 BRepClass3d_SolidClassifier SC(solid);
864 SC.PerformInfinitePoint(Precision::Confusion());
865 if ( SC.State() == TopAbs_IN) {
868 BS.Add(solid,TopoDS::Shell(myShape));
871 myShape.Closed(Standard_True);
876 //=======================================================================
878 //purpose : Return the result
879 //=======================================================================
880 const TopoDS_Shape& BRepFill_PipeShell::Shape() const
885 //=======================================================================
886 //function : ErrorOnSurface
888 //=======================================================================
890 Standard_Real BRepFill_PipeShell::ErrorOnSurface() const
892 return myErrorOnSurf;
895 //=======================================================================
896 //function : FirstShape
897 //purpose : Return the start section
898 //=======================================================================
899 const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
904 //=======================================================================
905 //function : LastShape
906 //purpose : Return the end section
907 //=======================================================================
908 const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
913 //=======================================================================
914 //function : Generated
916 //=======================================================================
917 // void BRepFill_PipeShell::Generated(const TopoDS_Shape& ,
918 // TopTools_ListOfShape& )
919 void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape,
920 TopTools_ListOfShape& theList)
922 // throw Standard_NotImplemented("Generated:Pas Fait");
926 if(myGenMap.IsBound(theShape)) {
927 theList = myGenMap.Find(theShape);
931 //=======================================================================
933 //purpose : - Check that everything is ready
934 // - Construct the law of section
935 // - Construct the law of location if required
936 // - Calculate First & Last
937 //=======================================================================
938 void BRepFill_PipeShell::Prepare()
941 if (!IsReady()) throw StdFail_NotDone("PipeShell");
942 if (!myLocation.IsNull() && !mySection.IsNull()) return; // It is ready
944 //Check set of section for right configuration of punctual sections
946 TopoDS_Iterator iter;
947 for (i = 2; i <= mySeq.Length()-1; i++)
949 Standard_Boolean wdeg = Standard_True;
950 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
952 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
953 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
956 throw Standard_Failure("Wrong usage of punctual sections");
958 if (mySeq.Length() <= 2)
960 Standard_Boolean wdeg = Standard_True;
961 for (i = 1; i <= mySeq.Length(); i++)
962 for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
964 const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
965 wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
968 throw Standard_Failure("Wrong usage of punctual sections");
971 // Construction of the law of location
972 if(myLocation.IsNull())
976 case GeomFill_IsCorrectedFrenet :
978 Handle(GeomFill_TrihedronLaw) TLaw =
979 new (GeomFill_CorrectedFrenet) ();
980 Handle(GeomFill_CurveAndTrihedron) Loc =
981 new (GeomFill_CurveAndTrihedron) (TLaw);
982 myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
987 throw Standard_ConstructionError("PipeShell");
992 //Transformation of the law (Transition Management)
993 PerformTransition(myTransition, myLocation, angmin);
996 // Construction of the section law
997 if (mySeq.Length() == 1) {
1000 Place(mySeq(1), theSect, aTrsf, p1);
1001 TopoDS_Wire aLocalShape = theSect;
1002 if (mySeq(1).IsLaw())
1003 mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
1004 // mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
1006 mySection = new BRepFill_ShapeLaw(aLocalShape);
1007 // mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
1009 WSeq.Append(theSect);
1010 //Simple case of single section
1011 myIndOfSec.Append(1);
1012 TopoDS_Iterator itw(theSect);
1013 for (; itw.More(); itw.Next())
1015 const TopoDS_Shape& anEdge = itw.Value();
1016 TopTools_ListOfShape Elist;
1017 Elist.Append(anEdge);
1018 myEdgeNewEdges.Bind(anEdge, Elist);
1020 ///////////////////////////////
1024 TColStd_SequenceOfReal Param;
1025 TColStd_SequenceOfInteger IndSec;
1026 GeomFill_SequenceOfTrsf Transformations;
1027 Standard_Integer NbL = myLocation->NbLaw();
1029 Standard_Real V1, V2, param;
1030 myLocation->CurvilinearBounds(NbL, V1, V2);
1032 Standard_Integer ideb = 0, ifin = 0;
1033 Standard_Integer iseq;
1034 for (iseq = 1; iseq <= mySeq.Length(); iseq++) {
1035 IndSec.Append(iseq);
1036 Place(mySeq(iseq), theSect, aTrsf, param);
1037 Param.Append(param);
1038 WSeq.Append(theSect);
1039 Transformations.Append(aTrsf);
1040 if (param==V1) ideb = iseq;
1041 if (param==V2) ifin = iseq;
1045 // looping sections ?
1046 if (myLocation->IsClosed()) {
1048 // place the initial section at the final position
1050 WSeq.Append(WSeq(ideb));
1053 // place the final section at the initial position
1055 WSeq.Append(WSeq(ifin));
1058 // it is necessary to find a medium section to impose by V1 and by V2
1059 Standard_Real pmin = RealLast(), pmax = RealFirst();
1060 TopoDS_Wire Wmin, Wmax;
1061 for (iseq = 1; iseq <= WSeq.Length(); iseq++) {
1062 if (Param.Value(iseq)<pmin) {
1063 pmin = Param.Value(iseq);
1064 Wmin = TopoDS::Wire(WSeq.Value(iseq));
1066 if (Param.Value(iseq)>pmax) {
1067 pmax = Param.Value(iseq);
1068 Wmax = TopoDS::Wire(WSeq.Value(iseq));
1071 // medium section between Wmin and Wmax
1073 Standard_Real dmin = Abs(pmin-V1);
1074 Standard_Real dmax = Abs(pmax-V2);
1075 if (ComputeSection(Wmin,Wmax,dmin,dmax,Wres)) {
1076 // impose section Wres at the beginning and the end
1079 IndSec.Append(WSeq.Length());
1082 IndSec.Append(WSeq.Length());
1087 // parse sections by increasing parameter
1088 Standard_Boolean play_again = Standard_True;
1089 while (play_again) {
1090 play_again = Standard_False;
1091 for (iseq=1;iseq<=WSeq.Length();iseq++) {
1092 for (Standard_Integer jseq=iseq+1;jseq<=WSeq.Length();jseq++) {
1093 if (Param.Value(iseq) > Param.Value(jseq)) {
1094 Param.Exchange(iseq,jseq);
1095 WSeq.Exchange(iseq,jseq);
1096 IndSec.Exchange(iseq,jseq);
1097 play_again = Standard_True;
1102 //Fill the array of real indices of sections
1103 for (Standard_Integer ii = 1; ii <= mySeq.Length(); ii++)
1104 for (Standard_Integer jj = 1; jj <= IndSec.Length(); jj++)
1105 if (IndSec(jj) == ii)
1107 myIndOfSec.Append(jj);
1113 char* name = new char[100];
1114 Standard_Integer NBSECT = 0;
1115 for (Standard_Integer i=1;i<=WSeq.Length();i++) {
1117 sprintf(name,"WSeq_%d",NBSECT);
1118 DBRep::Set(name,TopoDS::Wire(WSeq.Value(i)));
1125 // Calculate work sections
1126 TopTools_SequenceOfShape WorkingSections;
1127 WorkingSections.Clear();
1128 TopTools_DataMapOfShapeListOfShape WorkingMap;
1129 BRepFill_CompatibleWires Georges(WSeq);
1130 Georges.SetPercent(0.1);
1131 Georges.Perform(Standard_False);
1132 if (Georges.IsDone()) {
1133 WorkingSections = Georges.Shape();
1134 WorkingMap = Georges.Generated();
1135 //For each sub-edge of each section
1136 //we save its splits
1137 for (Standard_Integer ii = 1; ii <= WSeq.Length(); ii++)
1139 TopExp_Explorer Explo(WSeq(ii), TopAbs_EDGE);
1140 for (; Explo.More(); Explo.Next())
1142 const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1143 TopTools_ListOfShape aNewEdges = Georges.GeneratedShapes(anEdge);
1144 myEdgeNewEdges.Bind(anEdge, aNewEdges);
1149 throw Standard_ConstructionError("PipeShell : uncompatible wires");
1151 mySection = new (BRepFill_NSections) (WorkingSections,Transformations,Param,V1,V2);
1155 // modify the law of location if contact
1156 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1157 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1158 Standard_Real fs, f, l, Delta, Length;
1159 Handle(GeomFill_LocationGuide) Loc;
1160 Handle(GeomFill_SectionLaw) Sec = mySection->ConcatenedLaw();
1161 myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
1162 Sec->GetDomain(fs,l);
1163 Delta = (l-fs)/Length;
1165 Standard_Real angle, old_angle = 0;
1166 for (Standard_Integer ipath=1; ipath<=myLocation->NbLaw(); ipath++) {
1167 myLocation->CurvilinearBounds(ipath, f, l);
1168 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(ipath));
1169 Loc->Set(Sec, Standard_True, fs + f*Delta, fs + l*Delta,
1170 old_angle, angle); // force the rotation
1175 myStatus = myLocation->GetStatus();
1176 if (!mySection->IsDone())
1177 myStatus = GeomFill_PipeNotOk;
1180 //=======================================================================
1182 //purpose : Implement a Section in the local refernce frame
1183 // and return its parameter on the trajectory
1184 //=======================================================================
1185 void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
1188 Standard_Real& param)
1190 BRepFill_SectionPlacement Place(myLocation,
1194 Sec.WithCorrection());
1195 TopoDS_Wire TmpWire = Sec.Wire();
1196 aTrsf = Place.Transformation();
1197 //TopLoc_Location Loc2(Place.Transformation()), Loc1;
1198 //Loc1 = TmpWire.Location();
1199 //W.Location(Loc2.Multiplied(Loc1));
1200 //Transform the copy
1201 W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, Standard_True));
1202 ////////////////////////////////////
1203 param = Place.AbscissaOnPath();
1207 //=======================================================================
1208 //function : ResetLoc
1209 //purpose : Remove references to the sections in the laws of location
1210 //=======================================================================
1211 void BRepFill_PipeShell::ResetLoc()
1213 if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1214 || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1215 Handle(GeomFill_LocationGuide) Loc;
1216 for (Standard_Integer isec=1; isec<=myLocation->NbLaw(); isec++) {
1217 Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(isec));
1218 Loc->EraseRotation();// remove the rotation
1223 //=======================================================================
1224 //function : BuildHistory
1225 //purpose : Builds history for edges and vertices
1227 //=======================================================================
1228 void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
1230 //Filling of <myGenMap>
1231 const Handle(TopTools_HArray2OfShape)& anUEdges = theSweep.InterFaces();
1234 TopTools_DataMapOfIntegerShape IndWireMap;
1236 Standard_Integer indw, inde;
1237 TopoDS_Iterator itw;
1238 for (indw = 1; indw <= mySeq.Length(); indw++)
1240 const TopoDS_Wire& aSection = mySeq(indw).Wire();
1241 Standard_Boolean IsPunctual = mySeq(indw).IsPunctual();
1244 //for punctual sections (first or last)
1245 //we take all the wires generated along the path
1246 TopExp_Explorer Explo(aSection, TopAbs_VERTEX);
1247 const TopoDS_Shape& VerSection = Explo.Current();
1248 TopTools_ListOfShape Elist;
1249 for (Standard_Integer i = 1; i <= anUEdges->UpperRow(); i++)
1250 for (Standard_Integer j = 1; j <= anUEdges->UpperCol(); j++)
1251 Elist.Append(anUEdges->Value(i,j));
1252 myGenMap.Bind(VerSection, Elist);
1255 //Take the real index of section on the path
1256 Standard_Integer IndOfW = myIndOfSec(indw);
1257 const TopoDS_Wire& theWire = TopoDS::Wire(WSeq(IndOfW));
1258 BRepTools_WireExplorer wexp_sec(aSection);
1259 for (inde = 1; wexp_sec.More(); wexp_sec.Next())
1261 const TopoDS_Edge& anEdge = TopoDS::Edge(wexp_sec.Current());
1262 if (BRep_Tool::Degenerated(anEdge))
1265 TopoDS_Shell aShell;
1266 BB.MakeShell(aShell);
1267 TopoDS_Vertex aVertex [2];
1268 TopExp::Vertices(anEdge, aVertex[0], aVertex[1]);
1269 Standard_Integer SignOfAnEdge =
1270 (anEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
1272 //For each non-degenerated inde-th edge of <aSection>
1273 //we find inde-th edge in <theWire>
1274 TopoDS_Edge theEdge;
1275 BRepTools_WireExplorer wexp(theWire);
1276 for (Standard_Integer i = 1; wexp.More(); wexp.Next())
1278 theEdge = TopoDS::Edge(wexp.Current());
1279 if (BRep_Tool::Degenerated(anEdge))
1286 //Take the list of splits for <theEdge>
1287 const TopTools_ListOfShape& NewEdges = myEdgeNewEdges(theEdge);
1288 Standard_Integer SignOfANewEdge = 0, SignOfIndex = 0;
1289 TopTools_ListIteratorOfListOfShape iter(NewEdges);
1290 for (; iter.More(); iter.Next())
1292 const TopoDS_Edge& aNewEdge = TopoDS::Edge(iter.Value());
1293 SignOfANewEdge = (aNewEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
1294 Standard_Integer anIndE = mySection->IndexOfEdge(aNewEdge);
1295 SignOfIndex = (anIndE > 0)? 1 : -1;
1296 anIndE = Abs(anIndE);
1297 //For an edge generated shape is a "tape" -
1298 //a shell usually containing this edge and
1299 //passing from beginning of path to its end
1300 TopoDS_Shape aTape = theSweep.Tape(anIndE);
1301 TopoDS_Iterator itsh(aTape);
1302 for (; itsh.More(); itsh.Next())
1303 BB.Add(aShell, itsh.Value());
1306 //Processing of vertices of <anEdge>
1307 //We should choose right index in <anUEdges>
1308 //for each vertex of edge
1309 Standard_Integer ToReverse = SignOfAnEdge * SignOfANewEdge * SignOfIndex;
1310 Standard_Integer UIndex [2];
1311 UIndex[0] = Abs(mySection->IndexOfEdge(NewEdges.First()));
1312 UIndex[1] = Abs(mySection->IndexOfEdge(NewEdges.Last())) + ToReverse;
1313 if (ToReverse == -1)
1318 if (mySection->IsUClosed())
1320 if (UIndex[0] > mySection->NbLaw())
1322 if (UIndex[1] > mySection->NbLaw())
1325 //if (SignOfAnEdge * SignOfANewEdge == -1)
1326 if (SignOfAnEdge == -1 ||
1327 SignOfANewEdge == -1)
1328 { Standard_Integer Tmp = UIndex[0]; UIndex[0] = UIndex[1]; UIndex[1] = Tmp; }
1330 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1331 TopExp::MapShapesAndAncestors(aShell, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1332 for (Standard_Integer kk = 0; kk < 2; kk++)
1334 if (myGenMap.IsBound(aVertex[kk]))
1336 if (IndWireMap.IsBound(UIndex[kk]))
1338 TopTools_ListOfShape Wlist;
1339 Wlist.Append(IndWireMap(UIndex[kk]));
1340 myGenMap.Bind(aVertex[kk], Wlist);
1345 TopTools_SequenceOfShape SeqEdges;
1346 Standard_Integer jj;
1347 for (jj = 1; jj <= anUEdges->UpperCol(); jj++)
1348 SeqEdges.Append(anUEdges->Value(UIndex[kk], jj));
1350 //Assemble the wire ("rail" along the path)
1351 //checking for possible holes
1352 //(they appear with option "Round Corner")
1354 //Missed edges are taken from <aShell>
1357 const TopoDS_Edge& FirstEdge = TopoDS::Edge(SeqEdges(1));
1358 if (FirstEdge.IsNull())
1360 BB.Add(aWire, FirstEdge);
1361 TopoDS_Vertex FirstVertex, CurVertex;
1362 TopExp::Vertices(FirstEdge, FirstVertex, CurVertex);
1363 TopoDS_Edge CurEdge;
1364 for (jj = 2; jj <= SeqEdges.Length(); jj++)
1366 CurEdge = TopoDS::Edge(SeqEdges(jj));
1367 TopoDS_Vertex Vfirst, Vlast;
1368 TopExp::Vertices(CurEdge, Vfirst, Vlast);
1369 if (CurVertex.IsSame(Vfirst))
1373 const TopTools_ListOfShape& Elist = VEmap.FindFromKey(Vfirst);
1374 TopTools_ListIteratorOfListOfShape itl(Elist);
1375 for (; itl.More(); itl.Next())
1377 const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
1378 if (Candidate.IsSame(CurEdge))
1380 TopoDS_Vertex V1, V2;
1381 TopExp::Vertices(Candidate, V1, V2);
1382 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
1384 BB.Add(aWire, Candidate);
1390 BB.Add(aWire, CurEdge);
1391 } //for (jj = 2; jj <= SeqEdges.Length(); jj++)
1392 //case of closed wire
1393 if (mySection->IsVClosed() &&
1394 !CurVertex.IsSame(FirstVertex))
1396 const TopTools_ListOfShape& Elist = VEmap.FindFromKey(CurVertex);
1397 TopTools_ListIteratorOfListOfShape itl(Elist);
1398 for (; itl.More(); itl.Next())
1400 const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
1401 if (Candidate.IsSame(CurEdge))
1403 TopoDS_Vertex V1, V2;
1404 TopExp::Vertices(Candidate, V1, V2);
1405 if (V1.IsSame(FirstVertex) || V2.IsSame(FirstVertex))
1407 BB.Add(aWire, Candidate);
1412 TopTools_ListOfShape Wlist;
1413 Wlist.Append(aWire);
1414 myGenMap.Bind(aVertex[kk], Wlist);
1415 //Save already built wire with its index
1416 IndWireMap.Bind(UIndex[kk], aWire);
1417 } //for (Standard_Integer kk = 0; kk < 2; kk++)
1418 ////////////////////////////////////
1420 TopTools_ListOfShape ListShell;
1421 ListShell.Append(aShell);
1422 myGenMap.Bind(anEdge, ListShell);
1423 ////////////////////////
1431 // ---------------------------------------------------------------------------------
1432 // static function: BuildBoundaries
1434 // ---------------------------------------------------------------------------------
1435 Standard_Boolean BuildBoundaries(const BRepFill_Sweep& theSweep,
1436 const Handle(BRepFill_SectionLaw)& theSection,
1437 TopoDS_Shape& theBottom,
1438 TopoDS_Shape& theTop) {
1440 TopoDS_Wire aBottomWire;
1441 TopoDS_Wire aTopWire;
1443 aB.MakeWire(aBottomWire);
1444 aB.MakeWire(aTopWire);
1445 Standard_Boolean bfoundbottom = Standard_False;
1446 Standard_Boolean bfoundtop = Standard_False;
1447 Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1448 Standard_Integer i = 0;
1449 Standard_Boolean bAllSame = Standard_True;
1451 for(i = 1; i <= theSection->NbLaw(); i++) {
1452 const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1454 if(!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1455 aB.Add(aBottomWire, aBottomEdge);
1456 bfoundbottom = Standard_True;
1458 const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
1460 if(!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE)) {
1461 aB.Add(aTopWire, aTopEdge);
1462 bfoundtop = Standard_True;
1465 if(!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
1466 bAllSame = Standard_False;
1469 if(theSection->IsUClosed()) {
1470 aBottomWire.Closed(Standard_True);
1471 aTopWire.Closed(Standard_True);
1475 theBottom = aBottomWire;
1482 if(bAllSame && bfoundbottom && bfoundtop)
1485 return bfoundbottom || bfoundtop;