1 // Created on: 1995-10-27
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-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.
17 // Modified by skv - Tue Mar 15 16:20:43 2005
18 // Add methods for supporting history.
19 // Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455
21 #include <Adaptor3d_CurveOnSurface.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
24 #include <BRep_PointRepresentation.hxx>
25 #include <BRep_TEdge.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_TVertex.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <BRepAdaptor_Curve2d.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepAlgo_AsDes.hxx>
32 #include <BRepAlgo_Image.hxx>
33 #include <BRepCheck_Analyzer.hxx>
34 #include <BRepCheck_Edge.hxx>
35 #include <BRepCheck_Vertex.hxx>
36 #include <BRepClass3d_SolidClassifier.hxx>
37 #include <BRepGProp.hxx>
38 #include <BRepLib.hxx>
39 #include <BRepLib_FindSurface.hxx>
40 #include <BRepLib_MakeEdge.hxx>
41 #include <BRepLib_MakeFace.hxx>
42 #include <BRepLib_MakeVertex.hxx>
43 #include <BRepOffset_Analyse.hxx>
44 #include <BRepOffset_DataMapIteratorOfDataMapOfShapeOffset.hxx>
45 #include <BRepOffset_DataMapOfShapeMapOfShape.hxx>
46 #include <BRepOffset_DataMapOfShapeOffset.hxx>
47 #include <BRepOffset_Inter2d.hxx>
48 #include <BRepOffset_Inter3d.hxx>
49 #include <BRepOffset_Interval.hxx>
50 #include <BRepOffset_ListOfInterval.hxx>
51 #include <BRepOffset_MakeLoops.hxx>
52 #include <BRepOffset_MakeOffset.hxx>
53 #include <BRepOffset_Offset.hxx>
54 #include <BRepOffset_Tool.hxx>
55 #include <BRepTools.hxx>
56 #include <BRepTools_Quilt.hxx>
57 #include <BRepTools_Substitution.hxx>
58 #include <BRepTools_WireExplorer.hxx>
61 #include <GC_MakeCylindricalSurface.hxx>
62 #include <GCE2d_MakeLine.hxx>
63 #include <gce_MakeCone.hxx>
64 #include <gce_MakeDir.hxx>
65 #include <Geom2d_Line.hxx>
66 #include <Geom2d_TrimmedCurve.hxx>
67 #include <Geom2dAdaptor_HCurve.hxx>
68 #include <Geom_Circle.hxx>
69 #include <Geom_ConicalSurface.hxx>
70 #include <Geom_CylindricalSurface.hxx>
71 #include <Geom_OffsetSurface.hxx>
72 #include <Geom_Plane.hxx>
73 #include <Geom_SphericalSurface.hxx>
74 #include <Geom_SurfaceOfLinearExtrusion.hxx>
75 #include <Geom_TrimmedCurve.hxx>
76 #include <GeomAdaptor_HSurface.hxx>
77 #include <GeomAPI_ProjectPointOnCurve.hxx>
78 #include <GeomFill_Generator.hxx>
79 #include <GeomLib.hxx>
80 #include <gp_Cone.hxx>
81 #include <gp_Lin2d.hxx>
83 #include <GProp_GProps.hxx>
84 #include <IntTools_FClass2d.hxx>
85 #include <NCollection_List.hxx>
86 #include <Precision.hxx>
87 #include <Standard_ConstructionError.hxx>
88 #include <Standard_NotImplemented.hxx>
89 #include <TColStd_ListIteratorOfListOfInteger.hxx>
91 #include <TopExp_Explorer.hxx>
93 #include <TopoDS_Compound.hxx>
94 #include <TopoDS_Edge.hxx>
95 #include <TopoDS_Face.hxx>
96 #include <TopoDS_Iterator.hxx>
97 #include <TopoDS_Shape.hxx>
98 #include <TopoDS_Shell.hxx>
99 #include <TopoDS_Solid.hxx>
100 #include <TopoDS_Vertex.hxx>
101 #include <TopoDS_Wire.hxx>
102 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
103 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
104 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
105 #include <TopTools_DataMapOfShapeShape.hxx>
106 #include <TopTools_IndexedMapOfShape.hxx>
107 #include <TopTools_ListIteratorOfListOfShape.hxx>
108 #include <TopTools_ListOfShape.hxx>
109 #include <TopTools_MapIteratorOfMapOfShape.hxx>
110 #include <TopTools_MapOfShape.hxx>
111 #include <TopTools_SequenceOfShape.hxx>
112 #include <BRepBuilderAPI_Sewing.hxx>
113 #include <Geom_Line.hxx>
114 #include <NCollection_Vector.hxx>
115 #include <NCollection_IncAllocator.hxx>
117 #include <BOPAlgo_MakerVolume.hxx>
118 #include <BOPTools_AlgoTools.hxx>
127 #include <OSD_Chronometer.hxx>
129 Standard_Boolean AffichInt2d = Standard_False;
130 Standard_Boolean AffichOffC = Standard_False;
131 Standard_Boolean ChronBuild = Standard_False;
132 Standard_Integer NbAE = 0;
133 Standard_Integer NbAF = 0;
134 Standard_Integer NVP = 0;
135 Standard_Integer NVM = 0;
136 Standard_Integer NVN = 0;
137 static OSD_Chronometer Clock;
143 //=======================================================================
144 //function : DEBVerticesControl
146 //=======================================================================
148 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
149 Handle(BRepAlgo_AsDes) AsDes)
151 TopTools_ListOfShape LVP;
152 TopTools_ListIteratorOfListOfShape it1LE ;
153 TopTools_ListIteratorOfListOfShape it2LE ;
156 for (i = 1; i <= NewEdges.Extent(); i++) {
157 const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
158 if (AsDes->HasDescendant(NE)) {
159 for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
160 if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
161 LVP.Append(it1LE.Value());
162 cout <<"Vertex on at least 3 edges."<<endl;
165 sprintf (name,"VP_%d",NVP++);
166 DBRep::Set(name,it1LE.Value());
170 else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
171 cout <<"Vertex on more than 3 edges."<<endl;
174 sprintf (name,"VM_%d",NVM++);
175 DBRep::Set(name,it1LE.Value());
183 sprintf (name,"VN_%d",NVN++);
184 DBRep::Set(name,it1LE.Value());
191 //------------------------------------------------
192 // Try to mix spoiled vertices.
193 //------------------------------------------------
195 TopTools_ListIteratorOfListOfShape it1(LVP);
196 Standard_Real TolConf = 1.e-5;
197 Standard_Real Tol = Precision::Confusion();
198 //Standard_Integer i = 1;
201 for ( ; it1.More(); it1.Next()) {
202 TopoDS_Shape V1 = it1.Value();
203 gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
204 Standard_Real distmin = Precision::Infinite();
205 TopTools_ListIteratorOfListOfShape it2(LVP);
206 Standard_Integer j = 1;
208 for ( ; it2.More(); it2.Next()) {
210 TopoDS_Shape V2 = it2.Value();
211 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
212 if (!V1.IsSame(V2)) {
213 Standard_Real dist = P1.Distance(P2);
214 if (dist < distmin) distmin = dist;
215 if (dist < TolConf) {
218 const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
219 TopTools_ListIteratorOfListOfShape itAsDes;
220 for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
221 EWE2 = TopoDS::Edge(itAsDes.Value());
222 TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
223 UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
224 aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
225 B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
227 // BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
228 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
231 AsDes->Replace(V2,V1);
238 cout <<" distmin between VP : "<<distmin<<endl;
244 //=======================================================================
246 //=======================================================================
248 void GetEnlargedFaces(const TopoDS_Shape& theShape,
249 const BRepOffset_DataMapOfShapeOffset& theMapSF,
250 const TopTools_DataMapOfShapeShape& theMES,
251 TopTools_DataMapOfShapeShape& theFacesOrigins,
252 BRepAlgo_Image& theImage,
253 TopTools_ListOfShape& theLSF);
256 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
257 BRepAlgo_Image& theImage,
258 TopoDS_Shape& theShells);
261 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
262 const TopAbs_ShapeEnum theSSType,
263 TopoDS_Shape& theResult);
266 void UpdateInitOffset(BRepAlgo_Image& myInitOffset,
267 BRepAlgo_Image& myImageOffset,
268 const TopoDS_Shape& myOffsetShape,
269 const TopAbs_ShapeEnum &theShapeType);
272 void RemoveShapes(TopoDS_Shape& theS,
273 const TopTools_ListOfShape& theLS);
276 Standard_Boolean IsSolid(const TopoDS_Shape& theS);
279 void UpdateHistory(const TopTools_ListOfShape& theLF,
280 BOPAlgo_Builder& theGF,
281 BRepAlgo_Image& theImage);
284 Standard_Boolean IsPlanar(const TopoDS_Shape& theS);
287 void TrimEdge(TopoDS_Edge& NE,
288 const Handle(BRepAlgo_AsDes)& AsDes2d,
289 Handle(BRepAlgo_AsDes)& AsDes,
290 TopTools_DataMapOfShapeShape& theETrimEInf);
293 void TrimEdges(const TopoDS_Shape& theShape,
294 const Standard_Real theOffset,
295 BRepOffset_DataMapOfShapeOffset& theMapSF,
296 TopTools_DataMapOfShapeShape& theMES,
297 TopTools_DataMapOfShapeShape& theBuild,
298 Handle(BRepAlgo_AsDes)& theAsDes,
299 Handle(BRepAlgo_AsDes)& theAsDes2d,
300 TopTools_IndexedMapOfShape& theNewEdges,
301 TopTools_DataMapOfShapeShape& theETrimEInf,
302 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins);
305 void AppendToList(TopTools_ListOfShape& theL,
306 const TopoDS_Shape& theS);
308 static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
309 const Standard_Real theVParam,
310 const Handle(Geom_Surface)& theSurf,
311 const NCollection_Vector<gp_Pnt>& theBadPoints);
313 //---------------------------------------------------------------------
314 static void UpdateTolerance ( TopoDS_Shape& myShape,
315 const TopTools_IndexedMapOfShape& myFaces);
316 static Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
317 const Handle(Geom_Curve)& theCrv,
318 const Standard_Real theFirst,
319 const Standard_Real theLast);
321 static void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList);
322 //---------------------------------------------------------------------
324 static TopAbs_Orientation OrientationOfEdgeInFace(const TopoDS_Edge& theEdge,
325 const TopoDS_Face& theFace)
327 TopAbs_Orientation anOr = TopAbs_EXTERNAL;
329 TopExp_Explorer Explo(theFace, TopAbs_EDGE);
330 for (; Explo.More(); Explo.Next())
332 const TopoDS_Shape& anEdge = Explo.Current();
333 if (anEdge.IsSame(theEdge))
335 anOr = anEdge.Orientation();
344 static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
345 const TopoDS_Edge& E,
348 // Search the vertex in the edge
350 Standard_Boolean rev = Standard_False;
352 TopAbs_Orientation orient = TopAbs_INTERNAL;
354 TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
356 // if the edge has no vertices
357 // and is degenerated use the vertex orientation
360 if (!itv.More() && BRep_Tool::Degenerated(E)) {
361 orient = V.Orientation();
365 const TopoDS_Shape& Vcur = itv.Value();
366 if (V.IsSame(Vcur)) {
371 rev = E.Orientation() == TopAbs_REVERSED;
372 if (Vcur.Orientation() == V.Orientation()) {
380 if (!VF.IsNull()) orient = VF.Orientation();
384 if (orient == TopAbs_FORWARD) {
385 BRep_Tool::Range(E,f,l);
386 //return (rev) ? l : f;
388 return Standard_True;
391 else if (orient == TopAbs_REVERSED) {
392 BRep_Tool::Range(E,f,l);
393 //return (rev) ? f : l;
395 return Standard_True;
400 const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
401 L = L.Predivided(V.Location());
402 if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
403 BRep_ListIteratorOfListOfPointRepresentation itpr
404 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
406 while (itpr.More()) {
407 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
408 if (pr->IsPointOnCurve(C,L)) {
409 Standard_Real p = pr->Parameter();
410 Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
412 // Closed curves RLE 16 june 94
413 if (Precision::IsNegativeInfinite(f))
415 //return pr->Parameter();//p;
417 return Standard_True;
419 if (Precision::IsPositiveInfinite(l))
421 //return pr->Parameter();//p;
423 return Standard_True;
425 gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
426 gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
427 Standard_Real tol = BRep_Tool::Tolerance(V);
428 if (Pf.Distance(Pl) < tol) {
429 if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
430 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
431 else res = l;//p = l;
437 return Standard_True;
444 // let us try with the first pcurve
445 Handle(Geom2d_Curve) PC;
446 Handle(Geom_Surface) S;
447 BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
448 L = L.Predivided(V.Location());
449 BRep_ListIteratorOfListOfPointRepresentation itpr
450 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
452 while (itpr.More()) {
453 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
454 if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
455 Standard_Real p = pr->Parameter();
456 // Closed curves RLE 16 june 94
457 if (PC->IsClosed()) {
458 if ((p == PC->FirstParameter()) ||
459 (p == PC->LastParameter())) {
460 if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
461 else p = PC->LastParameter();
466 return Standard_True;
473 //throw Standard_NoSuchObject("BRep_Tool:: no parameter on edge");
474 return Standard_False;
477 //=======================================================================
478 //function : GetEdgePoints
479 //purpose : gets the first, last and middle points of the edge
480 //=======================================================================
481 static void GetEdgePoints(const TopoDS_Edge& anEdge,
482 const TopoDS_Face& aFace,
483 gp_Pnt& fPnt, gp_Pnt& mPnt,
487 Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
488 gp_Pnt2d fPnt2d = theCurve->Value(f);
489 gp_Pnt2d lPnt2d = theCurve->Value(l);
490 gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
491 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
492 fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
493 lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
494 mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
497 //=======================================================================
498 //function : FillContours
499 //purpose : fills free boundary contours and faces connected (MapEF)
500 //=======================================================================
501 static void FillContours(const TopoDS_Shape& aShape,
502 const BRepOffset_Analyse& Analyser,
503 TopTools_IndexedDataMapOfShapeListOfShape& Contours,
504 TopTools_DataMapOfShapeShape& MapEF)
506 TopTools_ListOfShape Edges;
508 TopExp_Explorer Explo(aShape, TopAbs_FACE);
509 BRepTools_WireExplorer Wexp;
511 for (; Explo.More(); Explo.Next())
513 TopoDS_Face aFace = TopoDS::Face(Explo.Current());
514 TopoDS_Iterator itf(aFace);
515 for (; itf.More(); itf.Next())
517 TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
518 for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
520 TopoDS_Edge anEdge = Wexp.Current();
521 if (BRep_Tool::Degenerated(anEdge))
523 const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
524 if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
526 MapEF.Bind(anEdge, aFace);
527 Edges.Append(anEdge);
533 TopTools_ListIteratorOfListOfShape itl;
534 while (!Edges.IsEmpty())
536 TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
538 TopoDS_Vertex StartVertex, CurVertex;
539 TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
540 TopTools_ListOfShape aContour;
541 aContour.Append(StartEdge);
542 while (!CurVertex.IsSame(StartVertex))
543 for (itl.Initialize(Edges); itl.More(); itl.Next())
545 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
546 TopoDS_Vertex V1, V2;
547 TopExp::Vertices(anEdge, V1, V2);
548 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
550 aContour.Append(anEdge);
551 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
556 Contours.Add(StartVertex, aContour);
561 //-----------------------------------------------------------------------
563 //=======================================================================
564 //function : BRepOffset_MakeOffset
566 //=======================================================================
568 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
570 myAsDes = new BRepAlgo_AsDes();
574 //=======================================================================
575 //function : BRepOffset_MakeOffset
577 //=======================================================================
579 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape& S,
580 const Standard_Real Offset,
581 const Standard_Real Tol,
582 const BRepOffset_Mode Mode,
583 const Standard_Boolean Inter,
584 const Standard_Boolean SelfInter,
585 const GeomAbs_JoinType Join,
586 const Standard_Boolean Thickening,
587 const Standard_Boolean RemoveIntEdges)
594 mySelfInter (SelfInter),
596 myThickening (Thickening),
597 myRemoveIntEdges(RemoveIntEdges),
598 myDone (Standard_False)
600 myAsDes = new BRepAlgo_AsDes();
605 //=======================================================================
606 //function : Initialize
608 //=======================================================================
610 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape& S,
611 const Standard_Real Offset,
612 const Standard_Real Tol,
613 const BRepOffset_Mode Mode,
614 const Standard_Boolean Inter,
615 const Standard_Boolean SelfInter,
616 const GeomAbs_JoinType Join,
617 const Standard_Boolean Thickening,
618 const Standard_Boolean RemoveIntEdges)
625 mySelfInter = SelfInter;
627 myThickening = Thickening;
628 myRemoveIntEdges = RemoveIntEdges;
629 myDone = Standard_False;
630 myIsPerformSewing = Standard_False;
631 myIsPlanar = Standard_False;
636 //=======================================================================
639 //=======================================================================
641 void BRepOffset_MakeOffset::Clear()
643 myOffsetShape.Nullify();
644 myInitOffsetFace .Clear();
645 myInitOffsetEdge .Clear();
646 myImageOffset .Clear();
648 myFaceOffset .Clear();
650 myDone = Standard_False;
653 //=======================================================================
656 //=======================================================================
658 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
663 myInitOffsetFace.SetRoot (F) ;
664 myInitOffsetFace.Bind (F,F);
665 myImageOffset.SetRoot (F) ;
668 //=======================================================================
669 //function : SetOffsetOnFace
671 //=======================================================================
673 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face& F,
674 const Standard_Real Off)
676 if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
677 myFaceOffset.Bind(F,Off);
680 //=======================================================================
681 //function : RemoveCorks
683 //=======================================================================
685 static void RemoveCorks (TopoDS_Shape& S,
686 TopTools_IndexedMapOfShape& Faces)
691 //-----------------------------------------------------
692 // Construction of a shape without caps.
693 // and Orientation of caps as in shape S.
694 //-----------------------------------------------------
695 TopExp_Explorer exp(S,TopAbs_FACE);
696 for (; exp.More(); exp.Next()) {
697 const TopoDS_Shape& Cork = exp.Current();
698 if (!Faces.Contains(Cork)) {
702 Faces.RemoveKey(Cork);
703 Faces.Add(Cork); // to reset it with proper orientation.
709 DBRep::Set("myInit", SS);
714 //=======================================================================
715 //function : IsConnectedShell
717 //=======================================================================
718 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
720 BRepTools_Quilt Glue;
723 TopoDS_Shape SS = Glue.Shells();
724 TopExp_Explorer Explo( SS, TopAbs_SHELL );
727 return Standard_False;
729 return Standard_True;
733 //=======================================================================
734 //function : MakeList
736 //=======================================================================
738 static void MakeList (TopTools_ListOfShape& OffsetFaces,
739 const BRepAlgo_Image& myInitOffsetFace,
740 const TopTools_IndexedMapOfShape& myFaces)
742 TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
743 for ( ; itLOF.More(); itLOF.Next()) {
744 const TopoDS_Shape& Root = itLOF.Value();
745 if (!myFaces.Contains(Root)) {
746 if (myInitOffsetFace.HasImage(Root)) {
747 TopTools_ListIteratorOfListOfShape aItLS(myInitOffsetFace.Image(Root));
748 for (; aItLS.More(); aItLS.Next()) {
749 OffsetFaces.Append(aItLS.Value());
756 //=======================================================================
759 //=======================================================================
761 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
764 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
765 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
766 Standard_Real TolV = BRep_Tool::Tolerance(V);
767 if (TolV > Tol) Tol = TolV;
772 //=======================================================================
773 //function : MakeOffsetShape
775 //=======================================================================
777 void BRepOffset_MakeOffset::MakeOffsetShape()
779 myDone = Standard_False;
781 // check if shape consists of only planar faces
782 myIsPlanar = IsPlanar(myShape);
783 //------------------------------------------
784 // Construction of myShape without caps.
785 //------------------------------------------
786 if(!myFaces.IsEmpty())
788 RemoveCorks (myShape,myFaces);
791 if (!CheckInputData())
793 // There is error in input data.
794 // Check Error() method.
798 TopAbs_State Side = TopAbs_IN;
799 if (myOffset < 0.) Side = TopAbs_OUT;
804 EvalMax(myShape,myTol);
805 // There are possible second variant: analytical continuation of arcsin.
806 Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
807 Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
808 myAnalyse.Perform(myShape,TolAngle);
809 //---------------------------------------------------
810 // Construction of Offset from preanalysis.
811 //---------------------------------------------------
812 //----------------------------
813 // MaJ of SD Face - Offset
814 //----------------------------
817 if (myJoin == GeomAbs_Arc)
819 else if (myJoin == GeomAbs_Intersection)
820 BuildOffsetByInter();
824 // if (mySelfInter) SelfInter(Modif);
828 BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
829 Intersection3D (Inter);
833 TopTools_IndexedMapOfShape& Modif = Inter.TouchedFaces();
834 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
836 if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges);
837 //-------------------------------------------------------
838 // Unwinding 2D and reconstruction of modified faces
839 //----------------------------------------------------
841 //-----------------------------------------------------
842 // Reconstruction of non modified faces sharing
843 // reconstructed edges
844 //------------------------------------------------------
845 if (!Modif.IsEmpty()) MakeFaces (Modif);
850 //-------------------------
851 // Construction of shells.
852 //-------------------------
854 if (myOffsetShape.IsNull()) {
856 myDone = Standard_False;
863 //----------------------------------
864 // Remove INTERNAL edges if necessary
865 //----------------------------------
866 if (myRemoveIntEdges) {
867 RemoveInternalEdges();
869 //----------------------------------
870 // Coding of regularities.
871 //----------------------------------
873 //----------------------
874 // Creation of solids.
875 //----------------------
878 //-----------------------------
879 // MAJ Tolerance edge and Vertex
880 // ----------------------------
881 if (!myOffsetShape.IsNull()) {
882 UpdateTolerance (myOffsetShape,myFaces);
883 BRepLib::UpdateTolerances( myOffsetShape );
886 CorrectConicalFaces();
888 // Result solid should be computed in MakeOffset scope.
892 BRepBuilderAPI_Sewing aSew(myTol);
893 aSew.Add(myOffsetShape);
895 myOffsetShape = aSew.SewedShape();
898 // Offset shape expected to be really closed after sewing.
899 myOffsetShape.Closed(Standard_True);
903 myDone = Standard_True;
908 //=======================================================================
909 //function : MakeThickSolid
911 //=======================================================================
913 void BRepOffset_MakeOffset::MakeThickSolid()
915 //--------------------------------------------------------------
916 // Construction of shell parallel to shell (initial without cap).
917 //--------------------------------------------------------------
922 // Save return code and myDone state.
926 //--------------------------------------------------------------------
927 // Construction of a solid with the initial shell, parallel shell
929 //--------------------------------------------------------------------
930 if (!myFaces.IsEmpty())
935 Standard_Integer NbF = myFaces.Extent();
939 BRepTools_Quilt Glue;
940 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
943 Glue.Add (exp.Current());
945 Standard_Boolean YaResult = 0;
946 if (!myOffsetShape.IsNull())
948 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
951 Glue.Add (exp.Current().Reversed());
956 cout << "OffsetShape does not contain a FACES." << endl;
963 cout << "OffsetShape is null!" << endl;
969 myDone = Standard_False;
970 myError = BRepOffset_UnknownError;
974 myOffsetShape = Glue.Shells();
975 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
977 B.Add(Res,exp.Current());
979 Res.Closed(Standard_True);
982 // Test of Validity of the result of thick Solid
983 // more face than the initial solid.
984 Standard_Integer NbOF = 0;
985 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
991 myDone = Standard_False;
992 myError = BRepOffset_UnknownError;
997 if (myOffset > 0 ) myOffsetShape.Reverse();
999 myDone = Standard_True;
1002 //=======================================================================
1005 //=======================================================================
1007 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
1012 //=======================================================================
1015 //=======================================================================
1017 BRepOffset_Error BRepOffset_MakeOffset::Error() const
1022 //=======================================================================
1025 //=======================================================================
1027 const TopoDS_Shape& BRepOffset_MakeOffset::Shape() const
1029 return myOffsetShape;
1032 //=======================================================================
1033 //function : MakeOffsetFaces
1035 //=======================================================================
1036 void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF)
1038 Standard_Real aCurOffset;
1039 TopTools_ListOfShape aLF;
1040 TopTools_DataMapOfShapeShape ShapeTgt;
1041 TopTools_ListIteratorOfListOfShape aItLF;
1043 Standard_Boolean OffsetOutside = (myOffset > 0.);
1045 BRepLib::SortFaces(myShape, aLF);
1047 aItLF.Initialize(aLF);
1048 for (; aItLF.More(); aItLF.Next()) {
1049 const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1050 aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
1051 BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
1052 TopTools_ListOfShape Let;
1053 myAnalyse.Edges(aF,BRepOffset_Tangent,Let);
1054 TopTools_ListIteratorOfListOfShape itl(Let);
1055 for (; itl.More(); itl.Next()) {
1056 const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1057 if ( !ShapeTgt.IsBound(Cur)) {
1058 TopoDS_Shape aLocalShape = OF.Generated(Cur);
1059 const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1060 ShapeTgt.Bind(Cur,OF.Generated(Cur));
1061 TopoDS_Vertex V1,V2,OV1,OV2;
1062 TopExp::Vertices (Cur,V1,V2);
1063 TopExp::Vertices (OTE,OV1,OV2);
1064 TopTools_ListOfShape LE;
1065 if (!ShapeTgt.IsBound(V1)) {
1066 myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1067 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1068 if (LE.Extent() == LA.Extent())
1069 ShapeTgt.Bind(V1,OV1);
1071 if (!ShapeTgt.IsBound(V2)) {
1073 myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1074 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1075 if (LE.Extent() == LA.Extent())
1076 ShapeTgt.Bind(V2,OV2);
1080 theMapSF.Bind(aF,OF);
1084 //=======================================================================
1085 //function : BuildOffsetByInter
1087 //=======================================================================
1088 void BRepOffset_MakeOffset::BuildOffsetByInter()
1092 cout << " CONSTRUCTION OF OFFSETS :" << endl;
1098 TopExp_Explorer Exp, Exp2, ExpC;
1099 TopTools_ListIteratorOfListOfShape itLF;
1101 //--------------------------------------------------------
1102 // Construction of faces parallel to initial faces
1103 //--------------------------------------------------------
1104 BRepOffset_DataMapOfShapeOffset MapSF;
1105 MakeOffsetFaces(MapSF);
1106 //--------------------------------------------------------------------
1107 // MES : Map of OffsetShape -> Extended Shapes.
1108 // Build : Map of Initial SS -> OffsetShape build by Inter.
1109 // can be an edge or a compound of edges
1110 //---------------------------------------------------------------------
1111 TopTools_DataMapOfShapeShape MES;
1112 TopTools_DataMapOfShapeShape Build;
1113 TopTools_ListOfShape Failed;
1114 TopAbs_State Side = TopAbs_IN;
1115 Handle(BRepAlgo_AsDes) AsDes = new BRepAlgo_AsDes();
1117 //-------------------------------------------------------------------
1118 // Extension of faces and calculation of new edges of intersection.
1119 //-------------------------------------------------------------------
1120 Standard_Boolean ExtentContext = 0;
1121 if (myOffset > 0) ExtentContext = 1;
1123 BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1124 // Intersection between parallel faces
1125 Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1126 // Intersection with caps.
1127 Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1130 //---------------------------------------------------------------------------------
1131 // Extension of neighbor edges of new edges and intersection between neighbors.
1132 //--------------------------------------------------------------------------------
1133 Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1134 IntersectEdges(myShape, MapSF, MES, Build, AsDes, AsDes2d);
1135 //-----------------------------------------------------------
1136 // Great restriction of new edges and update of AsDes.
1137 //------------------------------------------ ----------------
1138 TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
1139 TopTools_IndexedMapOfShape NewEdges;
1140 TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
1142 //Map of edges obtained after FACE-FACE (offsetted) intersection.
1143 //Key1 is edge trimmed by intersection points with other edges;
1144 //Item is not-trimmed edge.
1145 TrimEdges(myShape, myOffset, MapSF, MES, Build, AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins);
1147 //---------------------------------
1148 // Intersection 2D on //
1149 //---------------------------------
1150 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1151 TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
1152 TopTools_ListOfShape LFE;
1153 BRepAlgo_Image IMOE;
1154 GetEnlargedFaces(myShape, MapSF, MES, aFacesOrigins, IMOE, LFE);
1156 TopTools_ListIteratorOfListOfShape itLFE(LFE);
1157 for (; itLFE.More(); itLFE.Next())
1159 const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1160 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
1161 BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV);
1163 //----------------------------------------------
1164 // Intersections 2d on caps.
1165 //----------------------------------------------
1167 for (i = 1; i <= myFaces.Extent(); i++)
1169 const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1170 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
1171 BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV);
1174 BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes);
1175 //-------------------------------
1176 // Unwinding of extended Faces.
1177 //-------------------------------
1179 TopTools_MapOfShape aMFDone;
1181 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
1182 BuildSplitsOfExtendedFaces(LFE, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf, IMOE);
1184 TopTools_ListIteratorOfListOfShape aItLF(LFE);
1185 for (; aItLF.More(); aItLF.Next()) {
1186 const TopoDS_Shape& aS = aItLF.Value();
1191 myMakeLoops.Build(LFE, AsDes, IMOE);
1195 TopTools_IndexedMapOfShape COES;
1197 //---------------------------
1198 // MAJ SD. for faces //
1199 //---------------------------
1200 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1201 const TopoDS_Shape& FI = Exp.Current();
1202 myInitOffsetFace.SetRoot(FI);
1203 TopoDS_Face OF = MapSF(FI).Face();
1204 if (MES.IsBound(OF)) {
1205 OF = TopoDS::Face(MES(OF));
1206 if (IMOE.HasImage(OF)) {
1207 const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1208 myInitOffsetFace.Bind(FI,LOFE);
1209 for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1210 const TopoDS_Shape& OFE = itLF.Value();
1211 myImageOffset.SetRoot(OFE);
1214 sprintf(name,"AF_%d",NbAF++);
1215 DBRep::Set(name,OFE);
1218 TopTools_MapOfShape View;
1219 for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1220 Exp2.More(); Exp2.Next()) {
1221 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1223 myAsDes->Add (OFE,COE);
1226 sprintf(name,"AE_%d",NbAE++);
1227 DBRep::Set(name,COE);
1232 if (!myAsDes->HasDescendant(COE)) {
1233 TopoDS_Vertex CV1,CV2;
1234 TopExp::Vertices(COE,CV1,CV2);
1235 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1236 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1243 if (aMFDone.Contains(OF)) {
1247 myInitOffsetFace.Bind(FI,OF);
1248 myImageOffset.SetRoot(OF);
1251 sprintf(name,"AF_%d",NbAF++);
1252 DBRep::Set(name,OF);
1255 const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1256 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1257 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1258 if (IMOE.HasImage(OE)) {
1259 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1260 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1261 for (; itLOE.More(); itLOE.Next()) {
1262 TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1263 const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1264 // const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1265 myAsDes->Add(OF,COE);
1268 sprintf(name,"AE_%d",NbAE++);
1269 DBRep::Set(name,COE);
1274 if (!myAsDes->HasDescendant(COE)) {
1275 TopoDS_Vertex CV1,CV2;
1276 TopExp::Vertices(COE,CV1,CV2);
1277 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1278 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1283 myAsDes->Add(OF,OE);
1286 sprintf(name,"AE_%d",NbAE++);
1287 DBRep::Set(name,OE);
1292 const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1293 myAsDes->Add(OE,LV);
1299 myInitOffsetFace.Bind(FI,OF);
1300 myImageOffset.SetRoot(OF);
1301 TopTools_MapOfShape View;
1302 for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1303 Exp2.More(); Exp2.Next()) {
1305 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1306 myAsDes->Add (OF,COE);
1309 sprintf(name,"AE_%d",NbAE++);
1310 DBRep::Set(name,COE);
1315 if (View.Add(Exp2.Current())) {
1316 if (!myAsDes->HasDescendant(COE)) {
1317 TopoDS_Vertex CV1,CV2;
1318 TopExp::Vertices(COE,CV1,CV2);
1319 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1320 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1326 // Modified by skv - Tue Mar 15 16:20:43 2005
1327 // Add methods for supporting history.
1328 TopTools_MapOfShape aMapEdges;
1330 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1331 const TopoDS_Shape& aFaceRef = Exp.Current();
1333 Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1335 for (; Exp2.More(); Exp2.Next()) {
1336 const TopoDS_Shape& anEdgeRef = Exp2.Current();
1338 if (aMapEdges.Add(anEdgeRef)) {
1339 myInitOffsetEdge.SetRoot(anEdgeRef);
1340 if (Build.IsBound(anEdgeRef)) {
1341 TopoDS_Shape aNewShape = Build(anEdgeRef);
1343 if (aNewShape.ShapeType() == TopAbs_EDGE) {
1344 if (IMOE.HasImage(aNewShape)) {
1345 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1347 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1349 myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1350 } else { // aNewShape != TopAbs_EDGE
1351 TopTools_ListOfShape aListNewEdge;
1353 for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1354 const TopoDS_Shape &aResEdge = ExpC.Current();
1356 if (IMOE.HasImage(aResEdge)) {
1357 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1358 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1360 for (; aNewEIter.More(); aNewEIter.Next())
1361 aListNewEdge.Append(aNewEIter.Value());
1363 aListNewEdge.Append(aResEdge);
1366 myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1369 else { // Free boundary.
1370 TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1372 if (MES.IsBound(aNewEdge))
1373 aNewEdge = MES(aNewEdge);
1375 if (IMOE.HasImage(aNewEdge)) {
1376 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1378 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1380 myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1385 // Modified by skv - Tue Mar 15 16:20:43 2005
1387 //---------------------------
1389 //---------------------------
1390 //TopTools_MapOfShape View;
1391 for (i = 1; i <= myFaces.Extent(); i++) {
1392 const TopoDS_Shape& Cork = myFaces(i);
1393 const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1394 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1395 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1396 if (IMOE.HasImage(OE)) {
1397 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1398 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1399 for (; itLOE.More(); itLOE.Next()) {
1400 const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1401 myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1404 sprintf(name,"AE_%d",NbAE++);
1405 DBRep::Set(name,COE);
1410 if (!myAsDes->HasDescendant(COE)) {
1411 TopoDS_Vertex CV1,CV2;
1412 TopExp::Vertices(COE,CV1,CV2);
1413 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1414 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1419 myAsDes->Add(Cork,OE);
1420 if (AsDes->HasDescendant(OE)) {
1421 myAsDes->Add(OE,AsDes->Descendant(OE));
1425 sprintf(name,"AE_%d",NbAE++);
1426 DBRep::Set(name,OE);
1435 DEBVerticesControl (COES,myAsDes);
1436 if ( ChronBuild) Clock.Show();
1440 //=======================================================================
1441 //function : BuildOffsetByArc
1443 //=======================================================================
1444 void BRepOffset_MakeOffset::BuildOffsetByArc()
1448 cout << " CONSTRUCTION OF OFFSETS :" << endl;
1454 TopExp_Explorer Exp;
1455 TopTools_ListIteratorOfListOfShape itLF;
1456 TopTools_MapOfShape Done;
1458 //--------------------------------------------------------
1459 // Construction of faces parallel to initial faces
1460 //--------------------------------------------------------
1461 BRepOffset_DataMapOfShapeOffset MapSF;
1462 MakeOffsetFaces(MapSF);
1463 //--------------------------------------------------------
1464 // Construction of tubes on edge.
1465 //--------------------------------------------------------
1466 BRepOffset_Type OT = BRepOffset_Convex;
1467 if (myOffset < 0.) OT = BRepOffset_Concave;
1469 for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
1470 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1472 const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1473 if (Anc.Extent() == 2) {
1474 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1475 if (!L.IsEmpty() && L.First().Type() == OT) {
1476 Standard_Real CurOffset = myOffset;
1477 if ( myFaceOffset.IsBound(Anc.First()))
1478 CurOffset = myFaceOffset(Anc.First());
1479 TopoDS_Shape aLocalShapeGen = MapSF(Anc.First()).Generated(E);
1480 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
1481 aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
1482 TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
1483 // TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1484 // TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1485 // find if exits tangent edges in the original shape
1486 TopoDS_Edge E1f, E1l;
1487 TopoDS_Vertex V1f, V1l;
1488 TopExp::Vertices(E,V1f,V1l);
1489 TopTools_ListOfShape TangE;
1490 myAnalyse.TangentEdges(E,V1f,TangE);
1491 // find if the pipe on the tangent edges are soon created.
1492 TopTools_ListIteratorOfListOfShape itl(TangE);
1493 Standard_Boolean Find = Standard_False;
1494 for ( ; itl.More() && !Find; itl.Next()) {
1495 if ( MapSF.IsBound(itl.Value())) {
1496 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1497 E1f = TopoDS::Edge(aLocalShape);
1498 // E1f = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1499 Find = Standard_True;
1503 myAnalyse.TangentEdges(E,V1l,TangE);
1504 // find if the pipe on the tangent edges are soon created.
1505 itl.Initialize(TangE);
1506 Find = Standard_False;
1507 for ( ; itl.More() && !Find; itl.Next()) {
1508 if ( MapSF.IsBound(itl.Value())) {
1509 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1510 E1l = TopoDS::Edge(aLocalShape);
1511 // E1l = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1512 Find = Standard_True;
1515 BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1520 // ----------------------
1522 // ----------------------
1523 TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1524 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1525 /// TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1526 myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1527 myInitOffsetEdge.Bind (E,EOn1);
1532 //--------------------------------------------------------
1533 // Construction of spheres on vertex.
1534 //--------------------------------------------------------
1536 TopTools_ListIteratorOfListOfShape it;
1538 for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
1539 const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1541 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1542 TopTools_ListOfShape LE;
1543 myAnalyse.Edges(V,OT,LE);
1545 if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1546 TopTools_ListOfShape LOE;
1547 //--------------------------------------------------------
1548 // Return connected edges on tubes.
1549 //--------------------------------------------------------
1550 for (it.Initialize(LE) ; it.More(); it.Next()) {
1551 LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1553 //----------------------
1554 // construction sphere.
1555 //-----------------------
1556 const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1557 const TopoDS_Shape& FF = LLA.First();
1558 Standard_Real CurOffset = myOffset;
1559 if ( myFaceOffset.IsBound(FF))
1560 CurOffset = myFaceOffset(FF);
1562 BRepOffset_Offset OF(V,LOE,CurOffset);
1565 //--------------------------------------------------------------
1566 // Particular processing if V is at least a free border.
1567 //-------------------------------------------------------------
1568 TopTools_ListOfShape LBF;
1569 myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
1570 if (!LBF.IsEmpty()) {
1571 Standard_Boolean First = Standard_True;
1572 for (it.Initialize(LE) ; it.More(); it.Next()) {
1574 myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1575 myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1576 First = Standard_False;
1579 myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1586 //------------------------------------------------------------
1587 // Extension of parallel faces to the context.
1588 // Extended faces are ordered in DS and removed from MapSF.
1589 //------------------------------------------------------------
1590 if (!myFaces.IsEmpty()) ToContext (MapSF);
1592 //------------------------------------------------------
1594 //------------------------------------------------------
1595 BRepOffset_Type RT = BRepOffset_Concave;
1596 if (myOffset < 0.) RT = BRepOffset_Convex;
1597 BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1598 for ( ; It.More(); It.Next()) {
1599 const TopoDS_Shape& SI = It.Key();
1600 const BRepOffset_Offset& SF = It.Value();
1601 if (SF.Status() == BRepOffset_Reversed ||
1602 SF.Status() == BRepOffset_Degenerated ) {
1603 //------------------------------------------------
1604 // Degenerated or returned faces are not stored.
1605 //------------------------------------------------
1609 const TopoDS_Face& OF = It.Value().Face();
1610 myInitOffsetFace.Bind (SI,OF);
1611 myInitOffsetFace.SetRoot (SI); // Initial<-> Offset
1612 myImageOffset.SetRoot (OF); // FaceOffset root of images
1614 if (SI.ShapeType() == TopAbs_FACE) {
1615 for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1616 Exp.More(); Exp.Next()) {
1617 //--------------------------------------------------------------------
1618 // To each face are associatedthe edges that restrict that
1619 // The edges that do not generate tubes or are not tangent
1620 // to two faces are removed.
1621 //--------------------------------------------------------------------
1622 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1623 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1624 if (!L.IsEmpty() && L.First().Type() != RT) {
1625 TopAbs_Orientation OO = E.Orientation();
1626 TopoDS_Shape aLocalShape = It.Value().Generated(E);
1627 TopoDS_Edge OE = TopoDS::Edge(aLocalShape);
1628 // TopoDS_Edge OE = TopoDS::Edge(It.Value().Generated(E));
1629 myAsDes->Add (OF,OE.Oriented(OO));
1634 for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1635 Exp.More(); Exp.Next()) {
1636 myAsDes->Add (OF,Exp.Current());
1642 if ( ChronBuild) Clock.Show();
1648 //=======================================================================
1649 //function : SelfInter
1651 //=======================================================================
1653 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
1657 cout << " AUTODEBOUCLAGE:" << endl;
1663 throw Standard_NotImplemented();
1667 //=======================================================================
1668 //function : ToContext
1670 //=======================================================================
1672 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
1674 TopTools_DataMapOfShapeShape Created;
1675 TopTools_DataMapOfShapeShape MEF;
1676 TopTools_IndexedMapOfShape FacesToBuild;
1677 TopTools_ListIteratorOfListOfShape itl;
1678 TopExp_Explorer exp;
1680 // TopAbs_State Side = TopAbs_IN;
1681 // if (myOffset < 0.) Side = TopAbs_OUT;
1683 TopAbs_State Side = TopAbs_OUT;
1687 for (i = 1; i <= myFaces.Extent(); i++) {
1688 const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
1689 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1690 exp.More(); exp.Next()) {
1691 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1692 if (!myAnalyse.HasAncestor(E)) {
1693 //----------------------------------------------------------------
1694 // The edges of context faces that are not in the initial shape
1695 // can appear in the result.
1696 //----------------------------------------------------------------
1697 //myAsDes->Add(CF,E);
1703 //--------------------------------------------------------
1704 // Determine the edges and faces reconstructed by
1706 //---------------------------------------------------------
1708 for (j = 1; j <= myFaces.Extent(); j++) {
1709 const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
1710 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1711 exp.More(); exp.Next()) {
1712 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1713 if (myAnalyse.HasAncestor(E)) {
1714 const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
1715 for (itl.Initialize(LEA); itl.More(); itl.Next()) {
1716 const BRepOffset_Offset& OF = MapSF(itl.Value());
1717 FacesToBuild.Add(itl.Value());
1718 MEF.Bind(OF.Generated(E),CF);
1721 TopExp::Vertices(E,V[0],V[1]);
1722 for (Standard_Integer i = 0; i < 2; i++) {
1723 const TopTools_ListOfShape& LVA = myAnalyse.Ancestors(V[i]);
1724 for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
1725 const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
1726 if (MapSF.IsBound(EV)) {
1727 const BRepOffset_Offset& OF = MapSF(EV);
1728 FacesToBuild.Add(EV);
1729 MEF.Bind(OF.Generated(V[i]),CF);
1736 //---------------------------
1737 // Reconstruction of faces.
1738 //---------------------------
1740 BRepOffset_Type RT = BRepOffset_Concave;
1741 if (myOffset < 0.) RT = BRepOffset_Convex;
1743 TopAbs_Orientation Or;
1745 for (j = 1; j <= FacesToBuild.Extent(); j++) {
1746 const TopoDS_Shape& S = FacesToBuild(j);
1747 BRepOffset_Offset BOF;
1749 F = TopoDS::Face(BOF.Face());
1750 BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
1755 myInitOffsetFace.Bind (S,NF);
1756 myInitOffsetFace.SetRoot (S); // Initial<-> Offset
1757 myImageOffset.SetRoot (NF);
1759 if (S.ShapeType() == TopAbs_FACE) {
1760 for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1761 exp.More(); exp.Next()) {
1763 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
1764 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1765 OE = BOF.Generated(E);
1766 Or = E.Orientation();
1768 if (!L.IsEmpty() && L.First().Type() != RT) {
1769 if (Created.IsBound(OE)) {
1771 if (NE.Orientation() == TopAbs_REVERSED)
1772 NE.Orientation(TopAbs::Reverse(Or));
1775 myAsDes->Add(NF,NE);
1778 myAsDes->Add(NF,OE);
1784 //------------------
1786 //---------------------
1787 for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1788 exp.More(); exp.Next()) {
1789 myAsDes->Add (NF,exp.Current());
1795 //------------------
1797 //------------------
1798 TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
1799 for (itc.Initialize(Created); itc.More(); itc.Next()) {
1802 if (myInitOffsetEdge.IsImage(OE)) {
1803 TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
1804 Or = myInitOffsetEdge.Image(E).First().Orientation();
1805 if (NE.Orientation() == TopAbs_REVERSED)
1806 NE.Orientation(TopAbs::Reverse(Or));
1809 myInitOffsetEdge.Remove(OE);
1810 myInitOffsetEdge.Bind(E,NE);
1816 //=======================================================================
1817 //function : UpdateFaceOffset
1819 //=======================================================================
1821 void BRepOffset_MakeOffset::UpdateFaceOffset()
1823 TopTools_MapOfShape M;
1824 TopTools_DataMapOfShapeReal CopiedMap;
1825 CopiedMap.Assign(myFaceOffset);
1826 TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
1828 BRepOffset_Type RT = BRepOffset_Convex;
1829 if (myOffset < 0.) RT = BRepOffset_Concave;
1831 for ( ; it.More(); it.Next()) {
1832 const TopoDS_Face& F = TopoDS::Face(it.Key());
1833 Standard_Real CurOffset = CopiedMap(F);
1834 if ( !M.Add(F)) continue;
1837 Build.MakeCompound(Co);
1838 TopTools_MapOfShape Dummy;
1840 if (myJoin == GeomAbs_Arc)
1841 myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
1843 myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
1845 TopExp_Explorer exp(Co,TopAbs_FACE);
1846 for (; exp.More(); exp.Next()) {
1847 const TopoDS_Face& FF = TopoDS::Face(exp.Current());
1848 if ( !M.Add(FF)) continue;
1849 if ( myFaceOffset.IsBound(FF))
1850 myFaceOffset.UnBind(FF);
1851 myFaceOffset.Bind(FF,CurOffset);
1856 //=======================================================================
1857 //function : CorrectConicalFaces
1859 //=======================================================================
1861 void BRepOffset_MakeOffset::CorrectConicalFaces()
1863 if(myOffsetShape.IsNull())
1868 TopTools_SequenceOfShape Cones;
1869 TopTools_SequenceOfShape Circs;
1870 TopTools_SequenceOfShape Seams;
1871 Standard_Real TolApex = 1.e-5;
1875 TopTools_DataMapOfShapeListOfShape FacesOfCone;
1876 //TopTools_DataMapOfShapeShape DegEdges;
1877 TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
1878 if (myJoin == GeomAbs_Arc)
1880 for (; Explo.More(); Explo.Next())
1882 TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
1883 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
1884 //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
1885 //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
1887 TopTools_IndexedMapOfShape Emap;
1888 TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
1889 for (i = 1; i <= Emap.Extent(); i++)
1891 TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
1892 //Standard_Real f, l;
1893 //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
1894 //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
1895 if (BRep_Tool::Degenerated(anEdge))
1897 //Check if anEdge is a really degenerated edge or not
1898 BRepAdaptor_Curve BACurve(anEdge, aFace);
1899 gp_Pnt Pfirst, Plast, Pmid;
1900 Pfirst = BACurve.Value(BACurve.FirstParameter());
1901 Plast = BACurve.Value(BACurve.LastParameter());
1902 Pmid = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
1903 if (Pfirst.Distance(Plast) <= TolApex &&
1904 Pfirst.Distance(Pmid) <= TolApex)
1906 //Cones.Append( aFace );
1907 //Circs.Append( anEdge );
1908 //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
1909 TopoDS_Edge OrEdge =
1910 TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
1911 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1912 if ( FacesOfCone.IsBound(VF) )
1914 //add a face to the existing list
1915 TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
1916 aFaces.Append (aFace);
1917 //DegEdges.Bind(aFace, anEdge);
1921 //the vertex is not in the map => create a new key and items
1922 TopTools_ListOfShape aFaces;
1923 aFaces.Append (aFace);
1924 FacesOfCone.Bind(VF, aFaces);
1925 //DegEdges.Bind(aFace, anEdge);
1928 } //for (i = 1; i <= Emap.Extent(); i++)
1929 } //for (; fexp.More(); fexp.Next())
1930 } //if (myJoin == GeomAbs_Arc)
1932 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
1935 Standard_Boolean IsModified = Standard_False;
1936 for (; Cone.More(); Cone.Next() ) {
1937 gp_Sphere theSphere;
1938 Handle(Geom_SphericalSurface) aSphSurf;
1939 TopoDS_Wire SphereWire;
1940 BB.MakeWire(SphereWire);
1941 TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
1942 const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
1943 TopTools_ListIteratorOfListOfShape itFaces(Faces);
1944 Standard_Boolean isFirstFace = Standard_True;
1946 TopoDS_Vertex theFirstVertex, CurFirstVertex;
1947 for (; itFaces.More(); itFaces.Next())
1949 TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
1950 TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
1951 for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
1953 DegEdge = TopoDS::Edge(Explo.Current());
1954 if (BRep_Tool::Degenerated(DegEdge))
1956 TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
1957 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
1958 if (VF.IsSame(anApex))
1962 TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
1963 TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
1964 BB.Degenerated(CurEdge, Standard_False);
1965 BB.SameRange(CurEdge, Standard_False);
1966 BB.SameParameter(CurEdge, Standard_False);
1967 gp_Pnt fPnt, lPnt, mPnt;
1968 GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
1970 BRep_Tool::Range(CurEdge, f, l);
1973 gp_Vec aVec1(fPnt, mPnt);
1974 gp_Vec aVec2(fPnt, lPnt);
1975 gp_Vec aNorm = aVec1.Crossed(aVec2);
1976 gp_Pnt theApex = BRep_Tool::Pnt(anApex);
1977 gp_Vec ApexToFpnt(theApex, fPnt);
1978 gp_Vec Ydir = aNorm ^ ApexToFpnt;
1979 gp_Vec Xdir = Ydir ^ aNorm;
1980 //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
1981 gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
1982 theSphere.SetRadius(myOffset);
1983 theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
1984 aSphSurf = new Geom_SphericalSurface(theSphere);
1986 theFirstVertex = BRepLib_MakeVertex(fPnt);
1987 CurFirstVertex = theFirstVertex;
1990 TopoDS_Vertex v1, v2, FirstVert, EndVert;
1991 TopExp::Vertices(CurEdge, v1, v2);
1992 FirstVert = CurFirstVertex;
1993 if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
1994 EndVert = theFirstVertex;
1996 EndVert = BRepLib_MakeVertex(lPnt);
1997 CurEdge.Free( Standard_True );
1998 BB.Remove(CurEdge, v1);
1999 BB.Remove(CurEdge, v2);
2000 BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
2001 BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
2002 //take the curve from sphere an put it to the edge
2003 Standard_Real Uf, Vf, Ul, Vl;
2004 ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
2005 ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
2006 if (Abs(Ul) <= Precision::Confusion())
2008 Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
2012 gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
2013 if (Abs(Uf - f) > Precision::Confusion())
2015 aCircle.Rotate(aCircle.Axis(), f - Uf);
2016 aCurv = new Geom_Circle(aCircle);
2020 Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
2021 BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
2022 BB.Range(CurEdge, Uf, Ul, Standard_True);
2023 Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
2024 Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
2025 BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
2026 BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2027 BRepLib::SameParameter(CurEdge);
2028 BB.Add(SphereWire, CurEdge);
2029 //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2030 BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2031 gp_Pnt2d fPnt2d, lPnt2d;
2032 fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2033 lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2034 TopTools_IndexedMapOfShape Emap;
2035 TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2037 Standard_Integer j = 0, k;
2038 for (k = 1; k <= Emap.Extent(); k++)
2040 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2041 if (!BRep_Tool::Degenerated(anEdge))
2043 TopoDS_Vertex V1, V2;
2044 TopExp::Vertices(anEdge, V1, V2);
2045 if (V1.IsSame(v1) || V2.IsSame(v1))
2049 for (k = 0; k < j; k++)
2051 TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2052 TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2053 Eforward.Free(Standard_True);
2054 TopoDS_Vertex V1, V2;
2055 TopExp::Vertices( Eforward, V1, V2 );
2056 BRepAdaptor_Curve2d EEc( Eforward, aFace );
2057 gp_Pnt2d p2d1, p2d2;
2058 p2d1 = EEc.Value(EEc.FirstParameter());
2059 p2d2 = EEc.Value(EEc.LastParameter());
2062 TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2063 FirstVert : EndVert;
2064 BB.Remove( Eforward, V1 );
2065 BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2069 TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2070 FirstVert : EndVert;
2071 BB.Remove( Eforward, V2 );
2072 BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2076 isFirstFace = Standard_False;
2077 CurFirstVertex = EndVert;
2079 //Building new spherical face
2080 Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2081 gp_Pnt2d p2d1, p2d2;
2082 TopTools_ListOfShape EdgesOfWire;
2083 TopoDS_Iterator itw(SphereWire);
2084 for (; itw.More(); itw.Next())
2086 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2087 EdgesOfWire.Append(anEdge);
2089 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2090 p2d1 = aC2d->Value(f);
2091 p2d2 = aC2d->Value(l);
2092 if (p2d1.X() < Ufirst)
2094 if (p2d1.X() > Ulast)
2096 if (p2d2.X() < Ufirst)
2098 if (p2d2.X() > Ulast)
2101 TopTools_ListOfShape NewEdges;
2102 TopoDS_Edge FirstEdge;
2103 TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2104 for (; itl.More(); itl.Next())
2106 FirstEdge = TopoDS::Edge(itl.Value());
2108 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2109 p2d1 = aC2d->Value(f);
2110 p2d2 = aC2d->Value(l);
2111 if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2113 EdgesOfWire.Remove(itl);
2117 NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
2118 TopoDS_Vertex Vf1, CurVertex;
2119 TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2120 itl.Initialize(EdgesOfWire);
2123 const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2124 TopoDS_Vertex V1, V2;
2125 TopExp::Vertices(anEdge, V1, V2);
2126 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2128 NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
2129 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2130 EdgesOfWire.Remove(itl);
2136 Standard_Real Vfirst, Vlast;
2139 Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2143 Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2145 TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2146 TopoDS_Edge OldEdge, DegEdge;
2147 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2149 DegEdge = TopoDS::Edge(Explo.Current());
2150 if (BRep_Tool::Degenerated(DegEdge))
2153 TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
2154 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2156 OldEdge = TopoDS::Edge(Explo.Current());
2157 TopoDS_Vertex V1, V2;
2158 TopExp::Vertices(OldEdge, V1, V2);
2159 if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
2162 TopoDS_Vertex V1, V2;
2163 TopExp::Vertices(OldEdge, V1, V2);
2164 TopTools_ListOfShape LV1, LV2;
2165 LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
2166 LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
2167 BRepTools_Substitution theSubstitutor;
2168 theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
2170 theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
2171 theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
2172 theSubstitutor.Build(NewSphericalFace);
2173 if (theSubstitutor.IsCopied(NewSphericalFace))
2175 const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2176 NewSphericalFace = TopoDS::Face(listSh.First());
2179 //Adding NewSphericalFace to the shell
2180 Explo.Init( myOffsetShape, TopAbs_SHELL );
2181 TopoDS_Shape theShell = Explo.Current();
2182 theShell.Free( Standard_True );
2183 BB.Add( theShell, NewSphericalFace );
2184 IsModified = Standard_True;
2185 if(!theShell.Closed())
2187 if(BRep_Tool::IsClosed(theShell))
2189 theShell.Closed(Standard_True);
2199 if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2201 //Explo.Init( myOffsetShape, TopAbs_SHELL );
2203 //if (Explo.More()) {
2204 // TopoDS_Shape theShell = Explo.Current();
2205 // theShell.Closed( Standard_True );
2208 Standard_Integer NbShell = 0;
2211 BB.MakeCompound (NC);
2215 Sol.Closed(Standard_True);
2216 for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2217 TopoDS_Shell Sh = TopoDS::Shell(Explo.Current());
2218 //if (myThickening && myOffset > 0.)
2232 TopoDS_Iterator anIt(Sol);
2233 Standard_Boolean SolIsNull = !anIt.More();
2237 Standard_Integer nbs = 0;
2238 while(anIt.More()) {anIt.Next(); ++nbs;}
2241 BRepCheck_Analyzer aCheck(Sol, Standard_False);
2242 if(!aCheck.IsValid())
2244 TopTools_ListOfShape aSolList;
2245 CorrectSolid(Sol, aSolList);
2246 if(!aSolList.IsEmpty())
2249 TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
2250 for(; aSLIt.More(); aSLIt.Next())
2252 BB.Add(NC, aSLIt.Value());
2254 SolIsNull = Standard_True;
2260 anIt.Initialize(NC);
2261 Standard_Boolean NCIsNull = !anIt.More();
2262 if((!SolIsNull) && (!NCIsNull))
2267 else if(SolIsNull && (!NCIsNull))
2278 else if((!SolIsNull) && NCIsNull)
2280 myOffsetShape = Sol;
2290 //=======================================================================
2291 //function : Intersection3D
2293 //=======================================================================
2295 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2299 cout << " INTERSECTION 3D:" << endl;
2305 // In the Complete Intersection mode, implemented currently for planar
2306 // solids only, there is no need to intersect the faces here.
2307 // This intersection will be performed in the method BuildShellsCompleteInter
2308 // where the special treatment is applied to produced faces.
2310 // Make sure to match the parameters in which the method
2311 // BuildShellsCompleteInter is called.
2312 if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
2313 !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
2317 TopTools_ListOfShape OffsetFaces; // list of faces // created.
2318 MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2320 if (!myFaces.IsEmpty()) {
2321 Standard_Boolean InSide = (myOffset < 0.); // Temporary
2322 // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2323 // between the cap and the part.
2325 if (myJoin == GeomAbs_Arc)
2326 Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2332 Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2333 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2334 if (myJoin == GeomAbs_Intersection) {
2335 BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2339 //--------------------------------
2340 // Only between neighbor faces.
2341 //--------------------------------
2342 Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2345 if ( ChronBuild) Clock.Show();
2349 //=======================================================================
2350 //function : Intersection2D
2352 //=======================================================================
2354 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
2355 const TopTools_IndexedMapOfShape& NewEdges)
2359 cout << " INTERSECTION 2D:" << endl;
2364 //--------------------------------------------------------
2365 // calculate intersections2d on faces concerned by
2367 //---------------------------------------------------------
2368 //TopTools_MapIteratorOfMapOfShape it(Modif);
2369 //-----------------------------------------------
2370 // Intersection of edges 2 by 2.
2371 //-----------------------------------------------
2372 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2374 for (i = 1; i <= Modif.Extent(); i++) {
2375 const TopoDS_Face& F = TopoDS::Face(Modif(i));
2376 BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV);
2379 BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
2383 DEBVerticesControl (NewEdges,myAsDes);
2385 if ( ChronBuild) Clock.Show();
2390 //=======================================================================
2391 //function : MakeLoops
2393 //=======================================================================
2395 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
2399 cout << " DEBOUCLAGE 2D:" << endl;
2404 //TopTools_MapIteratorOfMapOfShape it(Modif);
2405 TopTools_ListOfShape LF,LC;
2406 //-----------------------------------------
2407 // unwinding of faces // modified.
2408 //-----------------------------------------
2410 for (i = 1; i <= Modif.Extent(); i++) {
2411 if (!myFaces.Contains(Modif(i)))
2412 LF.Append(Modif(i));
2415 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2416 BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset);
2419 myMakeLoops.Build(LF,myAsDes,myImageOffset);
2422 //-----------------------------------------
2423 // unwinding of caps.
2424 //-----------------------------------------
2425 for (i = 1; i <= myFaces.Extent(); i++)
2426 LC.Append(myFaces(i));
2428 Standard_Boolean InSide = 1;
2429 if (myOffset > 0 ) InSide = 0;
2430 myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2433 if ( ChronBuild) Clock.Show();
2437 //=======================================================================
2438 //function : MakeFaces
2439 //purpose : Reconstruction of topologically unchanged faces that
2440 // share edges that were reconstructed.
2441 //=======================================================================
2443 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
2447 cout << " RECONSTRUCTION OF FACES:" << endl;
2452 TopTools_ListIteratorOfListOfShape itr;
2453 const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2454 TopTools_ListOfShape LOF;
2455 //----------------------------------
2456 // Loop on all faces //.
2457 //----------------------------------
2458 for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2459 TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2460 if (!myImageOffset.HasImage(F)) {
2465 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2466 BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset);
2469 myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
2473 if ( ChronBuild) Clock.Show();
2477 //=======================================================================
2478 //function : UpdateInitOffset
2479 //purpose : Update and cleaning of myInitOffset
2480 //=======================================================================
2481 static void UpdateInitOffset (BRepAlgo_Image& myInitOffset,
2482 BRepAlgo_Image& myImageOffset,
2483 const TopoDS_Shape& myOffsetShape,
2484 const TopAbs_ShapeEnum &theShapeType) // skv
2486 BRepAlgo_Image NIOF;
2487 const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2488 TopTools_ListIteratorOfListOfShape it(Roots);
2489 for (; it.More(); it.Next()) {
2490 NIOF.SetRoot (it.Value());
2492 for (it.Initialize(Roots); it.More(); it.Next()) {
2493 const TopoDS_Shape& SI = it.Value();
2494 TopTools_ListOfShape LI;
2495 TopTools_ListOfShape L1;
2496 myInitOffset.LastImage(SI,L1);
2497 TopTools_ListIteratorOfListOfShape itL1(L1);
2498 for (; itL1.More(); itL1.Next()) {
2499 const TopoDS_Shape& O1 = itL1.Value();
2500 TopTools_ListOfShape L2;
2501 myImageOffset.LastImage(O1,L2);
2506 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
2507 // Supporting history.
2508 // NIOF.Filter(myOffsetShape,TopAbs_FACE);
2509 NIOF.Filter(myOffsetShape, theShapeType);
2510 // Modified by skv - Mon Apr 4 18:17:27 2005 End
2511 myInitOffset = NIOF;
2514 //=======================================================================
2515 //function : MakeMissingWalls
2517 //=======================================================================
2518 void BRepOffset_MakeOffset::MakeMissingWalls ()
2520 TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2521 TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2522 Standard_Real OffsetVal = Abs(myOffset);
2524 FillContours(myShape, myAnalyse, Contours, MapEF);
2526 for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++)
2528 TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
2529 TopoDS_Edge StartEdge;
2530 const TopTools_ListOfShape& aContour = Contours(ic);
2531 TopTools_ListIteratorOfListOfShape itl(aContour);
2532 Standard_Boolean FirstStep = Standard_True;
2533 TopoDS_Edge PrevEdge;
2534 TopoDS_Vertex PrevVertex = StartVertex;
2535 Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
2536 for (; itl.More(); itl.Next())
2538 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2539 TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
2541 // Check for offset existence.
2542 if (!myInitOffsetEdge.HasImage(anEdge))
2545 // Check for existence of two different vertices.
2546 TopTools_ListOfShape LOE, LOE2;
2547 myInitOffsetEdge.LastImage( anEdge, LOE );
2548 myImageOffset.LastImage( LOE.Last(), LOE2 );
2549 TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2550 TopoDS_Vertex V1, V2, V3, V4;
2551 TopExp::Vertices(OE, V4, V3);
2552 TopExp::Vertices(anEdge, V1, V2);
2553 Standard_Real aF, aL;
2554 const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
2556 (!aC->IsClosed() && !aC->IsPeriodic()))
2558 gp_Pnt aPntF = BRep_Tool::Pnt(V1);
2559 gp_Pnt aPntL = BRep_Tool::Pnt(V2);
2560 Standard_Real aDistE = aPntF.SquareDistance(aPntL);
2561 if ( aDistE < Precision::SquareConfusion())
2563 // Bad case: non closed, but vertexes mapped to same 3d point.
2567 Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
2568 if (aDistE < anEdgeTol)
2570 // Potential problems not detected via checkshape.
2571 gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
2572 gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
2573 if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
2575 // To avoid computation of complex analytical continuation of Sin / ArcSin.
2576 Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
2577 Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
2578 Standard_Real aCurrentAngle = gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
2579 if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
2580 Abs (aCurrentAngle) > aMaxAngle)
2582 // anEdge not collinear to offset edge.
2583 isBuildFromScratch = Standard_True;
2584 myIsPerformSewing = Standard_True;
2591 Standard_Boolean ToReverse = Standard_False;
2592 if (!V1.IsSame(PrevVertex))
2594 TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
2595 aVtx = V3; V3 = V4; V4 = aVtx;
2596 ToReverse = Standard_True;
2599 OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
2601 Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
2602 if (FirstStep || isBuildFromScratch)
2604 E4 = BRepLib_MakeEdge( V1, V4 );
2610 if (V2.IsSame(StartVertex) && !ArcOnV2)
2613 E3 = BRepLib_MakeEdge( V2, V3 );
2616 if (isBuildFromScratch)
2622 TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
2623 const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
2624 Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
2625 Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
2627 TopoDS_Wire theWire;
2628 BB.MakeWire(theWire);
2631 BB.Add(theWire, anEdge.Reversed());
2632 BB.Add(theWire, E3.Reversed());
2633 BB.Add(theWire, OE.Reversed());
2634 BB.Add(theWire, E4.Reversed());
2638 BB.Add(theWire, anEdge);
2639 BB.Add(theWire, E3);
2640 BB.Add(theWire, OE);
2641 BB.Add(theWire, E4);
2644 BRepLib::BuildCurves3d( theWire, myTol );
2645 theWire.Closed(Standard_True);
2646 TopoDS_Face NewFace;
2647 Handle(Geom_Surface) theSurf;
2648 BRepAdaptor_Curve BAcurve(anEdge);
2649 BRepAdaptor_Curve BAcurveOE(OE);
2650 Standard_Real fpar = BAcurve.FirstParameter();
2651 Standard_Real lpar = BAcurve.LastParameter();
2652 gp_Pnt PonE = BAcurve.Value(fpar);
2653 gp_Pnt PonOE = BAcurveOE.Value(fpar);
2654 gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
2655 Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
2656 Standard_Boolean IsPlanar = Standard_False;
2657 if (BAcurve.GetType() == GeomAbs_Circle &&
2658 BAcurveOE.GetType() == GeomAbs_Circle)
2660 gp_Circ aCirc = BAcurve.Circle();
2661 gp_Circ aCircOE = BAcurveOE.Circle();
2662 gp_Lin anAxisLine(aCirc.Axis());
2663 gp_Dir CircAxisDir = aCirc.Axis().Direction();
2664 if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
2665 anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
2666 { //cylinder, plane or cone
2667 if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
2668 theSurf = GC_MakeCylindricalSurface(aCirc).Value();
2669 else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
2670 IsPlanar = Standard_True;
2672 gp_Pnt PonEL = BAcurve.Value(lpar);
2673 if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
2674 Standard_Boolean bIsHole;
2675 TopoDS_Edge aE1, aE2;
2676 TopoDS_Wire aW1, aW2;
2677 Handle(Geom_Plane) aPL;
2678 IntTools_FClass2d aClsf;
2680 if (aCirc.Radius()>aCircOE.Radius()) {
2693 aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
2694 for (Standard_Integer i = 0; i < 2; ++i) {
2695 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
2696 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
2699 BB.MakeFace(aFace, aPL, Precision::Confusion());
2701 aClsf.Init(aFace, Precision::Confusion());
2702 bIsHole=aClsf.IsHole();
2703 if ((bIsHole && !i) || (!bIsHole && i)) {
2706 BB.Add(aW, aE.Reversed());
2710 BB.MakeFace(NewFace, aPL, Precision::Confusion());
2711 BB.Add(NewFace, aW1);
2712 BB.Add(NewFace, aW2);
2717 gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
2718 aCirc.Radius(), aCircOE.Radius());
2719 gp_Ax3 theAx3(aCirc.Position());
2720 if (CircAxisDir * theCone.Axis().Direction() < 0.)
2723 CircAxisDir.Reverse();
2725 theCone.SetPosition(theAx3);
2726 theSurf = new Geom_ConicalSurface(theCone);
2729 TopLoc_Location Loc;
2730 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
2731 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2732 Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
2733 OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
2734 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2735 aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
2736 aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
2740 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2743 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
2745 BB.MakeWire(theWire);
2746 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
2747 BB.Add(theWire, E4);
2748 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
2749 BB.Add(theWire, E3);
2750 theWire.Closed(Standard_True);
2755 BB.SameParameter(E3, Standard_False);
2756 BB.SameRange(E3, Standard_False);
2757 BB.SameParameter(E4, Standard_False);
2758 BB.SameRange(E4, Standard_False);
2759 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
2760 BB.Range(E3, theSurf, Loc, 0., OffsetVal);
2761 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2762 BB.Range(E4, theSurf, Loc, 0., OffsetVal);
2764 NewFace = BRepLib_MakeFace(theSurf, theWire);
2766 } //cylinder or cone
2767 } //if both edges are arcs of circles
2768 if (NewFace.IsNull())
2770 BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
2771 if (MF.Error() == BRepLib_FaceDone)
2773 NewFace = MF.Face();
2774 IsPlanar = Standard_True;
2776 else //Extrusion (by thrusections)
2778 Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
2779 Handle(Geom_TrimmedCurve) TrEdgeCurve =
2780 new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
2781 Standard_Real fparOE, lparOE;
2782 Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
2783 Handle(Geom_TrimmedCurve) TrOffsetCurve =
2784 new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
2785 GeomFill_Generator ThrusecGenerator;
2786 ThrusecGenerator.AddCurve( TrEdgeCurve );
2787 ThrusecGenerator.AddCurve( TrOffsetCurve );
2788 ThrusecGenerator.Perform( Precision::PConfusion() );
2789 theSurf = ThrusecGenerator.Surface();
2790 //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
2791 Standard_Real Uf, Ul, Vf, Vl;
2792 theSurf->Bounds(Uf, Ul, Vf, Vl);
2793 TopLoc_Location Loc;
2794 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
2795 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
2796 OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
2797 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
2798 Standard_Real UonV1 = (ToReverse)? Ul : Uf;
2799 Standard_Real UonV2 = (ToReverse)? Uf : Ul;
2800 aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
2801 aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
2804 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
2805 Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
2806 BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
2807 BB.Range(E3, Vf, Vl);
2811 BB.SameParameter(E3, Standard_False);
2812 BB.SameRange(E3, Standard_False);
2813 BB.SameParameter(E4, Standard_False);
2814 BB.SameRange(E4, Standard_False);
2815 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
2816 BB.Range(E3, theSurf, Loc, Vf, Vl);
2817 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
2818 BB.Range(E4, theSurf, Loc, Vf, Vl);
2819 Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
2820 BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
2821 BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
2822 Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
2823 BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
2824 BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
2826 NewFace = BRepLib_MakeFace(theSurf, theWire);
2831 Standard_Real fparOE = BAcurveOE.FirstParameter();
2832 Standard_Real lparOE = BAcurveOE.LastParameter();
2833 TopLoc_Location Loc;
2834 if (Abs(fpar - fparOE) > Precision::Confusion())
2836 const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
2837 gp_Pnt2d fp2d = EdgeLine2d->Value(fpar);
2838 gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
2839 aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
2840 Handle(Geom_Curve) aCurve;
2841 Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
2842 Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
2843 GeomAdaptor_Surface GAsurf( theSurf );
2844 Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
2845 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2846 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2847 Standard_Real max_deviation = 0., average_deviation;
2848 GeomLib::BuildCurve3d(Precision::Confusion(),
2849 ConS, FirstPar, LastPar,
2850 aCurve, max_deviation, average_deviation);
2851 BB.UpdateEdge( anE4, aCurve, max_deviation );
2852 BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
2853 BB.Range( anE4, FirstPar, LastPar );
2855 if (Abs(lpar - lparOE) > Precision::Confusion())
2857 const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
2858 gp_Pnt2d lp2d = EdgeLine2d->Value(lpar);
2859 gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
2860 aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
2861 Handle(Geom_Curve) aCurve;
2862 Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
2863 Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
2864 GeomAdaptor_Surface GAsurf( theSurf );
2865 Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
2866 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
2867 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
2868 Standard_Real max_deviation = 0., average_deviation;
2869 GeomLib::BuildCurve3d(Precision::Confusion(),
2870 ConS, FirstPar, LastPar,
2871 aCurve, max_deviation, average_deviation);
2872 BB.UpdateEdge( anE3, aCurve, max_deviation );
2873 BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
2874 BB.Range( anE3, FirstPar, LastPar );
2877 BRepLib::SameParameter(NewFace);
2878 BRepTools::Update(NewFace);
2880 TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
2881 TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
2882 if (OrInNewFace != TopAbs::Reverse(anOr))
2885 myWalls.Append(NewFace);
2888 TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
2889 TopoDS_Vertex arcV1, arcV2;
2890 TopExp::Vertices(anArc, arcV1, arcV2);
2891 Standard_Boolean ArcReverse = Standard_False;
2892 if (!arcV1.IsSame(V3))
2894 TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
2895 ArcReverse = Standard_True;
2897 TopoDS_Edge EA1, EA2;
2898 //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
2903 //////////////////////////////////////////////////////
2904 if (V2.IsSame(StartVertex))
2907 EA2 = BRepLib_MakeEdge( V2, arcV2 );
2908 anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
2909 if (EA1.Orientation() == TopAbs_REVERSED)
2911 EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
2912 TopoDS_Wire arcWire;
2913 BB.MakeWire(arcWire);
2914 BB.Add(arcWire, EA1);
2915 BB.Add(arcWire, anArc);
2916 BB.Add(arcWire, EA2);
2917 BRepLib::BuildCurves3d( arcWire, myTol );
2918 arcWire.Closed(Standard_True);
2919 TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
2920 BRepTools::Update(arcFace);
2921 myWalls.Append(arcFace);
2922 TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
2923 const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
2929 if (isBuildFromScratch)
2931 PrevEdge = TopoDS::Edge(E4);
2933 isBuildFromScratch = Standard_False;
2941 FirstStep = Standard_False;
2946 //=======================================================================
2947 //function : MakeShells
2949 //=======================================================================
2951 void BRepOffset_MakeOffset::MakeShells ()
2955 cout << " RECONSTRUCTION OF SHELLS:" << endl;
2961 // Prepare list of splits of the offset faces to make the shells
2962 TopTools_ListOfShape aLSF;
2963 const TopTools_ListOfShape& R = myImageOffset.Roots();
2964 TopTools_ListIteratorOfListOfShape it(R);
2966 for (; it.More(); it.Next()) {
2967 TopoDS_Shape aF = it.Value();
2968 if (myThickening) //offsetted faces must change their orientations
2971 TopTools_ListOfShape Image;
2972 myImageOffset.LastImage(aF,Image);
2973 TopTools_ListIteratorOfListOfShape it2(Image);
2974 for (; it2.More(); it2.Next()) {
2975 const TopoDS_Shape& aFIm = it2.Value();
2981 TopExp_Explorer Explo(myShape, TopAbs_FACE);
2982 for (; Explo.More(); Explo.Next()) {
2983 const TopoDS_Shape& aF = Explo.Current();
2987 it.Initialize(myWalls);
2988 for (; it.More(); it.Next()) {
2989 const TopoDS_Shape& aF = it.Value();
2994 if (aLSF.IsEmpty()) {
2998 Standard_Boolean bDone = Standard_False;
2999 if ((myJoin == GeomAbs_Intersection) && myInter &&
3000 !myThickening && myFaces.IsEmpty() &&
3001 IsSolid(myShape) && myIsPlanar) {
3003 TopoDS_Shape aShells;
3004 bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells);
3006 myOffsetShape = aShells;
3011 BRepTools_Quilt Glue;
3012 TopTools_ListIteratorOfListOfShape aItLS(aLSF);
3013 for (; aItLS.More(); aItLS.Next()) {
3014 Glue.Add(aItLS.Value());
3016 myOffsetShape = Glue.Shells();
3019 //Set correct value for closed flag
3020 TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3021 for(; Explo.More(); Explo.Next())
3023 TopoDS_Shape aS = Explo.Current();
3026 if(BRep_Tool::IsClosed(aS))
3028 aS.Closed(Standard_True);
3034 //=======================================================================
3035 //function : MakeSolid
3037 //=======================================================================
3039 void BRepOffset_MakeOffset::MakeSolid ()
3041 if (myOffsetShape.IsNull()) return;
3043 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
3044 // Supporting history.
3045 UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3046 UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3047 // Modified by skv - Mon Apr 4 18:17:27 2005 End
3048 TopExp_Explorer exp;
3050 Standard_Integer NbShell = 0;
3053 B.MakeCompound (NC);
3057 Sol.Closed(Standard_True);
3058 Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3059 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3060 TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3061 if (myThickening && myOffset > 0.)
3064 if (Sh.Closed() && aMakeSolid) {
3075 TopoDS_Iterator anIt(Sol);
3076 Standard_Boolean SolIsNull = !anIt.More();
3080 Standard_Integer nbs = 0;
3081 while(anIt.More()) {anIt.Next(); ++nbs;}
3084 BRepCheck_Analyzer aCheck(Sol, Standard_False);
3085 if(!aCheck.IsValid())
3087 TopTools_ListOfShape aSolList;
3088 CorrectSolid(Sol, aSolList);
3089 if(!aSolList.IsEmpty())
3092 TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
3093 for(; aSLIt.More(); aSLIt.Next())
3095 B.Add(NC, aSLIt.Value());
3097 SolIsNull = Standard_True;
3102 anIt.Initialize(NC);
3103 Standard_Boolean NCIsNull = !anIt.More();
3104 if((!SolIsNull) && (!NCIsNull))
3109 else if(SolIsNull && (!NCIsNull))
3120 else if((!SolIsNull) && NCIsNull)
3122 myOffsetShape = Sol;
3130 //=======================================================================
3131 //function : SelectShells
3133 //=======================================================================
3135 void BRepOffset_MakeOffset::SelectShells ()
3137 TopTools_MapOfShape FreeEdges;
3138 TopExp_Explorer exp(myShape,TopAbs_EDGE);
3139 //-------------------------------------------------------------
3140 // FreeEdges all edges that can have free border in the
3142 // 1 - free borders of myShape .
3143 //-------------------------------------------------------------
3144 for ( ; exp.More(); exp.Next()) {
3145 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3146 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3147 if (LA.Extent() < 2) {
3148 if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
3153 // myShape has free borders and there are no caps
3155 if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3157 myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3160 //=======================================================================
3161 //function : OffsetFacesFromShapes
3163 //=======================================================================
3165 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3167 return myInitOffsetFace;
3170 // Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3172 //=======================================================================
3173 //function : GetJoinType
3174 //purpose : Query offset join type.
3175 //=======================================================================
3177 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3182 //=======================================================================
3183 //function : OffsetEdgesFromShapes
3185 //=======================================================================
3187 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3189 return myInitOffsetEdge;
3192 // Modified by skv - Tue Mar 15 16:20:43 2005 End
3194 //=======================================================================
3195 //function : ClosingFaces
3197 //=======================================================================
3199 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3206 //=======================================================================
3207 //function : EncodeRegularity
3209 //=======================================================================
3211 void BRepOffset_MakeOffset::EncodeRegularity ()
3215 cout << " CODING OF REGULARITIES:" << endl;
3221 if (myOffsetShape.IsNull()) return;
3222 // find edges G1 in the result
3223 TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3226 TopTools_MapOfShape MS;
3228 for ( ; exp.More(); exp.Next()) {
3229 TopoDS_Edge OE = TopoDS::Edge(exp.Current());
3230 BRepLib::BuildCurve3d(OE,myTol);
3231 TopoDS_Edge ROE = OE;
3233 if ( !MS.Add(OE)) continue;
3235 if ( myImageOffset.IsImage(OE))
3236 ROE = TopoDS::Edge(myImageOffset.Root(OE));
3238 const TopTools_ListOfShape& LofOF = myAsDes->Ascendant(ROE);
3240 if (LofOF.Extent() != 2) {
3241 #ifdef OCCT_DEBUG_VERB
3242 cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
3247 const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3248 const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3250 if ( F1.IsNull() || F2.IsNull())
3253 const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3254 const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3256 TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3257 TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3259 if (F1.IsSame(F2)) {
3260 if (BRep_Tool::IsClosed(OE,F1)) {
3261 // Temporary Debug for the Bench.
3263 // In mode intersection, the edges are not coded in myInitOffsetEdge
3264 // so, manage case by case
3265 // Note DUB; for Hidden parts, it is NECESSARY to code CN
3266 // Analytic Surfaces.
3267 if (myJoin == GeomAbs_Intersection) {
3268 BRepAdaptor_Surface BS(F1,Standard_False);
3269 GeomAbs_SurfaceType SType = BS.GetType();
3270 if (SType == GeomAbs_Cylinder ||
3271 SType == GeomAbs_Cone ||
3272 SType == GeomAbs_Sphere ||
3273 SType == GeomAbs_Torus ) {
3274 B.Continuity(OE,F1,F1,GeomAbs_CN);
3277 // See YFR : MaJ of myInitOffsetFace
3280 else if (myInitOffsetEdge.IsImage(ROE)) {
3281 if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3282 const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3283 const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3284 GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3285 if (Conti == GeomAbs_CN) {
3286 B.Continuity(OE,F1,F1,GeomAbs_CN);
3288 else if ( Conti > GeomAbs_C0) {
3289 B.Continuity(OE,F1,F1,GeomAbs_G1);
3298 // code regularities G1 between :
3299 // - sphere and tube : one root is a vertex, the other is an edge
3300 // and the vertex is included in the edge
3301 // - face and tube : one root is a face, the other an edge
3302 // and the edge is included in the face
3303 // - face and face : if two root faces are tangent in
3304 // the initial shape, they will be tangent in the offset shape
3305 // - tube and tube : if 2 edges generating tubes are
3306 // tangents, the 2 will be tangent either.
3307 if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3308 TopoDS_Vertex V1,V2;
3309 TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3310 if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3311 B.Continuity(OE,F1,F2,GeomAbs_G1);
3314 else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3315 TopoDS_Vertex V1,V2;
3316 TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3317 if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3318 B.Continuity(OE,F1,F2,GeomAbs_G1);
3321 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3322 TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3323 for ( ; exp2.More(); exp2.Next()) {
3324 if ( exp2.Current().IsSame(Root2)) {
3325 B.Continuity(OE,F1,F2,GeomAbs_G1);
3330 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3331 TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3332 for ( ; exp2.More(); exp2.Next()) {
3333 if ( exp2.Current().IsSame(Root1)) {
3334 B.Continuity(OE,F1,F2,GeomAbs_G1);
3339 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3340 // if two root faces are tangent in
3341 // the initial shape, they will be tangent in the offset shape
3342 TopTools_ListOfShape LE;
3343 BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
3344 if ( LE.Extent() == 1) {
3345 const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3346 if ( myAnalyse.HasAncestor(Ed)) {
3347 const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3348 if (LI.Extent() == 1 &&
3349 LI.First().Type() == BRepOffset_Tangent) {
3350 B.Continuity(OE,F1,F2,GeomAbs_G1);
3355 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3356 TopTools_ListOfShape LV;
3357 BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
3358 if ( LV.Extent() == 1) {
3359 TopTools_ListOfShape LEdTg;
3360 myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3361 TopoDS::Vertex(LV.First()),
3363 TopTools_ListIteratorOfListOfShape it(LEdTg);
3364 for (; it.More(); it.Next()) {
3365 if ( it.Value().IsSame(Root2)) {
3366 B.Continuity(OE,F1,F2,GeomAbs_G1);
3375 if ( ChronBuild) Clock.Show();
3379 //=======================================================================
3380 //function : ComputeMaxDist
3382 //=======================================================================
3383 Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
3384 const Handle(Geom_Curve)& theCrv,
3385 const Standard_Real theFirst,
3386 const Standard_Real theLast)
3388 Standard_Real aMaxDist = 0.;
3389 Standard_Integer i, NCONTROL = 23;
3390 Standard_Real aPrm, aDist2;
3392 for (i = 0; i< NCONTROL; i++) {
3393 aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
3394 aP = theCrv->Value(aPrm);
3395 if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
3396 || Precision::IsInfinite(aP.Z()))
3398 return Precision::Infinite();
3400 aDist2 = thePlane.SquareDistance(aP);
3401 if (aDist2 > aMaxDist) aMaxDist = aDist2;
3403 return sqrt(aMaxDist)*1.05;
3405 //=======================================================================
3406 //function : UpDateTolerance
3408 //=======================================================================
3410 void UpdateTolerance (TopoDS_Shape& S,
3411 const TopTools_IndexedMapOfShape& Faces)
3414 TopTools_MapOfShape View;
3417 // The edges of caps are not modified.
3419 for (j = 1; j <= Faces.Extent(); j++) {
3420 const TopoDS_Shape& F = Faces(j);
3421 TopExp_Explorer Exp;
3422 for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3423 View.Add(Exp.Current());
3428 TopExp_Explorer ExpF;
3429 for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
3431 const TopoDS_Shape& F = ExpF.Current();
3432 if (Faces.Contains(F))
3436 BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
3437 TopExp_Explorer Exp;
3438 for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
3439 TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3440 Standard_Boolean isUpdated = Standard_False;
3441 if (aBAS.GetType() == GeomAbs_Plane)
3443 //Edge does not seem to have pcurve on plane,
3444 //so EdgeCorrector does not include it in tolerance calculation
3445 Standard_Real aFirst, aLast;
3446 Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
3447 Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
3448 B.UpdateEdge(E, aMaxDist);
3449 isUpdated = Standard_True;
3454 BRepCheck_Edge EdgeCorrector(E);
3455 Tol = EdgeCorrector.Tolerance();
3456 B.UpdateEdge(E, Tol);
3457 isUpdated = Standard_True;
3461 Tol = BRep_Tool::Tolerance(E);
3462 // Update the vertices.
3463 TopExp::Vertices(E, V[0], V[1]);
3465 for (Standard_Integer i = 0; i <= 1; i++) {
3466 if (View.Add(V[i])) {
3467 Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3469 BRepCheck_Vertex VertexCorrector(V[i]);
3470 B.UpdateVertex(V[i], VertexCorrector.Tolerance());
3471 // use the occasion to clean the vertices.
3472 (TV->ChangePoints()).Clear();
3474 B.UpdateVertex(V[i], Tol);
3481 //=======================================================================
3482 //function : CorrectSolid
3484 //=======================================================================
3485 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
3488 TopoDS_Shape anOuterShell;
3489 NCollection_List<Standard_Real> aVols;
3490 Standard_Real aVolMax = 0., anOuterVol = 0.;
3492 TopoDS_Iterator anIt(theSol);
3493 for(; anIt.More(); anIt.Next())
3495 const TopoDS_Shape& aSh = anIt.Value();
3496 GProp_GProps aVProps;
3497 BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
3498 if(Abs(aVProps.Mass()) > aVolMax)
3500 anOuterVol = aVProps.Mass();
3501 aVolMax = Abs(anOuterVol);
3504 aVols.Append(aVProps.Mass());
3507 if (Abs(anOuterVol) < Precision::Confusion()) {
3512 anOuterShell.Reverse();
3514 TopoDS_Solid aNewSol;
3515 aBB.MakeSolid(aNewSol);
3516 aNewSol.Closed(Standard_True);
3517 aBB.Add(aNewSol, anOuterShell);
3518 BRepClass3d_SolidClassifier aSolClass(aNewSol);
3520 anIt.Initialize(theSol);
3521 NCollection_List<Standard_Real>::Iterator aVIt(aVols);
3522 for(; anIt.More(); anIt.Next(), aVIt.Next())
3524 TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
3525 if(aSh.IsSame(anOuterShell))
3531 TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
3532 const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
3533 gp_Pnt aP = BRep_Tool::Pnt(aV);
3534 aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
3535 if(aSolClass.State() == TopAbs_IN)
3537 if(aVIt.Value() > 0.)
3541 aBB.Add(aNewSol, aSh);
3545 if(aVIt.Value() < 0.)
3550 aBB.MakeSolid(aSol);
3551 aSol.Closed(Standard_True);
3553 theSolList.Append(aSol);
3560 //=======================================================================
3561 //function : CheckInputData
3562 //purpose : Check input data for possiblity of offset perform.
3563 //=======================================================================
3564 Standard_Boolean BRepOffset_MakeOffset::CheckInputData()
3566 // Set initial error state.
3567 myError = BRepOffset_NoError;
3568 TopoDS_Shape aTmpShape;
3569 myBadShape = aTmpShape;
3572 if (Abs(myOffset) <= myTol)
3574 Standard_Boolean isFound = Standard_False;
3575 TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
3576 for( ; anIter.More(); anIter.Next())
3578 if (Abs(anIter.Value()) > myTol)
3580 isFound = Standard_True;
3587 // No face with non-null offset found.
3588 myError = BRepOffset_NullOffset;
3589 return Standard_False;
3593 // Connectivity of input shape.
3594 if (!IsConnectedShell(myShape))
3596 myError = BRepOffset_NotConnectedShell;
3597 return Standard_False;
3600 // Normals check and continuity check.
3601 const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
3602 Standard_Real aUmin, aUmax, aVmin, aVmax;
3603 TopExp_Explorer anExpSF(myShape, TopAbs_FACE);
3604 NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
3607 for( ; anExpSF.More(); anExpSF.Next())
3609 const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
3611 if (aPresenceMap.Contains(aF.TShape()))
3613 // Not perform computations with partner shapes,
3614 // since they are contain same geometry.
3617 aPresenceMap.Add(aF.TShape());
3619 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
3620 BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
3622 // Continuity check.
3623 if (aSurf->Continuity() == GeomAbs_C0)
3625 myError = BRepOffset_C0Geometry;
3626 return Standard_False;
3629 // Get degenerated points, to avoid check them.
3630 NCollection_Vector<gp_Pnt> aBad3dPnts;
3631 TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
3632 for( ; anExpFE.More(); anExpFE.Next())
3634 const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
3635 if (BRep_Tool::Degenerated(aE))
3637 aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
3641 // Geometry grid check.
3642 for(Standard_Integer i = 0; i <= aPntPerDim; i++)
3644 Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
3645 for(Standard_Integer j = 0; j <= aPntPerDim; j++)
3647 Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
3649 myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
3650 if (myError != BRepOffset_NoError)
3651 return Standard_False;
3655 // Vertex list check.
3656 TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
3657 for( ; anExpFV.More(); anExpFV.Next())
3659 const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
3660 aPnt2d = BRep_Tool::Parameters(aV, aF);
3662 myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
3663 if (myError != BRepOffset_NoError)
3664 return Standard_False;
3668 return Standard_True;
3672 //=======================================================================
3673 //function : GetBadShape
3674 //purpose : Get shape where problems detected.
3675 //=======================================================================
3676 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
3681 //=======================================================================
3682 //function : RemoveInternalEdges
3684 //=======================================================================
3685 void BRepOffset_MakeOffset::RemoveInternalEdges()
3687 Standard_Boolean bRemoveWire, bRemoveEdge;
3688 TopExp_Explorer aExpF, aExpW, aExpE;
3689 TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
3691 TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
3693 aExpF.Init(myOffsetShape, TopAbs_FACE);
3694 for (; aExpF.More(); aExpF.Next()) {
3695 TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
3697 TopTools_ListOfShape aLIW;
3699 aExpW.Init(aF, TopAbs_WIRE);
3700 for (; aExpW.More(); aExpW.Next()) {
3701 TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
3703 bRemoveWire = Standard_True;
3704 TopTools_ListOfShape aLIE;
3706 aExpE.Init(aW, TopAbs_EDGE);
3707 for (; aExpE.More(); aExpE.Next()) {
3708 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
3709 if (aE.Orientation() != TopAbs_INTERNAL) {
3710 bRemoveWire = Standard_False;
3714 const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
3715 bRemoveEdge = (aLF.Extent() == 1);
3720 bRemoveWire = Standard_False;
3727 else if (aLIE.Extent()) {
3728 RemoveShapes(aW, aLIE);
3732 if (aLIW.Extent()) {
3733 RemoveShapes(aF, aLIW);
3738 //=======================================================================
3739 // static methods implementation
3740 //=======================================================================
3742 //=======================================================================
3743 //function : checkSinglePoint
3744 //purpose : Check single point on surface for bad normals
3745 //=======================================================================
3746 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
3747 const Standard_Real theVParam,
3748 const Handle(Geom_Surface)& theSurf,
3749 const NCollection_Vector<gp_Pnt>& theBadPoints)
3753 theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
3755 if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3756 aD1V.SquareMagnitude() < Precision::SquareConfusion() )
3758 Standard_Boolean isKnownBadPnt = Standard_False;
3759 for(Standard_Integer anIdx = theBadPoints.Lower();
3760 anIdx <= theBadPoints.Upper();
3763 if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
3765 isKnownBadPnt = Standard_True;
3768 } // for(Standard_Integer anIdx = theBadPoints.Lower();
3772 return BRepOffset_BadNormalsOnGeometry;
3776 return BRepOffset_NoError;
3778 } // if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
3780 if (aD1U.IsParallel(aD1V, Precision::Confusion()))
3782 // Isolines are collinear.
3783 return BRepOffset_BadNormalsOnGeometry;
3786 return BRepOffset_NoError;
3789 //=======================================================================
3790 //function : RemoveShapes
3791 //purpose : Removes the shapes <theLS> from the shape <theS>
3792 //=======================================================================
3793 void RemoveShapes(TopoDS_Shape& theS,
3794 const TopTools_ListOfShape& theLS)
3798 Standard_Boolean bFree = theS.Free();
3799 theS.Free(Standard_True);
3801 TopTools_ListIteratorOfListOfShape aIt(theLS);
3802 for (; aIt.More(); aIt.Next()) {
3803 const TopoDS_Shape& aSI = aIt.Value();
3804 aBB.Remove(theS, aSI);
3810 //=======================================================================
3811 //function : UpdateHistory
3812 //purpose : Updates the history information
3813 //=======================================================================
3814 void UpdateHistory(const TopTools_ListOfShape& theLF,
3815 BOPAlgo_Builder& theGF,
3816 BRepAlgo_Image& theImage)
3818 TopTools_ListIteratorOfListOfShape aIt(theLF);
3819 for (; aIt.More(); aIt.Next()) {
3820 const TopoDS_Shape& aF = aIt.Value();
3821 const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
3822 if (aLFIm.Extent()) {
3823 if (theImage.HasImage(aF)) {
3824 theImage.Add(aF, aLFIm);
3827 theImage.Bind(aF, aLFIm);
3833 //=======================================================================
3834 //function : IntersectEdges
3836 //=======================================================================
3837 void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape,
3838 BRepOffset_DataMapOfShapeOffset& theMapSF,
3839 TopTools_DataMapOfShapeShape& theMES,
3840 TopTools_DataMapOfShapeShape& theBuild,
3841 Handle(BRepAlgo_AsDes)& theAsDes,
3842 Handle(BRepAlgo_AsDes)& theAsDes2d)
3844 Standard_Real aTolF;
3845 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
3846 TopExp_Explorer aExp(theShape, TopAbs_FACE);
3847 // intersect edges created from edges
3848 TopTools_IndexedMapOfShape aMFV;
3849 for (; aExp.More(); aExp.Next()) {
3850 const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
3851 aTolF = BRep_Tool::Tolerance(aF);
3852 BRepOffset_Inter2d::ConnexIntByInt
3853 (aF, theMapSF(aF), theMES, theBuild, theAsDes2d, myOffset, aTolF, aMFV, aDMVV);
3855 // intersect edges created from vertices
3856 Standard_Integer i, aNbF = aMFV.Extent();
3857 for (i = 1; i <= aNbF; ++i) {
3858 const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
3859 aTolF = BRep_Tool::Tolerance(aF);
3860 BRepOffset_Inter2d::ConnexIntByIntInVert
3861 (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, aDMVV);
3864 // fuse vertices on edges
3865 BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d);
3868 //=======================================================================
3869 //function : TrimEdges
3871 //=======================================================================
3872 void TrimEdges(const TopoDS_Shape& theShape,
3873 const Standard_Real theOffset,
3874 BRepOffset_DataMapOfShapeOffset& theMapSF,
3875 TopTools_DataMapOfShapeShape& theMES,
3876 TopTools_DataMapOfShapeShape& theBuild,
3877 Handle(BRepAlgo_AsDes)& theAsDes,
3878 Handle(BRepAlgo_AsDes)& theAsDes2d,
3879 TopTools_IndexedMapOfShape& theNewEdges,
3880 TopTools_DataMapOfShapeShape& theETrimEInf,
3881 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
3883 TopExp_Explorer Exp,Exp2,ExpC;
3888 for (Exp.Init(theShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
3889 const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
3890 NF = theMapSF(FI).Face();
3891 if (theMES.IsBound(NF)) {
3892 NF = TopoDS::Face(theMES(NF));
3895 TopTools_MapOfShape View;
3896 TopTools_IndexedMapOfShape VEmap;
3897 Standard_Integer i, aNb;
3899 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap);
3900 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
3902 aNb = VEmap.Extent();
3903 for (i = 1; i <= aNb; ++i) {
3904 const TopoDS_Shape& aS = VEmap(i);
3905 if (!View.Add(aS)) {
3909 if (theBuild.IsBound(aS)) {
3911 // keep connection to original edges
3912 ExpC.Init(NE, TopAbs_EDGE);
3913 for (; ExpC.More(); ExpC.Next()) {
3914 const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
3915 TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
3917 pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
3919 AppendToList(*pLEOr, aS);
3922 if (NE.ShapeType() == TopAbs_EDGE) {
3923 if (theNewEdges.Add(NE)) {
3924 TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf);
3928 //------------------------------------------------------------
3929 // The Intersections are on several edges.
3930 // The pieces without intersections with neighbors
3931 // are removed from AsDes.
3932 //------------------------------------------------------------
3933 for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
3934 TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
3935 if (theNewEdges.Add(NEC)) {
3936 if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
3937 TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf);
3940 if (theAsDes->HasAscendant(NEC)) {
3941 theAsDes->Remove(NEC);
3949 if (aS.ShapeType() != TopAbs_EDGE) {
3953 NE = theMapSF(FI).Generated(aS);
3954 //// modified by jgv, 19.12.03 for OCC4455 ////
3955 NE.Orientation(aS.Orientation());
3957 TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
3959 pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
3961 AppendToList(*pLEOr, aS);
3963 if (theMES.IsBound(NE)) {
3965 NE.Orientation(aS.Orientation());
3966 if (theNewEdges.Add(NE)) {
3967 TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf);
3971 TopoDS_Edge& anEdge = TopoDS::Edge(NE);
3972 BRepAdaptor_Curve aBAC(anEdge);
3973 if (aBAC.GetType() == GeomAbs_Line) {
3974 TopoDS_Edge aNewEdge;
3975 BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
3976 theETrimEInf.Bind(anEdge, aNewEdge);
3979 theAsDes->Add(NF,NE);
3985 //=======================================================================
3986 //function : TrimEdge
3987 //purpose : Trim the edge of the largest of descendants in AsDes2d.
3988 // Order in AsDes two vertices that have trimmed the edge.
3989 //=======================================================================
3990 void TrimEdge(TopoDS_Edge& NE,
3991 const Handle(BRepAlgo_AsDes)& AsDes2d,
3992 Handle(BRepAlgo_AsDes)& AsDes,
3993 TopTools_DataMapOfShapeShape& theETrimEInf)
3995 TopoDS_Edge aSourceEdge;
3996 TopoDS_Vertex V1,V2;
3997 Standard_Real aT1, aT2;
3999 TopExp::Vertices(NE, V1, V2);
4000 BRep_Tool::Range(NE, aT1, aT2);
4002 BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
4005 Standard_Real aSameParTol = Precision::Confusion();
4007 Standard_Real U = 0.;
4008 Standard_Real UMin = Precision::Infinite();
4009 Standard_Real UMax = -UMin;
4011 const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
4013 Standard_Boolean bTrim = Standard_False;
4015 if (LE.Extent() > 1) {
4016 TopTools_ListIteratorOfListOfShape it (LE);
4017 for (; it.More(); it.Next()) {
4018 TopoDS_Vertex V = TopoDS::Vertex(it.Value());
4019 if (NE.Orientation() == TopAbs_REVERSED)
4021 //V.Orientation(TopAbs_INTERNAL);
4022 if (!FindParameter(V, NE, U)) {
4024 Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
4025 gp_Pnt thePoint = BRep_Tool::Pnt(V);
4026 GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
4027 if (Projector.NbPoints() == 0)
4028 throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge no projection");
4029 U = Projector.LowerDistanceParameter();
4039 if (V1.IsNull() || V2.IsNull()) {
4040 throw Standard_ConstructionError("BRepOffset_MakeOffset::TrimEdge");
4042 if (!V1.IsSame(V2)) {
4043 NE.Free( Standard_True );
4045 TopAbs_Orientation Or = NE.Orientation();
4046 NE.Orientation(TopAbs_FORWARD);
4047 TopoDS_Vertex VF,VL;
4048 TopExp::Vertices (NE,VF,VL);
4051 B.Add (NE,V1.Oriented(TopAbs_FORWARD));
4052 B.Add (NE,V2.Oriented(TopAbs_REVERSED));
4053 B.Range(NE,UMin,UMax);
4055 AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
4056 AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
4057 BRepLib::SameParameter(NE, aSameParTol, Standard_True);
4059 bTrim = Standard_True;
4064 BRepAdaptor_Curve aBAC(NE);
4065 if (aBAC.GetType() == GeomAbs_Line) {
4066 if (AsDes->HasAscendant(NE)) {
4073 if (!theETrimEInf.IsBound(NE)) {
4074 theETrimEInf.Bind(NE, aSourceEdge);
4079 //=======================================================================
4080 //function : GetEnlargedFaces
4082 //=======================================================================
4083 void GetEnlargedFaces(const TopoDS_Shape& theShape,
4084 const BRepOffset_DataMapOfShapeOffset& theMapSF,
4085 const TopTools_DataMapOfShapeShape& theMES,
4086 TopTools_DataMapOfShapeShape& theFacesOrigins,
4087 BRepAlgo_Image& theImage,
4088 TopTools_ListOfShape& theLSF)
4090 TopExp_Explorer aExp(theShape, TopAbs_FACE);
4091 for (; aExp.More(); aExp.Next()) {
4092 const TopoDS_Shape& FI = aExp.Current();
4093 const TopoDS_Shape& OFI = theMapSF(FI).Face();
4094 if (theMES.IsBound(OFI)) {
4095 const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
4096 theLSF.Append(aLocalFace);
4097 theImage.SetRoot(aLocalFace);
4099 theFacesOrigins.Bind(aLocalFace, FI);
4104 //=======================================================================
4105 //function : BuildShellsCompleteInter
4106 //purpose : Make the shells from list of faces using MakerVolume algorithm.
4107 // In case there will be more than just one solid, it will be
4108 // rebuilt using only outer faces.
4109 //=======================================================================
4110 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
4111 BRepAlgo_Image& theImage,
4112 TopoDS_Shape& theShells)
4115 BOPAlgo_MakerVolume aMV1;
4116 aMV1.SetArguments(theLF);
4117 // we need to intersect the faces to process the tangential faces
4118 aMV1.SetIntersect(Standard_True);
4119 aMV1.SetAvoidInternalShapes(Standard_True);
4122 Standard_Boolean bDone = ! aMV1.HasErrors();
4127 UpdateHistory(theLF, aMV1, theImage);
4129 const TopoDS_Shape& aResult1 = aMV1.Shape();
4130 if (aResult1.ShapeType() == TopAbs_SOLID) {
4131 // result is the alone solid, nothing to do
4132 return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
4135 // Allocators for effective memory allocations
4136 // Global allocator for the long-living containers
4137 Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
4138 // Local allocator for the local containers
4139 Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
4141 // Since the <theImage> object does not support multiple ancestors,
4142 // prepare local copy of the origins, which will be used to resolve
4143 // non-manifold solids produced by Maker Volume algorithm by comparison
4144 // of the normal directions of the split faces with their origins.
4145 TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
4146 TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
4147 for (; aItLR.More(); aItLR.Next())
4149 const TopoDS_Shape& aFR = aItLR.Value();
4151 // Reset the local allocator
4152 anAllocLoc->Reset();
4153 // Find the last splits of the root face, including the ones
4154 // created during MakeVolume operation
4155 TopTools_ListOfShape aLFIm(anAllocLoc);
4156 theImage.LastImage(aFR, aLFIm);
4158 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4159 for (; aItLFIm.More(); aItLFIm.Next())
4161 const TopoDS_Shape& aFIm = aItLFIm.Value();
4162 TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
4164 pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
4170 // Reset the local allocator
4171 anAllocLoc->Reset();
4172 // It is necessary to rebuild the solids, avoiding internal faces
4173 // Map faces to solids
4174 TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
4175 TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
4177 Standard_Integer i, aNb = aDMFS.Extent();
4180 // unable to build any solid
4184 // get faces attached to only one solid
4185 TopTools_ListOfShape aLF(anAllocLoc);
4186 for (i = 1; i <= aNb; ++i) {
4187 const TopTools_ListOfShape& aLS = aDMFS(i);
4188 if (aLS.Extent() == 1) {
4189 const TopoDS_Shape& aF = aDMFS.FindKey(i);
4194 // make solids from the new list
4195 BOPAlgo_MakerVolume aMV2;
4196 aMV2.SetArguments(aLF);
4197 // no need to intersect this time
4198 aMV2.SetIntersect(Standard_False);
4199 aMV2.SetAvoidInternalShapes(Standard_True);
4201 bDone = ! aMV2.HasErrors();
4206 const TopoDS_Shape& aResult2 = aMV2.Shape();
4207 if (aResult2.ShapeType() == TopAbs_SOLID) {
4208 return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
4211 TopExp_Explorer aExp(aResult2, TopAbs_FACE);
4212 bDone = aExp.More();
4219 anAllocLoc->Reset();
4221 // the result is non-manifold - resolve it comparing normal
4222 // directions of the offset faces and original faces
4223 for (; aExp.More(); aExp.Next())
4225 const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
4226 const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
4229 Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
4230 "Origins map does not contain the split face");
4233 // Check orientation
4234 TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
4235 for (; aItLOr.More(); aItLOr.Next())
4237 const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
4238 if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
4246 // make solid from most outer faces with correct normal direction
4247 BOPAlgo_MakerVolume aMV3;
4248 aMV3.SetArguments(aLF);
4249 aMV3.SetIntersect(Standard_False);
4250 aMV3.SetAvoidInternalShapes(Standard_True);
4252 bDone = ! aMV3.HasErrors();
4257 const TopoDS_Shape& aResult3 = aMV3.Shape();
4258 return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
4261 //=======================================================================
4262 //function : GetSubShapes
4264 //=======================================================================
4265 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
4266 const TopAbs_ShapeEnum theSSType,
4267 TopoDS_Shape& theResult)
4269 TopExp_Explorer aExp(theShape, theSSType);
4271 return Standard_False;
4274 TopoDS_Compound aResult;
4275 BRep_Builder().MakeCompound(aResult);
4277 for (; aExp.More(); aExp.Next()) {
4278 const TopoDS_Shape& aSS = aExp.Current();
4279 BRep_Builder().Add(aResult, aSS);
4281 theResult = aResult;
4282 return Standard_True;
4285 //=======================================================================
4286 //function : IsPlanar
4287 //purpose : Checks if all the faces of the shape are planes
4288 //=======================================================================
4289 Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
4291 TopExp_Explorer aExp(theS, TopAbs_FACE);
4292 for (; aExp.More(); aExp.Next()) {
4293 const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
4294 BRepAdaptor_Surface aBAS(aF, Standard_False);
4295 if (aBAS.GetType() != GeomAbs_Plane) {
4299 return !aExp.More();
4302 //=======================================================================
4303 //function : IsSolid
4304 //purpose : Checks if the shape is solid
4305 //=======================================================================
4306 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
4308 TopExp_Explorer aExp(theS, TopAbs_SOLID);
4312 //=======================================================================
4313 //function : AppendToList
4314 //purpose : Add to a list only unique elements
4315 //=======================================================================
4316 void AppendToList(TopTools_ListOfShape& theList,
4317 const TopoDS_Shape& theShape)
4319 TopTools_ListIteratorOfListOfShape aIt(theList);
4320 for (; aIt.More(); aIt.Next()) {
4321 const TopoDS_Shape& aS = aIt.Value();
4322 if (aS.IsSame(theShape)) {
4326 theList.Append(theShape);