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>
116 #include <BOPAlgo_PaveFiller.hxx>
117 #include <BOPAlgo_Builder.hxx>
118 #include <BOPAlgo_MakerVolume.hxx>
119 #include <BOPCol_ListOfShape.hxx>
120 #include <BOPCol_DataMapOfShapeShape.hxx>
121 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
122 #include <BOPTools.hxx>
123 #include <BOPTools_AlgoTools3D.hxx>
124 #include <BOPTools_AlgoTools.hxx>
125 #include <IntTools_Context.hxx>
126 #include <IntTools_ShrunkRange.hxx>
127 #include <CPnts_AbscissaPoint.hxx>
136 #include <OSD_Chronometer.hxx>
138 Standard_Boolean AffichInt2d = Standard_False;
139 Standard_Boolean AffichOffC = Standard_False;
140 Standard_Boolean ChronBuild = Standard_False;
141 Standard_Integer NbAE = 0;
142 Standard_Integer NbAF = 0;
143 Standard_Integer NVP = 0;
144 Standard_Integer NVM = 0;
145 Standard_Integer NVN = 0;
146 static OSD_Chronometer Clock;
152 //=======================================================================
153 //function : DEBVerticesControl
155 //=======================================================================
157 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
158 Handle(BRepAlgo_AsDes) AsDes)
160 TopTools_ListOfShape LVP;
161 TopTools_ListIteratorOfListOfShape it1LE ;
162 TopTools_ListIteratorOfListOfShape it2LE ;
165 for (i = 1; i <= NewEdges.Extent(); i++) {
166 const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
167 if (AsDes->HasDescendant(NE)) {
168 for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
169 if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
170 LVP.Append(it1LE.Value());
171 cout <<"Vertex on at least 3 edges."<<endl;
174 sprintf (name,"VP_%d",NVP++);
175 DBRep::Set(name,it1LE.Value());
179 else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
180 cout <<"Vertex on more than 3 edges."<<endl;
183 sprintf (name,"VM_%d",NVM++);
184 DBRep::Set(name,it1LE.Value());
192 sprintf (name,"VN_%d",NVN++);
193 DBRep::Set(name,it1LE.Value());
200 //------------------------------------------------
201 // Try to mix spoiled vertices.
202 //------------------------------------------------
204 TopTools_ListIteratorOfListOfShape it1(LVP);
205 Standard_Real TolConf = 1.e-5;
206 Standard_Real Tol = Precision::Confusion();
207 //Standard_Integer i = 1;
210 for ( ; it1.More(); it1.Next()) {
211 TopoDS_Shape V1 = it1.Value();
212 gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
213 Standard_Real distmin = Precision::Infinite();
214 TopTools_ListIteratorOfListOfShape it2(LVP);
215 Standard_Integer j = 1;
217 for ( ; it2.More(); it2.Next()) {
219 TopoDS_Shape V2 = it2.Value();
220 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
221 if (!V1.IsSame(V2)) {
222 Standard_Real dist = P1.Distance(P2);
223 if (dist < distmin) distmin = dist;
224 if (dist < TolConf) {
227 const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
228 TopTools_ListIteratorOfListOfShape itAsDes;
229 for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
230 EWE2 = TopoDS::Edge(itAsDes.Value());
231 TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
232 UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
233 aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
234 B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
236 // BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
237 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
240 AsDes->Replace(V2,V1);
247 cout <<" distmin between VP : "<<distmin<<endl;
253 //=======================================================================
255 //=======================================================================
257 void SortFaces(const TopTools_ListOfShape& theLIm,
258 TopTools_ListOfShape& theLFImages,
259 const Standard_Boolean bKeepFirst);
262 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
263 const TopoDS_Shape& theSWhere,
264 TopoDS_Shape& theRes);
267 void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
268 BOPAlgo_Builder& theGF);
271 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
272 const Handle(IntTools_Context)& theCtx);
275 Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
276 const TopoDS_Edge& theE,
279 Standard_Boolean CheckBiNormals(const TopoDS_Face& aFIm,
280 const TopoDS_Face& aFOr,
281 const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
282 const TopTools_MapOfShape& theMFence,
283 Standard_Boolean& bKeep,
284 Standard_Boolean& bRem,
285 const Standard_Boolean RemoveInvalidFaces);
288 void CheckBiNormals(TopTools_ListOfShape& theLFImages,
289 const TopoDS_Face& theF,
290 const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
291 TopTools_ListOfShape& theLFKeep,
292 const Standard_Boolean RemoveInvalidFaces);
295 Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
296 const TopoDS_Face& theFOr);
299 void UpdateInitOffset(BRepAlgo_Image& myInitOffset,
300 BRepAlgo_Image& myImageOffset,
301 const TopoDS_Shape& myOffsetShape,
302 const TopAbs_ShapeEnum &theShapeType);
305 void RemoveShapes(TopoDS_Shape& theS,
306 const TopTools_ListOfShape& theLS);
309 Standard_Boolean IsSolid(const TopoDS_Shape& theS);
312 void UpdateHistory(const TopTools_ListOfShape& theLF,
313 BOPAlgo_Builder& theGF,
314 BRepAlgo_Image& theImage);
317 Standard_Boolean IsPlanar(const TopoDS_Shape& theS);
319 static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
320 const Standard_Real theVParam,
321 const Handle(Geom_Surface)& theSurf,
322 const NCollection_Vector<gp_Pnt>& theBadPoints);
324 //---------------------------------------------------------------------
325 static void UpdateTolerance ( TopoDS_Shape& myShape,
326 const TopTools_IndexedMapOfShape& myFaces);
328 static void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList);
329 //---------------------------------------------------------------------
331 static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
332 const TopoDS_Edge& E,
335 // Search the vertex in the edge
337 Standard_Boolean rev = Standard_False;
339 TopAbs_Orientation orient = TopAbs_INTERNAL;
341 TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
343 // if the edge has no vertices
344 // and is degenerated use the vertex orientation
347 if (!itv.More() && BRep_Tool::Degenerated(E)) {
348 orient = V.Orientation();
352 const TopoDS_Shape& Vcur = itv.Value();
353 if (V.IsSame(Vcur)) {
358 rev = E.Orientation() == TopAbs_REVERSED;
359 if (Vcur.Orientation() == V.Orientation()) {
367 if (!VF.IsNull()) orient = VF.Orientation();
371 if (orient == TopAbs_FORWARD) {
372 BRep_Tool::Range(E,f,l);
373 //return (rev) ? l : f;
375 return Standard_True;
378 else if (orient == TopAbs_REVERSED) {
379 BRep_Tool::Range(E,f,l);
380 //return (rev) ? f : l;
382 return Standard_True;
387 const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
388 L = L.Predivided(V.Location());
389 if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
390 BRep_ListIteratorOfListOfPointRepresentation itpr
391 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
393 while (itpr.More()) {
394 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
395 if (pr->IsPointOnCurve(C,L)) {
396 Standard_Real p = pr->Parameter();
397 Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
399 // Closed curves RLE 16 june 94
400 if (Precision::IsNegativeInfinite(f))
402 //return pr->Parameter();//p;
404 return Standard_True;
406 if (Precision::IsPositiveInfinite(l))
408 //return pr->Parameter();//p;
410 return Standard_True;
412 gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
413 gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
414 Standard_Real tol = BRep_Tool::Tolerance(V);
415 if (Pf.Distance(Pl) < tol) {
416 if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
417 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
418 else res = l;//p = l;
424 return Standard_True;
431 // let us try with the first pcurve
432 Handle(Geom2d_Curve) PC;
433 Handle(Geom_Surface) S;
434 BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
435 L = L.Predivided(V.Location());
436 BRep_ListIteratorOfListOfPointRepresentation itpr
437 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
439 while (itpr.More()) {
440 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
441 if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
442 Standard_Real p = pr->Parameter();
443 // Closed curves RLE 16 june 94
444 if (PC->IsClosed()) {
445 if ((p == PC->FirstParameter()) ||
446 (p == PC->LastParameter())) {
447 if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
448 else p = PC->LastParameter();
453 return Standard_True;
460 //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge");
461 return Standard_False;
464 //=======================================================================
465 //function : GetEdgePoints
466 //purpose : gets the first, last and middle points of the edge
467 //=======================================================================
468 static void GetEdgePoints(const TopoDS_Edge& anEdge,
469 const TopoDS_Face& aFace,
470 gp_Pnt& fPnt, gp_Pnt& mPnt,
474 Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
475 gp_Pnt2d fPnt2d = theCurve->Value(f);
476 gp_Pnt2d lPnt2d = theCurve->Value(l);
477 gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
478 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
479 fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
480 lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
481 mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
484 //=======================================================================
485 //function : FillContours
486 //purpose : fills free boundary contours and faces connected (MapEF)
487 //=======================================================================
488 static void FillContours(const TopoDS_Shape& aShape,
489 const BRepOffset_Analyse& Analyser,
490 TopTools_DataMapOfShapeListOfShape& Contours,
491 TopTools_DataMapOfShapeShape& MapEF)
493 TopTools_ListOfShape Edges;
495 TopExp_Explorer Explo(aShape, TopAbs_FACE);
496 BRepTools_WireExplorer Wexp;
498 for (; Explo.More(); Explo.Next())
500 TopoDS_Face aFace = TopoDS::Face(Explo.Current());
501 TopoDS_Iterator itf(aFace);
502 for (; itf.More(); itf.Next())
504 TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
505 for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
507 TopoDS_Edge anEdge = Wexp.Current();
508 if (BRep_Tool::Degenerated(anEdge))
510 const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
511 if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary)
513 MapEF.Bind(anEdge, aFace);
514 Edges.Append(anEdge);
520 TopTools_ListIteratorOfListOfShape itl;
521 while (!Edges.IsEmpty())
523 TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
525 TopoDS_Vertex StartVertex, CurVertex;
526 TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
527 TopTools_ListOfShape aContour;
528 aContour.Append(StartEdge);
529 while (!CurVertex.IsSame(StartVertex))
530 for (itl.Initialize(Edges); itl.More(); itl.Next())
532 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
533 TopoDS_Vertex V1, V2;
534 TopExp::Vertices(anEdge, V1, V2);
535 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
537 aContour.Append(anEdge);
538 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
543 Contours.Bind(StartVertex, aContour);
549 //-----------------------------------------------------------------------
551 //=======================================================================
552 //function : BRepOffset_MakeOffset
554 //=======================================================================
556 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
558 myAsDes = new BRepAlgo_AsDes();
562 //=======================================================================
563 //function : BRepOffset_MakeOffset
565 //=======================================================================
567 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape& S,
568 const Standard_Real Offset,
569 const Standard_Real Tol,
570 const BRepOffset_Mode Mode,
571 const Standard_Boolean Inter,
572 const Standard_Boolean SelfInter,
573 const GeomAbs_JoinType Join,
574 const Standard_Boolean Thickening,
575 const Standard_Boolean RemoveIntEdges,
576 const Standard_Boolean RemInvFaces)
583 mySelfInter (SelfInter),
585 myThickening (Thickening),
586 myRemoveIntEdges(RemoveIntEdges),
587 myRemoveInvalidFaces(RemInvFaces),
588 myDone (Standard_False)
591 myAsDes = new BRepAlgo_AsDes();
596 //=======================================================================
597 //function : Initialize
599 //=======================================================================
601 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape& S,
602 const Standard_Real Offset,
603 const Standard_Real Tol,
604 const BRepOffset_Mode Mode,
605 const Standard_Boolean Inter,
606 const Standard_Boolean SelfInter,
607 const GeomAbs_JoinType Join,
608 const Standard_Boolean Thickening,
609 const Standard_Boolean RemoveIntEdges,
610 const Standard_Boolean RemInvFaces)
617 mySelfInter = SelfInter;
619 myThickening = Thickening;
620 myRemoveIntEdges = RemoveIntEdges;
621 myRemoveInvalidFaces = RemInvFaces;
622 myDone = Standard_False;
623 myIsPerformSewing = Standard_False;
624 myIsPlanar = Standard_False;
629 //=======================================================================
632 //=======================================================================
634 void BRepOffset_MakeOffset::Clear()
636 myOffsetShape.Nullify();
637 myInitOffsetFace .Clear();
638 myInitOffsetEdge .Clear();
639 myImageOffset .Clear();
641 myFaceOffset .Clear();
643 myDone = Standard_False;
646 //=======================================================================
649 //=======================================================================
651 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
656 myInitOffsetFace.SetRoot (F) ;
657 myInitOffsetFace.Bind (F,F);
658 myImageOffset.SetRoot (F) ;
661 //=======================================================================
662 //function : SetOffsetOnFace
664 //=======================================================================
666 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face& F,
667 const Standard_Real Off)
669 if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F);
670 myFaceOffset.Bind(F,Off);
673 //=======================================================================
674 //function : RemoveCorks
676 //=======================================================================
678 static void RemoveCorks (TopoDS_Shape& S,
679 TopTools_IndexedMapOfShape& Faces)
684 //-----------------------------------------------------
685 // Construction of a shape without caps.
686 // and Orientation of caps as in shape S.
687 //-----------------------------------------------------
688 TopExp_Explorer exp(S,TopAbs_FACE);
689 for (; exp.More(); exp.Next()) {
690 const TopoDS_Shape& Cork = exp.Current();
691 if (!Faces.Contains(Cork)) {
695 //Faces.Remove (Cork);
696 //begin instead of Remove//
697 TopoDS_Shape LastShape = Faces(Faces.Extent());
699 if (Faces.FindIndex(Cork) != 0)
700 Faces.Substitute(Faces.FindIndex(Cork), LastShape);
701 //end instead of Remove //
702 Faces.Add(Cork); // to reset it with proper orientation.
708 DBRep::Set("myInit", SS);
713 //=======================================================================
714 //function : IsConnectedShell
716 //=======================================================================
717 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
719 BRepTools_Quilt Glue;
722 TopoDS_Shape SS = Glue.Shells();
723 TopExp_Explorer Explo( SS, TopAbs_SHELL );
726 return Standard_False;
728 return Standard_True;
732 //=======================================================================
733 //function : MakeList
735 //=======================================================================
737 static void MakeList (TopTools_ListOfShape& OffsetFaces,
738 const BRepAlgo_Image& myInitOffsetFace,
739 const TopTools_IndexedMapOfShape& myFaces)
741 TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
742 for ( ; itLOF.More(); itLOF.Next()) {
743 const TopoDS_Shape& Root = itLOF.Value();
744 if (!myFaces.Contains(Root)) {
745 if (myInitOffsetFace.HasImage(Root)) {
746 OffsetFaces.Append(myInitOffsetFace.Image(Root).First());
752 //=======================================================================
755 //=======================================================================
757 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
760 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
761 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
762 Standard_Real TolV = BRep_Tool::Tolerance(V);
763 if (TolV > Tol) Tol = TolV;
768 //=======================================================================
769 //function : MakeOffsetShape
771 //=======================================================================
773 void BRepOffset_MakeOffset::MakeOffsetShape()
775 myDone = Standard_False;
777 // check if shape consists of only planar faces
778 myIsPlanar = IsPlanar(myShape);
779 //------------------------------------------
780 // Construction of myShape without caps.
781 //------------------------------------------
782 if(!myFaces.IsEmpty())
784 RemoveCorks (myShape,myFaces);
787 if (!CheckInputData())
789 // There is error in input data.
790 // Check Error() method.
794 TopAbs_State Side = TopAbs_IN;
795 if (myOffset < 0.) Side = TopAbs_OUT;
800 EvalMax(myShape,myTol);
801 // There are possible second variant: analytical continuation of arcsin.
802 Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
803 Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
804 myAnalyse.Perform(myShape,TolAngle);
805 //---------------------------------------------------
806 // Construction of Offset from preanalysis.
807 //---------------------------------------------------
808 //----------------------------
809 // MaJ of SD Face - Offset
810 //----------------------------
813 if (myJoin == GeomAbs_Arc)
815 else if (myJoin == GeomAbs_Intersection)
816 BuildOffsetByInter();
820 // if (mySelfInter) SelfInter(Modif);
824 BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
825 Intersection3D (Inter);
829 TopTools_IndexedMapOfShape& Modif = Inter.TouchedFaces();
830 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
832 if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges);
833 //-------------------------------------------------------
834 // Unwinding 2D and reconstruction of modified faces
835 //----------------------------------------------------
837 //-----------------------------------------------------
838 // Reconstruction of non modified faces sharing
839 // reconstructed edges
840 //------------------------------------------------------
841 if (!Modif.IsEmpty()) MakeFaces (Modif);
846 //-------------------------
847 // Construction of shells.
848 //-------------------------
854 //----------------------------------
855 // Remove INTERNAL edges if necessary
856 //----------------------------------
857 if (myRemoveIntEdges) {
858 RemoveInternalEdges();
860 //----------------------------------
861 // Coding of regularities.
862 //----------------------------------
864 //----------------------
865 // Creation of solids.
866 //----------------------
869 //-----------------------------
870 // MAJ Tolerance edge and Vertex
871 // ----------------------------
872 if (!myOffsetShape.IsNull()) {
873 UpdateTolerance (myOffsetShape,myFaces);
874 BRepLib::UpdateTolerances( myOffsetShape );
877 CorrectConicalFaces();
879 // Result solid should be computed in MakeOffset scope.
883 BRepBuilderAPI_Sewing aSew(myTol);
884 aSew.Add(myOffsetShape);
886 myOffsetShape = aSew.SewedShape();
889 // Offset shape expected to be really closed after sewing.
890 myOffsetShape.Closed(Standard_True);
894 myDone = Standard_True;
899 //=======================================================================
900 //function : MakeThickSolid
902 //=======================================================================
904 void BRepOffset_MakeOffset::MakeThickSolid()
906 //--------------------------------------------------------------
907 // Construction of shell parallel to shell (initial without cap).
908 //--------------------------------------------------------------
913 // Save return code and myDone state.
917 //--------------------------------------------------------------------
918 // Construction of a solid with the initial shell, parallel shell
920 //--------------------------------------------------------------------
921 if (!myFaces.IsEmpty())
926 Standard_Integer NbF = myFaces.Extent();
930 BRepTools_Quilt Glue;
931 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
934 Glue.Add (exp.Current());
936 Standard_Boolean YaResult = 0;
937 if (!myOffsetShape.IsNull())
939 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
942 Glue.Add (exp.Current().Reversed());
947 cout << "OffsetShape does not contain a FACES." << endl;
954 cout << "OffsetShape is null!" << endl;
960 myDone = Standard_False;
961 myError = BRepOffset_UnknownError;
965 myOffsetShape = Glue.Shells();
966 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
968 B.Add(Res,exp.Current());
970 Res.Closed(Standard_True);
973 // Test of Validity of the result of thick Solid
974 // more face than the initial solid.
975 Standard_Integer NbOF = 0;
976 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
982 myDone = Standard_False;
983 myError = BRepOffset_UnknownError;
988 if (myOffset > 0 ) myOffsetShape.Reverse();
990 myDone = Standard_True;
993 //=======================================================================
996 //=======================================================================
998 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
1003 //=======================================================================
1006 //=======================================================================
1008 BRepOffset_Error BRepOffset_MakeOffset::Error() const
1013 //=======================================================================
1016 //=======================================================================
1018 const TopoDS_Shape& BRepOffset_MakeOffset::Shape() const
1020 return myOffsetShape;
1023 //=======================================================================
1024 //function : TrimEdge
1025 //purpose : Trim the edge of the largest of descendants in AsDes2d.
1026 // Order in AsDes two vertices that have trimmed the edge.
1027 //=======================================================================
1028 void TrimEdge(TopoDS_Edge& NE,
1029 const Handle(BRepAlgo_AsDes)& AsDes2d,
1030 Handle(BRepAlgo_AsDes)& AsDes)
1032 Standard_Real aSameParTol = Precision::Confusion();
1034 TopoDS_Vertex V1,V2;
1035 Standard_Real U = 0.;
1036 Standard_Real UMin = Precision::Infinite();
1037 Standard_Real UMax = -UMin;
1039 const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
1041 Standard_Boolean bTrim = Standard_False;
1043 if (LE.Extent() > 1) {
1044 TopTools_ListIteratorOfListOfShape it (LE);
1045 for (; it.More(); it.Next()) {
1046 TopoDS_Vertex V = TopoDS::Vertex(it.Value());
1047 if (NE.Orientation() == TopAbs_REVERSED)
1049 //V.Orientation(TopAbs_INTERNAL);
1050 if (!FindParameter(V, NE, U)) {
1052 Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
1053 gp_Pnt thePoint = BRep_Tool::Pnt(V);
1054 GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
1055 if (Projector.NbPoints() == 0)
1056 Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
1057 U = Projector.LowerDistanceParameter();
1067 if (V1.IsNull() || V2.IsNull()) {
1068 Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
1070 if (!V1.IsSame(V2)) {
1071 NE.Free( Standard_True );
1073 TopAbs_Orientation Or = NE.Orientation();
1074 NE.Orientation(TopAbs_FORWARD);
1075 TopoDS_Vertex VF,VL;
1076 TopExp::Vertices (NE,VF,VL);
1079 B.Add (NE,V1.Oriented(TopAbs_FORWARD));
1080 B.Add (NE,V2.Oriented(TopAbs_REVERSED));
1081 B.Range(NE,UMin,UMax);
1083 AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
1084 AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
1085 BRepLib::SameParameter(NE, aSameParTol, Standard_True);
1087 bTrim = Standard_True;
1092 BRepAdaptor_Curve aBAC(NE);
1093 if (aBAC.GetType() == GeomAbs_Line) {
1094 if (AsDes->HasAscendant(NE)) {
1101 //=======================================================================
1102 //function : BuildOffsetByInter
1104 //=======================================================================
1105 void BRepOffset_MakeOffset::BuildOffsetByInter()
1109 cout << " CONSTRUCTION OF OFFSETS :" << endl;
1115 BRepOffset_DataMapOfShapeOffset MapSF;
1116 TopTools_MapOfShape Done;
1117 Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
1118 //--------------------------------------------------------
1119 // Construction of faces parallel to initial faces
1120 //--------------------------------------------------------
1121 TopExp_Explorer Exp;
1122 TopTools_ListOfShape LF;
1123 TopTools_ListIteratorOfListOfShape itLF;
1125 BRepLib::SortFaces(myShape,LF);
1127 TopTools_DataMapOfShapeShape ShapeTgt;
1128 for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
1129 const TopoDS_Face& F = TopoDS::Face(itLF.Value());
1130 Standard_Real CurOffset = myOffset;
1131 if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
1132 BRepOffset_Offset OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
1133 TopTools_ListOfShape Let;
1134 myAnalyse.Edges(F,BRepOffset_Tangent,Let);
1135 TopTools_ListIteratorOfListOfShape itl(Let);
1137 for ( ; itl.More(); itl.Next()) {
1138 const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1139 if ( !ShapeTgt.IsBound(Cur)) {
1140 TopoDS_Shape aLocalShape = OF.Generated(Cur);
1141 const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1142 // const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
1143 ShapeTgt.Bind(Cur,OF.Generated(Cur));
1144 TopoDS_Vertex V1,V2,OV1,OV2;
1145 TopExp::Vertices (Cur,V1,V2);
1146 TopExp::Vertices (OTE,OV1,OV2);
1147 TopTools_ListOfShape LE;
1148 if (!ShapeTgt.IsBound(V1)) {
1149 myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
1150 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1151 if (LE.Extent() == LA.Extent())
1152 ShapeTgt.Bind(V1,OV1);
1154 if (!ShapeTgt.IsBound(V2)) {
1156 myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
1157 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1158 if (LE.Extent() == LA.Extent())
1159 ShapeTgt.Bind(V2,OV2);
1165 //--------------------------------------------------------------------
1166 // MES : Map of OffsetShape -> Extended Shapes.
1167 // Build : Map of Initial SS -> OffsetShape build by Inter.
1168 // can be an edge or a compound of edges
1169 //---------------------------------------------------------------------
1170 TopTools_DataMapOfShapeShape MES;
1171 TopTools_DataMapOfShapeShape Build;
1172 TopTools_ListOfShape Failed;
1173 TopAbs_State Side = TopAbs_IN;
1174 Handle(BRepAlgo_AsDes) AsDes = new BRepAlgo_AsDes();
1176 //-------------------------------------------------------------------
1177 // Extension of faces and calculation of new edges of intersection.
1178 //-------------------------------------------------------------------
1179 Standard_Boolean ExtentContext = 0;
1180 if (myOffset > 0) ExtentContext = 1;
1182 BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1183 // Intersection between parallel faces
1184 Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1185 // Intersection with caps.
1186 Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar);
1189 //---------------------------------------------------------------------------------
1190 // Extension of neighbor edges of new edges and intersection between neighbors.
1191 //--------------------------------------------------------------------------------
1192 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1193 Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1194 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next())
1196 const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1197 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(FI);
1198 BRepOffset_Inter2d::ConnexIntByInt (FI, MapSF(FI), MES, Build,
1199 AsDes, AsDes2d, myOffset, aCurrFaceTol, aDMVV);
1202 // fuse vertices on edges
1203 BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes2d);
1204 //-----------------------------------------------------------
1205 // Great restriction of new edges and update of AsDes.
1206 //------------------------------------------ ----------------
1207 TopTools_IndexedMapOfShape NewEdges;
1208 TopExp_Explorer Exp2,ExpC;
1212 TopTools_IndexedDataMapOfShapeListOfShape anOrigins;
1214 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1215 const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
1216 NF = MapSF(FI).Face();
1217 if (MES.IsBound(NF)) {
1218 NF = TopoDS::Face(MES(NF));
1221 TopTools_MapOfShape View;
1222 TopTools_IndexedMapOfShape VEmap;
1223 Standard_Integer i, aNb;
1225 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap);
1226 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
1228 aNb = VEmap.Extent();
1229 for (i = 1; i <= aNb; ++i) {
1230 const TopoDS_Shape& aS = VEmap(i);
1231 if (!View.Add(aS)) {
1235 if (Build.IsBound(aS)) {
1237 if (NE.ShapeType() == TopAbs_EDGE) {
1238 if (anOrigins.Contains(NE)) {
1239 anOrigins.ChangeFromKey(NE).Append(aS);
1242 TopTools_ListOfShape aLSx;
1244 anOrigins.Add(NE, aLSx);
1247 if (NewEdges.Add(NE)) {
1248 TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
1252 //------------------------------------------------------------
1253 // The Intersections are on several edges.
1254 // The pieces without intersections with neighbors
1255 // are removed from AsDes.
1256 //------------------------------------------------------------
1257 for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1258 TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
1259 if (NewEdges.Add(NEC)) {
1260 NEC.Free(Standard_True);
1261 if (anOrigins.Contains(NEC)) {
1262 anOrigins.ChangeFromKey(NEC).Append(aS);
1265 TopTools_ListOfShape aLSx;
1267 anOrigins.Add(NEC, aLSx);
1270 if (!AsDes2d->Descendant(NEC).IsEmpty()) {
1271 TrimEdge (NEC,AsDes2d,AsDes);
1274 if (AsDes->HasAscendant(NEC)) {
1283 if (aS.ShapeType() != TopAbs_EDGE) {
1287 NE = MapSF(FI).Generated(aS);
1288 //// modified by jgv, 19.12.03 for OCC4455 ////
1289 NE.Orientation(aS.Orientation());
1290 if (anOrigins.Contains(NE)) {
1291 anOrigins.ChangeFromKey(NE).Append(aS);
1294 TopTools_ListOfShape aLSx;
1296 anOrigins.Add(NE, aLSx);
1299 if (MES.IsBound(NE)) {
1301 NE.Orientation(aS.Orientation());
1302 if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);}
1309 //---------------------------------
1310 // Intersection 2D on //
1311 //---------------------------------
1312 TopTools_ListOfShape LFE;
1313 BRepAlgo_Image IMOE;
1314 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1315 const TopoDS_Shape& FI = Exp.Current();
1316 const TopoDS_Shape& OFI = MapSF(FI).Face();
1317 if (MES.IsBound(OFI)) {
1318 const TopoDS_Face& aLocalFace = TopoDS::Face(MES(OFI));
1319 LFE.Append(aLocalFace);
1320 IMOE.SetRoot(aLocalFace);
1322 if (anOrigins.Contains(aLocalFace)) {
1323 anOrigins.ChangeFromKey(aLocalFace).Append(FI);
1326 TopTools_ListOfShape aLSx;
1328 anOrigins.Add(aLocalFace, aLSx);
1334 TopTools_ListIteratorOfListOfShape itLFE(LFE);
1335 for (; itLFE.More(); itLFE.Next())
1337 const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1338 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
1339 BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV);
1341 //----------------------------------------------
1342 // Intersections 2d on caps.
1343 //----------------------------------------------
1345 for (i = 1; i <= myFaces.Extent(); i++)
1347 const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1348 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
1349 BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV);
1352 BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes);
1353 //-------------------------------
1354 // Unwinding of extended Faces.
1355 //-------------------------------
1357 TopTools_MapOfShape aMFDone;
1359 if ((myJoin == GeomAbs_Intersection) && myInter) {
1360 TopTools_ListOfShape aLFailed;
1361 BuildSplitsOfFaces(LFE, AsDes, anOrigins, IMOE, aLFailed, Standard_False);
1362 if (aLFailed.Extent()) {
1363 myMakeLoops.Build(aLFailed, AsDes, IMOE);
1366 if (LFE.Extent() != aLFailed.Extent()) {
1367 TopTools_MapOfShape aMFailed;
1368 TopTools_ListIteratorOfListOfShape aItLF(aLFailed);
1369 for (; aItLF.More(); aItLF.Next()) {
1370 const TopoDS_Shape& aS = aItLF.Value();
1374 aItLF.Initialize(LFE);
1375 for (; aItLF.More(); aItLF.Next()) {
1376 const TopoDS_Shape& aS = aItLF.Value();
1377 if (!aMFailed.Contains(aS)) {
1384 myMakeLoops.Build(LFE, AsDes, IMOE);
1388 TopTools_IndexedMapOfShape COES;
1390 //---------------------------
1391 // MAJ SD. for faces //
1392 //---------------------------
1393 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1394 const TopoDS_Shape& FI = Exp.Current();
1395 myInitOffsetFace.SetRoot(FI);
1396 TopoDS_Face OF = MapSF(FI).Face();
1397 if (MES.IsBound(OF)) {
1398 OF = TopoDS::Face(MES(OF));
1399 if (IMOE.HasImage(OF)) {
1400 const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1401 myInitOffsetFace.Bind(FI,LOFE);
1402 for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1403 const TopoDS_Shape& OFE = itLF.Value();
1404 myImageOffset.SetRoot(OFE);
1407 sprintf(name,"AF_%d",NbAF++);
1408 DBRep::Set(name,OFE);
1411 TopTools_MapOfShape View;
1412 for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1413 Exp2.More(); Exp2.Next()) {
1414 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1416 myAsDes->Add (OFE,COE);
1419 sprintf(name,"AE_%d",NbAE++);
1420 DBRep::Set(name,COE);
1425 if (!myAsDes->HasDescendant(COE)) {
1426 TopoDS_Vertex CV1,CV2;
1427 TopExp::Vertices(COE,CV1,CV2);
1428 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1429 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1436 if (aMFDone.Contains(OF)) {
1440 myInitOffsetFace.Bind(FI,OF);
1441 myImageOffset.SetRoot(OF);
1444 sprintf(name,"AF_%d",NbAF++);
1445 DBRep::Set(name,OF);
1448 const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1449 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1450 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1451 if (IMOE.HasImage(OE)) {
1452 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1453 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1454 for (; itLOE.More(); itLOE.Next()) {
1455 TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1456 const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1457 // const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1458 myAsDes->Add(OF,COE);
1461 sprintf(name,"AE_%d",NbAE++);
1462 DBRep::Set(name,COE);
1467 if (!myAsDes->HasDescendant(COE)) {
1468 TopoDS_Vertex CV1,CV2;
1469 TopExp::Vertices(COE,CV1,CV2);
1470 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1471 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1476 myAsDes->Add(OF,OE);
1479 sprintf(name,"AE_%d",NbAE++);
1480 DBRep::Set(name,OE);
1485 const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1486 myAsDes->Add(OE,LV);
1492 myInitOffsetFace.Bind(FI,OF);
1493 myImageOffset.SetRoot(OF);
1494 TopTools_MapOfShape View;
1495 for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1496 Exp2.More(); Exp2.Next()) {
1498 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1499 myAsDes->Add (OF,COE);
1502 sprintf(name,"AE_%d",NbAE++);
1503 DBRep::Set(name,COE);
1508 if (View.Add(Exp2.Current())) {
1509 if (!myAsDes->HasDescendant(COE)) {
1510 TopoDS_Vertex CV1,CV2;
1511 TopExp::Vertices(COE,CV1,CV2);
1512 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1513 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1519 // Modified by skv - Tue Mar 15 16:20:43 2005
1520 // Add methods for supporting history.
1521 TopTools_MapOfShape aMapEdges;
1523 for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
1524 const TopoDS_Shape& aFaceRef = Exp.Current();
1526 Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1528 for (; Exp2.More(); Exp2.Next()) {
1529 const TopoDS_Shape& anEdgeRef = Exp2.Current();
1531 if (aMapEdges.Add(anEdgeRef)) {
1532 myInitOffsetEdge.SetRoot(anEdgeRef);
1533 if (Build.IsBound(anEdgeRef)) {
1534 TopoDS_Shape aNewShape = Build(anEdgeRef);
1536 if (aNewShape.ShapeType() == TopAbs_EDGE) {
1537 if (IMOE.HasImage(aNewShape)) {
1538 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1540 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1542 myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1543 } else { // aNewShape != TopAbs_EDGE
1544 TopTools_ListOfShape aListNewEdge;
1546 for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1547 const TopoDS_Shape &aResEdge = ExpC.Current();
1549 if (IMOE.HasImage(aResEdge)) {
1550 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1551 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1553 for (; aNewEIter.More(); aNewEIter.Next())
1554 aListNewEdge.Append(aNewEIter.Value());
1556 aListNewEdge.Append(aResEdge);
1559 myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1562 else { // Free boundary.
1563 TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1565 if (MES.IsBound(aNewEdge))
1566 aNewEdge = MES(aNewEdge);
1568 if (IMOE.HasImage(aNewEdge)) {
1569 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1571 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1573 myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1578 // Modified by skv - Tue Mar 15 16:20:43 2005
1580 //---------------------------
1582 //---------------------------
1583 //TopTools_MapOfShape View;
1584 for (i = 1; i <= myFaces.Extent(); i++) {
1585 const TopoDS_Shape& Cork = myFaces(i);
1586 const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1587 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1588 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1589 if (IMOE.HasImage(OE)) {
1590 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1591 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1592 for (; itLOE.More(); itLOE.Next()) {
1593 const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1594 myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1597 sprintf(name,"AE_%d",NbAE++);
1598 DBRep::Set(name,COE);
1603 if (!myAsDes->HasDescendant(COE)) {
1604 TopoDS_Vertex CV1,CV2;
1605 TopExp::Vertices(COE,CV1,CV2);
1606 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1607 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1612 myAsDes->Add(Cork,OE);
1613 if (AsDes->HasDescendant(OE)) {
1614 myAsDes->Add(OE,AsDes->Descendant(OE));
1618 sprintf(name,"AE_%d",NbAE++);
1619 DBRep::Set(name,OE);
1628 DEBVerticesControl (COES,myAsDes);
1629 if ( ChronBuild) Clock.Show();
1633 //=======================================================================
1634 //function : BuildSplitsOfFaces
1636 //=======================================================================
1637 void BRepOffset_MakeOffset::BuildSplitsOfFaces
1638 (const TopTools_ListOfShape& theLF,
1639 const Handle(BRepAlgo_AsDes)& theAsDes,
1640 TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
1641 BRepAlgo_Image& theImage,
1642 TopTools_ListOfShape& theLFailed,
1643 const Standard_Boolean bLimited)
1646 theLFailed.Assign(theLF);
1650 BOPCol_ListOfShape aLS, aLF;
1651 BOPCol_ListIteratorOfListOfShape aIt;
1652 TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1;
1653 TopTools_DataMapOfShapeListOfShape anEImages;
1655 TopoDS_Compound aFaces;
1657 aBB.MakeCompound(aFaces);
1659 // firstly it is necessary to fuse all the edges
1660 Handle(IntTools_Context) aCtx = new IntTools_Context();
1662 aItLF.Initialize(theLF);
1663 for (; aItLF.More(); aItLF.Next()) {
1664 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1666 const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
1667 aItLE.Initialize(aLE);
1668 for (; aItLE.More(); aItLE.Next()) {
1669 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1670 if (BRep_Tool::Degenerated(aE)) {
1674 if (ProcessMicroEdge(aE, aCtx)) {
1682 if (aLS.Extent() > 1) {
1683 BOPAlgo_Builder aGFE;
1685 aGFE.SetArguments(aLS);
1687 if (aGFE.ErrorStatus() == 0) {
1688 // fill map with edges images
1689 aIt.Initialize(aLS);
1690 for (; aIt.More(); aIt.Next()) {
1691 const TopoDS_Shape& aE = aIt.Value();
1693 const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
1694 if (aLEIm.Extent()) {
1695 anEImages.Bind(aE, aLEIm);
1699 UpdateOrigins(theOrigins, aGFE);
1703 // now we can split the faces
1704 aItLF.Initialize(theLF);
1705 for (; aItLF.More(); aItLF.Next()) {
1706 const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
1710 aLS.Append(aF.Oriented(TopAbs_FORWARD));
1712 Standard_Integer iCountE = 0;
1713 TopTools_MapOfShape aMFE;
1714 TopExp_Explorer aExp(aF, TopAbs_EDGE);
1715 for (; aExp.More(); aExp.Next()) {
1716 const TopoDS_Shape& aE = aExp.Current();
1717 if (anEImages.IsBound(aE)) {
1718 const TopTools_ListOfShape& aLEIm = anEImages.Find(aE);
1719 aItLE.Initialize(aLEIm);
1720 for (; aItLE.More(); aItLE.Next()) {
1721 const TopoDS_Shape& aEIm = aItLE.Value();
1730 // the edges by which the offset face should be split
1731 const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
1732 aItLE.Initialize(aLE);
1733 for (; aItLE.More(); aItLE.Next()) {
1734 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
1735 if (BRep_Tool::Degenerated(aE)) {
1739 if (anEImages.IsBound(aE)) {
1740 const TopTools_ListOfShape& aLEIm = anEImages.Find(aE);
1741 aItLE1.Initialize(aLEIm);
1742 for (; aItLE1.More(); aItLE1.Next()) {
1743 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aItLE1.Value();
1744 // check for micro edge
1745 if (ProcessMicroEdge(aEIm, aCtx)) {
1750 if (!aMFE.Contains(aEIm)) {
1756 if (ProcessMicroEdge(aE, aCtx)) {
1760 if (!aMFE.Contains(aE)) {
1766 TopTools_ListOfShape aLFImages;
1768 // split the face by the edges
1770 if (bLimited && !theImage.HasImage(aF)) {
1771 aLFImages.Append(aF);
1772 theImage.Bind(aF, aLFImages);
1773 aBB.Add(aFaces, aF);
1778 BOPAlgo_Builder aGF;
1780 aGF.SetArguments(aLS);
1782 if (aGF.ErrorStatus()) {
1783 theLFailed.Append(aF);
1787 // splits of the offset shape
1788 aLFImages = aGF.Modified(aF);
1789 if (aLFImages.IsEmpty()) {
1790 theLFailed.Append(aF);
1794 TopTools_MapOfShape aME;
1795 // collect images of Edges
1796 aItLE.Initialize(aLE);
1797 for (; aItLE.More(); aItLE.Next()) {
1798 const TopoDS_Shape& aE = aItLE.Value();
1799 if (anEImages.IsBound(aE)) {
1800 TopTools_MapOfShape aMFence;
1801 TopTools_ListOfShape aLEImNew;
1802 Standard_Boolean bModif = Standard_False;
1804 TopTools_ListOfShape& aLEIm = anEImages.ChangeFind(aE);
1805 aItLE1.Initialize(aLEIm);
1806 for (; aItLE1.More(); aItLE1.Next()) {
1807 const TopoDS_Shape& aEIm = aItLE1.Value();
1808 const TopTools_ListOfShape& aLEImIm = aGF.Modified(aEIm);
1809 if (aLEImIm.Extent()) {
1810 bModif = Standard_True;
1811 TopTools_ListIteratorOfListOfShape aItLEIm(aLEImIm);
1812 for (; aItLEIm.More(); aItLEIm.Next()) {
1813 const TopoDS_Shape& aEImIm = aItLEIm.Value();
1814 if (aMFence.Add(aEImIm)) {
1815 aLEImNew.Append(aEImIm);
1821 aLEImNew.Append(aEIm);
1827 aLEIm.Assign(aLEImNew);
1831 const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
1832 if (aLEIm.Extent()) {
1833 anEImages.Bind(aE, aLEIm);
1834 TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
1835 for (; aItLEIm.More(); aItLEIm.Next()) {
1836 const TopoDS_Shape& aEIm = aItLEIm.Value();
1848 // to overcome the often errors in trimming edges it is
1849 // better to remove first the faces containing the boundaries
1850 // of the extended surfaces;
1851 Standard_Boolean bKeep;
1852 aItLE.Initialize(aLFImages);
1853 for (; aItLE.More();) {
1854 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLE.Value();
1856 aExp.Init(aFIm, TopAbs_EDGE);
1857 for (bKeep = Standard_True; aExp.More() && bKeep; aExp.Next()) {
1858 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
1860 if (BRep_Tool::Degenerated(aE)) {
1864 bKeep = aME.Contains(aE);
1871 aLFImages.Remove(aItLE);
1875 UpdateOrigins(theOrigins, aGF);
1877 if (aLFImages.Extent() >= 1) {
1878 TopTools_ListOfShape aLFKeep;
1880 // check offset faces on the coincidence of the
1881 // bi-normal directions with the original faces
1882 CheckBiNormals(aLFImages, aF, theOrigins, aLFKeep, myRemoveInvalidFaces);
1885 if (aLFImages.Extent() > 1) {
1886 TopTools_ListOfShape aLFTmp = aLFImages;
1889 SortFaces(aLFTmp, aLFImages, Standard_True);
1892 if (aLFKeep.Extent()) {
1893 TopTools_MapOfShape aMFence;
1894 aItLE.Initialize(aLFImages);
1895 for (; aItLE.More(); aItLE.Next()) {
1896 const TopoDS_Shape& aFIm = aItLE.Value();
1900 aItLE.Initialize(aLFKeep);
1901 for (; aItLE.More(); aItLE.Next()) {
1902 const TopoDS_Shape& aFIm = aItLE.Value();
1903 if (aMFence.Add(aFIm)) {
1904 aLFImages.Append(aFIm);
1911 // Fill history for faces
1912 if (aLFImages.Extent()) {
1913 if (theImage.HasImage(aF)) {
1914 theImage.Add(aF, aLFImages);
1917 theImage.Bind(aF, aLFImages);
1921 aItLE.Initialize(aLFImages);
1922 for (; aItLE.More(); aItLE.Next()) {
1923 const TopoDS_Shape& aFIm = aItLE.Value();
1924 aBB.Add(aFaces, aFIm);
1928 // fill history for edges
1929 TopTools_IndexedMapOfShape aMFE;
1930 TopExp::MapShapes(aFaces, TopAbs_EDGE, aMFE);
1932 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(anEImages);
1933 for (; aItEIm.More(); aItEIm.Next()) {
1934 const TopoDS_Shape& aE = aItEIm.Key();
1935 const TopTools_ListOfShape& aLEIm = aItEIm.Value();
1937 Standard_Boolean bHasImage = theImage.HasImage(aE);
1938 aItLE.Initialize(aLEIm);
1939 for (; aItLE.More(); aItLE.Next()) {
1940 const TopoDS_Shape& aEIm = aItLE.Value();
1941 if (aMFE.Contains(aEIm)) {
1943 theImage.Add(aE, aEIm);
1946 theImage.Bind(aE, aEIm);
1947 bHasImage = Standard_True;
1954 //=======================================================================
1955 //function : BuildOffsetByArc
1957 //=======================================================================
1958 void BRepOffset_MakeOffset::BuildOffsetByArc()
1962 cout << " CONSTRUCTION OF OFFSETS :" << endl;
1968 BRepOffset_DataMapOfShapeOffset MapSF;
1969 TopTools_MapOfShape Done;
1970 Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
1971 //--------------------------------------------------------
1972 // Construction of faces parallel to initial faces
1973 //--------------------------------------------------------
1974 TopExp_Explorer Exp;
1975 TopTools_ListOfShape LF;
1976 TopTools_ListIteratorOfListOfShape itLF;
1978 BRepLib::SortFaces(myShape,LF);
1980 TopTools_DataMapOfShapeShape EdgeTgt;
1981 for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
1982 const TopoDS_Face& F = TopoDS::Face(itLF.Value());
1983 Standard_Real CurOffset = myOffset;
1984 if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
1985 BRepOffset_Offset OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
1986 TopTools_ListOfShape Let;
1987 myAnalyse.Edges(F,BRepOffset_Tangent,Let);
1988 TopTools_ListIteratorOfListOfShape itl(Let);
1990 for ( ; itl.More(); itl.Next()) {
1991 const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1992 if ( !EdgeTgt.IsBound(Cur)) {
1993 TopoDS_Shape aLocalShape = OF.Generated(Cur);
1994 const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1995 // const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
1996 EdgeTgt.Bind(Cur,OF.Generated(Cur));
1997 TopoDS_Vertex V1,V2,OV1,OV2;
1998 TopExp::Vertices (Cur,V1,V2);
1999 TopExp::Vertices (OTE,OV1,OV2);
2000 TopTools_ListOfShape LE;
2001 if (!EdgeTgt.IsBound(V1)) {
2002 myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
2003 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
2004 if (LE.Extent() == LA.Extent())
2005 EdgeTgt.Bind(V1,OV1);
2007 if (!EdgeTgt.IsBound(V2)) {
2009 myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
2010 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
2011 if (LE.Extent() == LA.Extent())
2012 EdgeTgt.Bind(V2,OV2);
2018 //--------------------------------------------------------
2019 // Construction of tubes on edge.
2020 //--------------------------------------------------------
2021 BRepOffset_Type OT = BRepOffset_Convex;
2022 if (myOffset < 0.) OT = BRepOffset_Concave;
2024 for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) {
2025 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
2027 const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
2028 if (Anc.Extent() == 2) {
2029 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
2030 if (!L.IsEmpty() && L.First().Type() == OT) {
2031 Standard_Real CurOffset = myOffset;
2032 if ( myFaceOffset.IsBound(Anc.First()))
2033 CurOffset = myFaceOffset(Anc.First());
2034 TopoDS_Shape aLocalShapeGen = MapSF(Anc.First()).Generated(E);
2035 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
2036 aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
2037 TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
2038 // TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
2039 // TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
2040 // find if exits tangent edges in the original shape
2041 TopoDS_Edge E1f, E1l;
2042 TopoDS_Vertex V1f, V1l;
2043 TopExp::Vertices(E,V1f,V1l);
2044 TopTools_ListOfShape TangE;
2045 myAnalyse.TangentEdges(E,V1f,TangE);
2046 // find if the pipe on the tangent edges are soon created.
2047 TopTools_ListIteratorOfListOfShape itl(TangE);
2048 Standard_Boolean Find = Standard_False;
2049 for ( ; itl.More() && !Find; itl.Next()) {
2050 if ( MapSF.IsBound(itl.Value())) {
2051 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
2052 E1f = TopoDS::Edge(aLocalShape);
2053 // E1f = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
2054 Find = Standard_True;
2058 myAnalyse.TangentEdges(E,V1l,TangE);
2059 // find if the pipe on the tangent edges are soon created.
2060 itl.Initialize(TangE);
2061 Find = Standard_False;
2062 for ( ; itl.More() && !Find; itl.Next()) {
2063 if ( MapSF.IsBound(itl.Value())) {
2064 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
2065 E1l = TopoDS::Edge(aLocalShape);
2066 // E1l = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
2067 Find = Standard_True;
2070 BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
2075 // ----------------------
2077 // ----------------------
2078 TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
2079 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
2080 /// TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
2081 myInitOffsetEdge.SetRoot(E); // skv: supporting history.
2082 myInitOffsetEdge.Bind (E,EOn1);
2087 //--------------------------------------------------------
2088 // Construction of spheres on vertex.
2089 //--------------------------------------------------------
2091 TopTools_ListIteratorOfListOfShape it;
2093 for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) {
2094 const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
2096 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
2097 TopTools_ListOfShape LE;
2098 myAnalyse.Edges(V,OT,LE);
2100 if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
2101 TopTools_ListOfShape LOE;
2102 //--------------------------------------------------------
2103 // Return connected edges on tubes.
2104 //--------------------------------------------------------
2105 for (it.Initialize(LE) ; it.More(); it.Next()) {
2106 LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
2108 //----------------------
2109 // construction sphere.
2110 //-----------------------
2111 const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
2112 const TopoDS_Shape& FF = LLA.First();
2113 Standard_Real CurOffset = myOffset;
2114 if ( myFaceOffset.IsBound(FF))
2115 CurOffset = myFaceOffset(FF);
2117 BRepOffset_Offset OF(V,LOE,CurOffset);
2120 //--------------------------------------------------------------
2121 // Particular processing if V is at least a free border.
2122 //-------------------------------------------------------------
2123 TopTools_ListOfShape LBF;
2124 myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF);
2125 if (!LBF.IsEmpty()) {
2126 Standard_Boolean First = Standard_True;
2127 for (it.Initialize(LE) ; it.More(); it.Next()) {
2129 myInitOffsetEdge.SetRoot(V); // skv: supporting history.
2130 myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
2131 First = Standard_False;
2134 myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
2141 //------------------------------------------------------------
2142 // Extension of parallel faces to the context.
2143 // Extended faces are ordered in DS and removed from MapSF.
2144 //------------------------------------------------------------
2145 if (!myFaces.IsEmpty()) ToContext (MapSF);
2147 //------------------------------------------------------
2149 //------------------------------------------------------
2150 BRepOffset_Type RT = BRepOffset_Concave;
2151 if (myOffset < 0.) RT = BRepOffset_Convex;
2152 BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
2153 for ( ; It.More(); It.Next()) {
2154 const TopoDS_Shape& SI = It.Key();
2155 const BRepOffset_Offset& SF = It.Value();
2156 if (SF.Status() == BRepOffset_Reversed ||
2157 SF.Status() == BRepOffset_Degenerated ) {
2158 //------------------------------------------------
2159 // Degenerated or returned faces are not stored.
2160 //------------------------------------------------
2164 const TopoDS_Face& OF = It.Value().Face();
2165 myInitOffsetFace.Bind (SI,OF);
2166 myInitOffsetFace.SetRoot (SI); // Initial<-> Offset
2167 myImageOffset.SetRoot (OF); // FaceOffset root of images
2169 if (SI.ShapeType() == TopAbs_FACE) {
2170 for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2171 Exp.More(); Exp.Next()) {
2172 //--------------------------------------------------------------------
2173 // To each face are associatedthe edges that restrict that
2174 // The edges that do not generate tubes or are not tangent
2175 // to two faces are removed.
2176 //--------------------------------------------------------------------
2177 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
2178 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
2179 if (!L.IsEmpty() && L.First().Type() != RT) {
2180 TopAbs_Orientation OO = E.Orientation();
2181 TopoDS_Shape aLocalShape = It.Value().Generated(E);
2182 TopoDS_Edge OE = TopoDS::Edge(aLocalShape);
2183 // TopoDS_Edge OE = TopoDS::Edge(It.Value().Generated(E));
2184 myAsDes->Add (OF,OE.Oriented(OO));
2189 for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2190 Exp.More(); Exp.Next()) {
2191 myAsDes->Add (OF,Exp.Current());
2197 if ( ChronBuild) Clock.Show();
2203 //=======================================================================
2204 //function : SelfInter
2206 //=======================================================================
2208 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
2212 cout << " AUTODEBOUCLAGE:" << endl;
2218 Standard_NotImplemented::Raise();
2221 if ( ChronBuild) Clock.Show();
2226 //=======================================================================
2227 //function : ToContext
2229 //=======================================================================
2231 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
2233 TopTools_DataMapOfShapeShape Created;
2234 TopTools_DataMapOfShapeShape MEF;
2235 TopTools_IndexedMapOfShape FacesToBuild;
2236 TopTools_ListIteratorOfListOfShape itl;
2237 TopExp_Explorer exp;
2239 // TopAbs_State Side = TopAbs_IN;
2240 // if (myOffset < 0.) Side = TopAbs_OUT;
2242 TopAbs_State Side = TopAbs_OUT;
2246 for (i = 1; i <= myFaces.Extent(); i++) {
2247 const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
2248 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2249 exp.More(); exp.Next()) {
2250 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2251 if (!myAnalyse.HasAncestor(E)) {
2252 //----------------------------------------------------------------
2253 // The edges of context faces that are not in the initial shape
2254 // can appear in the result.
2255 //----------------------------------------------------------------
2256 //myAsDes->Add(CF,E);
2262 //--------------------------------------------------------
2263 // Determine the edges and faces reconstructed by
2265 //---------------------------------------------------------
2267 for (j = 1; j <= myFaces.Extent(); j++) {
2268 const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
2269 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2270 exp.More(); exp.Next()) {
2271 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2272 if (myAnalyse.HasAncestor(E)) {
2273 const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
2274 for (itl.Initialize(LEA); itl.More(); itl.Next()) {
2275 const BRepOffset_Offset& OF = MapSF(itl.Value());
2276 FacesToBuild.Add(itl.Value());
2277 MEF.Bind(OF.Generated(E),CF);
2280 TopExp::Vertices(E,V[0],V[1]);
2281 for (Standard_Integer i = 0; i < 2; i++) {
2282 const TopTools_ListOfShape& LVA = myAnalyse.Ancestors(V[i]);
2283 for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
2284 const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
2285 if (MapSF.IsBound(EV)) {
2286 const BRepOffset_Offset& OF = MapSF(EV);
2287 FacesToBuild.Add(EV);
2288 MEF.Bind(OF.Generated(V[i]),CF);
2295 //---------------------------
2296 // Reconstruction of faces.
2297 //---------------------------
2299 BRepOffset_Type RT = BRepOffset_Concave;
2300 if (myOffset < 0.) RT = BRepOffset_Convex;
2302 TopAbs_Orientation Or;
2304 for (j = 1; j <= FacesToBuild.Extent(); j++) {
2305 const TopoDS_Shape& S = FacesToBuild(j);
2306 BRepOffset_Offset BOF;
2308 F = TopoDS::Face(BOF.Face());
2309 BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
2314 myInitOffsetFace.Bind (S,NF);
2315 myInitOffsetFace.SetRoot (S); // Initial<-> Offset
2316 myImageOffset.SetRoot (NF);
2318 if (S.ShapeType() == TopAbs_FACE) {
2319 for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2320 exp.More(); exp.Next()) {
2322 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2323 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
2324 OE = BOF.Generated(E);
2325 Or = E.Orientation();
2327 if (!L.IsEmpty() && L.First().Type() != RT) {
2328 if (Created.IsBound(OE)) {
2330 if (NE.Orientation() == TopAbs_REVERSED)
2331 NE.Orientation(TopAbs::Reverse(Or));
2334 myAsDes->Add(NF,NE);
2337 myAsDes->Add(NF,OE);
2343 //------------------
2345 //---------------------
2346 for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2347 exp.More(); exp.Next()) {
2348 myAsDes->Add (NF,exp.Current());
2354 //------------------
2356 //------------------
2357 TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
2358 for (itc.Initialize(Created); itc.More(); itc.Next()) {
2361 if (myInitOffsetEdge.IsImage(OE)) {
2362 TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
2363 Or = myInitOffsetEdge.Image(E).First().Orientation();
2364 if (NE.Orientation() == TopAbs_REVERSED)
2365 NE.Orientation(TopAbs::Reverse(Or));
2368 myInitOffsetEdge.Remove(OE);
2369 myInitOffsetEdge.Bind(E,NE);
2375 //=======================================================================
2376 //function : UpdateFaceOffset
2378 //=======================================================================
2380 void BRepOffset_MakeOffset::UpdateFaceOffset()
2382 TopTools_MapOfShape M;
2383 TopTools_DataMapOfShapeReal CopiedMap;
2384 CopiedMap.Assign(myFaceOffset);
2385 TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
2387 BRepOffset_Type RT = BRepOffset_Convex;
2388 if (myOffset < 0.) RT = BRepOffset_Concave;
2390 for ( ; it.More(); it.Next()) {
2391 const TopoDS_Face& F = TopoDS::Face(it.Key());
2392 Standard_Real CurOffset = CopiedMap(F);
2393 if ( !M.Add(F)) continue;
2396 Build.MakeCompound(Co);
2397 TopTools_MapOfShape Dummy;
2399 if (myJoin == GeomAbs_Arc)
2400 myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT);
2402 myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent);
2404 TopExp_Explorer exp(Co,TopAbs_FACE);
2405 for (; exp.More(); exp.Next()) {
2406 const TopoDS_Face& FF = TopoDS::Face(exp.Current());
2407 if ( !M.Add(FF)) continue;
2408 if ( myFaceOffset.IsBound(FF))
2409 myFaceOffset.UnBind(FF);
2410 myFaceOffset.Bind(FF,CurOffset);
2415 //=======================================================================
2416 //function : CorrectConicalFaces
2418 //=======================================================================
2420 void BRepOffset_MakeOffset::CorrectConicalFaces()
2422 if(myOffsetShape.IsNull())
2427 TopTools_SequenceOfShape Cones;
2428 TopTools_SequenceOfShape Circs;
2429 TopTools_SequenceOfShape Seams;
2430 Standard_Real TolApex = 1.e-5;
2434 TopTools_DataMapOfShapeListOfShape FacesOfCone;
2435 //TopTools_DataMapOfShapeShape DegEdges;
2436 TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
2437 if (myJoin == GeomAbs_Arc)
2439 for (; Explo.More(); Explo.Next())
2441 TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
2442 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
2443 //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2444 //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
2446 TopTools_IndexedMapOfShape Emap;
2447 TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
2448 for (i = 1; i <= Emap.Extent(); i++)
2450 TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
2451 //Standard_Real f, l;
2452 //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
2453 //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
2454 if (BRep_Tool::Degenerated(anEdge))
2456 //Check if anEdge is a really degenerated edge or not
2457 BRepAdaptor_Curve BACurve(anEdge, aFace);
2458 gp_Pnt Pfirst, Plast, Pmid;
2459 Pfirst = BACurve.Value(BACurve.FirstParameter());
2460 Plast = BACurve.Value(BACurve.LastParameter());
2461 Pmid = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
2462 if (Pfirst.Distance(Plast) <= TolApex &&
2463 Pfirst.Distance(Pmid) <= TolApex)
2465 //Cones.Append( aFace );
2466 //Circs.Append( anEdge );
2467 //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
2468 TopoDS_Edge OrEdge =
2469 TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
2470 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2471 if ( FacesOfCone.IsBound(VF) )
2473 //add a face to the existing list
2474 TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
2475 aFaces.Append (aFace);
2476 //DegEdges.Bind(aFace, anEdge);
2480 //the vertex is not in the map => create a new key and items
2481 TopTools_ListOfShape aFaces;
2482 aFaces.Append (aFace);
2483 FacesOfCone.Bind(VF, aFaces);
2484 //DegEdges.Bind(aFace, anEdge);
2487 } //for (i = 1; i <= Emap.Extent(); i++)
2488 } //for (; fexp.More(); fexp.Next())
2489 } //if (myJoin == GeomAbs_Arc)
2491 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
2494 Standard_Boolean IsModified = Standard_False;
2495 for (; Cone.More(); Cone.Next() ) {
2496 gp_Sphere theSphere;
2497 Handle(Geom_SphericalSurface) aSphSurf;
2498 TopoDS_Wire SphereWire;
2499 BB.MakeWire(SphereWire);
2500 TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
2501 const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
2502 TopTools_ListIteratorOfListOfShape itFaces(Faces);
2503 Standard_Boolean isFirstFace = Standard_True;
2505 TopoDS_Vertex theFirstVertex, CurFirstVertex;
2506 for (; itFaces.More(); itFaces.Next())
2508 TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
2509 TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
2510 for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2512 DegEdge = TopoDS::Edge(Explo.Current());
2513 if (BRep_Tool::Degenerated(DegEdge))
2515 TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
2516 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2517 if (VF.IsSame(anApex))
2521 TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
2522 TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
2523 BB.Degenerated(CurEdge, Standard_False);
2524 BB.SameRange(CurEdge, Standard_False);
2525 BB.SameParameter(CurEdge, Standard_False);
2526 gp_Pnt fPnt, lPnt, mPnt;
2527 GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
2529 BRep_Tool::Range(CurEdge, f, l);
2532 gp_Vec aVec1(fPnt, mPnt);
2533 gp_Vec aVec2(fPnt, lPnt);
2534 gp_Vec aNorm = aVec1.Crossed(aVec2);
2535 gp_Pnt theApex = BRep_Tool::Pnt(anApex);
2536 gp_Vec ApexToFpnt(theApex, fPnt);
2537 gp_Vec Ydir = aNorm ^ ApexToFpnt;
2538 gp_Vec Xdir = Ydir ^ aNorm;
2539 //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
2540 gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
2541 theSphere.SetRadius(myOffset);
2542 theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
2543 aSphSurf = new Geom_SphericalSurface(theSphere);
2545 theFirstVertex = BRepLib_MakeVertex(fPnt);
2546 CurFirstVertex = theFirstVertex;
2549 TopoDS_Vertex v1, v2, FirstVert, EndVert;
2550 TopExp::Vertices(CurEdge, v1, v2);
2551 FirstVert = CurFirstVertex;
2552 if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
2553 EndVert = theFirstVertex;
2555 EndVert = BRepLib_MakeVertex(lPnt);
2556 CurEdge.Free( Standard_True );
2557 BB.Remove(CurEdge, v1);
2558 BB.Remove(CurEdge, v2);
2559 BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
2560 BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
2561 //take the curve from sphere an put it to the edge
2562 Standard_Real Uf, Vf, Ul, Vl;
2563 ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
2564 ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
2565 if (Abs(Ul) <= Precision::Confusion())
2567 Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
2571 gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
2572 if (Abs(Uf - f) > Precision::Confusion())
2574 aCircle.Rotate(aCircle.Axis(), f - Uf);
2575 aCurv = new Geom_Circle(aCircle);
2579 Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
2580 BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
2581 BB.Range(CurEdge, Uf, Ul, Standard_True);
2582 Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
2583 Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
2584 BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
2585 BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2586 BRepLib::SameParameter(CurEdge);
2587 BB.Add(SphereWire, CurEdge);
2588 //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2589 BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2590 gp_Pnt2d fPnt2d, lPnt2d;
2591 fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2592 lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2593 TopTools_IndexedMapOfShape Emap;
2594 TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2596 Standard_Integer j = 0, k;
2597 for (k = 1; k <= Emap.Extent(); k++)
2599 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2600 if (!BRep_Tool::Degenerated(anEdge))
2602 TopoDS_Vertex V1, V2;
2603 TopExp::Vertices(anEdge, V1, V2);
2604 if (V1.IsSame(v1) || V2.IsSame(v1))
2608 for (k = 0; k < j; k++)
2610 TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2611 TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2612 Eforward.Free(Standard_True);
2613 TopoDS_Vertex V1, V2;
2614 TopExp::Vertices( Eforward, V1, V2 );
2615 BRepAdaptor_Curve2d EEc( Eforward, aFace );
2616 gp_Pnt2d p2d1, p2d2;
2617 p2d1 = EEc.Value(EEc.FirstParameter());
2618 p2d2 = EEc.Value(EEc.LastParameter());
2621 TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2622 FirstVert : EndVert;
2623 BB.Remove( Eforward, V1 );
2624 BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2628 TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2629 FirstVert : EndVert;
2630 BB.Remove( Eforward, V2 );
2631 BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2635 isFirstFace = Standard_False;
2636 CurFirstVertex = EndVert;
2638 //Building new spherical face
2639 Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2640 gp_Pnt2d p2d1, p2d2;
2641 TopTools_ListOfShape EdgesOfWire;
2642 TopoDS_Iterator itw(SphereWire);
2643 for (; itw.More(); itw.Next())
2645 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2646 EdgesOfWire.Append(anEdge);
2648 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2649 p2d1 = aC2d->Value(f);
2650 p2d2 = aC2d->Value(l);
2651 if (p2d1.X() < Ufirst)
2653 if (p2d1.X() > Ulast)
2655 if (p2d2.X() < Ufirst)
2657 if (p2d2.X() > Ulast)
2660 TopTools_ListOfShape NewEdges;
2661 TopoDS_Edge FirstEdge;
2662 TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2663 for (; itl.More(); itl.Next())
2665 FirstEdge = TopoDS::Edge(itl.Value());
2667 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2668 p2d1 = aC2d->Value(f);
2669 p2d2 = aC2d->Value(l);
2670 if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2672 EdgesOfWire.Remove(itl);
2676 NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
2677 TopoDS_Vertex Vf1, CurVertex;
2678 TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2679 itl.Initialize(EdgesOfWire);
2682 const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2683 TopoDS_Vertex V1, V2;
2684 TopExp::Vertices(anEdge, V1, V2);
2685 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2687 NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
2688 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2689 EdgesOfWire.Remove(itl);
2695 Standard_Real Vfirst, Vlast;
2698 Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2702 Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2704 TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2705 TopoDS_Edge OldEdge, DegEdge;
2706 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2708 DegEdge = TopoDS::Edge(Explo.Current());
2709 if (BRep_Tool::Degenerated(DegEdge))
2712 TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
2713 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2715 OldEdge = TopoDS::Edge(Explo.Current());
2716 TopoDS_Vertex V1, V2;
2717 TopExp::Vertices(OldEdge, V1, V2);
2718 if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
2721 TopoDS_Vertex V1, V2;
2722 TopExp::Vertices(OldEdge, V1, V2);
2723 TopTools_ListOfShape LV1, LV2;
2724 LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
2725 LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
2726 BRepTools_Substitution theSubstitutor;
2727 theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
2729 theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
2730 theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
2731 theSubstitutor.Build(NewSphericalFace);
2732 if (theSubstitutor.IsCopied(NewSphericalFace))
2734 const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2735 NewSphericalFace = TopoDS::Face(listSh.First());
2738 //Adding NewSphericalFace to the shell
2739 Explo.Init( myOffsetShape, TopAbs_SHELL );
2740 TopoDS_Shape theShell = Explo.Current();
2741 theShell.Free( Standard_True );
2742 BB.Add( theShell, NewSphericalFace );
2743 IsModified = Standard_True;
2744 if(!theShell.Closed())
2746 if(BRep_Tool::IsClosed(theShell))
2748 theShell.Closed(Standard_True);
2758 if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2760 //Explo.Init( myOffsetShape, TopAbs_SHELL );
2762 //if (Explo.More()) {
2763 // TopoDS_Shape theShell = Explo.Current();
2764 // theShell.Closed( Standard_True );
2767 Standard_Integer NbShell = 0;
2770 BB.MakeCompound (NC);
2774 Sol.Closed(Standard_True);
2775 for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2776 TopoDS_Shell Sh = TopoDS::Shell(Explo.Current());
2777 //if (myThickening && myOffset > 0.)
2791 TopoDS_Iterator anIt(Sol);
2792 Standard_Boolean SolIsNull = !anIt.More();
2796 Standard_Integer nbs = 0;
2797 while(anIt.More()) {anIt.Next(); ++nbs;}
2800 BRepCheck_Analyzer aCheck(Sol, Standard_False);
2801 if(!aCheck.IsValid())
2803 TopTools_ListOfShape aSolList;
2804 CorrectSolid(Sol, aSolList);
2805 if(!aSolList.IsEmpty())
2808 TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
2809 for(; aSLIt.More(); aSLIt.Next())
2811 BB.Add(NC, aSLIt.Value());
2813 SolIsNull = Standard_True;
2819 anIt.Initialize(NC);
2820 Standard_Boolean NCIsNull = !anIt.More();
2821 if((!SolIsNull) && (!NCIsNull))
2826 else if(SolIsNull && (!NCIsNull))
2837 else if((!SolIsNull) && NCIsNull)
2839 myOffsetShape = Sol;
2849 //=======================================================================
2850 //function : Intersection3D
2852 //=======================================================================
2854 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter)
2858 cout << " INTERSECTION 3D:" << endl;
2863 TopTools_ListOfShape OffsetFaces; // list of faces // created.
2864 MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2866 if (!myFaces.IsEmpty()) {
2867 Standard_Boolean InSide = (myOffset < 0.); // Temporary
2868 // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2869 // between the cap and the part.
2871 if (myJoin == GeomAbs_Arc)
2872 Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge);
2878 Inter.CompletInt (OffsetFaces,myInitOffsetFace);
2879 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2880 if (myJoin == GeomAbs_Intersection) {
2881 BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2885 //--------------------------------
2886 // Only between neighbor faces.
2887 //--------------------------------
2888 Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace);
2891 if ( ChronBuild) Clock.Show();
2895 //=======================================================================
2896 //function : Intersection2D
2898 //=======================================================================
2900 void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Modif,
2901 const TopTools_IndexedMapOfShape& NewEdges)
2905 cout << " INTERSECTION 2D:" << endl;
2910 //--------------------------------------------------------
2911 // calculate intersections2d on faces concerned by
2913 //---------------------------------------------------------
2914 //TopTools_MapIteratorOfMapOfShape it(Modif);
2915 //-----------------------------------------------
2916 // Intersection of edges 2 by 2.
2917 //-----------------------------------------------
2918 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2920 for (i = 1; i <= Modif.Extent(); i++) {
2921 const TopoDS_Face& F = TopoDS::Face(Modif(i));
2922 BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV);
2925 BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes);
2929 DEBVerticesControl (NewEdges,myAsDes);
2931 if ( ChronBuild) Clock.Show();
2936 //=======================================================================
2937 //function : MakeLoops
2939 //=======================================================================
2941 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
2945 cout << " DEBOUCLAGE 2D:" << endl;
2950 //TopTools_MapIteratorOfMapOfShape it(Modif);
2951 TopTools_ListOfShape LF,LC;
2952 //-----------------------------------------
2953 // unwinding of faces // modified.
2954 //-----------------------------------------
2956 for (i = 1; i <= Modif.Extent(); i++) {
2957 if (!myFaces.Contains(Modif(i)))
2958 LF.Append(Modif(i));
2961 if ((myJoin == GeomAbs_Intersection) && myInter) {
2962 TopTools_ListOfShape aLFailed;
2963 TopTools_IndexedDataMapOfShapeListOfShape anOr;
2964 BuildSplitsOfFaces(LF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True);
2965 if (aLFailed.Extent()) {
2966 myMakeLoops.Build(aLFailed, myAsDes, myImageOffset);
2970 myMakeLoops.Build(LF,myAsDes,myImageOffset);
2973 //-----------------------------------------
2974 // unwinding of caps.
2975 //-----------------------------------------
2976 for (i = 1; i <= myFaces.Extent(); i++)
2977 LC.Append(myFaces(i));
2979 Standard_Boolean InSide = 1;
2980 if (myOffset > 0 ) InSide = 0;
2981 myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide);
2984 if ( ChronBuild) Clock.Show();
2988 //=======================================================================
2989 //function : MakeFaces
2990 //purpose : Reconstruction of topologically unchanged faces that
2991 // share edges that were reconstructed.
2992 //=======================================================================
2994 void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
2998 cout << " RECONSTRUCTION OF FACES:" << endl;
3003 TopTools_ListIteratorOfListOfShape itr;
3004 const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
3005 TopTools_ListOfShape LOF;
3006 //----------------------------------
3007 // Loop on all faces //.
3008 //----------------------------------
3009 for (itr.Initialize(Roots); itr.More(); itr.Next()) {
3010 TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
3011 if (!myImageOffset.HasImage(F)) {
3016 if ((myJoin == GeomAbs_Intersection) && myInter) {
3017 TopTools_ListOfShape aLFailed;
3018 TopTools_IndexedDataMapOfShapeListOfShape anOr;
3019 BuildSplitsOfFaces(LOF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True);
3020 if (aLFailed.Extent()) {
3021 myMakeLoops.BuildFaces(aLFailed, myAsDes, myImageOffset);
3025 myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
3029 if ( ChronBuild) Clock.Show();
3033 //=======================================================================
3034 //function : UpdateInitOffset
3035 //purpose : Update and cleaning of myInitOffset
3036 //=======================================================================
3037 static void UpdateInitOffset (BRepAlgo_Image& myInitOffset,
3038 BRepAlgo_Image& myImageOffset,
3039 const TopoDS_Shape& myOffsetShape,
3040 const TopAbs_ShapeEnum &theShapeType) // skv
3042 BRepAlgo_Image NIOF;
3043 const TopTools_ListOfShape& Roots = myInitOffset.Roots();
3044 TopTools_ListIteratorOfListOfShape it(Roots);
3045 for (; it.More(); it.Next()) {
3046 NIOF.SetRoot (it.Value());
3048 for (it.Initialize(Roots); it.More(); it.Next()) {
3049 const TopoDS_Shape& SI = it.Value();
3050 TopTools_ListOfShape LI;
3051 TopTools_ListOfShape L1;
3052 myInitOffset.LastImage(SI,L1);
3053 TopTools_ListIteratorOfListOfShape itL1(L1);
3054 for (; itL1.More(); itL1.Next()) {
3055 const TopoDS_Shape& O1 = itL1.Value();
3056 TopTools_ListOfShape L2;
3057 myImageOffset.LastImage(O1,L2);
3062 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
3063 // Supporting history.
3064 // NIOF.Filter(myOffsetShape,TopAbs_FACE);
3065 NIOF.Filter(myOffsetShape, theShapeType);
3066 // Modified by skv - Mon Apr 4 18:17:27 2005 End
3067 myInitOffset = NIOF;
3070 //=======================================================================
3071 //function : MakeMissingWalls
3073 //=======================================================================
3074 void BRepOffset_MakeOffset::MakeMissingWalls ()
3076 TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
3077 TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
3078 Standard_Real OffsetVal = Abs(myOffset);
3080 FillContours(myShape, myAnalyse, Contours, MapEF);
3082 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours);
3083 for (; iter.More(); iter.Next())
3085 TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key());
3086 TopoDS_Edge StartEdge;
3087 const TopTools_ListOfShape& aContour = iter.Value();
3088 TopTools_ListIteratorOfListOfShape itl(aContour);
3089 Standard_Boolean FirstStep = Standard_True;
3090 TopoDS_Edge PrevEdge;
3091 TopoDS_Vertex PrevVertex = StartVertex;
3092 Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
3093 for (; itl.More(); itl.Next())
3095 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
3097 // Check for offset existence.
3098 if (!myInitOffsetEdge.HasImage(anEdge))
3101 // Check for existence of two different vertices.
3102 TopTools_ListOfShape LOE, LOE2;
3103 myInitOffsetEdge.LastImage( anEdge, LOE );
3104 myImageOffset.LastImage( LOE.Last(), LOE2 );
3105 TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
3106 TopoDS_Vertex V1, V2, V3, V4;
3107 TopExp::Vertices(OE, V4, V3);
3108 TopExp::Vertices(anEdge, V1, V2);
3109 Standard_Real aF, aL;
3110 const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
3112 (!aC->IsClosed() && !aC->IsPeriodic()))
3114 gp_Pnt aPntF = BRep_Tool::Pnt(V1);
3115 gp_Pnt aPntL = BRep_Tool::Pnt(V2);
3116 Standard_Real aDistE = aPntF.SquareDistance(aPntL);
3117 if ( aDistE < Precision::SquareConfusion())
3119 // Bad case: non closed, but vertexes mapped to same 3d point.
3123 Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
3124 if (aDistE < anEdgeTol)
3126 // Potential problems not detected via checkshape.
3127 gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
3128 gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
3129 if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
3131 // To avoid computation of complex analytical continuation of Sin / ArcSin.
3132 Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
3133 Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
3134 Standard_Real aCurrentAngle = gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
3135 if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
3136 Abs (aCurrentAngle) > aMaxAngle)
3138 // anEdge not collinear to offset edge.
3139 isBuildFromScratch = Standard_True;
3140 myIsPerformSewing = Standard_True;
3147 Standard_Boolean ToReverse = Standard_False;
3148 if (!V1.IsSame(PrevVertex))
3150 TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
3151 aVtx = V3; V3 = V4; V4 = aVtx;
3152 ToReverse = Standard_True;
3155 OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
3157 Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
3158 if (FirstStep || isBuildFromScratch)
3160 E4 = BRepLib_MakeEdge( V1, V4 );
3166 if (V2.IsSame(StartVertex) && !ArcOnV2)
3169 E3 = BRepLib_MakeEdge( V2, V3 );
3172 if (isBuildFromScratch)
3178 TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
3179 const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
3180 Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
3181 Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
3183 TopoDS_Wire theWire;
3184 BB.MakeWire(theWire);
3187 BB.Add(theWire, anEdge.Reversed());
3188 BB.Add(theWire, E3.Reversed());
3189 BB.Add(theWire, OE.Reversed());
3190 BB.Add(theWire, E4.Reversed());
3194 BB.Add(theWire, anEdge);
3195 BB.Add(theWire, E3);
3196 BB.Add(theWire, OE);
3197 BB.Add(theWire, E4);
3200 BRepLib::BuildCurves3d( theWire, myTol );
3201 theWire.Closed(Standard_True);
3202 TopoDS_Face NewFace;
3203 Handle(Geom_Surface) theSurf;
3204 BRepAdaptor_Curve BAcurve(anEdge);
3205 BRepAdaptor_Curve BAcurveOE(OE);
3206 Standard_Real fpar = BAcurve.FirstParameter();
3207 Standard_Real lpar = BAcurve.LastParameter();
3208 gp_Pnt PonE = BAcurve.Value(fpar);
3209 gp_Pnt PonOE = BAcurveOE.Value(fpar);
3210 gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
3211 Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
3212 Standard_Boolean IsPlanar = Standard_False;
3213 if (BAcurve.GetType() == GeomAbs_Circle &&
3214 BAcurveOE.GetType() == GeomAbs_Circle)
3216 gp_Circ aCirc = BAcurve.Circle();
3217 gp_Circ aCircOE = BAcurveOE.Circle();
3218 gp_Lin anAxisLine(aCirc.Axis());
3219 gp_Dir CircAxisDir = aCirc.Axis().Direction();
3220 if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
3221 anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
3222 { //cylinder, plane or cone
3223 if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
3224 theSurf = GC_MakeCylindricalSurface(aCirc).Value();
3225 else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
3226 IsPlanar = Standard_True;
3228 gp_Pnt PonEL = BAcurve.Value(lpar);
3229 if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
3230 Standard_Boolean bIsHole;
3231 TopoDS_Edge aE1, aE2;
3232 TopoDS_Wire aW1, aW2;
3233 Handle(Geom_Plane) aPL;
3234 IntTools_FClass2d aClsf;
3236 if (aCirc.Radius()>aCircOE.Radius()) {
3249 aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
3250 for (Standard_Integer i = 0; i < 2; ++i) {
3251 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
3252 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
3255 BB.MakeFace(aFace, aPL, Precision::Confusion());
3257 aClsf.Init(aFace, Precision::Confusion());
3258 bIsHole=aClsf.IsHole();
3259 if ((bIsHole && !i) || (!bIsHole && i)) {
3262 BB.Add(aW, aE.Reversed());
3266 BB.MakeFace(NewFace, aPL, Precision::Confusion());
3267 BB.Add(NewFace, aW1);
3268 BB.Add(NewFace, aW2);
3273 gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
3274 aCirc.Radius(), aCircOE.Radius());
3275 gp_Ax3 theAx3(aCirc.Position());
3276 if (CircAxisDir * theCone.Axis().Direction() < 0.)
3279 CircAxisDir.Reverse();
3281 theCone.SetPosition(theAx3);
3282 theSurf = new Geom_ConicalSurface(theCone);
3285 TopLoc_Location Loc;
3286 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
3287 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3288 Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
3289 OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
3290 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3291 aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
3292 aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
3296 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3299 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
3301 BB.MakeWire(theWire);
3302 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
3303 BB.Add(theWire, E4);
3304 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
3305 BB.Add(theWire, E3);
3306 theWire.Closed(Standard_True);
3311 BB.SameParameter(E3, Standard_False);
3312 BB.SameRange(E3, Standard_False);
3313 BB.SameParameter(E4, Standard_False);
3314 BB.SameRange(E4, Standard_False);
3315 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
3316 BB.Range(E3, theSurf, Loc, 0., OffsetVal);
3317 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3318 BB.Range(E4, theSurf, Loc, 0., OffsetVal);
3320 NewFace = BRepLib_MakeFace(theSurf, theWire);
3322 } //cylinder or cone
3323 } //if both edges are arcs of circles
3324 if (NewFace.IsNull())
3326 BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
3327 if (MF.Error() == BRepLib_FaceDone)
3329 NewFace = MF.Face();
3330 IsPlanar = Standard_True;
3332 else //Extrusion (by thrusections)
3334 Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
3335 Handle(Geom_TrimmedCurve) TrEdgeCurve =
3336 new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
3337 Standard_Real fparOE, lparOE;
3338 Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
3339 Handle(Geom_TrimmedCurve) TrOffsetCurve =
3340 new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
3341 GeomFill_Generator ThrusecGenerator;
3342 ThrusecGenerator.AddCurve( TrEdgeCurve );
3343 ThrusecGenerator.AddCurve( TrOffsetCurve );
3344 ThrusecGenerator.Perform( Precision::PConfusion() );
3345 theSurf = ThrusecGenerator.Surface();
3346 //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
3347 Standard_Real Uf, Ul, Vf, Vl;
3348 theSurf->Bounds(Uf, Ul, Vf, Vl);
3349 TopLoc_Location Loc;
3350 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
3351 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3352 OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
3353 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3354 Standard_Real UonV1 = (ToReverse)? Ul : Uf;
3355 Standard_Real UonV2 = (ToReverse)? Uf : Ul;
3356 aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
3357 aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
3360 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3361 Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
3362 BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
3363 BB.Range(E3, Vf, Vl);
3367 BB.SameParameter(E3, Standard_False);
3368 BB.SameRange(E3, Standard_False);
3369 BB.SameParameter(E4, Standard_False);
3370 BB.SameRange(E4, Standard_False);
3371 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
3372 BB.Range(E3, theSurf, Loc, Vf, Vl);
3373 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3374 BB.Range(E4, theSurf, Loc, Vf, Vl);
3375 Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
3376 BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
3377 BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
3378 Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
3379 BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
3380 BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
3382 NewFace = BRepLib_MakeFace(theSurf, theWire);
3387 Standard_Real fparOE = BAcurveOE.FirstParameter();
3388 Standard_Real lparOE = BAcurveOE.LastParameter();
3389 TopLoc_Location Loc;
3390 if (Abs(fpar - fparOE) > Precision::Confusion())
3392 const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
3393 gp_Pnt2d fp2d = EdgeLine2d->Value(fpar);
3394 gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
3395 aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
3396 Handle(Geom_Curve) aCurve;
3397 Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
3398 Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
3399 GeomAdaptor_Surface GAsurf( theSurf );
3400 Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
3401 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
3402 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3403 Standard_Real max_deviation = 0., average_deviation;
3404 GeomLib::BuildCurve3d(Precision::Confusion(),
3405 ConS, FirstPar, LastPar,
3406 aCurve, max_deviation, average_deviation);
3407 BB.UpdateEdge( anE4, aCurve, max_deviation );
3408 BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
3409 BB.Range( anE4, FirstPar, LastPar );
3411 if (Abs(lpar - lparOE) > Precision::Confusion())
3413 const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
3414 gp_Pnt2d lp2d = EdgeLine2d->Value(lpar);
3415 gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
3416 aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
3417 Handle(Geom_Curve) aCurve;
3418 Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
3419 Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
3420 GeomAdaptor_Surface GAsurf( theSurf );
3421 Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
3422 Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
3423 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3424 Standard_Real max_deviation = 0., average_deviation;
3425 GeomLib::BuildCurve3d(Precision::Confusion(),
3426 ConS, FirstPar, LastPar,
3427 aCurve, max_deviation, average_deviation);
3428 BB.UpdateEdge( anE3, aCurve, max_deviation );
3429 BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
3430 BB.Range( anE3, FirstPar, LastPar );
3433 BRepLib::SameParameter(NewFace);
3434 BRepTools::Update(NewFace);
3435 myWalls.Append(NewFace);
3438 TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
3439 TopoDS_Vertex arcV1, arcV2;
3440 TopExp::Vertices(anArc, arcV1, arcV2);
3441 Standard_Boolean ArcReverse = Standard_False;
3442 if (!arcV1.IsSame(V3))
3444 TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
3445 ArcReverse = Standard_True;
3447 TopoDS_Edge EA1, EA2;
3448 //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
3453 //////////////////////////////////////////////////////
3454 if (V2.IsSame(StartVertex))
3457 EA2 = BRepLib_MakeEdge( V2, arcV2 );
3458 anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
3459 if (EA1.Orientation() == TopAbs_REVERSED)
3461 EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
3462 TopoDS_Wire arcWire;
3463 BB.MakeWire(arcWire);
3464 BB.Add(arcWire, EA1);
3465 BB.Add(arcWire, anArc);
3466 BB.Add(arcWire, EA2);
3467 BRepLib::BuildCurves3d( arcWire, myTol );
3468 arcWire.Closed(Standard_True);
3469 TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
3470 BRepTools::Update(arcFace);
3471 myWalls.Append(arcFace);
3472 TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
3473 const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
3479 if (isBuildFromScratch)
3481 PrevEdge = TopoDS::Edge(E4);
3483 isBuildFromScratch = Standard_False;
3491 FirstStep = Standard_False;
3496 //=======================================================================
3497 //function : MakeShells
3499 //=======================================================================
3501 void BRepOffset_MakeOffset::MakeShells ()
3505 cout << " RECONSTRUCTION OF SHELLS:" << endl;
3511 TopTools_IndexedDataMapOfShapeListOfShape anOrigins;
3513 BOPCol_ListOfShape aLSF;
3514 const TopTools_ListOfShape& R = myImageOffset.Roots();
3515 TopTools_ListIteratorOfListOfShape it(R);
3517 for (; it.More(); it.Next()) {
3518 TopTools_ListOfShape Image;
3519 myImageOffset.LastImage(it.Value(),Image);
3520 TopTools_ListIteratorOfListOfShape it2(Image);
3521 for (; it2.More(); it2.Next()) {
3522 const TopoDS_Shape& aF = it2.Value();
3525 if (anOrigins.Contains(aF)) {
3526 anOrigins.ChangeFromKey(aF).Append(it.Value());
3529 TopTools_ListOfShape aLOr;
3530 aLOr.Append(it.Value());
3531 anOrigins.Add(aF, aLOr);
3537 TopExp_Explorer Explo(myShape, TopAbs_FACE);
3538 for (; Explo.More(); Explo.Next()) {
3539 const TopoDS_Shape& aF = Explo.Current();
3543 it.Initialize(myWalls);
3544 for (; it.More(); it.Next()) {
3545 const TopoDS_Shape& aF = it.Value();
3550 Standard_Boolean bDone = Standard_False;
3551 if ((myJoin == GeomAbs_Intersection) && myInter &&
3552 !myThickening && myFaces.IsEmpty() &&
3553 IsSolid(myShape) && myIsPlanar) {
3555 // make shells using MakerVolume algorithm
3556 Standard_Integer i, aNb;
3557 TopTools_ListIteratorOfListOfShape aItLS, aItLS1;
3560 BOPAlgo_MakerVolume aMV1;
3561 aMV1.SetArguments(aLSF);
3562 aMV1.SetIntersect(Standard_True);
3565 bDone = (aMV1.ErrorStatus() == 0);
3567 UpdateHistory(aLSF, aMV1, myImageOffset);
3569 TopoDS_Shape aResult = aMV1.Shape();
3571 TopTools_IndexedMapOfShape aMFResult;
3572 TopExp::MapShapes(aResult, TopAbs_FACE, aMFResult);
3575 Standard_Boolean bGood = Standard_True;
3576 if (myRemoveInvalidFaces) {
3577 BOPCol_ListIteratorOfListOfShape aItLSF(aLSF);
3578 for (; aItLSF.More(); aItLSF.Next()) {
3579 const TopoDS_Shape& aFx = aItLSF.Value();
3580 if (!aMFResult.Contains(aFx)) {
3581 const TopTools_ListOfShape& aLFMx = aMV1.Modified(aFx);
3582 if (aLFMx.IsEmpty()) {
3583 bGood = Standard_False;
3590 TopoDS_Compound aShells;
3591 aBB.MakeCompound(aShells);
3594 myOffsetShape = aShells;
3597 if (aResult.ShapeType() == TopAbs_COMPOUND) {
3598 // collect faces attached to only one solid
3599 BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
3600 BOPCol_ListOfShape aLSF2;
3602 BOPTools::MapShapesAndAncestors(aResult, TopAbs_FACE, TopAbs_SOLID, aMFS);
3603 aNb = aMFS.Extent();
3607 for (i = 1; i <= aNb; ++i) {
3608 const BOPCol_ListOfShape& aLSx = aMFS(i);
3609 if (aLSx.Extent() == 1) {
3610 const TopoDS_Shape& aFx = aMFS.FindKey(i);
3615 // make solids from the new list
3616 BOPAlgo_MakerVolume aMV2;
3618 aMV2.SetArguments(aLSF2);
3619 aMV2.SetIntersect(Standard_False);
3622 bDone = (aMV2.ErrorStatus() == 0);
3624 aResult = aMV2.Shape();
3625 if (aResult.ShapeType() == TopAbs_COMPOUND) {
3626 BOPCol_ListOfShape aLSF3;
3628 TopExp_Explorer aExp(aResult, TopAbs_FACE);
3629 for (; aExp.More(); aExp.Next()) {
3630 const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
3632 // check orientation
3633 if (!anOrigins.Contains(aF)) {
3638 const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aF);
3639 aItLS.Initialize(aLFOr);
3640 for (; aItLS.More(); aItLS.Next()) {
3641 const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
3643 if (CheckNormals(aF, aFOr)) {
3650 // make solid containing most outer faces
3651 BOPAlgo_MakerVolume aMV3;
3653 aMV3.SetArguments(aLSF3);
3654 aMV3.SetIntersect(Standard_False);
3657 bDone = (aMV3.ErrorStatus() == 0);
3659 aResult = aMV3.Shape();
3666 TopExp_Explorer aExp(aResult, TopAbs_SHELL);
3667 bDone = aExp.More();
3668 for (; aExp.More(); aExp.Next()) {
3669 const TopoDS_Shell& aSh = *(TopoDS_Shell*)&aExp.Current();
3670 aBB.Add(aShells, aSh);
3672 myOffsetShape = aShells;
3678 BRepTools_Quilt Glue;
3679 BOPCol_ListIteratorOfListOfShape aItLS;
3681 aItLS.Initialize(aLSF);
3682 for (; aItLS.More(); aItLS.Next()) {
3683 const TopoDS_Shape& aF = aItLS.Value();
3686 myOffsetShape = Glue.Shells();
3689 //Set correct value for closed flag
3690 TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3691 for(; Explo.More(); Explo.Next())
3693 TopoDS_Shape aS = Explo.Current();
3696 if(BRep_Tool::IsClosed(aS))
3698 aS.Closed(Standard_True);
3704 //=======================================================================
3705 //function : MakeSolid
3707 //=======================================================================
3709 void BRepOffset_MakeOffset::MakeSolid ()
3711 if (myOffsetShape.IsNull()) return;
3713 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
3714 // Supporting history.
3715 UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3716 UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3717 // Modified by skv - Mon Apr 4 18:17:27 2005 End
3718 TopExp_Explorer exp;
3720 Standard_Integer NbShell = 0;
3723 B.MakeCompound (NC);
3727 Sol.Closed(Standard_True);
3728 Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3729 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3730 TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3731 if (myThickening && myOffset > 0.)
3734 if (Sh.Closed() && aMakeSolid) {
3745 TopoDS_Iterator anIt(Sol);
3746 Standard_Boolean SolIsNull = !anIt.More();
3750 Standard_Integer nbs = 0;
3751 while(anIt.More()) {anIt.Next(); ++nbs;}
3754 BRepCheck_Analyzer aCheck(Sol, Standard_False);
3755 if(!aCheck.IsValid())
3757 TopTools_ListOfShape aSolList;
3758 CorrectSolid(Sol, aSolList);
3759 if(!aSolList.IsEmpty())
3762 TopTools_ListIteratorOfListOfShape aSLIt(aSolList);
3763 for(; aSLIt.More(); aSLIt.Next())
3765 B.Add(NC, aSLIt.Value());
3767 SolIsNull = Standard_True;
3772 anIt.Initialize(NC);
3773 Standard_Boolean NCIsNull = !anIt.More();
3774 if((!SolIsNull) && (!NCIsNull))
3779 else if(SolIsNull && (!NCIsNull))
3790 else if((!SolIsNull) && NCIsNull)
3792 myOffsetShape = Sol;
3800 //=======================================================================
3801 //function : SelectShells
3803 //=======================================================================
3805 void BRepOffset_MakeOffset::SelectShells ()
3807 TopTools_MapOfShape FreeEdges;
3808 TopExp_Explorer exp(myShape,TopAbs_EDGE);
3809 //-------------------------------------------------------------
3810 // FreeEdges all edges that can have free border in the
3812 // 1 - free borders of myShape .
3813 //-------------------------------------------------------------
3814 for ( ; exp.More(); exp.Next()) {
3815 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3816 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3817 if (LA.Extent() < 2) {
3818 if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) {
3823 // myShape has free borders and there are no caps
3825 if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3827 myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3830 //=======================================================================
3831 //function : OffsetFacesFromShapes
3833 //=======================================================================
3835 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3837 return myInitOffsetFace;
3840 // Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3842 //=======================================================================
3843 //function : GetJoinType
3844 //purpose : Query offset join type.
3845 //=======================================================================
3847 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3852 //=======================================================================
3853 //function : OffsetEdgesFromShapes
3855 //=======================================================================
3857 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3859 return myInitOffsetEdge;
3862 // Modified by skv - Tue Mar 15 16:20:43 2005 End
3864 //=======================================================================
3865 //function : ClosingFaces
3867 //=======================================================================
3869 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3876 //=======================================================================
3877 //function : EncodeRegularity
3879 //=======================================================================
3881 void BRepOffset_MakeOffset::EncodeRegularity ()
3885 cout << " CODING OF REGULARITIES:" << endl;
3891 if (myOffsetShape.IsNull()) return;
3892 // find edges G1 in the result
3893 TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3896 TopTools_MapOfShape MS;
3898 for ( ; exp.More(); exp.Next()) {
3899 TopoDS_Edge OE = TopoDS::Edge(exp.Current());
3900 BRepLib::BuildCurve3d(OE,myTol);
3901 TopoDS_Edge ROE = OE;
3903 if ( !MS.Add(OE)) continue;
3905 if ( myImageOffset.IsImage(OE))
3906 ROE = TopoDS::Edge(myImageOffset.Root(OE));
3908 const TopTools_ListOfShape& LofOF = myAsDes->Ascendant(ROE);
3910 if (LofOF.Extent() != 2) {
3911 #ifdef OCCT_DEBUG_VERB
3912 cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl;
3917 const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3918 const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3920 if ( F1.IsNull() || F2.IsNull())
3923 const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3924 const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3926 TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3927 TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3929 if (F1.IsSame(F2)) {
3930 if (BRep_Tool::IsClosed(OE,F1)) {
3931 // Temporary Debug for the Bench.
3933 // In mode intersection, the edges are not coded in myInitOffsetEdge
3934 // so, manage case by case
3935 // Note DUB; for Hidden parts, it is NECESSARY to code CN
3936 // Analytic Surfaces.
3937 if (myJoin == GeomAbs_Intersection) {
3938 BRepAdaptor_Surface BS(F1,Standard_False);
3939 GeomAbs_SurfaceType SType = BS.GetType();
3940 if (SType == GeomAbs_Cylinder ||
3941 SType == GeomAbs_Cone ||
3942 SType == GeomAbs_Sphere ||
3943 SType == GeomAbs_Torus ) {
3944 B.Continuity(OE,F1,F1,GeomAbs_CN);
3947 // See YFR : MaJ of myInitOffsetFace
3950 else if (myInitOffsetEdge.IsImage(ROE)) {
3951 if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3952 const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3953 const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3954 GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3955 if (Conti == GeomAbs_CN) {
3956 B.Continuity(OE,F1,F1,GeomAbs_CN);
3958 else if ( Conti > GeomAbs_C0) {
3959 B.Continuity(OE,F1,F1,GeomAbs_G1);
3968 // code regularities G1 between :
3969 // - sphere and tube : one root is a vertex, the other is an edge
3970 // and the vertex is included in the edge
3971 // - face and tube : one root is a face, the other an edge
3972 // and the edge is included in the face
3973 // - face and face : if two root faces are tangent in
3974 // the initial shape, they will be tangent in the offset shape
3975 // - tube and tube : if 2 edges generating tubes are
3976 // tangents, the 2 will be tangent either.
3977 if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3978 TopoDS_Vertex V1,V2;
3979 TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3980 if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3981 B.Continuity(OE,F1,F2,GeomAbs_G1);
3984 else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3985 TopoDS_Vertex V1,V2;
3986 TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3987 if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3988 B.Continuity(OE,F1,F2,GeomAbs_G1);
3991 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3992 TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3993 for ( ; exp2.More(); exp2.Next()) {
3994 if ( exp2.Current().IsSame(Root2)) {
3995 B.Continuity(OE,F1,F2,GeomAbs_G1);
4000 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
4001 TopExp_Explorer exp2(Root2,TopAbs_EDGE);
4002 for ( ; exp2.More(); exp2.Next()) {
4003 if ( exp2.Current().IsSame(Root1)) {
4004 B.Continuity(OE,F1,F2,GeomAbs_G1);
4009 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
4010 // if two root faces are tangent in
4011 // the initial shape, they will be tangent in the offset shape
4012 TopTools_ListOfShape LE,LV;
4013 BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1),
4014 TopoDS::Face(Root2),
4016 if ( LE.Extent() == 1) {
4017 const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
4018 if ( myAnalyse.HasAncestor(Ed)) {
4019 const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
4020 if (LI.Extent() == 1 &&
4021 LI.First().Type() == BRepOffset_Tangent) {
4022 B.Continuity(OE,F1,F2,GeomAbs_G1);
4027 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
4028 TopTools_ListOfShape LV;
4029 TopExp_Explorer exp1;
4030 for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) {
4031 TopExp_Explorer exp2(F2,TopAbs_EDGE);
4032 for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
4033 if (exp1.Current().IsSame(exp2.Current())) {
4034 LV.Append(exp1.Current());
4038 if ( LV.Extent() == 1) {
4039 TopTools_ListOfShape LEdTg;
4040 myAnalyse.TangentEdges(TopoDS::Edge(Root1),
4041 TopoDS::Vertex(LV.First()),
4043 TopTools_ListIteratorOfListOfShape it(LEdTg);
4044 for (; it.More(); it.Next()) {
4045 if ( it.Value().IsSame(Root2)) {
4046 B.Continuity(OE,F1,F2,GeomAbs_G1);
4055 if ( ChronBuild) Clock.Show();
4061 //=======================================================================
4062 //function : UpDateTolerance
4064 //=======================================================================
4066 void UpdateTolerance (TopoDS_Shape& S,
4067 const TopTools_IndexedMapOfShape& Faces)
4070 TopTools_MapOfShape View;
4073 // The edges of caps are not modified.
4075 for (j = 1; j <= Faces.Extent(); j++) {
4076 const TopoDS_Shape& F = Faces(j);
4077 TopExp_Explorer Exp;
4078 for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
4079 View.Add(Exp.Current());
4083 TopExp_Explorer Exp;
4084 for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) {
4085 TopoDS_Edge E = TopoDS::Edge(Exp.Current());
4087 Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E);
4088 Standard_Real Tol = EdgeCorrector->Tolerance();
4089 B.UpdateEdge (E,Tol);
4091 // Update the vertices.
4092 TopExp::Vertices(E,V[0],V[1]);
4094 for (Standard_Integer i = 0 ; i <=1 ; i++) {
4095 if (View.Add(V[i])) {
4096 Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
4098 Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]);
4099 B.UpdateVertex (V[i],VertexCorrector->Tolerance());
4100 // use the occasion to clean the vertices.
4101 (TV->ChangePoints()).Clear();
4103 B.UpdateVertex(V[i],Tol);
4109 //=======================================================================
4110 //function : CorrectSolid
4112 //=======================================================================
4113 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
4116 TopoDS_Shape anOuterShell;
4117 NCollection_List<Standard_Real> aVols;
4118 Standard_Real aVolMax = 0., anOuterVol = 0.;
4120 TopoDS_Iterator anIt(theSol);
4121 for(; anIt.More(); anIt.Next())
4123 const TopoDS_Shape& aSh = anIt.Value();
4124 GProp_GProps aVProps;
4125 BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
4126 if(Abs(aVProps.Mass()) > aVolMax)
4128 anOuterVol = aVProps.Mass();
4129 aVolMax = Abs(anOuterVol);
4132 aVols.Append(aVProps.Mass());
4137 anOuterShell.Reverse();
4139 TopoDS_Solid aNewSol;
4140 aBB.MakeSolid(aNewSol);
4141 aNewSol.Closed(Standard_True);
4142 aBB.Add(aNewSol, anOuterShell);
4143 BRepClass3d_SolidClassifier aSolClass(aNewSol);
4145 anIt.Initialize(theSol);
4146 NCollection_List<Standard_Real>::Iterator aVIt(aVols);
4147 for(; anIt.More(); anIt.Next(), aVIt.Next())
4149 TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
4150 if(aSh.IsSame(anOuterShell))
4156 TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
4157 const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
4158 gp_Pnt aP = BRep_Tool::Pnt(aV);
4159 aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
4160 if(aSolClass.State() == TopAbs_IN)
4162 if(aVIt.Value() > 0.)
4166 aBB.Add(aNewSol, aSh);
4170 if(aVIt.Value() < 0.)
4175 aBB.MakeSolid(aSol);
4176 aSol.Closed(Standard_True);
4178 theSolList.Append(aSol);
4185 //=======================================================================
4186 //function : CheckInputData
4187 //purpose : Check input data for possiblity of offset perform.
4188 //=======================================================================
4189 Standard_Boolean BRepOffset_MakeOffset::CheckInputData()
4191 // Set initial error state.
4192 myError = BRepOffset_NoError;
4193 TopoDS_Shape aTmpShape;
4194 myBadShape = aTmpShape;
4197 if (Abs(myOffset) <= myTol)
4199 Standard_Boolean isFound = Standard_False;
4200 TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
4201 for( ; anIter.More(); anIter.Next())
4203 if (Abs(anIter.Value()) > myTol)
4205 isFound = Standard_True;
4212 // No face with non-null offset found.
4213 myError = BRepOffset_NullOffset;
4214 return Standard_False;
4218 // Connectivity of input shape.
4219 if (!IsConnectedShell(myShape))
4221 myError = BRepOffset_NotConnectedShell;
4222 return Standard_False;
4225 // Normals check and continuity check.
4226 const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
4227 Standard_Real aUmin, aUmax, aVmin, aVmax;
4228 TopExp_Explorer anExpSF(myShape, TopAbs_FACE);
4229 NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
4232 for( ; anExpSF.More(); anExpSF.Next())
4234 const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
4236 if (aPresenceMap.Contains(aF.TShape()))
4238 // Not perform computations with partner shapes,
4239 // since they are contain same geometry.
4242 aPresenceMap.Add(aF.TShape());
4244 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
4245 BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
4247 // Continuity check.
4248 if (aSurf->Continuity() == GeomAbs_C0)
4250 myError = BRepOffset_C0Geometry;
4251 return Standard_False;
4254 // Get degenerated points, to avoid check them.
4255 NCollection_Vector<gp_Pnt> aBad3dPnts;
4256 TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
4257 for( ; anExpFE.More(); anExpFE.Next())
4259 const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
4260 if (BRep_Tool::Degenerated(aE))
4262 aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
4266 // Geometry grid check.
4267 for(Standard_Integer i = 0; i <= aPntPerDim; i++)
4269 Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
4270 for(Standard_Integer j = 0; j <= aPntPerDim; j++)
4272 Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
4274 myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
4275 if (myError != BRepOffset_NoError)
4276 return Standard_False;
4280 // Vertex list check.
4281 TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
4282 for( ; anExpFV.More(); anExpFV.Next())
4284 const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
4285 aPnt2d = BRep_Tool::Parameters(aV, aF);
4287 myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
4288 if (myError != BRepOffset_NoError)
4289 return Standard_False;
4293 return Standard_True;
4297 //=======================================================================
4298 //function : GetBadShape
4299 //purpose : Get shape where problems detected.
4300 //=======================================================================
4301 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
4306 //=======================================================================
4307 //function : RemoveInternalEdges
4309 //=======================================================================
4310 void BRepOffset_MakeOffset::RemoveInternalEdges()
4312 Standard_Boolean bRemoveWire, bRemoveEdge;
4313 TopExp_Explorer aExpF, aExpW, aExpE;
4314 TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
4316 TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4318 aExpF.Init(myOffsetShape, TopAbs_FACE);
4319 for (; aExpF.More(); aExpF.Next()) {
4320 TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
4322 TopTools_ListOfShape aLIW;
4324 aExpW.Init(aF, TopAbs_WIRE);
4325 for (; aExpW.More(); aExpW.Next()) {
4326 TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
4328 bRemoveWire = Standard_True;
4329 TopTools_ListOfShape aLIE;
4331 aExpE.Init(aW, TopAbs_EDGE);
4332 for (; aExpE.More(); aExpE.Next()) {
4333 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
4334 if (aE.Orientation() != TopAbs_INTERNAL) {
4335 bRemoveWire = Standard_False;
4339 const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
4340 bRemoveEdge = (aLF.Extent() == 1);
4345 bRemoveWire = Standard_False;
4352 else if (aLIE.Extent()) {
4353 RemoveShapes(aW, aLIE);
4357 if (aLIW.Extent()) {
4358 RemoveShapes(aF, aLIW);
4363 //=======================================================================
4364 // static methods implementation
4365 //=======================================================================
4367 //=======================================================================
4368 //function : checkSinglePoint
4369 //purpose : Check single point on surface for bad normals
4370 //=======================================================================
4371 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
4372 const Standard_Real theVParam,
4373 const Handle(Geom_Surface)& theSurf,
4374 const NCollection_Vector<gp_Pnt>& theBadPoints)
4378 theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
4380 if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4381 aD1V.SquareMagnitude() < Precision::SquareConfusion() )
4383 Standard_Boolean isKnownBadPnt = Standard_False;
4384 for(Standard_Integer anIdx = theBadPoints.Lower();
4385 anIdx <= theBadPoints.Upper();
4388 if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
4390 isKnownBadPnt = Standard_True;
4393 } // for(Standard_Integer anIdx = theBadPoints.Lower();
4397 return BRepOffset_BadNormalsOnGeometry;
4401 return BRepOffset_NoError;
4403 } // if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4405 if (aD1U.IsParallel(aD1V, Precision::Confusion()))
4407 // Isolines are collinear.
4408 return BRepOffset_BadNormalsOnGeometry;
4411 return BRepOffset_NoError;
4414 //=======================================================================
4415 //function : RemoveShapes
4416 //purpose : Removes the shapes <theLS> from the shape <theS>
4417 //=======================================================================
4418 void RemoveShapes(TopoDS_Shape& theS,
4419 const TopTools_ListOfShape& theLS)
4423 Standard_Boolean bFree = theS.Free();
4424 theS.Free(Standard_True);
4426 TopTools_ListIteratorOfListOfShape aIt(theLS);
4427 for (; aIt.More(); aIt.Next()) {
4428 const TopoDS_Shape& aSI = aIt.Value();
4429 aBB.Remove(theS, aSI);
4435 //=======================================================================
4436 //function : SortFaces
4438 //=======================================================================
4439 void SortFaces(const TopTools_ListOfShape& theLIm,
4440 TopTools_ListOfShape& theLFImages,
4441 const Standard_Boolean bKeepFirst)
4443 Standard_Integer bKeep; // 1 - keep; -1 - remove
4444 Standard_Boolean bFlag, bProceeded;
4445 TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
4446 TopTools_ListOfShape aLFKeep, aLFLeft, aLFTmp;
4447 TopTools_MapOfShape aMV;
4448 TopTools_ListIteratorOfListOfShape aItLF;
4449 TopExp_Explorer aExp;
4453 bKeep = bKeepFirst ? 1 : -1;
4460 bProceeded = Standard_False;
4462 // map list of images edge - faces
4463 aItLF.Initialize(aLFTmp);
4464 for (; aItLF.More(); aItLF.Next()) {
4465 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4466 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4469 // find images that have edge attached to only one face
4470 aItLF.Initialize(aLFTmp);
4471 for (; aItLF.More(); aItLF.Next()) {
4472 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4473 aExp.Init(aFIm, TopAbs_EDGE);
4474 for (bFlag = Standard_False; aExp.More(); aExp.Next()) {
4475 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
4476 const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
4477 if (aLEF.Extent() == 1) {
4478 TopoDS_Vertex aV1, aV2;
4479 TopExp::Vertices(aE, aV1, aV2);
4483 bFlag = Standard_True;
4488 aLFKeep.Append(aFIm);
4489 bProceeded = Standard_True;
4492 aLFLeft.Append(aFIm);
4496 // map shapes left for processing
4501 aItLF.Initialize(aLFTmp);
4502 for (; aItLF.More(); aItLF.Next()) {
4503 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4504 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4507 // find outer edges and check if they touch the first part of edges
4508 aItLF.Initialize(aLFTmp);
4509 for (; aItLF.More(); aItLF.Next()) {
4510 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4511 aExp.Init(aFIm, TopAbs_EDGE);
4512 for (bFlag = Standard_False; aExp.More() && !bFlag; aExp.Next()) {
4513 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
4514 const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
4515 if (aLEF.Extent() == 1) {
4516 TopoDS_Vertex aV1, aV2;
4517 TopExp::Vertices(aE, aV1, aV2);
4519 bFlag = aMV.Contains(aV1) || aMV.Contains(aV2);
4524 aLFKeep.Append(aFIm);
4525 bProceeded = Standard_True;
4528 aLFLeft.Append(aFIm);
4533 // aLFKeep should be kept
4534 // aLFLeft left for further processing
4535 aItLF.Initialize(aLFKeep);
4536 for (; aItLF.More(); aItLF.Next()) {
4537 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4538 theLFImages.Append(aFIm);
4542 if (aLFLeft.IsEmpty()) {
4554 //=======================================================================
4555 //function : FindShape
4557 //=======================================================================
4558 Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
4559 const TopoDS_Shape& theSWhere,
4560 TopoDS_Shape& theRes)
4562 Standard_Boolean bFound = Standard_False;
4563 TopAbs_ShapeEnum aType = theSWhat.ShapeType();
4564 TopExp_Explorer aExp(theSWhere, aType);
4565 for (; aExp.More(); aExp.Next()) {
4566 const TopoDS_Shape& aS = aExp.Current();
4567 if (aS.IsSame(theSWhat)) {
4569 bFound = Standard_True;
4576 //=======================================================================
4577 //function : UpdateOrigins
4579 //=======================================================================
4580 void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
4581 BOPAlgo_Builder& theGF)
4583 TopTools_ListOfShape aLSTmp;
4584 TopTools_MapOfShape aMFence;
4585 BOPCol_ListIteratorOfListOfShape aItA;
4586 TopTools_ListIteratorOfListOfShape aIt, aIt1;
4588 const BOPCol_ListOfShape& aLSU = theGF.Arguments();
4589 aItA.Initialize(aLSU);
4590 for (; aItA.More(); aItA.Next()) {
4591 const TopoDS_Shape& aS = aItA.Value();
4593 if (!theOrigins.Contains(aS)) {
4597 const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
4598 if (aLSIm.IsEmpty()) {
4602 const TopTools_ListOfShape& aLS = theOrigins.FindFromKey(aS);
4604 aIt.Initialize(aLSIm);
4605 for (; aIt.More(); aIt.Next()) {
4606 const TopoDS_Shape& aSIm = aIt.Value();
4608 if (!theOrigins.Contains(aSIm)) {
4609 theOrigins.Add(aSIm, aLS);
4615 TopTools_ListOfShape& aLS1 = theOrigins.ChangeFromKey(aSIm);
4616 aLSTmp.Assign(aLS1);
4619 aIt1.Initialize(aLSTmp);
4620 for (; aIt1.More(); aIt1.Next()) {
4621 const TopoDS_Shape& aS1 = aIt1.Value();
4622 if (aMFence.Add(aS1)) {
4627 aIt1.Initialize(aLS);
4628 for (; aIt1.More(); aIt1.Next()) {
4629 const TopoDS_Shape& aS1 = aIt1.Value();
4630 if (aMFence.Add(aS1)) {
4638 //=======================================================================
4639 //function : ProcessMicroEdge
4641 //=======================================================================
4642 Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
4643 const Handle(IntTools_Context)& theCtx)
4645 TopoDS_Vertex aV1, aV2;
4646 TopExp::Vertices(theEdge, aV1, aV2);
4647 Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull();
4649 return Standard_False;
4652 Standard_Boolean bMicro;
4653 bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx);
4655 BRepAdaptor_Curve aBAC(theEdge);
4656 if (aBAC.GetType() == GeomAbs_Line) {
4658 Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC);
4660 aBB.UpdateVertex(aV1, aLen/2.);
4661 aBB.UpdateVertex(aV2, aLen/2.);
4668 //=======================================================================
4669 //function : ComputeBiNormal
4671 //=======================================================================
4672 Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
4673 const TopoDS_Edge& theE,
4676 Standard_Boolean bDone = Standard_False;
4677 Standard_Real aT1, aT2, aTm;
4679 const Handle(Geom2d_Curve)& aC2d =
4680 BRep_Tool::CurveOnSurface(theE, theF, aT1, aT2);
4681 if (aC2d.IsNull()) {
4688 const Handle(Geom_Curve)& aC3d =
4689 BRep_Tool::Curve(theE, aT1, aT2);
4691 aTm = (aT1 + aT2) * 0.5;
4692 aP = aC3d->Value(aTm);
4694 BOPTools_AlgoTools3D::PointNearEdge(theE, theF, aTm, 1.e-5, aP2dNear, aPNear);
4696 gp_Vec aVB(aP, aPNear);
4697 theDB = gp_Dir(aVB);
4701 //=======================================================================
4702 //function : CheckBiNormals
4704 //=======================================================================
4705 Standard_Boolean CheckBiNormals
4706 (const TopoDS_Face& aFIm,
4707 const TopoDS_Face& aFOr,
4708 const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
4709 const TopTools_MapOfShape& theMFence,
4710 Standard_Boolean& bKeep,
4711 Standard_Boolean& bRemove,
4712 const Standard_Boolean RemoveInvalidFaces)
4714 bKeep = Standard_True;
4715 bRemove = Standard_False;
4717 Standard_Boolean bChecked;
4718 Standard_Integer aNbEdgesChecked;
4719 Standard_Real anAngle;
4720 TopTools_IndexedMapOfShape aMEInv;
4722 aNbEdgesChecked = 0;
4724 const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
4725 TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
4726 for (; aExp.More(); aExp.Next()) {
4727 const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
4729 if (BRep_Tool::Degenerated(aEIm)) {
4733 if (!theOrigins.Contains(aEIm)) {
4737 const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm);
4738 const TopoDS_Shape& aSOr = aLEOr.First();
4739 if (aSOr.ShapeType() != TopAbs_EDGE) {
4743 if (aLEOr.Extent() > 1) {
4744 TopTools_MapOfShape aME, aMV;
4745 Standard_Integer aNbE, aNbV;
4747 TopTools_ListIteratorOfListOfShape aItLS(aLEOr);
4748 for (; aItLS.More(); aItLS.Next()) {
4749 const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aItLS.Value();
4752 TopExp_Explorer aExpE(aEOr, TopAbs_VERTEX);
4753 for (; aExpE.More(); aExpE.Next()) {
4754 const TopoDS_Shape& aV = aExpE.Current();
4759 aNbV = aMV.Extent();
4760 aNbE = aME.Extent();
4762 if ((aNbE > 1) && (aNbV == 2*aNbE)) {
4767 if (!RemoveInvalidFaces) {
4768 if (theMFence.Contains(aEIm)) {
4769 bChecked = Standard_True;
4770 bKeep = Standard_True;
4771 bRemove = Standard_False;
4776 const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aLEOr.First();
4779 if (!FindShape(aEOr, aFOr, aEOrF)) {
4783 // compute bi-normal for face aFIm on the edge aEIm
4785 if (!ComputeBiNormal(aFIm, aEIm, aDB1)) {
4789 // compute bi-normal for face aFOr on the edge aEOrF
4791 if (!ComputeBiNormal(aFOr, aEOrF, aDB2)) {
4797 anAngle = aDB1.Angle(aDB2);
4798 if (Abs(anAngle - M_PI) < 1.e-4) {
4803 bChecked = (aNbEdgesChecked > 0);
4808 // decide whether to remove the split face or not
4810 Standard_Integer aNb = aMEInv.Extent();
4815 if (aNb == aNbEdgesChecked) {
4816 bKeep = Standard_False;
4817 bRemove = Standard_True;
4821 for (Standard_Integer i = 1; i <= aNb; ++i) {
4822 const TopoDS_Shape& aE = aMEInv(i);
4823 if (theMFence.Contains(aE)) {
4824 bKeep = Standard_False;
4825 bRemove = Standard_True;
4834 //=======================================================================
4835 //function : CheckBiNormals
4837 //=======================================================================
4839 (TopTools_ListOfShape& theLFImages,
4840 const TopoDS_Face& theF,
4841 const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
4842 TopTools_ListOfShape& theLFKeep,
4843 const Standard_Boolean RemoveInvalidFaces)
4845 Standard_Boolean bChecked, bKeep, bRem;
4846 Standard_Integer i, aNb;
4847 TopTools_ListOfShape aLFKeep;
4848 TopTools_MapOfShape aMEToKeep;
4849 TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
4850 TopTools_ListIteratorOfListOfShape aItLF;
4852 // collect outer edges
4853 aItLF.Initialize(theLFImages);
4854 for (; aItLF.More(); aItLF.Next()) {
4855 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4856 TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4859 aNb = aDMELF.Extent();
4860 for (i = 1; i <= aNb; ++i) {
4861 const TopTools_ListOfShape& aLF = aDMELF(i);
4862 if (aLF.Extent() == 1) {
4863 const TopoDS_Shape& aE = aDMELF.FindKey(i);
4868 const TopoDS_Face& aFOr = *(TopoDS_Face*)&theOrigins.FindFromKey(theF).First();
4870 aItLF.Initialize(theLFImages);
4871 for (; aItLF.More(); ) {
4872 const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
4874 bChecked = CheckBiNormals(aFIm, aFOr, theOrigins, aMEToKeep, bKeep, bRem, RemoveInvalidFaces);
4878 theLFImages.Remove(aItLF);
4882 theLFKeep.Append(aFIm);
4893 //=======================================================================
4894 //function : CheckNormals
4896 //=======================================================================
4897 Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
4898 const TopoDS_Face& theFOr)
4901 Standard_Real aUMin, aUMax, aVMin, aVMax, aU, aV, anAngle;
4903 gp_Vec aVecU, aVecV, aVNIm, aVNOr;
4904 Standard_Boolean bIsCollinear;
4906 BRepAdaptor_Surface aSFIm(theFIm), aSFOr(theFOr);
4908 aUMin = aSFIm.FirstUParameter();
4909 aUMax = aSFIm.LastUParameter();
4910 aVMin = aSFIm.FirstVParameter();
4911 aVMax = aSFIm.LastVParameter();
4913 aU = (aUMin + aUMax) * 0.5;
4914 if (Precision::IsInfinite(aUMin) &&
4915 Precision::IsInfinite(aUMax)) {
4918 else if (Precision::IsInfinite(aUMin) &&
4919 !Precision::IsInfinite(aUMax)) {
4922 else if (!Precision::IsInfinite(aUMin) &&
4923 Precision::IsInfinite(aUMax)) {
4927 aV = (aVMin + aVMax) * 0.5;
4928 if (Precision::IsInfinite(aVMin) &&
4929 Precision::IsInfinite(aVMax)) {
4932 else if (Precision::IsInfinite(aVMin) &&
4933 !Precision::IsInfinite(aVMax)) {
4936 else if (!Precision::IsInfinite(aVMin) &&
4937 Precision::IsInfinite(aVMax)) {
4941 aSFIm.D1(aU, aV, aP, aVecU, aVecV);
4942 aVNIm = aVecU.Crossed(aVecV);
4943 if (theFIm.Orientation() == TopAbs_REVERSED) {
4947 aSFOr.D1(aU, aV, aP, aVecU, aVecV);
4948 aVNOr = aVecU.Crossed(aVecV);
4949 if (theFOr.Orientation() == TopAbs_REVERSED) {
4953 anAngle = aVNIm.Angle(aVNOr);
4954 bIsCollinear = (anAngle < Precision::Confusion());
4955 return bIsCollinear;
4958 //=======================================================================
4959 //function : IsSolid
4960 //purpose : Check if the shape is solid
4961 //=======================================================================
4962 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
4964 TopExp_Explorer aExp(theS, TopAbs_SOLID);
4968 //=======================================================================
4969 //function : UpdateHistory
4970 //purpose : Updates the history information
4971 //=======================================================================
4972 void UpdateHistory(const TopTools_ListOfShape& theLF,
4973 BOPAlgo_Builder& theGF,
4974 BRepAlgo_Image& theImage)
4976 TopTools_ListIteratorOfListOfShape aIt(theLF);
4977 for (; aIt.More(); aIt.Next()) {
4978 const TopoDS_Shape& aF = aIt.Value();
4979 const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
4980 if (aLFIm.Extent()) {
4981 if (theImage.HasImage(aF)) {
4982 theImage.Add(aF, aLFIm);
4985 theImage.Bind(aF, aLFIm);
4991 //=======================================================================
4992 //function : IsPlanar
4994 //=======================================================================
4995 Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
4997 Standard_Boolean bRet;
4998 TopExp_Explorer aExp(theS, TopAbs_FACE);
4999 for (bRet = Standard_True; aExp.More() && bRet; aExp.Next()) {
5000 const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
5001 BRepAdaptor_Surface aBAS(aF, Standard_False);
5002 bRet = (aBAS.GetType() == GeomAbs_Plane);