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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
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
20
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>
59 #include <ElCLib.hxx>
60 #include <ElSLib.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_Curve.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_Surface.hxx>
77 #include <GeomAPI_ProjectPointOnCurve.hxx>
78 #include <GeomFill_Generator.hxx>
79 #include <GeomLib.hxx>
80 #include <GeomLib_IsPlanarSurface.hxx>
81 #include <gp_Cone.hxx>
82 #include <gp_Lin2d.hxx>
83 #include <gp_Pnt.hxx>
84 #include <GProp_GProps.hxx>
85 #include <IntTools_FClass2d.hxx>
86 #include <NCollection_List.hxx>
87 #include <Precision.hxx>
88 #include <Standard_ConstructionError.hxx>
89 #include <Standard_NotImplemented.hxx>
90 #include <TColStd_ListIteratorOfListOfInteger.hxx>
91 #include <TopExp.hxx>
92 #include <TopExp_Explorer.hxx>
93 #include <TopoDS.hxx>
94 #include <TopoDS_Compound.hxx>
95 #include <TopoDS_Edge.hxx>
96 #include <TopoDS_Face.hxx>
97 #include <TopoDS_Iterator.hxx>
98 #include <TopoDS_Shape.hxx>
99 #include <TopoDS_Shell.hxx>
100 #include <TopoDS_Solid.hxx>
101 #include <TopoDS_Vertex.hxx>
102 #include <TopoDS_Wire.hxx>
103 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
104 #include <TopTools_DataMapIteratorOfDataMapOfShapeReal.hxx>
105 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
106 #include <TopTools_DataMapOfShapeShape.hxx>
107 #include <TopTools_IndexedMapOfShape.hxx>
108 #include <TopTools_ListIteratorOfListOfShape.hxx>
109 #include <TopTools_ListOfShape.hxx>
110 #include <TopTools_MapIteratorOfMapOfShape.hxx>
111 #include <TopTools_MapOfShape.hxx>
112 #include <TopTools_SequenceOfShape.hxx>
113 #include <BRepBuilderAPI_Sewing.hxx>
114 #include <Geom_Line.hxx>
115 #include <NCollection_Vector.hxx>
116 #include <NCollection_IncAllocator.hxx>
117 //
118 #include <BOPAlgo_MakerVolume.hxx>
119 #include <BOPTools_AlgoTools.hxx>
120
121 #include <stdio.h>
122 // POP for NT
123 #ifdef DRAW
124
125 #include <DBRep.hxx>
126 #endif
127 #ifdef OCCT_DEBUG
128 #include <OSD_Chronometer.hxx>
129 //#define DEB_VERB
130 Standard_Boolean AffichInt2d = Standard_False;
131 Standard_Boolean AffichOffC = Standard_False;
132 Standard_Boolean ChronBuild = Standard_False;
133 Standard_Integer NbAE = 0;
134 Standard_Integer NbAF = 0;
135 Standard_Integer NVP = 0;
136 Standard_Integer NVM = 0;
137 Standard_Integer NVN = 0;
138 static OSD_Chronometer Clock;
139 char name[100];
140
141
142
143
144 //=======================================================================
145 //function : DEBVerticesControl
146 //purpose :
147 //=======================================================================
148
DEBVerticesControl(const TopTools_IndexedMapOfShape & NewEdges,Handle (BRepAlgo_AsDes)AsDes)149 static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
150 Handle(BRepAlgo_AsDes) AsDes)
151 {
152 TopTools_ListOfShape LVP;
153 TopTools_ListIteratorOfListOfShape it1LE ;
154 TopTools_ListIteratorOfListOfShape it2LE ;
155
156 Standard_Integer i;
157 for (i = 1; i <= NewEdges.Extent(); i++) {
158 const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i));
159 if (AsDes->HasDescendant(NE)) {
160 for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) {
161 if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) {
162 LVP.Append(it1LE.Value());
163 std::cout <<"Vertex on at least 3 edges."<<std::endl;
164 #ifdef DRAW
165 if (AffichInt2d) {
166 sprintf (name,"VP_%d",NVP++);
167 DBRep::Set(name,it1LE.Value());
168 }
169 #endif
170 }
171 else if (AsDes->Ascendant(it1LE.Value()).Extent() > 3) {
172 std::cout <<"Vertex on more than 3 edges."<<std::endl;
173 #ifdef DRAW
174 if (AffichInt2d) {
175 sprintf (name,"VM_%d",NVM++);
176 DBRep::Set(name,it1LE.Value());
177 }
178 #endif
179
180 }
181 else {
182 #ifdef DRAW
183 if (AffichInt2d) {
184 sprintf (name,"VN_%d",NVN++);
185 DBRep::Set(name,it1LE.Value());
186 }
187 #endif
188 }
189 }
190 }
191 }
192 //------------------------------------------------
193 // Try to mix spoiled vertices.
194 //------------------------------------------------
195 BRep_Builder B;
196 TopTools_ListIteratorOfListOfShape it1(LVP);
197 Standard_Real TolConf = 1.e-5;
198 Standard_Real Tol = Precision::Confusion();
199 //Standard_Integer i = 1;
200
201 i = 1;
202 for ( ; it1.More(); it1.Next()) {
203 TopoDS_Shape V1 = it1.Value();
204 gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
205 Standard_Real distmin = Precision::Infinite();
206 TopTools_ListIteratorOfListOfShape it2(LVP);
207 Standard_Integer j = 1;
208
209 for ( ; it2.More(); it2.Next()) {
210 if (j > i) {
211 TopoDS_Shape V2 = it2.Value();
212 gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
213 if (!V1.IsSame(V2)) {
214 Standard_Real dist = P1.Distance(P2);
215 if (dist < distmin) distmin = dist;
216 if (dist < TolConf) {
217 Standard_Real UV2;
218 TopoDS_Edge EWE2;
219 const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
220 TopTools_ListIteratorOfListOfShape itAsDes;
221 for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) {
222 EWE2 = TopoDS::Edge(itAsDes.Value());
223 TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL);
224 UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
225 aLocalShape = V1.Oriented(TopAbs_INTERNAL) ;
226 B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
227 // UV2 =
228 // BRep_Tool::Parameter(TopoDS::Vertex(),EWE2);
229 // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
230 // UV2,EWE2,Tol);
231 }
232 AsDes->Replace(V2,V1);
233 }
234 }
235 }
236 j++;
237 }
238 i++;
239 std::cout <<" distmin between VP : "<<distmin<<std::endl;
240 }
241 }
242 #endif
243
244 namespace
245 {
246 //=======================================================================
247 //function : BRepOffset_PIOperation
248 //purpose : List of operations to be supported by the Progress Indicator
249 //=======================================================================
250 enum BRepOffset_PIOperation
251 {
252 PIOperation_CheckInputData = 0,
253 PIOperation_Analyse,
254 PIOperation_BuildOffsetBy,
255 PIOperation_Intersection,
256 PIOperation_MakeMissingWalls,
257 PIOperation_MakeShells,
258 PIOperation_MakeSolid,
259 PIOperation_Sewing,
260 PIOperation_Last
261 };
262
263 //=======================================================================
264 //function : normalizeSteps
265 //purpose : Normalization of progress steps
266 //=======================================================================
normalizeSteps(const Standard_Real theWhole,TColStd_Array1OfReal & theSteps)267 static void normalizeSteps(const Standard_Real theWhole,
268 TColStd_Array1OfReal& theSteps)
269 {
270 Standard_Real aSum = 0.;
271 for (Standard_Integer i = theSteps.Lower(); i <= theSteps.Upper(); ++i)
272 {
273 aSum += theSteps(i);
274 }
275
276 // Normalize steps
277 for (Standard_Integer i = theSteps.Lower(); i <= theSteps.Upper(); ++i)
278 {
279 theSteps(i) = theWhole * theSteps(i) / aSum;
280 }
281 }
282
283 }
284
285 //=======================================================================
286 // static methods
287 //=======================================================================
288 static
289 void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
290 const BRepOffset_DataMapOfShapeOffset& theMapSF,
291 const TopTools_DataMapOfShapeShape& theMES,
292 TopTools_DataMapOfShapeShape& theFacesOrigins,
293 BRepAlgo_Image& theImage,
294 TopTools_ListOfShape& theLSF);
295
296 static
297 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
298 BRepAlgo_Image& theImage,
299 TopoDS_Shape& theShells,
300 const Message_ProgressRange& theRange);
301
302 static
303 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
304 const TopAbs_ShapeEnum theSSType,
305 TopoDS_Shape& theResult);
306
307 static
308 void UpdateInitOffset(BRepAlgo_Image& myInitOffset,
309 BRepAlgo_Image& myImageOffset,
310 const TopoDS_Shape& myOffsetShape,
311 const TopAbs_ShapeEnum &theShapeType);
312
313 static
314 void RemoveShapes(TopoDS_Shape& theS,
315 const TopTools_ListOfShape& theLS);
316
317 static
318 Standard_Boolean IsSolid(const TopoDS_Shape& theS);
319
320 static
321 void UpdateHistory(const TopTools_ListOfShape& theLF,
322 BOPAlgo_Builder& theGF,
323 BRepAlgo_Image& theImage);
324
325 static
326 void RemoveSeamAndDegeneratedEdges(const TopoDS_Face& theFace,
327 const TopoDS_Face& theOldFace);
328
329 static
330 Standard_Boolean TrimEdge(TopoDS_Edge& NE,
331 const Handle(BRepAlgo_AsDes)& AsDes2d,
332 Handle(BRepAlgo_AsDes)& AsDes,
333 TopTools_DataMapOfShapeShape& theETrimEInf);
334
335 static
336 Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
337 const Standard_Real theOffset,
338 const BRepOffset_Analyse& Analyse,
339 BRepOffset_DataMapOfShapeOffset& theMapSF,
340 TopTools_DataMapOfShapeShape& theMES,
341 TopTools_DataMapOfShapeShape& theBuild,
342 Handle(BRepAlgo_AsDes)& theAsDes,
343 Handle(BRepAlgo_AsDes)& theAsDes2d,
344 TopTools_IndexedMapOfShape& theNewEdges,
345 TopTools_DataMapOfShapeShape& theETrimEInf,
346 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins);
347
348 static
349 void AppendToList(TopTools_ListOfShape& theL,
350 const TopoDS_Shape& theS);
351
352 static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
353 const Standard_Real theVParam,
354 const Handle(Geom_Surface)& theSurf,
355 const NCollection_Vector<gp_Pnt>& theBadPoints);
356
357 //---------------------------------------------------------------------
358 static void UpdateTolerance ( TopoDS_Shape& myShape,
359 const TopTools_IndexedMapOfShape& myFaces);
360 static Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
361 const Handle(Geom_Curve)& theCrv,
362 const Standard_Real theFirst,
363 const Standard_Real theLast);
364
365 static void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList);
366 //---------------------------------------------------------------------
367
OrientationOfEdgeInFace(const TopoDS_Edge & theEdge,const TopoDS_Face & theFace)368 static TopAbs_Orientation OrientationOfEdgeInFace(const TopoDS_Edge& theEdge,
369 const TopoDS_Face& theFace)
370 {
371 TopAbs_Orientation anOr = TopAbs_EXTERNAL;
372
373 TopExp_Explorer Explo(theFace, TopAbs_EDGE);
374 for (; Explo.More(); Explo.Next())
375 {
376 const TopoDS_Shape& anEdge = Explo.Current();
377 if (anEdge.IsSame(theEdge))
378 {
379 anOr = anEdge.Orientation();
380 break;
381 }
382 }
383
384 return anOr;
385 }
386
387 //
FindParameter(const TopoDS_Vertex & V,const TopoDS_Edge & E,Standard_Real & U)388 static Standard_Boolean FindParameter(const TopoDS_Vertex& V,
389 const TopoDS_Edge& E,
390 Standard_Real& U)
391 {
392 // Search the vertex in the edge
393
394 Standard_Boolean rev = Standard_False;
395 TopoDS_Shape VF;
396 TopAbs_Orientation orient = TopAbs_INTERNAL;
397
398 TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD));
399
400 // if the edge has no vertices
401 // and is degenerated use the vertex orientation
402 // RLE, june 94
403
404 if (!itv.More() && BRep_Tool::Degenerated(E)) {
405 orient = V.Orientation();
406 }
407
408 while (itv.More()) {
409 const TopoDS_Shape& Vcur = itv.Value();
410 if (V.IsSame(Vcur)) {
411 if (VF.IsNull()) {
412 VF = Vcur;
413 }
414 else {
415 rev = E.Orientation() == TopAbs_REVERSED;
416 if (Vcur.Orientation() == V.Orientation()) {
417 VF = Vcur;
418 }
419 }
420 }
421 itv.Next();
422 }
423
424 if (!VF.IsNull()) orient = VF.Orientation();
425
426 Standard_Real f,l;
427
428 if (orient == TopAbs_FORWARD) {
429 BRep_Tool::Range(E,f,l);
430 //return (rev) ? l : f;
431 U = (rev) ? l : f;
432 return Standard_True;
433 }
434
435 else if (orient == TopAbs_REVERSED) {
436 BRep_Tool::Range(E,f,l);
437 //return (rev) ? f : l;
438 U = (rev) ? f : l;
439 return Standard_True;
440 }
441
442 else {
443 TopLoc_Location L;
444 const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l);
445 L = L.Predivided(V.Location());
446 if (!C.IsNull() || BRep_Tool::Degenerated(E)) {
447 BRep_ListIteratorOfListOfPointRepresentation itpr
448 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
449
450 while (itpr.More()) {
451 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
452 if (pr->IsPointOnCurve(C,L)) {
453 Standard_Real p = pr->Parameter();
454 Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux
455 if (!C.IsNull()) {
456 // Closed curves RLE 16 june 94
457 if (Precision::IsNegativeInfinite(f))
458 {
459 //return pr->Parameter();//p;
460 U = pr->Parameter();
461 return Standard_True;
462 }
463 if (Precision::IsPositiveInfinite(l))
464 {
465 //return pr->Parameter();//p;
466 U = pr->Parameter();
467 return Standard_True;
468 }
469 gp_Pnt Pf = C->Value(f).Transformed(L.Transformation());
470 gp_Pnt Pl = C->Value(l).Transformed(L.Transformation());
471 Standard_Real tol = BRep_Tool::Tolerance(V);
472 if (Pf.Distance(Pl) < tol) {
473 if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) {
474 if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f;
475 else res = l;//p = l;
476 }
477 }
478 }
479 //return res;//p;
480 U = res;
481 return Standard_True;
482 }
483 itpr.Next();
484 }
485 }
486 else {
487 // no 3d curve !!
488 // let us try with the first pcurve
489 Handle(Geom2d_Curve) PC;
490 Handle(Geom_Surface) S;
491 BRep_Tool::CurveOnSurface(E,PC,S,L,f,l);
492 L = L.Predivided(V.Location());
493 BRep_ListIteratorOfListOfPointRepresentation itpr
494 ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points());
495
496 while (itpr.More()) {
497 const Handle(BRep_PointRepresentation)& pr = itpr.Value();
498 if (pr->IsPointOnCurveOnSurface(PC,S,L)) {
499 Standard_Real p = pr->Parameter();
500 // Closed curves RLE 16 june 94
501 if (PC->IsClosed()) {
502 if ((p == PC->FirstParameter()) ||
503 (p == PC->LastParameter())) {
504 if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter();
505 else p = PC->LastParameter();
506 }
507 }
508 //return p;
509 U = p;
510 return Standard_True;
511 }
512 itpr.Next();
513 }
514 }
515 }
516
517 //throw Standard_NoSuchObject("BRep_Tool:: no parameter on edge");
518 return Standard_False;
519 }
520
521 //=======================================================================
522 //function : GetEdgePoints
523 //purpose : gets the first, last and middle points of the edge
524 //=======================================================================
GetEdgePoints(const TopoDS_Edge & anEdge,const TopoDS_Face & aFace,gp_Pnt & fPnt,gp_Pnt & mPnt,gp_Pnt & lPnt)525 static void GetEdgePoints(const TopoDS_Edge& anEdge,
526 const TopoDS_Face& aFace,
527 gp_Pnt& fPnt, gp_Pnt& mPnt,
528 gp_Pnt& lPnt)
529 {
530 Standard_Real f, l;
531 Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l );
532 gp_Pnt2d fPnt2d = theCurve->Value(f);
533 gp_Pnt2d lPnt2d = theCurve->Value(l);
534 gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l));
535 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
536 fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y());
537 lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y());
538 mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y());
539 }
540
541 //=======================================================================
542 //function : FillContours
543 //purpose : fills free boundary contours and faces connected (MapEF)
544 //=======================================================================
FillContours(const TopoDS_Shape & aShape,const BRepOffset_Analyse & Analyser,TopTools_IndexedDataMapOfShapeListOfShape & Contours,TopTools_DataMapOfShapeShape & MapEF)545 static void FillContours(const TopoDS_Shape& aShape,
546 const BRepOffset_Analyse& Analyser,
547 TopTools_IndexedDataMapOfShapeListOfShape& Contours,
548 TopTools_DataMapOfShapeShape& MapEF)
549 {
550 TopTools_ListOfShape Edges;
551
552 TopExp_Explorer Explo(aShape, TopAbs_FACE);
553 BRepTools_WireExplorer Wexp;
554
555 for (; Explo.More(); Explo.Next())
556 {
557 TopoDS_Face aFace = TopoDS::Face(Explo.Current());
558 TopoDS_Iterator itf(aFace);
559 for (; itf.More(); itf.Next())
560 {
561 TopoDS_Wire aWire = TopoDS::Wire(itf.Value());
562 for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next())
563 {
564 TopoDS_Edge anEdge = Wexp.Current();
565 if (BRep_Tool::Degenerated(anEdge))
566 continue;
567 const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge);
568 if (!Lint.IsEmpty() && Lint.First().Type() == ChFiDS_FreeBound)
569 {
570 MapEF.Bind(anEdge, aFace);
571 Edges.Append(anEdge);
572 }
573 }
574 }
575 }
576
577 TopTools_ListIteratorOfListOfShape itl;
578 while (!Edges.IsEmpty())
579 {
580 TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First());
581 Edges.RemoveFirst();
582 TopoDS_Vertex StartVertex, CurVertex;
583 TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True);
584 TopTools_ListOfShape aContour;
585 aContour.Append(StartEdge);
586 while (!CurVertex.IsSame(StartVertex))
587 for (itl.Initialize(Edges); itl.More(); itl.Next())
588 {
589 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
590 TopoDS_Vertex V1, V2;
591 TopExp::Vertices(anEdge, V1, V2);
592 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
593 {
594 aContour.Append(anEdge);
595 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
596 Edges.Remove(itl);
597 break;
598 }
599 }
600 Contours.Add(StartVertex, aContour);
601 }
602 }
603
604 //
605 //-----------------------------------------------------------------------
606 //
607 //=======================================================================
608 //function : BRepOffset_MakeOffset
609 //purpose :
610 //=======================================================================
611
BRepOffset_MakeOffset()612 BRepOffset_MakeOffset::BRepOffset_MakeOffset()
613 {
614 myAsDes = new BRepAlgo_AsDes();
615 }
616
617
618 //=======================================================================
619 //function : BRepOffset_MakeOffset
620 //purpose :
621 //=======================================================================
622
BRepOffset_MakeOffset(const TopoDS_Shape & S,const Standard_Real Offset,const Standard_Real Tol,const BRepOffset_Mode Mode,const Standard_Boolean Inter,const Standard_Boolean SelfInter,const GeomAbs_JoinType Join,const Standard_Boolean Thickening,const Standard_Boolean RemoveIntEdges,const Message_ProgressRange & theRange)623 BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape& S,
624 const Standard_Real Offset,
625 const Standard_Real Tol,
626 const BRepOffset_Mode Mode,
627 const Standard_Boolean Inter,
628 const Standard_Boolean SelfInter,
629 const GeomAbs_JoinType Join,
630 const Standard_Boolean Thickening,
631 const Standard_Boolean RemoveIntEdges,
632 const Message_ProgressRange& theRange)
633 :
634 myOffset (Offset),
635 myTol (Tol),
636 myInitialShape (S),
637 myShape (S),
638 myMode (Mode),
639 myInter (Inter),
640 mySelfInter (SelfInter),
641 myJoin (Join),
642 myThickening (Thickening),
643 myRemoveIntEdges(RemoveIntEdges),
644 myDone (Standard_False)
645 {
646 myAsDes = new BRepAlgo_AsDes();
647 myIsLinearizationAllowed = Standard_True;
648
649 MakeOffsetShape(theRange);
650 }
651
652
653 //=======================================================================
654 //function : Initialize
655 //purpose :
656 //=======================================================================
657
Initialize(const TopoDS_Shape & S,const Standard_Real Offset,const Standard_Real Tol,const BRepOffset_Mode Mode,const Standard_Boolean Inter,const Standard_Boolean SelfInter,const GeomAbs_JoinType Join,const Standard_Boolean Thickening,const Standard_Boolean RemoveIntEdges)658 void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape& S,
659 const Standard_Real Offset,
660 const Standard_Real Tol,
661 const BRepOffset_Mode Mode,
662 const Standard_Boolean Inter,
663 const Standard_Boolean SelfInter,
664 const GeomAbs_JoinType Join,
665 const Standard_Boolean Thickening,
666 const Standard_Boolean RemoveIntEdges)
667 {
668 myOffset = Offset;
669 myInitialShape = S;
670 myShape = S;
671 myTol = Tol;
672 myMode = Mode;
673 myInter = Inter;
674 mySelfInter = SelfInter;
675 myJoin = Join;
676 myThickening = Thickening;
677 myRemoveIntEdges = RemoveIntEdges;
678 myIsLinearizationAllowed = Standard_True;
679 myDone = Standard_False;
680 myIsPerformSewing = Standard_False;
681 myIsPlanar = Standard_False;
682 Clear();
683 }
684
685
686 //=======================================================================
687 //function : Clear
688 //purpose :
689 //=======================================================================
690
Clear()691 void BRepOffset_MakeOffset::Clear()
692 {
693 myOffsetShape.Nullify();
694 myInitOffsetFace .Clear();
695 myInitOffsetEdge .Clear();
696 myImageOffset .Clear();
697 myImageVV .Clear();
698 myFaces .Clear();
699 myOriginalFaces .Clear();
700 myFaceOffset .Clear();
701 myEdgeIntEdges .Clear();
702 myAsDes ->Clear();
703 myDone = Standard_False;
704 myGenerated.Clear();
705 myResMap.Clear();
706 }
707
708 //=======================================================================
709 //function : AllowLinearization
710 //purpose :
711 //=======================================================================
712
AllowLinearization(const Standard_Boolean theIsAllowed)713 void BRepOffset_MakeOffset::AllowLinearization(const Standard_Boolean theIsAllowed)
714 {
715 myIsLinearizationAllowed = theIsAllowed;
716 }
717
718 //=======================================================================
719 //function : AddFace
720 //purpose :
721 //=======================================================================
722
AddFace(const TopoDS_Face & F)723 void BRepOffset_MakeOffset::AddFace(const TopoDS_Face& F) {
724
725 myOriginalFaces.Add(F);
726 }
727
728 //=======================================================================
729 //function : SetOffsetOnFace
730 //purpose :
731 //=======================================================================
732
SetOffsetOnFace(const TopoDS_Face & F,const Standard_Real Off)733 void BRepOffset_MakeOffset::SetOffsetOnFace(const TopoDS_Face& F,
734 const Standard_Real Off)
735 {
736 myFaceOffset.Bind(F, Off);
737 }
738
739 //=======================================================================
740 //function : RemoveCorks
741 //purpose :
742 //=======================================================================
743
RemoveCorks(TopoDS_Shape & S,TopTools_IndexedMapOfShape & Faces)744 static void RemoveCorks (TopoDS_Shape& S,
745 TopTools_IndexedMapOfShape& Faces)
746 {
747 TopoDS_Compound SS;
748 BRep_Builder B;
749 B.MakeCompound (SS);
750 //-----------------------------------------------------
751 // Construction of a shape without caps.
752 // and Orientation of caps as in shape S.
753 //-----------------------------------------------------
754 TopExp_Explorer exp(S,TopAbs_FACE);
755 for (; exp.More(); exp.Next()) {
756 const TopoDS_Shape& Cork = exp.Current();
757 if (!Faces.Contains(Cork)) {
758 B.Add(SS,Cork);
759 }
760 else {
761 Faces.RemoveKey(Cork);
762 Faces.Add(Cork); // to reset it with proper orientation.
763 }
764 }
765 S = SS;
766 #ifdef DRAW
767 if ( AffichOffC)
768 DBRep::Set("myInit", SS);
769 #endif
770
771 }
772
773 //=======================================================================
774 //function : IsConnectedShell
775 //purpose :
776 //=======================================================================
IsConnectedShell(const TopoDS_Shape & S)777 static Standard_Boolean IsConnectedShell( const TopoDS_Shape& S )
778 {
779 BRepTools_Quilt Glue;
780 Glue.Add( S );
781
782 TopoDS_Shape SS = Glue.Shells();
783 TopExp_Explorer Explo( SS, TopAbs_SHELL );
784 Explo.Next();
785 if (Explo.More())
786 return Standard_False;
787
788 return Standard_True;
789 }
790
791
792 //=======================================================================
793 //function : MakeList
794 //purpose :
795 //=======================================================================
796
MakeList(TopTools_ListOfShape & OffsetFaces,const BRepAlgo_Image & myInitOffsetFace,const TopTools_IndexedMapOfShape & myFaces)797 static void MakeList (TopTools_ListOfShape& OffsetFaces,
798 const BRepAlgo_Image& myInitOffsetFace,
799 const TopTools_IndexedMapOfShape& myFaces)
800 {
801 TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots());
802 for ( ; itLOF.More(); itLOF.Next()) {
803 const TopoDS_Shape& Root = itLOF.Value();
804 if (!myFaces.Contains(Root)) {
805 if (myInitOffsetFace.HasImage(Root)) {
806 TopTools_ListIteratorOfListOfShape aItLS(myInitOffsetFace.Image(Root));
807 for (; aItLS.More(); aItLS.Next()) {
808 OffsetFaces.Append(aItLS.Value());
809 }
810 }
811 }
812 }
813 }
814
815 //=======================================================================
816 //function : EvalMax
817 //purpose :
818 //=======================================================================
819
EvalMax(const TopoDS_Shape & S,Standard_Real & Tol)820 static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
821 {
822 TopExp_Explorer exp;
823 for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) {
824 const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
825 Standard_Real TolV = BRep_Tool::Tolerance(V);
826 if (TolV > Tol) Tol = TolV;
827 }
828 }
829
830 //=======================================================================
831 //function : SetFaces
832 //purpose :
833 //=======================================================================
834
SetFaces()835 void BRepOffset_MakeOffset::SetFaces()
836 {
837 for (Standard_Integer ii = 1; ii <= myOriginalFaces.Extent(); ii++)
838 {
839 TopoDS_Face aFace = TopoDS::Face(myOriginalFaces(ii));
840 const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aFace);
841 if (aPlanface)
842 aFace = TopoDS::Face(*aPlanface);
843
844 myFaces.Add(aFace);
845 //-------------
846 // MAJ SD.
847 //-------------
848 myInitOffsetFace.SetRoot (aFace) ;
849 myInitOffsetFace.Bind (aFace, aFace);
850 myImageOffset.SetRoot (aFace) ;
851 }
852 }
853
854 //=======================================================================
855 //function : SetFacesWithOffset
856 //purpose :
857 //=======================================================================
858
SetFacesWithOffset()859 void BRepOffset_MakeOffset::SetFacesWithOffset()
860 {
861 TopTools_DataMapIteratorOfDataMapOfShapeShape anItmap(myFacePlanfaceMap);
862 for (; anItmap.More(); anItmap.Next())
863 {
864 TopoDS_Face aFace = TopoDS::Face(anItmap.Key());
865 TopoDS_Face aPlanface = TopoDS::Face(anItmap.Value());
866 if (myFaceOffset.IsBound(aFace))
867 {
868 Standard_Real anOffset = myFaceOffset(aFace);
869 myFaceOffset.UnBind(aFace);
870 myFaceOffset.Bind(aPlanface, anOffset);
871 }
872 }
873 }
874
875 //=======================================================================
876 //function : MakeOffsetShape
877 //purpose :
878 //=======================================================================
879
MakeOffsetShape(const Message_ProgressRange & theRange)880 void BRepOffset_MakeOffset::MakeOffsetShape(const Message_ProgressRange& theRange)
881 {
882 myDone = Standard_False;
883 //
884
885 // check if shape consists of only planar faces
886 myIsPlanar = IsPlanar();
887
888 SetFaces();
889 SetFacesWithOffset();
890
891 BuildFaceComp();
892
893 //------------------------------------------
894 // Construction of myShape without caps.
895 //------------------------------------------
896 if(!myFaces.IsEmpty())
897 {
898 RemoveCorks (myShape, myOriginalFaces);
899 RemoveCorks (myFaceComp, myFaces);
900 }
901
902 Message_ProgressScope aPS(theRange, "Making offset shape", 100);
903
904 TColStd_Array1OfReal aSteps(0, PIOperation_Last - 1);
905 analyzeProgress(100., aSteps);
906
907 if (!CheckInputData(aPS.Next(aSteps(PIOperation_CheckInputData))) || myError != BRepOffset_NoError)
908 {
909 // There is error in input data.
910 // Check Error() method.
911 return;
912 }
913 myError = BRepOffset_NoError;
914 TopAbs_State Side = TopAbs_IN;
915 if (myOffset < 0.) Side = TopAbs_OUT;
916
917 // ------------
918 // Preanalyse.
919 // ------------
920 EvalMax(myShape,myTol);
921 // There are possible second variant: analytical continuation of arcsin.
922 Standard_Real TolAngleCoeff = Min(myTol / (Abs(myOffset * 0.5) + Precision::Confusion()), 1.0);
923 Standard_Real TolAngle = 4*ASin(TolAngleCoeff);
924 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar)
925 {
926 myAnalyse.SetOffsetValue (myOffset);
927 myAnalyse.SetFaceOffsetMap (myFaceOffset);
928 }
929 myAnalyse.Perform(myFaceComp,TolAngle, aPS.Next(aSteps(PIOperation_Analyse)));
930 if (!aPS.More())
931 {
932 myError = BRepOffset_UserBreak;
933 return;
934 }
935 //---------------------------------------------------
936 // Construction of Offset from preanalysis.
937 //---------------------------------------------------
938 //----------------------------
939 // MaJ of SD Face - Offset
940 //----------------------------
941 UpdateFaceOffset();
942
943 if (myJoin == GeomAbs_Arc)
944 BuildOffsetByArc(aPS.Next(aSteps(PIOperation_BuildOffsetBy)));
945 else if (myJoin == GeomAbs_Intersection)
946 BuildOffsetByInter(aPS.Next(aSteps(PIOperation_BuildOffsetBy)));
947 if (myError != BRepOffset_NoError)
948 {
949 return;
950 }
951 //-----------------
952 // Auto unwinding.
953 //-----------------
954 // if (mySelfInter) SelfInter(Modif);
955 //-----------------
956 // Intersection 3d .
957 //-----------------
958 Message_ProgressScope aPSInter(aPS.Next(aSteps(PIOperation_Intersection)), NULL, 100);
959 aPSInter.SetName((myJoin == GeomAbs_Arc) ? "Connect offset faces by arc" :
960 "Connect offset faces by intersection");
961
962 BRepOffset_Inter3d Inter(myAsDes,Side,myTol);
963 Intersection3D (Inter, aPSInter.Next(90));
964 if (myError != BRepOffset_NoError)
965 {
966 return;
967 }
968 //-----------------
969 // Intersection2D
970 //-----------------
971 TopTools_IndexedMapOfShape& Modif = Inter.TouchedFaces();
972 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
973
974 if (!Modif.IsEmpty())
975 {
976 Intersection2D(Modif, NewEdges, aPSInter.Next(4));
977 if (myError != BRepOffset_NoError)
978 {
979 return;
980 }
981 }
982
983 //-------------------------------------------------------
984 // Unwinding 2D and reconstruction of modified faces
985 //----------------------------------------------------
986 MakeLoops (Modif, aPSInter.Next(4));
987 if (myError != BRepOffset_NoError)
988 {
989 return;
990 }
991 //-----------------------------------------------------
992 // Reconstruction of non modified faces sharing
993 // reconstructed edges
994 //------------------------------------------------------
995 if (!Modif.IsEmpty())
996 {
997 MakeFaces(Modif, aPSInter.Next(2));
998 if (myError != BRepOffset_NoError)
999 {
1000 return;
1001 }
1002 }
1003
1004 aPSInter.Close();
1005
1006 if (myThickening)
1007 {
1008 MakeMissingWalls(aPS.Next(aSteps(PIOperation_MakeMissingWalls)));
1009 if (myError != BRepOffset_NoError)
1010 {
1011 return;
1012 }
1013 }
1014
1015 //-------------------------
1016 // Construction of shells.
1017 //-------------------------
1018 MakeShells (aPS.Next(aSteps(PIOperation_MakeShells)));
1019 if (myError != BRepOffset_NoError)
1020 {
1021 return;
1022 }
1023 if (myOffsetShape.IsNull()) {
1024 // not done
1025 myDone = Standard_False;
1026 return;
1027 }
1028 //--------------
1029 // Unwinding 3D.
1030 //--------------
1031 SelectShells ();
1032 //----------------------------------
1033 // Remove INTERNAL edges if necessary
1034 //----------------------------------
1035 if (myRemoveIntEdges) {
1036 RemoveInternalEdges();
1037 }
1038 //----------------------------------
1039 // Coding of regularities.
1040 //----------------------------------
1041 EncodeRegularity();
1042 //----------------------------------
1043 // Replace roots in history maps
1044 //----------------------------------
1045 ReplaceRoots();
1046 //----------------------
1047 // Creation of solids.
1048 //----------------------
1049 MakeSolid (aPS.Next(aSteps(PIOperation_MakeSolid)));
1050 if (myError != BRepOffset_NoError)
1051 {
1052 return;
1053 }
1054 //-----------------------------
1055 // MAJ Tolerance edge and Vertex
1056 // ----------------------------
1057 if (!myOffsetShape.IsNull()) {
1058 UpdateTolerance (myOffsetShape,myFaces);
1059 BRepLib::UpdateTolerances( myOffsetShape );
1060 }
1061
1062 CorrectConicalFaces();
1063
1064 // Result solid should be computed in MakeOffset scope.
1065 if (myThickening &&
1066 myIsPerformSewing)
1067 {
1068 BRepBuilderAPI_Sewing aSew(myTol);
1069 aSew.Add(myOffsetShape);
1070 aSew.Perform(aPS.Next(aSteps(PIOperation_Sewing) / 2.));
1071 if (!aPS.More())
1072 {
1073 myError = BRepOffset_UserBreak;
1074 return;
1075 }
1076 myOffsetShape = aSew.SewedShape();
1077
1078 // Rebuild solid.
1079 // Offset shape expected to be really closed after sewing.
1080 myOffsetShape.Closed(Standard_True);
1081 MakeSolid(aPS.Next(aSteps(PIOperation_Sewing) / 2.));
1082 if (myError != BRepOffset_NoError)
1083 {
1084 return;
1085 }
1086 }
1087
1088 myDone = Standard_True;
1089 }
1090
1091
1092
1093 //=======================================================================
1094 //function : MakeThickSolid
1095 //purpose :
1096 //=======================================================================
1097
MakeThickSolid(const Message_ProgressRange & theRange)1098 void BRepOffset_MakeOffset::MakeThickSolid(const Message_ProgressRange& theRange)
1099 {
1100 //--------------------------------------------------------------
1101 // Construction of shell parallel to shell (initial without cap).
1102 //--------------------------------------------------------------
1103 MakeOffsetShape (theRange);
1104
1105 if (!myDone)
1106 {
1107 // Save return code and myDone state.
1108 return;
1109 }
1110
1111 //--------------------------------------------------------------------
1112 // Construction of a solid with the initial shell, parallel shell
1113 // limited by caps.
1114 //--------------------------------------------------------------------
1115 if (!myFaces.IsEmpty())
1116 {
1117 TopoDS_Solid Res;
1118 TopExp_Explorer exp;
1119 BRep_Builder B;
1120 Standard_Integer NbF = myFaces.Extent();
1121
1122 B.MakeSolid(Res);
1123
1124 BRepTools_Quilt Glue;
1125 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next())
1126 {
1127 NbF++;
1128 Glue.Add (exp.Current());
1129 }
1130 Standard_Boolean YaResult = 0;
1131 if (!myOffsetShape.IsNull())
1132 {
1133 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
1134 {
1135 YaResult = 1;
1136 Glue.Add (exp.Current().Reversed());
1137 }
1138 #ifdef OCCT_DEBUG
1139 if(YaResult == 0)
1140 {
1141 std::cout << "OffsetShape does not contain a FACES." << std::endl;
1142 }
1143 #endif
1144 }
1145 #ifdef OCCT_DEBUG
1146 else
1147 {
1148 std::cout << "OffsetShape is null!" << std::endl;
1149 }
1150 #endif
1151
1152 if (YaResult == 0)
1153 {
1154 myDone = Standard_False;
1155 myError = BRepOffset_UnknownError;
1156 return;
1157 }
1158
1159 myOffsetShape = Glue.Shells();
1160 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next())
1161 {
1162 B.Add(Res,exp.Current());
1163 }
1164 Res.Closed(Standard_True);
1165 myOffsetShape = Res;
1166
1167 // Test of Validity of the result of thick Solid
1168 // more face than the initial solid.
1169 Standard_Integer NbOF = 0;
1170 for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next())
1171 {
1172 NbOF++;
1173 }
1174 if (NbOF <= NbF)
1175 {
1176 myDone = Standard_False;
1177 myError = BRepOffset_UnknownError;
1178 return;
1179 }
1180 }
1181
1182 if (myOffset > 0 ) myOffsetShape.Reverse();
1183
1184 myDone = Standard_True;
1185 }
1186
1187 //=======================================================================
1188 //function : IsDone
1189 //purpose :
1190 //=======================================================================
1191
IsDone() const1192 Standard_Boolean BRepOffset_MakeOffset::IsDone() const
1193 {
1194 return myDone;
1195 }
1196
1197 //=======================================================================
1198 //function : Error
1199 //purpose :
1200 //=======================================================================
1201
Error() const1202 BRepOffset_Error BRepOffset_MakeOffset::Error() const
1203 {
1204 return myError;
1205 }
1206
1207 //=======================================================================
1208 //function : Shape
1209 //purpose :
1210 //=======================================================================
1211
Shape() const1212 const TopoDS_Shape& BRepOffset_MakeOffset::Shape() const
1213 {
1214 return myOffsetShape;
1215 }
1216
1217 //=======================================================================
1218 //function : MakeOffsetFaces
1219 //purpose :
1220 //=======================================================================
MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset & theMapSF,const Message_ProgressRange & theRange)1221 void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF, const Message_ProgressRange& theRange)
1222 {
1223 Standard_Real aCurOffset;
1224 TopTools_ListOfShape aLF;
1225 TopTools_DataMapOfShapeShape ShapeTgt;
1226 TopTools_ListIteratorOfListOfShape aItLF;
1227 //
1228 Standard_Boolean OffsetOutside = (myOffset > 0.);
1229 //
1230 BRepLib::SortFaces(myFaceComp, aLF);
1231 //
1232 Message_ProgressScope aPS(theRange, "Making offset faces", aLF.Size());
1233 aItLF.Initialize(aLF);
1234 for (; aItLF.More(); aItLF.Next(), aPS.Next()) {
1235 if (!aPS.More())
1236 {
1237 myError = BRepOffset_UserBreak;
1238 return;
1239 }
1240 const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
1241 aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
1242 BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
1243 TopTools_ListOfShape Let;
1244 myAnalyse.Edges(aF,ChFiDS_Tangential,Let);
1245 TopTools_ListIteratorOfListOfShape itl(Let);
1246 for (; itl.More(); itl.Next()) {
1247 const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
1248 if ( !ShapeTgt.IsBound(Cur) && !myAnalyse.HasGenerated (Cur)) {
1249 TopoDS_Shape aLocalShape = OF.Generated(Cur);
1250 const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
1251 ShapeTgt.Bind(Cur,OF.Generated(Cur));
1252 TopoDS_Vertex V1,V2,OV1,OV2;
1253 TopExp::Vertices (Cur,V1,V2);
1254 TopExp::Vertices (OTE,OV1,OV2);
1255 TopTools_ListOfShape LE;
1256 if (!ShapeTgt.IsBound(V1)) {
1257 myAnalyse.Edges(V1,ChFiDS_Tangential,LE);
1258 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
1259 if (LE.Extent() == LA.Extent())
1260 ShapeTgt.Bind(V1,OV1);
1261 }
1262 if (!ShapeTgt.IsBound(V2)) {
1263 LE.Clear();
1264 myAnalyse.Edges(V2,ChFiDS_Tangential,LE);
1265 const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
1266 if (LE.Extent() == LA.Extent())
1267 ShapeTgt.Bind(V2,OV2);
1268 }
1269 }
1270 }
1271 theMapSF.Bind(aF,OF);
1272 }
1273 //
1274 const TopTools_ListOfShape& aNewFaces = myAnalyse.NewFaces();
1275 for (TopTools_ListOfShape::Iterator it (aNewFaces); it.More(); it.Next())
1276 {
1277 const TopoDS_Face& aF = TopoDS::Face (it.Value());
1278 BRepOffset_Offset OF(aF, 0.0, ShapeTgt, OffsetOutside, myJoin);
1279 theMapSF.Bind (aF, OF);
1280 }
1281 }
1282
1283 //=======================================================================
1284 //function : BuildOffsetByInter
1285 //purpose :
1286 //=======================================================================
BuildOffsetByInter(const Message_ProgressRange & theRange)1287 void BRepOffset_MakeOffset::BuildOffsetByInter(const Message_ProgressRange& theRange)
1288 {
1289 #ifdef OCCT_DEBUG
1290 if ( ChronBuild) {
1291 std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
1292 Clock.Reset();
1293 Clock.Start();
1294 }
1295 #endif
1296
1297 Message_ProgressScope aPSOuter(theRange, "Connect offset faces by intersection", 100);
1298 // just for better management and visualization of the progress steps
1299 // define a nested enum listing all the steps of the current method.
1300 enum BuildOffsetByInter_PISteps
1301 {
1302 BuildOffsetByInter_MakeOffsetFaces = 0,
1303 BuildOffsetByInter_ConnexIntByInt,
1304 BuildOffsetByInter_ContextIntByInt,
1305 BuildOffsetByInter_IntersectEdges,
1306 BuildOffsetByInter_CompleteEdgesIntersection,
1307 BuildOffsetByInter_BuildFaces,
1308 BuildOffsetByInter_FillHistoryForOffsets,
1309 BuildOffsetByInter_FillHistoryForDeepenings,
1310 BuildOffsetByInter_Last
1311 };
1312
1313 Standard_Real aNbFaces = myFaceComp.NbChildren() + myAnalyse.NewFaces().Extent() + myFaces.Extent();
1314 Standard_Real anOffsetsPart = (myFaceComp.NbChildren() + myAnalyse.NewFaces().Extent()) / aNbFaces;
1315 Standard_Real aDeepeningsPart = myFaces.Extent() / aNbFaces;
1316
1317 TColStd_Array1OfReal aSteps(0, BuildOffsetByInter_Last - 1);
1318 {
1319 aSteps.Init(0);
1320
1321 Standard_Boolean isInter = myJoin == GeomAbs_Intersection;
1322 Standard_Real aFaceInter = isInter ? 25. : 50.;
1323 Standard_Real aBuildFaces = isInter ? 50. : 25.;
1324 aSteps(BuildOffsetByInter_MakeOffsetFaces) = 5.;
1325 aSteps(BuildOffsetByInter_ConnexIntByInt) = aFaceInter * anOffsetsPart;
1326 aSteps(BuildOffsetByInter_ContextIntByInt) = aFaceInter * aDeepeningsPart;
1327 aSteps(BuildOffsetByInter_IntersectEdges) = 10.;
1328 aSteps(BuildOffsetByInter_CompleteEdgesIntersection) = 5.;
1329 aSteps(BuildOffsetByInter_BuildFaces) = aBuildFaces;
1330 aSteps(BuildOffsetByInter_FillHistoryForOffsets) = 5. * anOffsetsPart;
1331 aSteps(BuildOffsetByInter_FillHistoryForDeepenings) = 5. * aDeepeningsPart;
1332 normalizeSteps(100., aSteps);
1333 }
1334
1335 TopExp_Explorer Exp, Exp2, ExpC;
1336 TopTools_ListIteratorOfListOfShape itLF;
1337
1338 //--------------------------------------------------------
1339 // Construction of faces parallel to initial faces
1340 //--------------------------------------------------------
1341 BRepOffset_DataMapOfShapeOffset MapSF;
1342 MakeOffsetFaces(MapSF, aPSOuter.Next(aSteps(BuildOffsetByInter_MakeOffsetFaces)));
1343 if (!aPSOuter.More())
1344 {
1345 myError = BRepOffset_UserBreak;
1346 return;
1347 }
1348 //--------------------------------------------------------------------
1349 // MES : Map of OffsetShape -> Extended Shapes.
1350 // Build : Map of Initial SS -> OffsetShape build by Inter.
1351 // can be an edge or a compound of edges
1352 //---------------------------------------------------------------------
1353 TopTools_DataMapOfShapeShape MES;
1354 TopTools_DataMapOfShapeShape Build;
1355 TopTools_ListOfShape Failed;
1356 TopAbs_State Side = TopAbs_IN;
1357 Handle(BRepAlgo_AsDes) AsDes = new BRepAlgo_AsDes();
1358
1359 //-------------------------------------------------------------------
1360 // Extension of faces and calculation of new edges of intersection.
1361 //-------------------------------------------------------------------
1362 Standard_Boolean ExtentContext = 0;
1363 if (myOffset > 0) ExtentContext = 1;
1364
1365 BRepOffset_Inter3d Inter3 (AsDes,Side,myTol);
1366 // Intersection between parallel faces
1367 Inter3.ConnexIntByInt(myFaceComp, MapSF, myAnalyse, MES, Build, Failed,
1368 aPSOuter.Next(aSteps(BuildOffsetByInter_ConnexIntByInt)), myIsPlanar);
1369 if (!aPSOuter.More())
1370 {
1371 myError = BRepOffset_UserBreak;
1372 return;
1373 }
1374 // Intersection with caps.
1375 Inter3.ContextIntByInt(myFaces, ExtentContext, MapSF, myAnalyse, MES, Build, Failed,
1376 aPSOuter.Next(aSteps(BuildOffsetByInter_ContextIntByInt)), myIsPlanar);
1377 if (!aPSOuter.More())
1378 {
1379 myError = BRepOffset_UserBreak;
1380 return;
1381 }
1382
1383 TopTools_ListOfShape aLFaces;
1384 for (Exp.Init(myFaceComp,TopAbs_FACE) ; Exp.More(); Exp.Next())
1385 aLFaces.Append (Exp.Current());
1386 for (TopTools_ListOfShape::Iterator it (myAnalyse.NewFaces()); it.More(); it.Next())
1387 aLFaces.Append (it.Value());
1388 //---------------------------------------------------------------------------------
1389 // Extension of neighbor edges of new edges and intersection between neighbors.
1390 //--------------------------------------------------------------------------------
1391 Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
1392 IntersectEdges(aLFaces, MapSF, MES, Build, AsDes, AsDes2d,
1393 aPSOuter.Next(aSteps(BuildOffsetByInter_IntersectEdges)));
1394 if (myError != BRepOffset_NoError)
1395 {
1396 return;
1397 }
1398 //-----------------------------------------------------------
1399 // Great restriction of new edges and update of AsDes.
1400 //------------------------------------------ ----------------
1401 TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
1402 TopTools_IndexedMapOfShape NewEdges;
1403 TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
1404 //
1405 //Map of edges obtained after FACE-FACE (offsetted) intersection.
1406 //Key1 is edge trimmed by intersection points with other edges;
1407 //Item is not-trimmed edge.
1408 if (!TrimEdges(myFaceComp, myOffset, myAnalyse, MapSF, MES, Build,
1409 AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins))
1410 {
1411 myError = BRepOffset_CannotTrimEdges;
1412 return;
1413 }
1414 //
1415 //---------------------------------
1416 // Intersection 2D on //
1417 //---------------------------------
1418 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
1419 TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
1420 TopTools_ListOfShape LFE;
1421 BRepAlgo_Image IMOE;
1422 GetEnlargedFaces(aLFaces, MapSF, MES, aFacesOrigins, IMOE, LFE);
1423 //
1424 TopTools_ListIteratorOfListOfShape itLFE(LFE);
1425 Message_ProgressScope aPS2d(aPSOuter.Next(aSteps(BuildOffsetByInter_CompleteEdgesIntersection)), NULL, 2);
1426 Message_ProgressScope aPS2dOffsets(aPS2d.Next(2. * anOffsetsPart), NULL, LFE.Size());
1427 for (; itLFE.More(); itLFE.Next())
1428 {
1429 if (!aPS2dOffsets.More())
1430 {
1431 myError = BRepOffset_UserBreak;
1432 return;
1433 }
1434 const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value());
1435 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF);
1436 BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, myEdgeIntEdges, aDMVV, aPS2dOffsets.Next());
1437 }
1438 //----------------------------------------------
1439 // Intersections 2d on caps.
1440 //----------------------------------------------
1441 Standard_Integer i;
1442 Message_ProgressScope aPS2dCaps(aPS2d.Next(2. * aDeepeningsPart), NULL, myFaces.Extent());
1443 for (i = 1; i <= myFaces.Extent(); i++)
1444 {
1445 if (!aPS2dCaps.More())
1446 {
1447 myError = BRepOffset_UserBreak;
1448 return;
1449 }
1450 const TopoDS_Face& Cork = TopoDS::Face(myFaces(i));
1451 Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork);
1452 BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, myEdgeIntEdges, aDMVV, aPS2dCaps.Next());
1453 }
1454 //
1455 BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes, myImageVV);
1456 //-------------------------------
1457 // Unwinding of extended Faces.
1458 //-------------------------------
1459 //
1460 TopTools_MapOfShape aMFDone;
1461 //
1462 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
1463 BuildSplitsOfExtendedFaces(LFE, myAnalyse, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf,
1464 IMOE, aPSOuter.Next(aSteps(BuildOffsetByInter_BuildFaces)));
1465 if (myError != BRepOffset_NoError)
1466 {
1467 return;
1468 }
1469 //
1470 TopTools_ListIteratorOfListOfShape aItLF(LFE);
1471 for (; aItLF.More(); aItLF.Next()) {
1472 const TopoDS_Shape& aS = aItLF.Value();
1473 aMFDone.Add(aS);
1474 }
1475 }
1476 else {
1477 myMakeLoops.Build(LFE, AsDes, IMOE, myImageVV, aPSOuter.Next(aSteps(BuildOffsetByInter_BuildFaces)));
1478 if (!aPSOuter.More())
1479 {
1480 myError = BRepOffset_UserBreak;
1481 return;
1482 }
1483 }
1484 //
1485 #ifdef OCCT_DEBUG
1486 TopTools_IndexedMapOfShape COES;
1487 #endif
1488 //---------------------------
1489 // MAJ SD. for faces //
1490 //---------------------------
1491 Message_ProgressScope aPSHist(aPSOuter.Next(aSteps(BuildOffsetByInter_FillHistoryForOffsets)),
1492 "Fill history for offset faces", aLFaces.Size());
1493 for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next(), aPSHist.Next())
1494 {
1495 if (!aPSHist.More())
1496 {
1497 myError = BRepOffset_UserBreak;
1498 return;
1499 }
1500 const TopoDS_Shape& FI = it.Value();
1501 myInitOffsetFace.SetRoot(FI);
1502 TopoDS_Face OF = MapSF(FI).Face();
1503 if (MES.IsBound(OF)) {
1504 OF = TopoDS::Face(MES(OF));
1505 if (IMOE.HasImage(OF)) {
1506 const TopTools_ListOfShape& LOFE = IMOE.Image(OF);
1507 myInitOffsetFace.Bind(FI,LOFE);
1508 for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) {
1509 const TopoDS_Shape& OFE = itLF.Value();
1510 myImageOffset.SetRoot(OFE);
1511 #ifdef DRAW
1512 if (AffichInt2d) {
1513 sprintf(name,"AF_%d",NbAF++);
1514 DBRep::Set(name,OFE);
1515 }
1516 #endif
1517 TopTools_MapOfShape View;
1518 for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1519 Exp2.More(); Exp2.Next()) {
1520 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1521
1522 myAsDes->Add (OFE,COE);
1523 #ifdef DRAW
1524 if (AffichInt2d) {
1525 sprintf(name,"AE_%d",NbAE++);
1526 DBRep::Set(name,COE);
1527 COES.Add(COE);
1528 }
1529 #endif
1530 if (View.Add(COE)){
1531 if (!myAsDes->HasDescendant(COE)) {
1532 TopoDS_Vertex CV1,CV2;
1533 TopExp::Vertices(COE,CV1,CV2);
1534 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1535 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1536 }
1537 }
1538 }
1539 }
1540 }
1541 else {
1542 if (aMFDone.Contains(OF)) {
1543 continue;
1544 }
1545 //
1546 myInitOffsetFace.Bind(FI,OF);
1547 myImageOffset.SetRoot(OF);
1548 #ifdef DRAW
1549 if (AffichInt2d) {
1550 sprintf(name,"AF_%d",NbAF++);
1551 DBRep::Set(name,OF);
1552 }
1553 #endif
1554 const TopTools_ListOfShape& LE = AsDes->Descendant(OF);
1555 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1556 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1557 if (IMOE.HasImage(OE)) {
1558 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1559 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1560 for (; itLOE.More(); itLOE.Next()) {
1561 TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation());
1562 const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape);
1563 // const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation()));
1564 myAsDes->Add(OF,COE);
1565 #ifdef DRAW
1566 if (AffichInt2d) {
1567 sprintf(name,"AE_%d",NbAE++);
1568 DBRep::Set(name,COE);
1569 COES.Add(COE);
1570 }
1571 #endif
1572
1573 if (!myAsDes->HasDescendant(COE)) {
1574 TopoDS_Vertex CV1,CV2;
1575 TopExp::Vertices(COE,CV1,CV2);
1576 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1577 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1578 }
1579 }
1580 }
1581 else {
1582 myAsDes->Add(OF,OE);
1583 #ifdef DRAW
1584 if (AffichInt2d) {
1585 sprintf(name,"AE_%d",NbAE++);
1586 DBRep::Set(name,OE);
1587 COES.Add(OE);
1588 }
1589 #endif
1590
1591 const TopTools_ListOfShape& LV = AsDes->Descendant(OE);
1592 myAsDes->Add(OE,LV);
1593 }
1594 }
1595 }
1596 }
1597 else {
1598 myInitOffsetFace.Bind(FI,OF);
1599 myImageOffset.SetRoot(OF);
1600 TopTools_MapOfShape View;
1601 for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1602 Exp2.More(); Exp2.Next()) {
1603
1604 const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current());
1605 myAsDes->Add (OF,COE);
1606 #ifdef DRAW
1607 if (AffichInt2d) {
1608 sprintf(name,"AE_%d",NbAE++);
1609 DBRep::Set(name,COE);
1610 COES.Add(COE);
1611 }
1612 #endif
1613
1614 if (View.Add(Exp2.Current())) {
1615 if (!myAsDes->HasDescendant(COE)) {
1616 TopoDS_Vertex CV1,CV2;
1617 TopExp::Vertices(COE,CV1,CV2);
1618 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1619 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1620 }
1621 }
1622 }
1623 }
1624 }
1625 // Modified by skv - Tue Mar 15 16:20:43 2005
1626 // Add methods for supporting history.
1627 TopTools_MapOfShape aMapEdges;
1628
1629 for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
1630 {
1631 const TopoDS_Shape& aFaceRef = it.Value();
1632 Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1633
1634 for (; Exp2.More(); Exp2.Next()) {
1635 const TopoDS_Shape& anEdgeRef = Exp2.Current();
1636
1637 if (aMapEdges.Add(anEdgeRef)) {
1638 myInitOffsetEdge.SetRoot(anEdgeRef);
1639 if (Build.IsBound(anEdgeRef)) {
1640 TopoDS_Shape aNewShape = Build(anEdgeRef);
1641
1642 if (aNewShape.ShapeType() == TopAbs_EDGE) {
1643 if (IMOE.HasImage(aNewShape)) {
1644 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape);
1645
1646 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1647 } else
1648 myInitOffsetEdge.Bind (anEdgeRef, aNewShape);
1649 } else { // aNewShape != TopAbs_EDGE
1650 TopTools_ListOfShape aListNewEdge;
1651
1652 for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
1653 const TopoDS_Shape &aResEdge = ExpC.Current();
1654
1655 if (IMOE.HasImage(aResEdge)) {
1656 const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge);
1657 TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE);
1658
1659 for (; aNewEIter.More(); aNewEIter.Next())
1660 aListNewEdge.Append(aNewEIter.Value());
1661 } else
1662 aListNewEdge.Append(aResEdge);
1663 }
1664
1665 myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge);
1666 }
1667 }
1668 else { // Free boundary.
1669 TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef);
1670
1671 if (MES.IsBound(aNewEdge))
1672 aNewEdge = MES(aNewEdge);
1673
1674 if (IMOE.HasImage(aNewEdge)) {
1675 const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge);
1676
1677 myInitOffsetEdge.Bind (anEdgeRef, aListNewE);
1678 } else
1679 myInitOffsetEdge.Bind (anEdgeRef, aNewEdge);
1680 }
1681 }
1682 }
1683 }
1684 // Modified by skv - Tue Mar 15 16:20:43 2005
1685
1686 //---------------------------
1687 // MAJ SD. for caps
1688 //---------------------------
1689 //TopTools_MapOfShape View;
1690 Message_ProgressScope aPSHist2(aPSOuter.Next(aSteps(BuildOffsetByInter_FillHistoryForDeepenings)),
1691 "Fill history for deepening faces", myFaces.Extent());
1692 for (i = 1; i <= myFaces.Extent(); i++, aPSHist2.Next()) {
1693 if (!aPSHist2.More())
1694 {
1695 myError = BRepOffset_UserBreak;
1696 return;
1697 }
1698 const TopoDS_Shape& Cork = myFaces(i);
1699 const TopTools_ListOfShape& LE = AsDes->Descendant(Cork);
1700 for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) {
1701 const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value());
1702 if (IMOE.HasImage(OE)) {
1703 const TopTools_ListOfShape& LOE = IMOE.Image(OE);
1704 TopTools_ListIteratorOfListOfShape itLOE(LOE);
1705 for (; itLOE.More(); itLOE.Next()) {
1706 const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value());
1707 myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ;
1708 #ifdef DRAW
1709 if (AffichInt2d) {
1710 sprintf(name,"AE_%d",NbAE++);
1711 DBRep::Set(name,COE);
1712 COES.Add(COE);
1713 }
1714 #endif
1715
1716 if (!myAsDes->HasDescendant(COE)) {
1717 TopoDS_Vertex CV1,CV2;
1718 TopExp::Vertices(COE,CV1,CV2);
1719 if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD));
1720 if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED));
1721 }
1722 }
1723 }
1724 else {
1725 myAsDes->Add(Cork,OE);
1726 if (AsDes->HasDescendant(OE)) {
1727 myAsDes->Add(OE,AsDes->Descendant(OE));
1728 }
1729 #ifdef DRAW
1730 if (AffichInt2d) {
1731 sprintf(name,"AE_%d",NbAE++);
1732 DBRep::Set(name,OE);
1733 COES.Add(OE);
1734 }
1735 #endif
1736 }
1737 }
1738 }
1739
1740 #ifdef OCCT_DEBUG
1741 DEBVerticesControl (COES,myAsDes);
1742 if ( ChronBuild) Clock.Show();
1743 #endif
1744
1745 }
1746
1747 //=======================================================================
1748 //function : ReplaceRoots
1749 //purpose :
1750 //=======================================================================
ReplaceRoots()1751 void BRepOffset_MakeOffset::ReplaceRoots()
1752 {
1753 // Replace the artificial faces and edges in InitOffset maps with the original ones.
1754 TopTools_MapOfShape View;
1755 for (TopExp_Explorer anExpF (myFaceComp, TopAbs_EDGE); anExpF.More(); anExpF.Next())
1756 {
1757 const TopoDS_Shape& aF = anExpF.Current();
1758 for (TopExp_Explorer anExpE (aF, TopAbs_EDGE); anExpE.More(); anExpE.Next())
1759 {
1760 const TopoDS_Shape& aE = anExpE.Current();
1761 if (!View.Add (aE))
1762 continue;
1763
1764 TopoDS_Shape aFGen = myAnalyse.Generated (aE);
1765 if (aFGen.IsNull())
1766 continue;
1767
1768 myInitOffsetFace.ReplaceRoot (aFGen, aE);
1769
1770 for (TopoDS_Iterator itV (aE); itV.More(); itV.Next())
1771 {
1772 const TopoDS_Shape& aV = itV.Value();
1773 if (!View.Add (aV))
1774 continue;
1775
1776 TopoDS_Shape aEGen = myAnalyse.Generated (aV);
1777 if (aEGen.IsNull())
1778 continue;
1779
1780 myInitOffsetEdge.ReplaceRoot (aEGen, aV);
1781 }
1782 }
1783 }
1784 }
1785
1786 //=======================================================================
1787 //function : BuildFaceComp
1788 //purpose : Make a compound containing actual faces (including planar faces instead of their originals)
1789 //=======================================================================
BuildFaceComp()1790 void BRepOffset_MakeOffset::BuildFaceComp()
1791 {
1792 BRep_Builder aBB;
1793 aBB.MakeCompound(myFaceComp);
1794 TopExp_Explorer anExplo(myShape, TopAbs_FACE);
1795 for (; anExplo.More(); anExplo.Next())
1796 {
1797 TopoDS_Shape aFace = anExplo.Current();
1798 TopAbs_Orientation anOr = aFace.Orientation();
1799 const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aFace);
1800 if (aPlanface)
1801 aFace = *aPlanface;
1802 aBB.Add(myFaceComp, aFace.Oriented(anOr));
1803 }
1804 }
1805
1806 //=======================================================================
1807 //function : BuildOffsetByArc
1808 //purpose :
1809 //=======================================================================
BuildOffsetByArc(const Message_ProgressRange & theRange)1810 void BRepOffset_MakeOffset::BuildOffsetByArc(const Message_ProgressRange& theRange)
1811 {
1812 #ifdef OCCT_DEBUG
1813 if ( ChronBuild) {
1814 std::cout << " CONSTRUCTION OF OFFSETS :" << std::endl;
1815 Clock.Reset();
1816 Clock.Start();
1817 }
1818 #endif
1819
1820 TopExp_Explorer Exp;
1821 TopTools_ListIteratorOfListOfShape itLF;
1822 TopTools_MapOfShape Done;
1823 Message_ProgressScope aPSOuter(theRange, NULL, 10);
1824 //--------------------------------------------------------
1825 // Construction of faces parallel to initial faces
1826 //--------------------------------------------------------
1827 BRepOffset_DataMapOfShapeOffset MapSF;
1828 MakeOffsetFaces(MapSF, aPSOuter.Next());
1829 if (myError != BRepOffset_NoError)
1830 {
1831 return;
1832 }
1833 //--------------------------------------------------------
1834 // Construction of tubes on edge.
1835 //--------------------------------------------------------
1836 ChFiDS_TypeOfConcavity OT = ChFiDS_Convex;
1837 if (myOffset < 0.) OT = ChFiDS_Concave;
1838
1839 Message_ProgressScope aPS1(aPSOuter.Next(4), "Constructing tubes on edges", 1, Standard_True);
1840 for (Exp.Init(myFaceComp,TopAbs_EDGE); Exp.More(); Exp.Next(), aPS1.Next()) {
1841 if (!aPS1.More())
1842 {
1843 myError = BRepOffset_UserBreak;
1844 return;
1845 }
1846 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
1847 if (Done.Add(E)) {
1848 const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E);
1849 if (Anc.Extent() == 2) {
1850 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
1851 if (!L.IsEmpty() && L.First().Type() == OT) {
1852 Standard_Real CurOffset = myOffset;
1853 if ( myFaceOffset.IsBound(Anc.First()))
1854 CurOffset = myFaceOffset(Anc.First());
1855 TopoDS_Shape aLocalShapeGen = MapSF(Anc.First()).Generated(E);
1856 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShapeGen);
1857 aLocalShapeGen = MapSF(Anc.Last()).Generated(E);
1858 TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShapeGen);
1859 // TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1860 // TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E));
1861 // find if exits tangent edges in the original shape
1862 TopoDS_Edge E1f, E1l;
1863 TopoDS_Vertex V1f, V1l;
1864 TopExp::Vertices(E,V1f,V1l);
1865 TopTools_ListOfShape TangE;
1866 myAnalyse.TangentEdges(E,V1f,TangE);
1867 // find if the pipe on the tangent edges are soon created.
1868 TopTools_ListIteratorOfListOfShape itl(TangE);
1869 Standard_Boolean Find = Standard_False;
1870 for ( ; itl.More() && !Find; itl.Next()) {
1871 if ( MapSF.IsBound(itl.Value())) {
1872 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f);
1873 E1f = TopoDS::Edge(aLocalShape);
1874 // E1f = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f));
1875 Find = Standard_True;
1876 }
1877 }
1878 TangE.Clear();
1879 myAnalyse.TangentEdges(E,V1l,TangE);
1880 // find if the pipe on the tangent edges are soon created.
1881 itl.Initialize(TangE);
1882 Find = Standard_False;
1883 for ( ; itl.More() && !Find; itl.Next()) {
1884 if ( MapSF.IsBound(itl.Value())) {
1885 TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l);
1886 E1l = TopoDS::Edge(aLocalShape);
1887 // E1l = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l));
1888 Find = Standard_True;
1889 }
1890 }
1891 BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l);
1892 MapSF.Bind(E,OF);
1893 }
1894 }
1895 else {
1896 // ----------------------
1897 // free border.
1898 // ----------------------
1899 TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E);
1900 TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape);
1901 /// TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E));
1902 myInitOffsetEdge.SetRoot(E); // skv: supporting history.
1903 myInitOffsetEdge.Bind (E,EOn1);
1904 }
1905 }
1906 }
1907
1908 //--------------------------------------------------------
1909 // Construction of spheres on vertex.
1910 //--------------------------------------------------------
1911 Done.Clear();
1912 TopTools_ListIteratorOfListOfShape it;
1913 Message_ProgressScope aPS2(aPSOuter.Next(4), "Constructing spheres on vertices", 1, Standard_True);
1914 for (Exp.Init(myFaceComp,TopAbs_VERTEX); Exp.More(); Exp.Next(), aPS2.Next()) {
1915 if (!aPS2.More())
1916 {
1917 myError = BRepOffset_UserBreak;
1918 return;
1919 }
1920 const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current());
1921 if (Done.Add(V)) {
1922 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V);
1923 TopTools_ListOfShape LE;
1924 myAnalyse.Edges(V,OT,LE);
1925
1926 if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) {
1927 TopTools_ListOfShape LOE;
1928 //--------------------------------------------------------
1929 // Return connected edges on tubes.
1930 //--------------------------------------------------------
1931 for (it.Initialize(LE) ; it.More(); it.Next()) {
1932 LOE.Append(MapSF(it.Value()).Generated(V).Reversed());
1933 }
1934 //----------------------
1935 // construction sphere.
1936 //-----------------------
1937 const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First());
1938 const TopoDS_Shape& FF = LLA.First();
1939 Standard_Real CurOffset = myOffset;
1940 if ( myFaceOffset.IsBound(FF))
1941 CurOffset = myFaceOffset(FF);
1942
1943 BRepOffset_Offset OF(V,LOE,CurOffset);
1944 MapSF.Bind(V,OF);
1945 }
1946 //--------------------------------------------------------------
1947 // Particular processing if V is at least a free border.
1948 //-------------------------------------------------------------
1949 TopTools_ListOfShape LBF;
1950 myAnalyse.Edges(V,ChFiDS_FreeBound,LBF);
1951 if (!LBF.IsEmpty()) {
1952 Standard_Boolean First = Standard_True;
1953 for (it.Initialize(LE) ; it.More(); it.Next()) {
1954 if (First) {
1955 myInitOffsetEdge.SetRoot(V); // skv: supporting history.
1956 myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V));
1957 First = Standard_False;
1958 }
1959 else {
1960 myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V));
1961 }
1962 }
1963 }
1964 }
1965 }
1966
1967 //------------------------------------------------------------
1968 // Extension of parallel faces to the context.
1969 // Extended faces are ordered in DS and removed from MapSF.
1970 //------------------------------------------------------------
1971 if (!myFaces.IsEmpty()) ToContext (MapSF);
1972
1973 //------------------------------------------------------
1974 // MAJ SD.
1975 //------------------------------------------------------
1976 ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
1977 if (myOffset < 0.) RT = ChFiDS_Convex;
1978 BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF);
1979 Message_ProgressScope aPS3(aPSOuter.Next(), NULL, MapSF.Size());
1980 for ( ; It.More(); It.Next(), aPS3.Next()) {
1981 if (!aPS3.More())
1982 {
1983 myError = BRepOffset_UserBreak;
1984 return;
1985 }
1986 const TopoDS_Shape& SI = It.Key();
1987 const BRepOffset_Offset& SF = It.Value();
1988 if (SF.Status() == BRepOffset_Reversed ||
1989 SF.Status() == BRepOffset_Degenerated ) {
1990 //------------------------------------------------
1991 // Degenerated or returned faces are not stored.
1992 //------------------------------------------------
1993 continue;
1994 }
1995
1996 const TopoDS_Face& OF = It.Value().Face();
1997 myInitOffsetFace.Bind (SI,OF);
1998 myInitOffsetFace.SetRoot (SI); // Initial<-> Offset
1999 myImageOffset.SetRoot (OF); // FaceOffset root of images
2000
2001 if (SI.ShapeType() == TopAbs_FACE) {
2002 for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2003 Exp.More(); Exp.Next()) {
2004 //--------------------------------------------------------------------
2005 // To each face are associatedthe edges that restrict that
2006 // The edges that do not generate tubes or are not tangent
2007 // to two faces are removed.
2008 //--------------------------------------------------------------------
2009 const TopoDS_Edge& E = TopoDS::Edge(Exp.Current());
2010 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
2011 if (!L.IsEmpty() && L.First().Type() != RT) {
2012 TopAbs_Orientation OO = E.Orientation();
2013 TopoDS_Shape aLocalShape = It.Value().Generated(E);
2014 TopoDS_Edge OE = TopoDS::Edge(aLocalShape);
2015 // TopoDS_Edge OE = TopoDS::Edge(It.Value().Generated(E));
2016 myAsDes->Add (OF,OE.Oriented(OO));
2017 }
2018 }
2019 }
2020 else {
2021 for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2022 Exp.More(); Exp.Next()) {
2023 myAsDes->Add (OF,Exp.Current());
2024 }
2025 }
2026 }
2027
2028 #ifdef OCCT_DEBUG
2029 if ( ChronBuild) Clock.Show();
2030 #endif
2031 }
2032
2033
2034
2035 //=======================================================================
2036 //function : SelfInter
2037 //purpose :
2038 //=======================================================================
2039
SelfInter(TopTools_MapOfShape &)2040 void BRepOffset_MakeOffset::SelfInter(TopTools_MapOfShape& /*Modif*/)
2041 {
2042 #ifdef OCCT_DEBUG
2043 if ( ChronBuild) {
2044 std::cout << " AUTODEBOUCLAGE:" << std::endl;
2045 Clock.Reset();
2046 Clock.Start();
2047 }
2048 #endif
2049
2050 throw Standard_NotImplemented();
2051 }
2052
2053
2054 //=======================================================================
2055 //function : ToContext
2056 //purpose :
2057 //=======================================================================
2058
ToContext(BRepOffset_DataMapOfShapeOffset & MapSF)2059 void BRepOffset_MakeOffset::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF)
2060 {
2061 TopTools_DataMapOfShapeShape Created;
2062 TopTools_DataMapOfShapeShape MEF;
2063 TopTools_IndexedMapOfShape FacesToBuild;
2064 TopTools_ListIteratorOfListOfShape itl;
2065 TopExp_Explorer exp;
2066
2067 // TopAbs_State Side = TopAbs_IN;
2068 // if (myOffset < 0.) Side = TopAbs_OUT;
2069
2070 TopAbs_State Side = TopAbs_OUT;
2071
2072 /*
2073 Standard_Integer i;
2074 for (i = 1; i <= myFaces.Extent(); i++) {
2075 const TopoDS_Face& CF = TopoDS::Face(myFaces(i));
2076 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2077 exp.More(); exp.Next()) {
2078 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2079 if (!myAnalyse.HasAncestor(E)) {
2080 //----------------------------------------------------------------
2081 // The edges of context faces that are not in the initial shape
2082 // can appear in the result.
2083 //----------------------------------------------------------------
2084 //myAsDes->Add(CF,E);
2085 }
2086 }
2087 }
2088 */
2089
2090 //--------------------------------------------------------
2091 // Determine the edges and faces reconstructed by
2092 // intersection.
2093 //---------------------------------------------------------
2094 Standard_Integer j;
2095 for (j = 1; j <= myFaces.Extent(); j++) {
2096 const TopoDS_Face& CF = TopoDS::Face(myFaces(j));
2097 for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2098 exp.More(); exp.Next()) {
2099 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2100 if (myAnalyse.HasAncestor(E)) {
2101 const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E);
2102 for (itl.Initialize(LEA); itl.More(); itl.Next()) {
2103 const BRepOffset_Offset& OF = MapSF(itl.Value());
2104 FacesToBuild.Add(itl.Value());
2105 MEF.Bind(OF.Generated(E),CF);
2106 }
2107 TopoDS_Vertex V[2];
2108 TopExp::Vertices(E,V[0],V[1]);
2109 for (Standard_Integer i = 0; i < 2; i++) {
2110 const TopTools_ListOfShape& LVA = myAnalyse.Ancestors(V[i]);
2111 for ( itl.Initialize(LVA); itl.More(); itl.Next()) {
2112 const TopoDS_Edge& EV = TopoDS::Edge(itl.Value());
2113 if (MapSF.IsBound(EV)) {
2114 const BRepOffset_Offset& OF = MapSF(EV);
2115 FacesToBuild.Add(EV);
2116 MEF.Bind(OF.Generated(V[i]),CF);
2117 }
2118 }
2119 }
2120 }
2121 }
2122 }
2123 //---------------------------
2124 // Reconstruction of faces.
2125 //---------------------------
2126 TopoDS_Face F,NF;
2127 ChFiDS_TypeOfConcavity RT = ChFiDS_Concave;
2128 if (myOffset < 0.) RT = ChFiDS_Convex;
2129 TopoDS_Shape OE,NE;
2130 TopAbs_Orientation Or;
2131
2132 for (j = 1; j <= FacesToBuild.Extent(); j++) {
2133 const TopoDS_Shape& S = FacesToBuild(j);
2134 BRepOffset_Offset BOF;
2135 BOF = MapSF(S);
2136 F = TopoDS::Face(BOF.Face());
2137 BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF);
2138 MapSF.UnBind(S);
2139 //--------------
2140 // MAJ SD.
2141 //--------------
2142 myInitOffsetFace.Bind (S,NF);
2143 myInitOffsetFace.SetRoot (S); // Initial<-> Offset
2144 myImageOffset.SetRoot (NF);
2145
2146 if (S.ShapeType() == TopAbs_FACE) {
2147 for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2148 exp.More(); exp.Next()) {
2149
2150 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
2151 const BRepOffset_ListOfInterval& L = myAnalyse.Type(E);
2152 OE = BOF.Generated(E);
2153 Or = E.Orientation();
2154 OE.Orientation(Or);
2155 if (!L.IsEmpty() && L.First().Type() != RT) {
2156 if (Created.IsBound(OE)) {
2157 NE = Created(OE);
2158 if (NE.Orientation() == TopAbs_REVERSED)
2159 NE.Orientation(TopAbs::Reverse(Or));
2160 else
2161 NE.Orientation(Or);
2162 myAsDes->Add(NF,NE);
2163 }
2164 else {
2165 myAsDes->Add(NF,OE);
2166 }
2167 }
2168 }
2169 }
2170 else {
2171 //------------------
2172 // Tube
2173 //---------------------
2174 for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
2175 exp.More(); exp.Next()) {
2176 myAsDes->Add (NF,exp.Current());
2177 }
2178 }
2179 MapSF.UnBind(S);
2180 }
2181
2182 //------------------
2183 // MAJ free borders
2184 //------------------
2185 TopTools_DataMapIteratorOfDataMapOfShapeShape itc;
2186 for (itc.Initialize(Created); itc.More(); itc.Next()) {
2187 OE = itc.Key();
2188 NE = itc.Value();
2189 if (myInitOffsetEdge.IsImage(OE)) {
2190 TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE);
2191 Or = myInitOffsetEdge.Image(E).First().Orientation();
2192 if (NE.Orientation() == TopAbs_REVERSED)
2193 NE.Orientation(TopAbs::Reverse(Or));
2194 else
2195 NE.Orientation(Or);
2196 myInitOffsetEdge.Remove(OE);
2197 myInitOffsetEdge.Bind(E,NE);
2198 }
2199 }
2200 }
2201
2202
2203 //=======================================================================
2204 //function : UpdateFaceOffset
2205 //purpose :
2206 //=======================================================================
2207
UpdateFaceOffset()2208 void BRepOffset_MakeOffset::UpdateFaceOffset()
2209 {
2210 TopTools_MapOfShape M;
2211 TopTools_DataMapOfShapeReal CopiedMap;
2212 CopiedMap.Assign(myFaceOffset);
2213 TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap);
2214
2215 ChFiDS_TypeOfConcavity RT = ChFiDS_Convex;
2216 if (myOffset < 0.) RT = ChFiDS_Concave;
2217
2218 for ( ; it.More(); it.Next()) {
2219 const TopoDS_Face& F = TopoDS::Face(it.Key());
2220 Standard_Real CurOffset = CopiedMap(F);
2221 if ( !M.Add(F)) continue;
2222 TopoDS_Compound Co;
2223 BRep_Builder Build;
2224 Build.MakeCompound(Co);
2225 TopTools_MapOfShape Dummy;
2226 Build.Add(Co,F);
2227 if (myJoin == GeomAbs_Arc)
2228 myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential,RT);
2229 else
2230 myAnalyse.AddFaces(F,Co,Dummy,ChFiDS_Tangential);
2231
2232 TopExp_Explorer exp(Co,TopAbs_FACE);
2233 for (; exp.More(); exp.Next()) {
2234 const TopoDS_Face& FF = TopoDS::Face(exp.Current());
2235 if ( !M.Add(FF)) continue;
2236 if ( myFaceOffset.IsBound(FF))
2237 myFaceOffset.UnBind(FF);
2238 myFaceOffset.Bind(FF,CurOffset);
2239 }
2240 }
2241 }
2242
2243 //=======================================================================
2244 //function : CorrectConicalFaces
2245 //purpose :
2246 //=======================================================================
2247
CorrectConicalFaces()2248 void BRepOffset_MakeOffset::CorrectConicalFaces()
2249 {
2250 if(myOffsetShape.IsNull())
2251 {
2252 return;
2253 }
2254 //
2255 TopTools_SequenceOfShape Cones;
2256 TopTools_SequenceOfShape Circs;
2257 TopTools_SequenceOfShape Seams;
2258 Standard_Real TolApex = 1.e-5;
2259
2260 Standard_Integer i;
2261
2262 TopTools_DataMapOfShapeListOfShape FacesOfCone;
2263 //TopTools_DataMapOfShapeShape DegEdges;
2264 TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE );
2265 if (myJoin == GeomAbs_Arc)
2266 {
2267 for (; Explo.More(); Explo.Next())
2268 {
2269 TopoDS_Face aFace = TopoDS::Face( Explo.Current() );
2270 Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace );
2271 //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2272 //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //???
2273
2274 TopTools_IndexedMapOfShape Emap;
2275 TopExp::MapShapes( aFace, TopAbs_EDGE, Emap );
2276 for (i = 1; i <= Emap.Extent(); i++)
2277 {
2278 TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) );
2279 //Standard_Real f, l;
2280 //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l );
2281 //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape());
2282 if (BRep_Tool::Degenerated(anEdge))
2283 {
2284 //Check if anEdge is a really degenerated edge or not
2285 BRepAdaptor_Curve BACurve(anEdge, aFace);
2286 gp_Pnt Pfirst, Plast, Pmid;
2287 Pfirst = BACurve.Value(BACurve.FirstParameter());
2288 Plast = BACurve.Value(BACurve.LastParameter());
2289 Pmid = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.);
2290 if (Pfirst.Distance(Plast) <= TolApex &&
2291 Pfirst.Distance(Pmid) <= TolApex)
2292 continue;
2293 //Cones.Append( aFace );
2294 //Circs.Append( anEdge );
2295 //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge );
2296 TopoDS_Edge OrEdge =
2297 TopoDS::Edge( myInitOffsetEdge.Root( anEdge) );
2298 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2299 if ( FacesOfCone.IsBound(VF) )
2300 {
2301 //add a face to the existing list
2302 TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF);
2303 aFaces.Append (aFace);
2304 //DegEdges.Bind(aFace, anEdge);
2305 }
2306 else
2307 {
2308 //the vertex is not in the map => create a new key and items
2309 TopTools_ListOfShape aFaces;
2310 aFaces.Append (aFace);
2311 FacesOfCone.Bind(VF, aFaces);
2312 //DegEdges.Bind(aFace, anEdge);
2313 }
2314 }
2315 } //for (i = 1; i <= Emap.Extent(); i++)
2316 } //for (; fexp.More(); fexp.Next())
2317 } //if (myJoin == GeomAbs_Arc)
2318
2319 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone);
2320 BRep_Builder BB;
2321 TopLoc_Location L;
2322 Standard_Boolean IsModified = Standard_False;
2323 for (; Cone.More(); Cone.Next() ) {
2324 gp_Sphere theSphere;
2325 Handle(Geom_SphericalSurface) aSphSurf;
2326 TopoDS_Wire SphereWire;
2327 BB.MakeWire(SphereWire);
2328 TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key());
2329 const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex);
2330 TopTools_ListIteratorOfListOfShape itFaces(Faces);
2331 Standard_Boolean isFirstFace = Standard_True;
2332 gp_Pnt FirstPoint;
2333 TopoDS_Vertex theFirstVertex, CurFirstVertex;
2334 for (; itFaces.More(); itFaces.Next())
2335 {
2336 TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First());
2337 TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace));
2338 for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2339 {
2340 DegEdge = TopoDS::Edge(Explo.Current());
2341 if (BRep_Tool::Degenerated(DegEdge))
2342 {
2343 TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) );
2344 TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge );
2345 if (VF.IsSame(anApex))
2346 break;
2347 }
2348 }
2349 TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD);
2350 TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape);
2351 BB.Degenerated(CurEdge, Standard_False);
2352 BB.SameRange(CurEdge, Standard_False);
2353 BB.SameParameter(CurEdge, Standard_False);
2354 gp_Pnt fPnt, lPnt, mPnt;
2355 GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt);
2356 Standard_Real f, l;
2357 BRep_Tool::Range(CurEdge, f, l);
2358 if (isFirstFace)
2359 {
2360 gp_Vec aVec1(fPnt, mPnt);
2361 gp_Vec aVec2(fPnt, lPnt);
2362 gp_Vec aNorm = aVec1.Crossed(aVec2);
2363 gp_Pnt theApex = BRep_Tool::Pnt(anApex);
2364 gp_Vec ApexToFpnt(theApex, fPnt);
2365 gp_Vec Ydir = aNorm ^ ApexToFpnt;
2366 gp_Vec Xdir = Ydir ^ aNorm;
2367 //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f);
2368 gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir));
2369 theSphere.SetRadius(myOffset);
2370 theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/);
2371 aSphSurf = new Geom_SphericalSurface(theSphere);
2372 FirstPoint = fPnt;
2373 theFirstVertex = BRepLib_MakeVertex(fPnt);
2374 CurFirstVertex = theFirstVertex;
2375 }
2376
2377 TopoDS_Vertex v1, v2, FirstVert, EndVert;
2378 TopExp::Vertices(CurEdge, v1, v2);
2379 FirstVert = CurFirstVertex;
2380 if (lPnt.Distance(FirstPoint) <= Precision::Confusion())
2381 EndVert = theFirstVertex;
2382 else
2383 EndVert = BRepLib_MakeVertex(lPnt);
2384 CurEdge.Free( Standard_True );
2385 BB.Remove(CurEdge, v1);
2386 BB.Remove(CurEdge, v2);
2387 BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD));
2388 BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED));
2389 //take the curve from sphere an put it to the edge
2390 Standard_Real Uf, Vf, Ul, Vl;
2391 ElSLib::Parameters( theSphere, fPnt, Uf, Vf );
2392 ElSLib::Parameters( theSphere, lPnt, Ul, Vl );
2393 if (Abs(Ul) <= Precision::Confusion())
2394 Ul = 2.*M_PI;
2395 Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf);
2396 /*
2397 if (!isFirstFace)
2398 {
2399 gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ();
2400 if (Abs(Uf - f) > Precision::Confusion())
2401 {
2402 aCircle.Rotate(aCircle.Axis(), f - Uf);
2403 aCurv = new Geom_Circle(aCircle);
2404 }
2405 }
2406 */
2407 Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul);
2408 BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion());
2409 BB.Range(CurEdge, Uf, Ul, Standard_True);
2410 Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() );
2411 Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul);
2412 BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion());
2413 BB.Range(CurEdge, aSphSurf, L, Uf, Ul);
2414 BRepLib::SameParameter(CurEdge);
2415 BB.Add(SphereWire, CurEdge);
2416 //Modifying correspondent edges in aFace: substitute vertices common with CurEdge
2417 BRepAdaptor_Curve2d BAc2d(CurEdge, aFace);
2418 gp_Pnt2d fPnt2d, lPnt2d;
2419 fPnt2d = BAc2d.Value(BAc2d.FirstParameter());
2420 lPnt2d = BAc2d.Value(BAc2d.LastParameter());
2421 TopTools_IndexedMapOfShape Emap;
2422 TopExp::MapShapes(aFace, TopAbs_EDGE, Emap);
2423 TopoDS_Edge EE [2];
2424 Standard_Integer j = 0, k;
2425 for (k = 1; k <= Emap.Extent(); k++)
2426 {
2427 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k));
2428 if (!BRep_Tool::Degenerated(anEdge))
2429 {
2430 TopoDS_Vertex V1, V2;
2431 TopExp::Vertices(anEdge, V1, V2);
2432 if (V1.IsSame(v1) || V2.IsSame(v1))
2433 EE[j++] = anEdge;
2434 }
2435 }
2436 for (k = 0; k < j; k++)
2437 {
2438 TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD);
2439 TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
2440 Eforward.Free(Standard_True);
2441 TopoDS_Vertex V1, V2;
2442 TopExp::Vertices( Eforward, V1, V2 );
2443 BRepAdaptor_Curve2d EEc( Eforward, aFace );
2444 gp_Pnt2d p2d1, p2d2;
2445 p2d1 = EEc.Value(EEc.FirstParameter());
2446 p2d2 = EEc.Value(EEc.LastParameter());
2447 if (V1.IsSame(v1))
2448 {
2449 TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())?
2450 FirstVert : EndVert;
2451 BB.Remove( Eforward, V1 );
2452 BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) );
2453 }
2454 else
2455 {
2456 TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())?
2457 FirstVert : EndVert;
2458 BB.Remove( Eforward, V2 );
2459 BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) );
2460 }
2461 }
2462
2463 isFirstFace = Standard_False;
2464 CurFirstVertex = EndVert;
2465 }
2466 //Building new spherical face
2467 Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
2468 gp_Pnt2d p2d1, p2d2;
2469 TopTools_ListOfShape EdgesOfWire;
2470 TopoDS_Iterator itw(SphereWire);
2471 for (; itw.More(); itw.Next())
2472 {
2473 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
2474 EdgesOfWire.Append(anEdge);
2475 Standard_Real f, l;
2476 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l);
2477 p2d1 = aC2d->Value(f);
2478 p2d2 = aC2d->Value(l);
2479 if (p2d1.X() < Ufirst)
2480 Ufirst = p2d1.X();
2481 if (p2d1.X() > Ulast)
2482 Ulast = p2d1.X();
2483 if (p2d2.X() < Ufirst)
2484 Ufirst = p2d2.X();
2485 if (p2d2.X() > Ulast)
2486 Ulast = p2d2.X();
2487 }
2488 TopTools_ListOfShape NewEdges;
2489 TopoDS_Edge FirstEdge;
2490 TopTools_ListIteratorOfListOfShape itl(EdgesOfWire);
2491 for (; itl.More(); itl.Next())
2492 {
2493 FirstEdge = TopoDS::Edge(itl.Value());
2494 Standard_Real f, l;
2495 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l);
2496 p2d1 = aC2d->Value(f);
2497 p2d2 = aC2d->Value(l);
2498 if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion())
2499 {
2500 EdgesOfWire.Remove(itl);
2501 break;
2502 }
2503 }
2504 NewEdges.Append(FirstEdge.Oriented(TopAbs_FORWARD));
2505 TopoDS_Vertex Vf1, CurVertex;
2506 TopExp::Vertices(FirstEdge, Vf1, CurVertex);
2507 itl.Initialize(EdgesOfWire);
2508 while (itl.More())
2509 {
2510 const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
2511 TopoDS_Vertex V1, V2;
2512 TopExp::Vertices(anEdge, V1, V2);
2513 if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
2514 {
2515 NewEdges.Append(anEdge.Oriented(TopAbs_FORWARD));
2516 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
2517 EdgesOfWire.Remove(itl);
2518 }
2519 else
2520 itl.Next();
2521 }
2522
2523 Standard_Real Vfirst, Vlast;
2524 if (p2d1.Y() > 0.)
2525 {
2526 Vfirst = p2d1.Y(); Vlast = M_PI/2.;
2527 }
2528 else
2529 {
2530 Vfirst = -M_PI/2.; Vlast = p2d1.Y();
2531 }
2532 TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion());
2533 TopoDS_Edge OldEdge, DegEdge;
2534 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2535 {
2536 DegEdge = TopoDS::Edge(Explo.Current());
2537 if (BRep_Tool::Degenerated(DegEdge))
2538 break;
2539 }
2540 TopoDS_Vertex DegVertex = TopExp::FirstVertex(DegEdge);
2541 for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next())
2542 {
2543 OldEdge = TopoDS::Edge(Explo.Current());
2544 TopoDS_Vertex V1, V2;
2545 TopExp::Vertices(OldEdge, V1, V2);
2546 if (!V1.IsSame(DegVertex) && !V2.IsSame(DegVertex))
2547 break;
2548 }
2549 TopoDS_Vertex V1, V2;
2550 TopExp::Vertices(OldEdge, V1, V2);
2551 TopTools_ListOfShape LV1, LV2;
2552 LV1.Append(Vf1.Oriented(TopAbs_FORWARD));
2553 LV2.Append(CurVertex.Oriented(TopAbs_FORWARD));
2554 BRepTools_Substitution theSubstitutor;
2555 theSubstitutor.Substitute(V1.Oriented(TopAbs_FORWARD), LV1);
2556 if (!V1.IsSame(V2))
2557 theSubstitutor.Substitute(V2.Oriented(TopAbs_FORWARD), LV2);
2558 theSubstitutor.Substitute(OldEdge.Oriented(TopAbs_FORWARD), NewEdges);
2559 theSubstitutor.Build(NewSphericalFace);
2560 if (theSubstitutor.IsCopied(NewSphericalFace))
2561 {
2562 const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace);
2563 NewSphericalFace = TopoDS::Face(listSh.First());
2564 }
2565
2566 //Adding NewSphericalFace to the shell
2567 Explo.Init( myOffsetShape, TopAbs_SHELL );
2568 TopoDS_Shape theShell = Explo.Current();
2569 theShell.Free( Standard_True );
2570 BB.Add( theShell, NewSphericalFace );
2571 IsModified = Standard_True;
2572 if(!theShell.Closed())
2573 {
2574 if(BRep_Tool::IsClosed(theShell))
2575 {
2576 theShell.Closed(Standard_True);
2577 }
2578 }
2579 }
2580 //
2581 if(!IsModified)
2582 {
2583 return;
2584 }
2585 //
2586 if (myShape.ShapeType() == TopAbs_SOLID || myThickening)
2587 {
2588 //Explo.Init( myOffsetShape, TopAbs_SHELL );
2589
2590 //if (Explo.More()) {
2591 // TopoDS_Shape theShell = Explo.Current();
2592 // theShell.Closed( Standard_True );
2593 //}
2594
2595 Standard_Integer NbShell = 0;
2596 TopoDS_Compound NC;
2597 TopoDS_Shape S1;
2598 BB.MakeCompound (NC);
2599
2600 TopoDS_Solid Sol;
2601 BB.MakeSolid(Sol);
2602 Sol.Closed(Standard_True);
2603 for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) {
2604 TopoDS_Shell Sh = TopoDS::Shell(Explo.Current());
2605 //if (myThickening && myOffset > 0.)
2606 // Sh.Reverse();
2607 NbShell++;
2608 if (Sh.Closed()) {
2609 BB.Add(Sol,Sh);
2610 }
2611 else {
2612 BB.Add (NC,Sh);
2613 if(NbShell == 1)
2614 {
2615 S1 = Sh;
2616 }
2617 }
2618 }
2619 Standard_Integer nbs = Sol.NbChildren();
2620 Standard_Boolean SolIsNull = (nbs == 0);
2621 //Checking solid
2622 if (nbs > 1)
2623 {
2624 BRepCheck_Analyzer aCheck (Sol, Standard_False);
2625 if (!aCheck.IsValid ())
2626 {
2627 TopTools_ListOfShape aSolList;
2628 CorrectSolid (Sol, aSolList);
2629 if (!aSolList.IsEmpty ())
2630 {
2631 BB.Add (NC, Sol);
2632 TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
2633 for (; aSLIt.More (); aSLIt.Next ())
2634 {
2635 BB.Add (NC, aSLIt.Value ());
2636 }
2637 SolIsNull = Standard_True;
2638 }
2639 }
2640 }
2641 //
2642 Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
2643 if((!SolIsNull) && (!NCIsNull))
2644 {
2645 BB.Add(NC, Sol);
2646 myOffsetShape = NC;
2647 }
2648 else if(SolIsNull && (!NCIsNull))
2649 {
2650 if (NbShell == 1)
2651 {
2652 myOffsetShape = S1;
2653 }
2654 else
2655 {
2656 myOffsetShape = NC;
2657 }
2658 }
2659 else if((!SolIsNull) && NCIsNull)
2660 {
2661 myOffsetShape = Sol;
2662 }
2663 else
2664 {
2665 myOffsetShape = NC;
2666 }
2667 }
2668 }
2669
2670
2671 //=======================================================================
2672 //function : Intersection3D
2673 //purpose :
2674 //=======================================================================
2675
Intersection3D(BRepOffset_Inter3d & Inter,const Message_ProgressRange & theRange)2676 void BRepOffset_MakeOffset::Intersection3D(BRepOffset_Inter3d& Inter, const Message_ProgressRange& theRange)
2677 {
2678 #ifdef OCCT_DEBUG
2679 if (ChronBuild) {
2680 std::cout << " INTERSECTION 3D:" << std::endl;
2681 Clock.Reset();
2682 Clock.Start();
2683 }
2684 #endif
2685 Message_ProgressScope aPS(theRange, NULL, (myFaces.Extent() && myJoin == GeomAbs_Arc) ? 2 : 1);
2686
2687 // In the Complete Intersection mode, implemented currently for planar
2688 // solids only, there is no need to intersect the faces here.
2689 // This intersection will be performed in the method BuildShellsCompleteInter
2690 // where the special treatment is applied to produced faces.
2691 //
2692 // Make sure to match the parameters in which the method
2693 // BuildShellsCompleteInter is called.
2694 if (myInter && (myJoin == GeomAbs_Intersection) && myIsPlanar &&
2695 !myThickening && myFaces.IsEmpty() && IsSolid(myShape))
2696 return;
2697
2698
2699 TopTools_ListOfShape OffsetFaces; // list of faces // created.
2700 MakeList (OffsetFaces,myInitOffsetFace,myFaces);
2701
2702 if (!myFaces.IsEmpty()) {
2703 Standard_Boolean InSide = (myOffset < 0.); // Temporary
2704 // it is necessary to calculate Inside taking account of the concavity or convexity of edges
2705 // between the cap and the part.
2706
2707 if (myJoin == GeomAbs_Arc)
2708 Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge, aPS.Next());
2709 }
2710 if (myInter) {
2711 //-------------
2712 //Complete.
2713 //-------------
2714 Inter.CompletInt (OffsetFaces,myInitOffsetFace, aPS.Next());
2715 if (!aPS.More())
2716 {
2717 myError = BRepOffset_UserBreak;
2718 return;
2719 }
2720 TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges();
2721 if (myJoin == GeomAbs_Intersection) {
2722 BRepOffset_Tool::CorrectOrientation (myFaceComp,NewEdges,myAsDes,myInitOffsetFace,myOffset);
2723 }
2724 }
2725 else {
2726 //--------------------------------
2727 // Only between neighbor faces.
2728 //--------------------------------
2729 Inter.ConnexIntByArc(OffsetFaces,myFaceComp,myAnalyse,myInitOffsetFace, aPS.Next());
2730 if (!aPS.More())
2731 {
2732 myError = BRepOffset_UserBreak;
2733 return;
2734 }
2735 }
2736 #ifdef OCCT_DEBUG
2737 if ( ChronBuild) Clock.Show();
2738 #endif
2739 }
2740
2741 //=======================================================================
2742 //function : Intersection2D
2743 //purpose :
2744 //=======================================================================
2745
Intersection2D(const TopTools_IndexedMapOfShape & Modif,const TopTools_IndexedMapOfShape & NewEdges,const Message_ProgressRange & theRange)2746 void BRepOffset_MakeOffset::Intersection2D (const TopTools_IndexedMapOfShape& Modif,
2747 const TopTools_IndexedMapOfShape& NewEdges,
2748 const Message_ProgressRange& theRange)
2749 {
2750 #ifdef OCCT_DEBUG
2751 if (ChronBuild) {
2752 std::cout << " INTERSECTION 2D:" << std::endl;
2753 Clock.Reset();
2754 Clock.Start();
2755 }
2756 #endif
2757 //--------------------------------------------------------
2758 // calculate intersections2d on faces concerned by
2759 // intersection3d
2760 //---------------------------------------------------------
2761 //TopTools_MapIteratorOfMapOfShape it(Modif);
2762 //-----------------------------------------------
2763 // Intersection of edges 2 by 2.
2764 //-----------------------------------------------
2765 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
2766 Standard_Integer i;
2767 Message_ProgressScope aPS(theRange, "Intersection 2D", Modif.Extent());
2768 for (i = 1; i <= Modif.Extent(); i++) {
2769 if (!aPS.More())
2770 {
2771 myError = BRepOffset_UserBreak;
2772 return;
2773 }
2774 const TopoDS_Face& F = TopoDS::Face(Modif(i));
2775 BRepOffset_Inter2d::Compute(myAsDes, F, NewEdges, myTol, myEdgeIntEdges, aDMVV, aPS.Next());
2776 }
2777 //
2778 BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes, myImageVV);
2779 //
2780 #ifdef OCCT_DEBUG
2781 if (AffichInt2d) {
2782 DEBVerticesControl (NewEdges,myAsDes);
2783 }
2784 if ( ChronBuild) Clock.Show();
2785 #endif
2786 }
2787
2788
2789 //=======================================================================
2790 //function : MakeLoops
2791 //purpose :
2792 //=======================================================================
2793
MakeLoops(TopTools_IndexedMapOfShape & Modif,const Message_ProgressRange & theRange)2794 void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif, const Message_ProgressRange& theRange)
2795 {
2796 #ifdef OCCT_DEBUG
2797 if (ChronBuild) {
2798 std::cout << " DEBOUCLAGE 2D:" << std::endl;
2799 Clock.Reset();
2800 Clock.Start();
2801 }
2802 #endif
2803 //TopTools_MapIteratorOfMapOfShape it(Modif);
2804 TopTools_ListOfShape LF,LC;
2805 //-----------------------------------------
2806 // unwinding of faces // modified.
2807 //-----------------------------------------
2808 Standard_Integer i;
2809 for (i = 1; i <= Modif.Extent(); i++) {
2810 if (!myFaces.Contains(Modif(i)))
2811 LF.Append(Modif(i));
2812 }
2813 //
2814 Message_ProgressScope aPS(theRange, NULL, LF.Extent() + myFaces.Extent());
2815 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2816 BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset, aPS.Next(LF.Extent()));
2817 }
2818 else {
2819 myMakeLoops.Build(LF,myAsDes,myImageOffset,myImageVV, aPS.Next(LF.Extent()));
2820 }
2821 if (!aPS.More())
2822 {
2823 myError = BRepOffset_UserBreak;
2824 return;
2825 }
2826
2827 //-----------------------------------------
2828 // unwinding of caps.
2829 //-----------------------------------------
2830 for (i = 1; i <= myFaces.Extent(); i++)
2831 LC.Append(myFaces(i));
2832
2833 Standard_Boolean InSide = 1;
2834 if (myOffset > 0 ) InSide = 0;
2835 myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide, aPS.Next(LC.Extent()));
2836
2837 #ifdef OCCT_DEBUG
2838 if ( ChronBuild) Clock.Show();
2839 #endif
2840 }
2841
2842 //=======================================================================
2843 //function : MakeFaces
2844 //purpose : Reconstruction of topologically unchanged faces that
2845 // share edges that were reconstructed.
2846 //=======================================================================
2847
MakeFaces(TopTools_IndexedMapOfShape &,const Message_ProgressRange & theRange)2848 void BRepOffset_MakeOffset::MakeFaces (TopTools_IndexedMapOfShape& /*Modif*/,
2849 const Message_ProgressRange& theRange)
2850 {
2851 #ifdef OCCT_DEBUG
2852 if (ChronBuild) {
2853 std::cout << " RECONSTRUCTION OF FACES:" << std::endl;
2854 Clock.Reset();
2855 Clock.Start();
2856 }
2857 #endif
2858 TopTools_ListIteratorOfListOfShape itr;
2859 const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots();
2860 TopTools_ListOfShape LOF;
2861 //----------------------------------
2862 // Loop on all faces //.
2863 //----------------------------------
2864 for (itr.Initialize(Roots); itr.More(); itr.Next()) {
2865 TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First());
2866 if (!myImageOffset.HasImage(F)) {
2867 LOF.Append(F);
2868 }
2869 }
2870 //
2871 Message_ProgressScope aPS(theRange, NULL, 1);
2872 if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
2873 BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset, aPS.Next());
2874 }
2875 else {
2876 myMakeLoops.BuildFaces(LOF, myAsDes, myImageOffset, aPS.Next());
2877 }
2878 if (!aPS.More())
2879 {
2880 myError = BRepOffset_UserBreak;
2881 return;
2882 }
2883 #ifdef OCCT_DEBUG
2884 if ( ChronBuild) Clock.Show();
2885 #endif
2886 }
2887
2888 //=======================================================================
2889 //function : UpdateInitOffset
2890 //purpose : Update and cleaning of myInitOffset
2891 //=======================================================================
UpdateInitOffset(BRepAlgo_Image & myInitOffset,BRepAlgo_Image & myImageOffset,const TopoDS_Shape & myOffsetShape,const TopAbs_ShapeEnum & theShapeType)2892 static void UpdateInitOffset (BRepAlgo_Image& myInitOffset,
2893 BRepAlgo_Image& myImageOffset,
2894 const TopoDS_Shape& myOffsetShape,
2895 const TopAbs_ShapeEnum &theShapeType) // skv
2896 {
2897 BRepAlgo_Image NIOF;
2898 const TopTools_ListOfShape& Roots = myInitOffset.Roots();
2899 TopTools_ListIteratorOfListOfShape it(Roots);
2900 for (; it.More(); it.Next()) {
2901 NIOF.SetRoot (it.Value());
2902 }
2903 for (it.Initialize(Roots); it.More(); it.Next()) {
2904 const TopoDS_Shape& SI = it.Value();
2905 TopTools_ListOfShape LI;
2906 TopTools_ListOfShape L1;
2907 myInitOffset.LastImage(SI,L1);
2908 TopTools_ListIteratorOfListOfShape itL1(L1);
2909 for (; itL1.More(); itL1.Next()) {
2910 const TopoDS_Shape& O1 = itL1.Value();
2911 TopTools_ListOfShape L2;
2912 myImageOffset.LastImage(O1,L2);
2913 LI.Append(L2);
2914 }
2915 NIOF.Bind(SI,LI);
2916 }
2917 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
2918 // Supporting history.
2919 // NIOF.Filter(myOffsetShape,TopAbs_FACE);
2920 NIOF.Filter(myOffsetShape, theShapeType);
2921 // Modified by skv - Mon Apr 4 18:17:27 2005 End
2922 myInitOffset = NIOF;
2923 }
2924
2925 //=======================================================================
2926 //function : MakeMissingWalls
2927 //purpose :
2928 //=======================================================================
MakeMissingWalls(const Message_ProgressRange & theRange)2929 void BRepOffset_MakeOffset::MakeMissingWalls (const Message_ProgressRange& theRange)
2930 {
2931 TopTools_IndexedDataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
2932 TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face
2933 Standard_Real OffsetVal = Abs(myOffset);
2934
2935 FillContours(myFaceComp, myAnalyse, Contours, MapEF);
2936
2937 Message_ProgressScope aPS(theRange, "Making missing walls", Contours.Extent());
2938 for (Standard_Integer ic = 1; ic <= Contours.Extent(); ic++, aPS.Next())
2939 {
2940 if (!aPS.More())
2941 {
2942 myError = BRepOffset_UserBreak;
2943 return;
2944 }
2945 TopoDS_Vertex StartVertex = TopoDS::Vertex(Contours.FindKey(ic));
2946 TopoDS_Edge StartEdge;
2947 const TopTools_ListOfShape& aContour = Contours(ic);
2948 TopTools_ListIteratorOfListOfShape itl(aContour);
2949 Standard_Boolean FirstStep = Standard_True;
2950 TopoDS_Edge PrevEdge;
2951 TopoDS_Vertex PrevVertex = StartVertex;
2952 Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
2953 for (; itl.More(); itl.Next())
2954 {
2955 TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
2956 TopoDS_Face aFaceOfEdge = TopoDS::Face(MapEF(anEdge));
2957
2958 // Check for offset existence.
2959 if (!myInitOffsetEdge.HasImage(anEdge))
2960 continue;
2961
2962 // Check for existence of two different vertices.
2963 TopTools_ListOfShape LOE, LOE2;
2964 myInitOffsetEdge.LastImage( anEdge, LOE );
2965 myImageOffset.LastImage( LOE.Last(), LOE2 );
2966 TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
2967 TopoDS_Vertex V1, V2, V3, V4;
2968 TopExp::Vertices(OE, V4, V3);
2969 TopExp::Vertices(anEdge, V1, V2);
2970 Standard_Real aF, aL;
2971 const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
2972 if (!aC.IsNull() &&
2973 (!aC->IsClosed() && !aC->IsPeriodic()))
2974 {
2975 gp_Pnt aPntF = BRep_Tool::Pnt(V1);
2976 gp_Pnt aPntL = BRep_Tool::Pnt(V2);
2977 Standard_Real aDistE = aPntF.SquareDistance(aPntL);
2978 if ( aDistE < Precision::SquareConfusion())
2979 {
2980 // Bad case: non closed, but vertexes mapped to same 3d point.
2981 continue;
2982 }
2983
2984 Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
2985 if (aDistE < anEdgeTol)
2986 {
2987 // Potential problems not detected via checkshape.
2988 gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
2989 gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
2990 if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
2991 {
2992 // To avoid computation of complex analytical continuation of Sin / ArcSin.
2993 Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
2994 Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
2995 Standard_Real aCurrentAngle = gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
2996 if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
2997 Abs (aCurrentAngle) > aMaxAngle)
2998 {
2999 // anEdge not collinear to offset edge.
3000 isBuildFromScratch = Standard_True;
3001 myIsPerformSewing = Standard_True;
3002 continue;
3003 }
3004 }
3005 }
3006 }
3007
3008 Standard_Boolean ToReverse = Standard_False;
3009 if (!V1.IsSame(PrevVertex))
3010 {
3011 TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
3012 aVtx = V3; V3 = V4; V4 = aVtx;
3013 ToReverse = Standard_True;
3014 }
3015
3016 OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
3017 TopoDS_Edge E3, E4;
3018 Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
3019 if (FirstStep || isBuildFromScratch)
3020 {
3021 E4 = BRepLib_MakeEdge( V1, V4 );
3022 if (FirstStep)
3023 StartEdge = E4;
3024 }
3025 else
3026 E4 = PrevEdge;
3027 if (V2.IsSame(StartVertex) && !ArcOnV2)
3028 E3 = StartEdge;
3029 else
3030 E3 = BRepLib_MakeEdge( V2, V3 );
3031 E4.Reverse();
3032
3033 if (isBuildFromScratch)
3034 {
3035 E3.Reverse();
3036 E4.Reverse();
3037 }
3038
3039 TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
3040 const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
3041 Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
3042 Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
3043 BRep_Builder BB;
3044 TopoDS_Wire theWire;
3045 BB.MakeWire(theWire);
3046 if (ToReverse)
3047 {
3048 BB.Add(theWire, anEdge.Reversed());
3049 BB.Add(theWire, E3.Reversed());
3050 BB.Add(theWire, OE.Reversed());
3051 BB.Add(theWire, E4.Reversed());
3052 }
3053 else
3054 {
3055 BB.Add(theWire, anEdge);
3056 BB.Add(theWire, E3);
3057 BB.Add(theWire, OE);
3058 BB.Add(theWire, E4);
3059 }
3060
3061 BRepLib::BuildCurves3d( theWire, myTol );
3062 theWire.Closed(Standard_True);
3063 TopoDS_Face NewFace;
3064 Handle(Geom_Surface) theSurf;
3065 BRepAdaptor_Curve BAcurve(anEdge);
3066 BRepAdaptor_Curve BAcurveOE(OE);
3067 Standard_Real fpar = BAcurve.FirstParameter();
3068 Standard_Real lpar = BAcurve.LastParameter();
3069 gp_Pnt PonE = BAcurve.Value(fpar);
3070 gp_Pnt PonOE = BAcurveOE.Value(fpar);
3071 gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
3072 Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
3073 Standard_Boolean IsPlanar = Standard_False;
3074 if (BAcurve.GetType() == GeomAbs_Circle &&
3075 BAcurveOE.GetType() == GeomAbs_Circle)
3076 {
3077 gp_Circ aCirc = BAcurve.Circle();
3078 gp_Circ aCircOE = BAcurveOE.Circle();
3079 gp_Lin anAxisLine(aCirc.Axis());
3080 gp_Dir CircAxisDir = aCirc.Axis().Direction();
3081 if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
3082 anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
3083 { //cylinder, plane or cone
3084 if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
3085 theSurf = GC_MakeCylindricalSurface(aCirc).Value();
3086 else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
3087 IsPlanar = Standard_True;
3088 //
3089 gp_Pnt PonEL = BAcurve.Value(lpar);
3090 if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
3091 Standard_Boolean bIsHole;
3092 TopoDS_Edge aE1, aE2;
3093 TopoDS_Wire aW1, aW2;
3094 Handle(Geom_Plane) aPL;
3095 IntTools_FClass2d aClsf;
3096 //
3097 if (aCirc.Radius()>aCircOE.Radius()) {
3098 aE1 = anEdge;
3099 aE2 = OE;
3100 } else {
3101 aE1 = OE;
3102 aE2 = anEdge;
3103 }
3104 //
3105 BB.MakeWire(aW1);
3106 BB.Add(aW1, aE1);
3107 BB.MakeWire(aW2);
3108 BB.Add(aW2, aE2);
3109 //
3110 aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
3111 for (Standard_Integer i = 0; i < 2; ++i) {
3112 TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
3113 TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
3114 //
3115 TopoDS_Face aFace;
3116 BB.MakeFace(aFace, aPL, Precision::Confusion());
3117 BB.Add (aFace, aW);
3118 aClsf.Init(aFace, Precision::Confusion());
3119 bIsHole=aClsf.IsHole();
3120 if ((bIsHole && !i) || (!bIsHole && i)) {
3121 aW.Nullify();
3122 BB.MakeWire(aW);
3123 BB.Add(aW, aE.Reversed());
3124 }
3125 }
3126 //
3127 BB.MakeFace(NewFace, aPL, Precision::Confusion());
3128 BB.Add(NewFace, aW1);
3129 BB.Add(NewFace, aW2);
3130 }
3131 }
3132 else //case of cone
3133 {
3134 gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
3135 aCirc.Radius(), aCircOE.Radius());
3136 gp_Ax3 theAx3(aCirc.Position());
3137 if (CircAxisDir * theCone.Axis().Direction() < 0.)
3138 {
3139 theAx3.ZReverse();
3140 CircAxisDir.Reverse();
3141 }
3142 theCone.SetPosition(theAx3);
3143 theSurf = new Geom_ConicalSurface(theCone);
3144 }
3145 if (!IsPlanar) {
3146 TopLoc_Location Loc;
3147 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
3148 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3149 Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
3150 OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
3151 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3152 aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
3153 aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
3154 if (E3.IsSame(E4))
3155 {
3156 if (Coeff > 0.)
3157 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3158 else
3159 {
3160 BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
3161 theWire.Nullify();
3162 BB.MakeWire(theWire);
3163 BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
3164 BB.Add(theWire, E4);
3165 BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
3166 BB.Add(theWire, E3);
3167 theWire.Closed(Standard_True);
3168 }
3169 }
3170 else
3171 {
3172 BB.SameParameter(E3, Standard_False);
3173 BB.SameRange(E3, Standard_False);
3174 BB.SameParameter(E4, Standard_False);
3175 BB.SameRange(E4, Standard_False);
3176 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
3177 BB.Range(E3, theSurf, Loc, 0., OffsetVal);
3178 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3179 BB.Range(E4, theSurf, Loc, 0., OffsetVal);
3180 }
3181 NewFace = BRepLib_MakeFace(theSurf, theWire);
3182 }
3183 } //cylinder or cone
3184 } //if both edges are arcs of circles
3185 if (NewFace.IsNull())
3186 {
3187 BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
3188 if (MF.Error() == BRepLib_FaceDone)
3189 {
3190 NewFace = MF.Face();
3191 IsPlanar = Standard_True;
3192 }
3193 else //Extrusion (by thrusections)
3194 {
3195 Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
3196 Handle(Geom_TrimmedCurve) TrEdgeCurve =
3197 new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
3198 Standard_Real fparOE, lparOE;
3199 Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
3200 Handle(Geom_TrimmedCurve) TrOffsetCurve =
3201 new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
3202 GeomFill_Generator ThrusecGenerator;
3203 ThrusecGenerator.AddCurve( TrEdgeCurve );
3204 ThrusecGenerator.AddCurve( TrOffsetCurve );
3205 ThrusecGenerator.Perform( Precision::PConfusion() );
3206 theSurf = ThrusecGenerator.Surface();
3207 //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
3208 Standard_Real Uf, Ul, Vf, Vl;
3209 theSurf->Bounds(Uf, Ul, Vf, Vl);
3210 TopLoc_Location Loc;
3211 EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
3212 BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
3213 OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
3214 BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
3215 Standard_Real UonV1 = (ToReverse)? Ul : Uf;
3216 Standard_Real UonV2 = (ToReverse)? Uf : Ul;
3217 aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
3218 aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
3219 if (E3.IsSame(E4))
3220 {
3221 BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
3222 Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
3223 BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
3224 BB.Range(E3, Vf, Vl);
3225 }
3226 else
3227 {
3228 BB.SameParameter(E3, Standard_False);
3229 BB.SameRange(E3, Standard_False);
3230 BB.SameParameter(E4, Standard_False);
3231 BB.SameRange(E4, Standard_False);
3232 BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
3233 BB.Range(E3, theSurf, Loc, Vf, Vl);
3234 BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
3235 BB.Range(E4, theSurf, Loc, Vf, Vl);
3236 Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
3237 BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
3238 BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
3239 Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
3240 BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
3241 BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
3242 }
3243 NewFace = BRepLib_MakeFace(theSurf, theWire);
3244 }
3245 }
3246 if (!IsPlanar)
3247 {
3248 Standard_Real fparOE = BAcurveOE.FirstParameter();
3249 Standard_Real lparOE = BAcurveOE.LastParameter();
3250 TopLoc_Location Loc;
3251 if (Abs(fpar - fparOE) > Precision::Confusion())
3252 {
3253 const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
3254 gp_Pnt2d fp2d = EdgeLine2d->Value(fpar);
3255 gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
3256 aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
3257 Handle(Geom_Curve) aCurve;
3258 Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
3259 Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
3260 GeomAdaptor_Surface GAsurf( theSurf );
3261 Handle(Geom2dAdaptor_Curve) HC2d = new Geom2dAdaptor_Curve( AC2d );
3262 Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf );
3263 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3264 Standard_Real max_deviation = 0., average_deviation;
3265 GeomLib::BuildCurve3d(Precision::Confusion(),
3266 ConS, FirstPar, LastPar,
3267 aCurve, max_deviation, average_deviation);
3268 BB.UpdateEdge( anE4, aCurve, max_deviation );
3269 BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
3270 BB.Range( anE4, FirstPar, LastPar );
3271 }
3272 if (Abs(lpar - lparOE) > Precision::Confusion())
3273 {
3274 const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
3275 gp_Pnt2d lp2d = EdgeLine2d->Value(lpar);
3276 gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
3277 aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
3278 Handle(Geom_Curve) aCurve;
3279 Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
3280 Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
3281 GeomAdaptor_Surface GAsurf( theSurf );
3282 Handle(Geom2dAdaptor_Curve) HC2d = new Geom2dAdaptor_Curve( AC2d );
3283 Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf );
3284 Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
3285 Standard_Real max_deviation = 0., average_deviation;
3286 GeomLib::BuildCurve3d(Precision::Confusion(),
3287 ConS, FirstPar, LastPar,
3288 aCurve, max_deviation, average_deviation);
3289 BB.UpdateEdge( anE3, aCurve, max_deviation );
3290 BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
3291 BB.Range( anE3, FirstPar, LastPar );
3292 }
3293 }
3294 BRepLib::SameParameter(NewFace);
3295 BRepTools::Update(NewFace);
3296 //Check orientation
3297 TopAbs_Orientation anOr = OrientationOfEdgeInFace(anEdge, aFaceOfEdge);
3298 TopAbs_Orientation OrInNewFace = OrientationOfEdgeInFace(anEdge, NewFace);
3299 if (OrInNewFace != TopAbs::Reverse(anOr))
3300 NewFace.Reverse();
3301 ///////////////////
3302 myWalls.Append(NewFace);
3303 if (ArcOnV2)
3304 {
3305 TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
3306 TopoDS_Vertex arcV1, arcV2;
3307 TopExp::Vertices(anArc, arcV1, arcV2);
3308 Standard_Boolean ArcReverse = Standard_False;
3309 if (!arcV1.IsSame(V3))
3310 {
3311 TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
3312 ArcReverse = Standard_True;
3313 }
3314 TopoDS_Edge EA1, EA2;
3315 //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
3316 EA1 = E3;
3317 EA1.Reverse();
3318 if (ToReverse)
3319 EA1.Reverse();
3320 //////////////////////////////////////////////////////
3321 if (V2.IsSame(StartVertex))
3322 EA2 = StartEdge;
3323 else
3324 EA2 = BRepLib_MakeEdge( V2, arcV2 );
3325 anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
3326 if (EA1.Orientation() == TopAbs_REVERSED)
3327 anArc.Reverse();
3328 EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
3329 TopoDS_Wire arcWire;
3330 BB.MakeWire(arcWire);
3331 BB.Add(arcWire, EA1);
3332 BB.Add(arcWire, anArc);
3333 BB.Add(arcWire, EA2);
3334 BRepLib::BuildCurves3d( arcWire, myTol );
3335 arcWire.Closed(Standard_True);
3336 TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
3337 BRepTools::Update(arcFace);
3338 myWalls.Append(arcFace);
3339 TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
3340 const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
3341 PrevEdge = CEA2;
3342 PrevVertex = V2;
3343 }
3344 else
3345 {
3346 if (isBuildFromScratch)
3347 {
3348 PrevEdge = TopoDS::Edge(E4);
3349 PrevVertex = V1;
3350 isBuildFromScratch = Standard_False;
3351 }
3352 else
3353 {
3354 PrevEdge = E3;
3355 PrevVertex = V2;
3356 }
3357 }
3358 FirstStep = Standard_False;
3359 }
3360 }
3361 }
3362
3363 //=======================================================================
3364 //function : MakeShells
3365 //purpose :
3366 //=======================================================================
3367
MakeShells(const Message_ProgressRange & theRange)3368 void BRepOffset_MakeOffset::MakeShells (const Message_ProgressRange& theRange)
3369 {
3370 #ifdef OCCT_DEBUG
3371 if (ChronBuild) {
3372 std::cout << " RECONSTRUCTION OF SHELLS:" << std::endl;
3373 Clock.Reset();
3374 Clock.Start();
3375 }
3376 #endif
3377 //
3378 Message_ProgressScope aPS(theRange, "Making shells", 1);
3379 // Prepare list of splits of the offset faces to make the shells
3380 TopTools_ListOfShape aLSF;
3381 const TopTools_ListOfShape& R = myImageOffset.Roots();
3382 TopTools_ListIteratorOfListOfShape it(R);
3383 //
3384 for (; it.More(); it.Next()) {
3385 if (!aPS.More())
3386 {
3387 myError = BRepOffset_UserBreak;
3388 return;
3389 }
3390 TopoDS_Shape aF = it.Value();
3391 if (myThickening) //offsetted faces must change their orientations
3392 aF.Reverse();
3393 //
3394 TopTools_ListOfShape Image;
3395 myImageOffset.LastImage(aF,Image);
3396 TopTools_ListIteratorOfListOfShape it2(Image);
3397 for (; it2.More(); it2.Next()) {
3398 const TopoDS_Shape& aFIm = it2.Value();
3399 aLSF.Append(aFIm);
3400 }
3401 }
3402 //
3403 if (myThickening) {
3404 TopExp_Explorer Explo(myShape, TopAbs_FACE);
3405 for (; Explo.More(); Explo.Next()) {
3406 const TopoDS_Shape& aF = Explo.Current();
3407 aLSF.Append(aF);
3408 }
3409 //
3410 it.Initialize(myWalls);
3411 for (; it.More(); it.Next()) {
3412 const TopoDS_Shape& aF = it.Value();
3413 aLSF.Append(aF);
3414 }
3415 }
3416 //
3417 if (aLSF.IsEmpty()) {
3418 return;
3419 }
3420 //
3421 Standard_Boolean bDone = Standard_False;
3422 if ((myJoin == GeomAbs_Intersection) && myInter &&
3423 !myThickening && myFaces.IsEmpty() &&
3424 IsSolid(myShape) && myIsPlanar) {
3425 //
3426 TopoDS_Shape aShells;
3427 bDone = BuildShellsCompleteInter(aLSF, myImageOffset, aShells, aPS.Next());
3428 if (bDone) {
3429 myOffsetShape = aShells;
3430 }
3431 }
3432 //
3433 if (!bDone) {
3434 BRepTools_Quilt Glue;
3435 TopTools_ListIteratorOfListOfShape aItLS(aLSF);
3436 for (; aItLS.More(); aItLS.Next()) {
3437 Glue.Add(aItLS.Value());
3438 }
3439 myOffsetShape = Glue.Shells();
3440 }
3441 //
3442 //Set correct value for closed flag
3443 TopExp_Explorer Explo(myOffsetShape, TopAbs_SHELL);
3444 for(; Explo.More(); Explo.Next())
3445 {
3446 TopoDS_Shape aS = Explo.Current();
3447 if(!aS.Closed())
3448 {
3449 if(BRep_Tool::IsClosed(aS))
3450 {
3451 aS.Closed(Standard_True);
3452 }
3453 }
3454 }
3455 }
3456
3457 //=======================================================================
3458 //function : MakeSolid
3459 //purpose :
3460 //=======================================================================
3461
MakeSolid(const Message_ProgressRange & theRange)3462 void BRepOffset_MakeOffset::MakeSolid (const Message_ProgressRange& theRange)
3463 {
3464 if (myOffsetShape.IsNull()) return;
3465
3466 // Modified by skv - Mon Apr 4 18:17:27 2005 Begin
3467 // Supporting history.
3468 UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE);
3469 UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE);
3470 // Modified by skv - Mon Apr 4 18:17:27 2005 End
3471 TopExp_Explorer exp;
3472 BRep_Builder B;
3473 Standard_Integer NbShell = 0;
3474 TopoDS_Compound NC;
3475 TopoDS_Shape S1;
3476 B.MakeCompound (NC);
3477
3478 Message_ProgressScope aPS(theRange, "Making solid", 1);
3479
3480 TopoDS_Solid Sol;
3481 B.MakeSolid(Sol);
3482 Sol.Closed(Standard_True);
3483 Standard_Boolean aMakeSolid = (myShape.ShapeType() == TopAbs_SOLID) || myThickening;
3484 for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) {
3485 if (!aPS.More())
3486 {
3487 myError = BRepOffset_UserBreak;
3488 return;
3489 }
3490 TopoDS_Shell Sh = TopoDS::Shell(exp.Current());
3491 if (myThickening && myOffset > 0.)
3492 Sh.Reverse();
3493 NbShell++;
3494 if (Sh.Closed() && aMakeSolid) {
3495 B.Add(Sol,Sh);
3496 }
3497 else {
3498 B.Add (NC,Sh);
3499 if(NbShell == 1)
3500 {
3501 S1 = Sh;
3502 }
3503 }
3504 }
3505 Standard_Integer nbs = Sol.NbChildren();
3506 Standard_Boolean SolIsNull = (nbs == 0);
3507 //Checking solid
3508 if (nbs > 1)
3509 {
3510 BRepCheck_Analyzer aCheck (Sol, Standard_False);
3511 if (!aCheck.IsValid ())
3512 {
3513 TopTools_ListOfShape aSolList;
3514 CorrectSolid (Sol, aSolList);
3515 if (!aSolList.IsEmpty ())
3516 {
3517 B.Add (NC, Sol);
3518 TopTools_ListIteratorOfListOfShape aSLIt (aSolList);
3519 for (; aSLIt.More (); aSLIt.Next ())
3520 {
3521 B.Add (NC, aSLIt.Value ());
3522 }
3523 SolIsNull = Standard_True;
3524 }
3525 }
3526 }
3527 Standard_Boolean NCIsNull = (NC.NbChildren() == 0);
3528 if((!SolIsNull) && (!NCIsNull))
3529 {
3530 B.Add(NC, Sol);
3531 myOffsetShape = NC;
3532 }
3533 else if(SolIsNull && (!NCIsNull))
3534 {
3535 if (NbShell == 1)
3536 {
3537 myOffsetShape = S1;
3538 }
3539 else
3540 {
3541 myOffsetShape = NC;
3542 }
3543 }
3544 else if((!SolIsNull) && NCIsNull)
3545 {
3546 myOffsetShape = Sol;
3547 }
3548 else
3549 {
3550 myOffsetShape = NC;
3551 }
3552 }
3553
3554 //=======================================================================
3555 //function : SelectShells
3556 //purpose :
3557 //=======================================================================
3558
SelectShells()3559 void BRepOffset_MakeOffset::SelectShells ()
3560 {
3561 TopTools_MapOfShape FreeEdges;
3562 TopExp_Explorer exp(myFaceComp,TopAbs_EDGE);
3563 //-------------------------------------------------------------
3564 // FreeEdges all edges that can have free border in the
3565 // parallel shell
3566 // 1 - free borders of myShape .
3567 //-------------------------------------------------------------
3568 for ( ; exp.More(); exp.Next()) {
3569 const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3570 const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E);
3571 if (LA.Extent() < 2) {
3572 if (myAnalyse.Type(E).First().Type() == ChFiDS_FreeBound) {
3573 FreeEdges.Add(E);
3574 }
3575 }
3576 }
3577 // myShape has free borders and there are no caps
3578 // no unwinding 3d.
3579 if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return;
3580
3581 myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges);
3582 }
3583
3584 //=======================================================================
3585 //function : OffsetFacesFromShapes
3586 //purpose :
3587 //=======================================================================
3588
OffsetFacesFromShapes() const3589 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetFacesFromShapes() const
3590 {
3591 return myInitOffsetFace;
3592 }
3593
3594 // Modified by skv - Tue Mar 15 16:20:43 2005 Begin
3595
3596 //=======================================================================
3597 //function : GetJoinType
3598 //purpose : Query offset join type.
3599 //=======================================================================
3600
GetJoinType() const3601 GeomAbs_JoinType BRepOffset_MakeOffset::GetJoinType() const
3602 {
3603 return myJoin;
3604 }
3605
3606 //=======================================================================
3607 //function : OffsetEdgesFromShapes
3608 //purpose :
3609 //=======================================================================
3610
OffsetEdgesFromShapes() const3611 const BRepAlgo_Image& BRepOffset_MakeOffset::OffsetEdgesFromShapes() const
3612 {
3613 return myInitOffsetEdge;
3614 }
3615
3616 // Modified by skv - Tue Mar 15 16:20:43 2005 End
3617
3618 //=======================================================================
3619 //function : ClosingFaces
3620 //purpose :
3621 //=======================================================================
3622
ClosingFaces() const3623 const TopTools_IndexedMapOfShape& BRepOffset_MakeOffset::ClosingFaces () const
3624 {
3625 return myOriginalFaces;
3626 }
3627
3628
3629
3630 //=======================================================================
3631 //function : EncodeRegularity
3632 //purpose :
3633 //=======================================================================
3634
EncodeRegularity()3635 void BRepOffset_MakeOffset::EncodeRegularity ()
3636 {
3637 #ifdef OCCT_DEBUG
3638 if (ChronBuild) {
3639 std::cout << " CODING OF REGULARITIES:" << std::endl;
3640 Clock.Reset();
3641 Clock.Start();
3642 }
3643 #endif
3644
3645 if (myOffsetShape.IsNull()) return;
3646 // find edges G1 in the result
3647 TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE);
3648
3649 BRep_Builder B;
3650 TopTools_MapOfShape MS;
3651
3652 for ( ; exp.More(); exp.Next()) {
3653 TopoDS_Edge OE = TopoDS::Edge(exp.Current());
3654 BRepLib::BuildCurve3d(OE,myTol);
3655 TopoDS_Edge ROE = OE;
3656
3657 if ( !MS.Add(OE)) continue;
3658
3659 if ( myImageOffset.IsImage(OE))
3660 ROE = TopoDS::Edge(myImageOffset.Root(OE));
3661
3662 const TopTools_ListOfShape& LofOF = myAsDes->Ascendant(ROE);
3663
3664 if (LofOF.Extent() != 2) {
3665 #ifdef OCCT_DEBUG_VERB
3666 std::cout << " Edge shared by " << LofOF.Extent() << " Faces" << std::endl;
3667 #endif
3668 continue;
3669 }
3670
3671 const TopoDS_Face& F1 = TopoDS::Face(LofOF.First());
3672 const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() );
3673
3674 if ( F1.IsNull() || F2.IsNull())
3675 continue;
3676
3677 const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1);
3678 const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2);
3679
3680 TopAbs_ShapeEnum Type1 = Root1.ShapeType();
3681 TopAbs_ShapeEnum Type2 = Root2.ShapeType();
3682
3683 if (F1.IsSame(F2)) {
3684 if (BRep_Tool::IsClosed(OE,F1)) {
3685 // Temporary Debug for the Bench.
3686 // Check with YFR.
3687 // In mode intersection, the edges are not coded in myInitOffsetEdge
3688 // so, manage case by case
3689 // Note DUB; for Hidden parts, it is NECESSARY to code CN
3690 // Analytic Surfaces.
3691 if (myJoin == GeomAbs_Intersection) {
3692 BRepAdaptor_Surface BS(F1,Standard_False);
3693 GeomAbs_SurfaceType SType = BS.GetType();
3694 if (SType == GeomAbs_Cylinder ||
3695 SType == GeomAbs_Cone ||
3696 SType == GeomAbs_Sphere ||
3697 SType == GeomAbs_Torus ) {
3698 B.Continuity(OE,F1,F1,GeomAbs_CN);
3699 }
3700 else {
3701 // See YFR : MaJ of myInitOffsetFace
3702 }
3703 }
3704 else if (myInitOffsetEdge.IsImage(ROE)) {
3705 if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3706 const TopoDS_Face& FRoot = TopoDS::Face(Root1);
3707 const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE));
3708 GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot);
3709 if (Conti == GeomAbs_CN) {
3710 B.Continuity(OE,F1,F1,GeomAbs_CN);
3711 }
3712 else if ( Conti > GeomAbs_C0) {
3713 B.Continuity(OE,F1,F1,GeomAbs_G1);
3714 }
3715 }
3716 }
3717 }
3718 continue;
3719 }
3720
3721
3722 // code regularities G1 between :
3723 // - sphere and tube : one root is a vertex, the other is an edge
3724 // and the vertex is included in the edge
3725 // - face and tube : one root is a face, the other an edge
3726 // and the edge is included in the face
3727 // - face and face : if two root faces are tangent in
3728 // the initial shape, they will be tangent in the offset shape
3729 // - tube and tube : if 2 edges generating tubes are
3730 // tangents, the 2 will be tangent either.
3731 if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) {
3732 TopoDS_Vertex V1,V2;
3733 TopExp::Vertices(TopoDS::Edge(Root1), V1, V2);
3734 if ( V1.IsSame(Root2) || V2.IsSame(Root2)) {
3735 B.Continuity(OE,F1,F2,GeomAbs_G1);
3736 }
3737 }
3738 else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) {
3739 TopoDS_Vertex V1,V2;
3740 TopExp::Vertices(TopoDS::Edge(Root2), V1, V2);
3741 if ( V1.IsSame(Root1) || V2.IsSame(Root1)) {
3742 B.Continuity(OE,F1,F2,GeomAbs_G1);
3743 }
3744 }
3745 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) {
3746 TopExp_Explorer exp2(Root1,TopAbs_EDGE);
3747 for ( ; exp2.More(); exp2.Next()) {
3748 if ( exp2.Current().IsSame(Root2)) {
3749 B.Continuity(OE,F1,F2,GeomAbs_G1);
3750 break;
3751 }
3752 }
3753 }
3754 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) {
3755 TopExp_Explorer exp2(Root2,TopAbs_EDGE);
3756 for ( ; exp2.More(); exp2.Next()) {
3757 if ( exp2.Current().IsSame(Root1)) {
3758 B.Continuity(OE,F1,F2,GeomAbs_G1);
3759 break;
3760 }
3761 }
3762 }
3763 else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) {
3764 // if two root faces are tangent in
3765 // the initial shape, they will be tangent in the offset shape
3766 TopTools_ListOfShape LE;
3767 BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_EDGE, LE);
3768 if ( LE.Extent() == 1) {
3769 const TopoDS_Edge& Ed = TopoDS::Edge(LE.First());
3770 if ( myAnalyse.HasAncestor(Ed)) {
3771 const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed);
3772 if (LI.Extent() == 1 &&
3773 LI.First().Type() == ChFiDS_Tangential) {
3774 B.Continuity(OE,F1,F2,GeomAbs_G1);
3775 }
3776 }
3777 }
3778 }
3779 else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) {
3780 TopTools_ListOfShape LV;
3781 BRepOffset_Tool::FindCommonShapes(Root1, Root2, TopAbs_VERTEX, LV);
3782 if ( LV.Extent() == 1) {
3783 TopTools_ListOfShape LEdTg;
3784 myAnalyse.TangentEdges(TopoDS::Edge(Root1),
3785 TopoDS::Vertex(LV.First()),
3786 LEdTg);
3787 TopTools_ListIteratorOfListOfShape it(LEdTg);
3788 for (; it.More(); it.Next()) {
3789 if ( it.Value().IsSame(Root2)) {
3790 B.Continuity(OE,F1,F2,GeomAbs_G1);
3791 break;
3792 }
3793 }
3794 }
3795 }
3796 }
3797
3798 #ifdef OCCT_DEBUG
3799 if ( ChronBuild) Clock.Show();
3800 #endif
3801 }
3802
3803 //=======================================================================
3804 //function : ComputeMaxDist
3805 //purpose :
3806 //=======================================================================
ComputeMaxDist(const gp_Pln & thePlane,const Handle (Geom_Curve)& theCrv,const Standard_Real theFirst,const Standard_Real theLast)3807 Standard_Real ComputeMaxDist(const gp_Pln& thePlane,
3808 const Handle(Geom_Curve)& theCrv,
3809 const Standard_Real theFirst,
3810 const Standard_Real theLast)
3811 {
3812 Standard_Real aMaxDist = 0.;
3813 Standard_Integer i, NCONTROL = 23;
3814 Standard_Real aPrm, aDist2;
3815 gp_Pnt aP;
3816 for (i = 0; i< NCONTROL; i++) {
3817 aPrm = ((NCONTROL - 1 - i)*theFirst + i*theLast) / (NCONTROL - 1);
3818 aP = theCrv->Value(aPrm);
3819 if (Precision::IsInfinite(aP.X()) || Precision::IsInfinite(aP.Y())
3820 || Precision::IsInfinite(aP.Z()))
3821 {
3822 return Precision::Infinite();
3823 }
3824 aDist2 = thePlane.SquareDistance(aP);
3825 if (aDist2 > aMaxDist) aMaxDist = aDist2;
3826 }
3827 return sqrt(aMaxDist)*1.05;
3828 }
3829 //=======================================================================
3830 //function : UpDateTolerance
3831 //purpose :
3832 //=======================================================================
3833
UpdateTolerance(TopoDS_Shape & S,const TopTools_IndexedMapOfShape & Faces)3834 void UpdateTolerance (TopoDS_Shape& S,
3835 const TopTools_IndexedMapOfShape& Faces)
3836 {
3837 BRep_Builder B;
3838 TopTools_MapOfShape View;
3839 TopoDS_Vertex V[2];
3840
3841 // The edges of caps are not modified.
3842 Standard_Integer j;
3843 for (j = 1; j <= Faces.Extent(); j++) {
3844 const TopoDS_Shape& F = Faces(j);
3845 TopExp_Explorer Exp;
3846 for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) {
3847 View.Add(Exp.Current());
3848 }
3849 }
3850
3851 Standard_Real Tol;
3852 TopExp_Explorer ExpF;
3853 for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
3854 {
3855 const TopoDS_Shape& F = ExpF.Current();
3856 if (Faces.Contains(F))
3857 {
3858 continue;
3859 }
3860 BRepAdaptor_Surface aBAS(TopoDS::Face(F), Standard_False);
3861 TopExp_Explorer Exp;
3862 for (Exp.Init(F, TopAbs_EDGE); Exp.More(); Exp.Next()) {
3863 TopoDS_Edge E = TopoDS::Edge(Exp.Current());
3864 Standard_Boolean isUpdated = Standard_False;
3865 if (aBAS.GetType() == GeomAbs_Plane)
3866 {
3867 //Edge does not seem to have pcurve on plane,
3868 //so EdgeCorrector does not include it in tolerance calculation
3869 Standard_Real aFirst, aLast;
3870 Handle(Geom_Curve) aCrv = BRep_Tool::Curve(E, aFirst, aLast);
3871 Standard_Real aMaxDist = ComputeMaxDist(aBAS.Plane(), aCrv, aFirst, aLast);
3872 E.Locked (Standard_False);
3873 B.UpdateEdge(E, aMaxDist);
3874 isUpdated = Standard_True;
3875 }
3876 if (View.Add(E))
3877 {
3878
3879 BRepCheck_Edge EdgeCorrector(E);
3880 Tol = EdgeCorrector.Tolerance();
3881 B.UpdateEdge(E, Tol);
3882 isUpdated = Standard_True;
3883 }
3884 if (isUpdated)
3885 {
3886 Tol = BRep_Tool::Tolerance(E);
3887 // Update the vertices.
3888 TopExp::Vertices(E, V[0], V[1]);
3889
3890 for (Standard_Integer i = 0; i <= 1; i++) {
3891 if (View.Add(V[i])) {
3892 Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape());
3893 TV->Tolerance(0.);
3894 BRepCheck_Vertex VertexCorrector(V[i]);
3895 V[i].Locked (Standard_False);
3896 B.UpdateVertex(V[i], VertexCorrector.Tolerance());
3897 // use the occasion to clean the vertices.
3898 (TV->ChangePoints()).Clear();
3899 }
3900 B.UpdateVertex(V[i], Tol);
3901 }
3902 }
3903 }
3904 }
3905 }
3906
3907 //=======================================================================
3908 //function : CorrectSolid
3909 //purpose :
3910 //=======================================================================
CorrectSolid(TopoDS_Solid & theSol,TopTools_ListOfShape & theSolList)3911 void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
3912 {
3913 BRep_Builder aBB;
3914 TopoDS_Shape anOuterShell;
3915 NCollection_List<Standard_Real> aVols;
3916 Standard_Real aVolMax = 0., anOuterVol = 0.;
3917
3918 TopoDS_Iterator anIt(theSol);
3919 for(; anIt.More(); anIt.Next())
3920 {
3921 const TopoDS_Shape& aSh = anIt.Value();
3922 GProp_GProps aVProps;
3923 BRepGProp::VolumeProperties(aSh, aVProps, Standard_True);
3924 if(Abs(aVProps.Mass()) > aVolMax)
3925 {
3926 anOuterVol = aVProps.Mass();
3927 aVolMax = Abs(anOuterVol);
3928 anOuterShell = aSh;
3929 }
3930 aVols.Append(aVProps.Mass());
3931 }
3932 //
3933 if (Abs(anOuterVol) < Precision::Confusion()) {
3934 return;
3935 }
3936 if(anOuterVol < 0.)
3937 {
3938 anOuterShell.Reverse();
3939 }
3940 TopoDS_Solid aNewSol;
3941 aBB.MakeSolid(aNewSol);
3942 aNewSol.Closed(Standard_True);
3943 aBB.Add(aNewSol, anOuterShell);
3944 BRepClass3d_SolidClassifier aSolClass(aNewSol);
3945 //
3946 anIt.Initialize(theSol);
3947 NCollection_List<Standard_Real>::Iterator aVIt(aVols);
3948 for(; anIt.More(); anIt.Next(), aVIt.Next())
3949 {
3950 TopoDS_Shell aSh = TopoDS::Shell(anIt.Value());
3951 if(aSh.IsSame(anOuterShell))
3952 {
3953 continue;
3954 }
3955 else
3956 {
3957 TopExp_Explorer aVExp(aSh, TopAbs_VERTEX);
3958 const TopoDS_Vertex& aV = TopoDS::Vertex(aVExp.Current());
3959 gp_Pnt aP = BRep_Tool::Pnt(aV);
3960 aSolClass.Perform(aP, BRep_Tool::Tolerance(aV));
3961 if(aSolClass.State() == TopAbs_IN)
3962 {
3963 if(aVIt.Value() > 0.)
3964 {
3965 aSh.Reverse();
3966 }
3967 aBB.Add(aNewSol, aSh);
3968 }
3969 else
3970 {
3971 if(aVIt.Value() < 0.)
3972 {
3973 aSh.Reverse();
3974 }
3975 TopoDS_Solid aSol;
3976 aBB.MakeSolid(aSol);
3977 aSol.Closed(Standard_True);
3978 aBB.Add(aSol, aSh);
3979 theSolList.Append(aSol);
3980 }
3981 }
3982 }
3983 theSol = aNewSol;
3984 }
3985
3986 //=======================================================================
3987 //function : CheckInputData
3988 //purpose : Check input data for possibility of offset perform.
3989 //=======================================================================
CheckInputData(const Message_ProgressRange & theRange)3990 Standard_Boolean BRepOffset_MakeOffset::CheckInputData(const Message_ProgressRange& theRange)
3991 {
3992 // Set initial error state.
3993 myError = BRepOffset_NoError;
3994 TopoDS_Shape aTmpShape;
3995 myBadShape = aTmpShape;
3996 Message_ProgressScope aPS(theRange, NULL, 1);
3997 // Non-null offset.
3998 if (Abs(myOffset) <= myTol)
3999 {
4000 Standard_Boolean isFound = Standard_False;
4001 TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset);
4002 for( ; anIter.More(); anIter.Next())
4003 {
4004 if (Abs(anIter.Value()) > myTol)
4005 {
4006 isFound = Standard_True;
4007 break;
4008 }
4009 }
4010
4011 if (!isFound)
4012 {
4013 // No face with non-null offset found.
4014 myError = BRepOffset_NullOffset;
4015 return Standard_False;
4016 }
4017 }
4018
4019 // Connectivity of input shape.
4020 if (!IsConnectedShell(myFaceComp))
4021 {
4022 myError = BRepOffset_NotConnectedShell;
4023 return Standard_False;
4024 }
4025
4026 // Normals check and continuity check.
4027 const Standard_Integer aPntPerDim = 20; // 21 points on each dimension.
4028 Standard_Real aUmin, aUmax, aVmin, aVmax;
4029 TopExp_Explorer anExpSF(myFaceComp, TopAbs_FACE);
4030 NCollection_Map<Handle(TopoDS_TShape)> aPresenceMap;
4031 TopLoc_Location L;
4032 gp_Pnt2d aPnt2d;
4033 for( ; anExpSF.More(); anExpSF.Next())
4034 {
4035 if (!aPS.More())
4036 {
4037 myError = BRepOffset_UserBreak;
4038 return Standard_False;
4039 }
4040 const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current());
4041
4042 if (aPresenceMap.Contains(aF.TShape()))
4043 {
4044 // Not perform computations with partner shapes,
4045 // since they are contain same geometry.
4046 continue;
4047 }
4048 aPresenceMap.Add(aF.TShape());
4049
4050 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L);
4051 BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax);
4052
4053 // Continuity check.
4054 if (aSurf->Continuity() == GeomAbs_C0)
4055 {
4056 myError = BRepOffset_C0Geometry;
4057 return Standard_False;
4058 }
4059
4060 // Get degenerated points, to avoid check them.
4061 NCollection_Vector<gp_Pnt> aBad3dPnts;
4062 TopExp_Explorer anExpFE(aF, TopAbs_EDGE);
4063 for( ; anExpFE.More(); anExpFE.Next())
4064 {
4065 const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current());
4066 if (BRep_Tool::Degenerated(aE))
4067 {
4068 aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE))));
4069 }
4070 }
4071
4072 // Geometry grid check.
4073 for(Standard_Integer i = 0; i <= aPntPerDim; i++)
4074 {
4075 Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim;
4076 for(Standard_Integer j = 0; j <= aPntPerDim; j++)
4077 {
4078 Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim;
4079
4080 myError = checkSinglePoint(aUParam, aVParam, aSurf, aBad3dPnts);
4081 if (myError != BRepOffset_NoError)
4082 return Standard_False;
4083 }
4084 }
4085
4086 // Vertex list check.
4087 TopExp_Explorer anExpFV(aF, TopAbs_VERTEX);
4088 for( ; anExpFV.More(); anExpFV.Next())
4089 {
4090 const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current());
4091 aPnt2d = BRep_Tool::Parameters(aV, aF);
4092
4093 myError = checkSinglePoint(aPnt2d.X(), aPnt2d.Y(), aSurf, aBad3dPnts);
4094 if (myError != BRepOffset_NoError)
4095 return Standard_False;
4096 }
4097 }
4098
4099 return Standard_True;
4100 }
4101
4102
4103 //=======================================================================
4104 //function : GetBadShape
4105 //purpose : Get shape where problems detected.
4106 //=======================================================================
GetBadShape() const4107 const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const
4108 {
4109 return myBadShape;
4110 }
4111
4112 //=======================================================================
4113 //function : RemoveInternalEdges
4114 //purpose :
4115 //=======================================================================
RemoveInternalEdges()4116 void BRepOffset_MakeOffset::RemoveInternalEdges()
4117 {
4118 Standard_Boolean bRemoveWire, bRemoveEdge;
4119 TopExp_Explorer aExpF, aExpW, aExpE;
4120 TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
4121 //
4122 TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF);
4123 //
4124 aExpF.Init(myOffsetShape, TopAbs_FACE);
4125 for (; aExpF.More(); aExpF.Next()) {
4126 TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
4127 //
4128 TopTools_ListOfShape aLIW;
4129 //
4130 aExpW.Init(aF, TopAbs_WIRE);
4131 for (; aExpW.More(); aExpW.Next()) {
4132 TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current();
4133 //
4134 bRemoveWire = Standard_True;
4135 TopTools_ListOfShape aLIE;
4136 //
4137 aExpE.Init(aW, TopAbs_EDGE);
4138 for (; aExpE.More(); aExpE.Next()) {
4139 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
4140 if (aE.Orientation() != TopAbs_INTERNAL) {
4141 bRemoveWire = Standard_False;
4142 continue;
4143 }
4144 //
4145 const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE);
4146 bRemoveEdge = (aLF.Extent() == 1);
4147 if (bRemoveEdge) {
4148 aLIE.Append(aE);
4149 }
4150 else {
4151 bRemoveWire = Standard_False;
4152 }
4153 }
4154 //
4155 if (bRemoveWire) {
4156 aLIW.Append(aW);
4157 }
4158 else if (aLIE.Extent()) {
4159 RemoveShapes(aW, aLIE);
4160 }
4161 }
4162 //
4163 if (aLIW.Extent()) {
4164 RemoveShapes(aF, aLIW);
4165 }
4166 }
4167 }
4168
4169 //=======================================================================
4170 // static methods implementation
4171 //=======================================================================
4172
4173 //=======================================================================
4174 //function : checkSinglePoint
4175 //purpose : Check single point on surface for bad normals
4176 //=======================================================================
checkSinglePoint(const Standard_Real theUParam,const Standard_Real theVParam,const Handle (Geom_Surface)& theSurf,const NCollection_Vector<gp_Pnt> & theBadPoints)4177 BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
4178 const Standard_Real theVParam,
4179 const Handle(Geom_Surface)& theSurf,
4180 const NCollection_Vector<gp_Pnt>& theBadPoints)
4181 {
4182 gp_Pnt aPnt;
4183 gp_Vec aD1U, aD1V;
4184 theSurf->D1(theUParam, theVParam, aPnt, aD1U, aD1V);
4185
4186 if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4187 aD1V.SquareMagnitude() < Precision::SquareConfusion() )
4188 {
4189 Standard_Boolean isKnownBadPnt = Standard_False;
4190 for(Standard_Integer anIdx = theBadPoints.Lower();
4191 anIdx <= theBadPoints.Upper();
4192 ++anIdx)
4193 {
4194 if (aPnt.SquareDistance(theBadPoints(anIdx)) < Precision::SquareConfusion())
4195 {
4196 isKnownBadPnt = Standard_True;
4197 break;
4198 }
4199 } // for(Standard_Integer anIdx = theBadPoints.Lower();
4200
4201 if (!isKnownBadPnt)
4202 {
4203 return BRepOffset_BadNormalsOnGeometry;
4204 }
4205 else
4206 {
4207 return BRepOffset_NoError;
4208 }
4209 } // if (aD1U.SquareMagnitude() < Precision::SquareConfusion() ||
4210
4211 if (aD1U.IsParallel(aD1V, Precision::Confusion()))
4212 {
4213 // Isolines are collinear.
4214 return BRepOffset_BadNormalsOnGeometry;
4215 }
4216
4217 return BRepOffset_NoError;
4218 }
4219
4220 //=======================================================================
4221 //function : RemoveShapes
4222 //purpose : Removes the shapes <theLS> from the shape <theS>
4223 //=======================================================================
RemoveShapes(TopoDS_Shape & theS,const TopTools_ListOfShape & theLS)4224 void RemoveShapes(TopoDS_Shape& theS,
4225 const TopTools_ListOfShape& theLS)
4226 {
4227 BRep_Builder aBB;
4228 //
4229 Standard_Boolean bFree = theS.Free();
4230 theS.Free(Standard_True);
4231 //
4232 TopTools_ListIteratorOfListOfShape aIt(theLS);
4233 for (; aIt.More(); aIt.Next()) {
4234 const TopoDS_Shape& aSI = aIt.Value();
4235 aBB.Remove(theS, aSI);
4236 }
4237 //
4238 theS.Free(bFree);
4239 }
4240
4241 //=======================================================================
4242 //function : UpdateHistory
4243 //purpose : Updates the history information
4244 //=======================================================================
UpdateHistory(const TopTools_ListOfShape & theLF,BOPAlgo_Builder & theGF,BRepAlgo_Image & theImage)4245 void UpdateHistory(const TopTools_ListOfShape& theLF,
4246 BOPAlgo_Builder& theGF,
4247 BRepAlgo_Image& theImage)
4248 {
4249 TopTools_ListIteratorOfListOfShape aIt(theLF);
4250 for (; aIt.More(); aIt.Next()) {
4251 const TopoDS_Shape& aF = aIt.Value();
4252 const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
4253 if (aLFIm.Extent()) {
4254 if (theImage.HasImage(aF)) {
4255 theImage.Add(aF, aLFIm);
4256 }
4257 else {
4258 theImage.Bind(aF, aLFIm);
4259 }
4260 }
4261 }
4262 }
4263
4264 //=======================================================================
4265 //function : IntersectEdges
4266 //purpose :
4267 //=======================================================================
IntersectEdges(const TopTools_ListOfShape & theFaces,BRepOffset_DataMapOfShapeOffset & theMapSF,TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theBuild,Handle (BRepAlgo_AsDes)& theAsDes,Handle (BRepAlgo_AsDes)& theAsDes2d,const Message_ProgressRange & theRange)4268 void BRepOffset_MakeOffset::IntersectEdges(const TopTools_ListOfShape& theFaces,
4269 BRepOffset_DataMapOfShapeOffset& theMapSF,
4270 TopTools_DataMapOfShapeShape& theMES,
4271 TopTools_DataMapOfShapeShape& theBuild,
4272 Handle(BRepAlgo_AsDes)& theAsDes,
4273 Handle(BRepAlgo_AsDes)& theAsDes2d,
4274 const Message_ProgressRange& theRange)
4275 {
4276 Standard_Real aTolF;
4277 TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
4278 // intersect edges created from edges
4279 TopTools_IndexedMapOfShape aMFV;
4280 Message_ProgressScope aPSOuter(theRange, NULL , 2);
4281 Message_ProgressScope aPS1(aPSOuter.Next(), NULL, theFaces.Size());
4282 for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
4283 {
4284 const TopoDS_Face& aF = TopoDS::Face (it.Value());
4285 aTolF = BRep_Tool::Tolerance (aF);
4286 if (!BRepOffset_Inter2d::ConnexIntByInt(aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d,
4287 myOffset, aTolF, myAnalyse, aMFV, myImageVV, myEdgeIntEdges, aDMVV, aPS1.Next()))
4288 {
4289 myError = BRepOffset_CannotExtentEdge;
4290 return;
4291 }
4292 if (!aPS1.More())
4293 {
4294 myError = BRepOffset_UserBreak;
4295 return;
4296 }
4297 }
4298 // intersect edges created from vertices
4299 Standard_Integer i, aNbF = aMFV.Extent();
4300 Message_ProgressScope aPS2(aPSOuter.Next(), "Intersecting edges created from vertices", aNbF);
4301 for (i = 1; i <= aNbF; ++i) {
4302 const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
4303 aTolF = BRep_Tool::Tolerance(aF);
4304 BRepOffset_Inter2d::ConnexIntByIntInVert
4305 (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, myAnalyse, aDMVV, aPS2.Next());
4306 if (!aPS2.More())
4307 {
4308 myError = BRepOffset_UserBreak;
4309 return;
4310 }
4311 }
4312 //
4313 // fuse vertices on edges
4314 if (!BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d, myImageVV))
4315 {
4316 myError = BRepOffset_CannotFuseVertices;
4317 return;
4318 }
4319 }
4320
4321 //=======================================================================
4322 //function : TrimEdges
4323 //purpose :
4324 //=======================================================================
TrimEdges(const TopoDS_Shape & theShape,const Standard_Real theOffset,const BRepOffset_Analyse & Analyse,BRepOffset_DataMapOfShapeOffset & theMapSF,TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theBuild,Handle (BRepAlgo_AsDes)& theAsDes,Handle (BRepAlgo_AsDes)& theAsDes2d,TopTools_IndexedMapOfShape & theNewEdges,TopTools_DataMapOfShapeShape & theETrimEInf,TopTools_DataMapOfShapeListOfShape & theEdgesOrigins)4325 Standard_Boolean TrimEdges(const TopoDS_Shape& theShape,
4326 const Standard_Real theOffset,
4327 const BRepOffset_Analyse& Analyse,
4328 BRepOffset_DataMapOfShapeOffset& theMapSF,
4329 TopTools_DataMapOfShapeShape& theMES,
4330 TopTools_DataMapOfShapeShape& theBuild,
4331 Handle(BRepAlgo_AsDes)& theAsDes,
4332 Handle(BRepAlgo_AsDes)& theAsDes2d,
4333 TopTools_IndexedMapOfShape& theNewEdges,
4334 TopTools_DataMapOfShapeShape& theETrimEInf,
4335 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
4336 {
4337 TopExp_Explorer Exp,Exp2,ExpC;
4338 TopoDS_Shape NE;
4339 TopoDS_Edge TNE;
4340 TopoDS_Face NF;
4341
4342 TopTools_ListOfShape aLFaces;
4343 for (Exp.Init (theShape, TopAbs_FACE); Exp.More(); Exp.Next())
4344 aLFaces.Append (Exp.Current());
4345
4346 TopTools_MapOfShape aMFGenerated;
4347 TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
4348 for (TopTools_ListOfShape::Iterator it (Analyse.NewFaces()); it.More(); it.Next())
4349 {
4350 const TopoDS_Shape& aFG = it.Value();
4351 aLFaces.Append (aFG);
4352 aMFGenerated.Add (aFG);
4353 TopExp::MapShapesAndUniqueAncestors (aFG, TopAbs_EDGE, TopAbs_FACE, aDMEF);
4354 }
4355
4356 for (TopTools_ListOfShape::Iterator it (aLFaces); it.More(); it.Next())
4357 {
4358 const TopoDS_Face& FI = TopoDS::Face (it.Value());
4359 NF = theMapSF(FI).Face();
4360 if (theMES.IsBound(NF)) {
4361 NF = TopoDS::Face(theMES(NF));
4362 }
4363 //
4364 TopTools_MapOfShape View;
4365 TopTools_IndexedMapOfShape VEmap;
4366 Standard_Integer i, aNb;
4367 //
4368 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap);
4369 TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
4370 //
4371 aNb = VEmap.Extent();
4372 for (i = 1; i <= aNb; ++i) {
4373 const TopoDS_Shape& aS = VEmap(i);
4374 if (!View.Add(aS)) {
4375 continue;
4376 }
4377 //
4378 if (theBuild.IsBound(aS)) {
4379 NE = theBuild(aS);
4380 // keep connection to original edges
4381 ExpC.Init(NE, TopAbs_EDGE);
4382 for (; ExpC.More(); ExpC.Next()) {
4383 const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
4384 TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
4385 if (!pLEOr) {
4386 pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
4387 }
4388 AppendToList(*pLEOr, aS);
4389 }
4390 // trim edges
4391 if (NE.ShapeType() == TopAbs_EDGE) {
4392 if (theNewEdges.Add(NE)) {
4393 if (!TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf))
4394 return Standard_False;
4395 }
4396 }
4397 else {
4398 //------------------------------------------------------------
4399 // The Intersections are on several edges.
4400 // The pieces without intersections with neighbors
4401 // are removed from AsDes.
4402 //------------------------------------------------------------
4403 for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
4404 TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
4405 if (theNewEdges.Add(NEC)) {
4406 if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
4407 if(!TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf))
4408 return Standard_False;
4409 }
4410 else {
4411 if (theAsDes->HasAscendant(NEC)) {
4412 theAsDes->Remove(NEC);
4413 }
4414 }
4415 }
4416 }
4417 }
4418 }
4419 else {
4420 if (aS.ShapeType() != TopAbs_EDGE) {
4421 continue;
4422 }
4423 if (aMFGenerated.Contains (FI) && aDMEF.FindFromKey (aS).Extent() == 1)
4424 continue;
4425
4426 NE = theMapSF(FI).Generated(aS);
4427 //// modified by jgv, 19.12.03 for OCC4455 ////
4428 NE.Orientation(aS.Orientation());
4429 //
4430 TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
4431 if (!pLEOr) {
4432 pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
4433 }
4434 AppendToList(*pLEOr, aS);
4435 //
4436 if (theMES.IsBound(NE)) {
4437 NE = theMES(NE);
4438 NE.Orientation(aS.Orientation());
4439 if (theNewEdges.Add(NE)) {
4440 if (!TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf))
4441 return Standard_False;
4442 }
4443 }
4444 else {
4445 TopoDS_Edge& anEdge = TopoDS::Edge(NE);
4446 BRepAdaptor_Curve aBAC(anEdge);
4447 if (aBAC.GetType() == GeomAbs_Line) {
4448 TopoDS_Edge aNewEdge;
4449 BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
4450 theETrimEInf.Bind(anEdge, aNewEdge);
4451 }
4452 }
4453 theAsDes->Add(NF,NE);
4454 }
4455 }
4456 }
4457 return Standard_True;
4458 }
4459
4460 //=======================================================================
4461 //function : TrimEdge
4462 //purpose : Trim the edge of the largest of descendants in AsDes2d.
4463 // Order in AsDes two vertices that have trimmed the edge.
4464 //=======================================================================
TrimEdge(TopoDS_Edge & NE,const Handle (BRepAlgo_AsDes)& AsDes2d,Handle (BRepAlgo_AsDes)& AsDes,TopTools_DataMapOfShapeShape & theETrimEInf)4465 Standard_Boolean TrimEdge(TopoDS_Edge& NE,
4466 const Handle(BRepAlgo_AsDes)& AsDes2d,
4467 Handle(BRepAlgo_AsDes)& AsDes,
4468 TopTools_DataMapOfShapeShape& theETrimEInf)
4469 {
4470 TopoDS_Edge aSourceEdge;
4471 TopoDS_Vertex V1,V2;
4472 Standard_Real aT1, aT2;
4473 //
4474 TopExp::Vertices(NE, V1, V2);
4475 BRep_Tool::Range(NE, aT1, aT2);
4476 //
4477 BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
4478 //
4479 //
4480 Standard_Real aSameParTol = Precision::Confusion();
4481
4482 Standard_Real U = 0.;
4483 Standard_Real UMin = Precision::Infinite();
4484 Standard_Real UMax = -UMin;
4485
4486 const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
4487 //
4488 Standard_Boolean bTrim = Standard_False;
4489 //
4490 if (LE.Extent() > 1) {
4491 TopTools_ListIteratorOfListOfShape it (LE);
4492 for (; it.More(); it.Next()) {
4493 TopoDS_Vertex V = TopoDS::Vertex(it.Value());
4494 if (NE.Orientation() == TopAbs_REVERSED)
4495 V.Reverse();
4496 //V.Orientation(TopAbs_INTERNAL);
4497 if (!FindParameter(V, NE, U)) {
4498 Standard_Real f, l;
4499 Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
4500 gp_Pnt thePoint = BRep_Tool::Pnt(V);
4501 GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
4502 if (Projector.NbPoints() == 0)
4503 {
4504 return Standard_False;
4505 }
4506 U = Projector.LowerDistanceParameter();
4507 }
4508 if (U < UMin) {
4509 UMin = U; V1 = V;
4510 }
4511 if (U > UMax) {
4512 UMax = U; V2 = V;
4513 }
4514 }
4515 //
4516 if (V1.IsNull() || V2.IsNull()) {
4517 return Standard_False;
4518 }
4519 if (!V1.IsSame(V2)) {
4520 NE.Free( Standard_True );
4521 BRep_Builder B;
4522 TopAbs_Orientation Or = NE.Orientation();
4523 NE.Orientation(TopAbs_FORWARD);
4524 TopoDS_Vertex VF,VL;
4525 TopExp::Vertices (NE,VF,VL);
4526 B.Remove(NE,VF);
4527 B.Remove(NE,VL);
4528 B.Add (NE,V1.Oriented(TopAbs_FORWARD));
4529 B.Add (NE,V2.Oriented(TopAbs_REVERSED));
4530 B.Range(NE,UMin,UMax);
4531 NE.Orientation(Or);
4532 AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
4533 AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
4534 BRepLib::SameParameter(NE, aSameParTol, Standard_True);
4535 //
4536 bTrim = Standard_True;
4537 }
4538 }
4539 //
4540 if (!bTrim) {
4541 BRepAdaptor_Curve aBAC(NE);
4542 if (aBAC.GetType() == GeomAbs_Line) {
4543 if (AsDes->HasAscendant(NE)) {
4544 AsDes->Remove(NE);
4545 }
4546 }
4547 }
4548 else
4549 {
4550 if (!theETrimEInf.IsBound(NE)) {
4551 theETrimEInf.Bind(NE, aSourceEdge);
4552 }
4553 }
4554 return Standard_True;
4555 }
4556
4557 //=======================================================================
4558 //function : GetEnlargedFaces
4559 //purpose :
4560 //=======================================================================
GetEnlargedFaces(const TopTools_ListOfShape & theFaces,const BRepOffset_DataMapOfShapeOffset & theMapSF,const TopTools_DataMapOfShapeShape & theMES,TopTools_DataMapOfShapeShape & theFacesOrigins,BRepAlgo_Image & theImage,TopTools_ListOfShape & theLSF)4561 void GetEnlargedFaces(const TopTools_ListOfShape& theFaces,
4562 const BRepOffset_DataMapOfShapeOffset& theMapSF,
4563 const TopTools_DataMapOfShapeShape& theMES,
4564 TopTools_DataMapOfShapeShape& theFacesOrigins,
4565 BRepAlgo_Image& theImage,
4566 TopTools_ListOfShape& theLSF)
4567 {
4568 for (TopTools_ListOfShape::Iterator it (theFaces); it.More(); it.Next())
4569 {
4570 const TopoDS_Shape& FI = it.Value();
4571 const TopoDS_Shape& OFI = theMapSF(FI).Face();
4572 if (theMES.IsBound(OFI)) {
4573 const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
4574 theLSF.Append(aLocalFace);
4575 theImage.SetRoot(aLocalFace);
4576 theFacesOrigins.Bind(aLocalFace, FI);
4577 }
4578 }
4579 }
4580
4581 //=======================================================================
4582 //function : BuildShellsCompleteInter
4583 //purpose : Make the shells from list of faces using MakerVolume algorithm.
4584 // In case there will be more than just one solid, it will be
4585 // rebuilt using only outer faces.
4586 //=======================================================================
BuildShellsCompleteInter(const TopTools_ListOfShape & theLF,BRepAlgo_Image & theImage,TopoDS_Shape & theShells,const Message_ProgressRange & theRange)4587 Standard_Boolean BuildShellsCompleteInter(const TopTools_ListOfShape& theLF,
4588 BRepAlgo_Image& theImage,
4589 TopoDS_Shape& theShells,
4590 const Message_ProgressRange& theRange)
4591 {
4592 Message_ProgressScope aPS(theRange, NULL, 5);
4593 // make solids
4594 BOPAlgo_MakerVolume aMV1;
4595 aMV1.SetArguments(theLF);
4596 // we need to intersect the faces to process the tangential faces
4597 aMV1.SetIntersect(Standard_True);
4598 aMV1.SetAvoidInternalShapes(Standard_True);
4599 aMV1.Perform(aPS.Next(3));
4600 //
4601 Standard_Boolean bDone = ! aMV1.HasErrors();
4602 if (!bDone) {
4603 return bDone;
4604 }
4605 //
4606 UpdateHistory(theLF, aMV1, theImage);
4607 //
4608 const TopoDS_Shape& aResult1 = aMV1.Shape();
4609 if (aResult1.ShapeType() == TopAbs_SOLID) {
4610 // result is the alone solid, nothing to do
4611 return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
4612 }
4613
4614 // Allocators for effective memory allocations
4615 // Global allocator for the long-living containers
4616 Handle(NCollection_IncAllocator) anAllocGlob = new NCollection_IncAllocator;
4617 // Local allocator for the local containers
4618 Handle(NCollection_IncAllocator) anAllocLoc = new NCollection_IncAllocator;
4619
4620 // Since the <theImage> object does not support multiple ancestors,
4621 // prepare local copy of the origins, which will be used to resolve
4622 // non-manifold solids produced by Maker Volume algorithm by comparison
4623 // of the normal directions of the split faces with their origins.
4624 TopTools_DataMapOfShapeListOfShape anOrigins(1, anAllocGlob);
4625 TopTools_ListIteratorOfListOfShape aItLR(theImage.Roots());
4626 for (; aItLR.More(); aItLR.Next())
4627 {
4628 const TopoDS_Shape& aFR = aItLR.Value();
4629
4630 // Reset the local allocator
4631 anAllocLoc->Reset();
4632 // Find the last splits of the root face, including the ones
4633 // created during MakeVolume operation
4634 TopTools_ListOfShape aLFIm(anAllocLoc);
4635 theImage.LastImage(aFR, aLFIm);
4636
4637 TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
4638 for (; aItLFIm.More(); aItLFIm.Next())
4639 {
4640 const TopoDS_Shape& aFIm = aItLFIm.Value();
4641 TopTools_ListOfShape *pLFOr = anOrigins.ChangeSeek(aFIm);
4642 if (!pLFOr) {
4643 pLFOr = anOrigins.Bound(aFIm, TopTools_ListOfShape(anAllocGlob));
4644 }
4645 pLFOr->Append(aFR);
4646 }
4647 }
4648
4649 // Reset the local allocator
4650 anAllocLoc->Reset();
4651 // It is necessary to rebuild the solids, avoiding internal faces
4652 // Map faces to solids
4653 TopTools_IndexedDataMapOfShapeListOfShape aDMFS(1, anAllocLoc);
4654 TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
4655 //
4656 Standard_Integer i, aNb = aDMFS.Extent();
4657 bDone = (aNb > 0);
4658 if (!bDone) {
4659 // unable to build any solid
4660 return bDone;
4661 }
4662 //
4663 // get faces attached to only one solid
4664 TopTools_ListOfShape aLF(anAllocLoc);
4665 for (i = 1; i <= aNb; ++i) {
4666 const TopTools_ListOfShape& aLS = aDMFS(i);
4667 if (aLS.Extent() == 1) {
4668 const TopoDS_Shape& aF = aDMFS.FindKey(i);
4669 aLF.Append(aF);
4670 }
4671 }
4672 //
4673 // make solids from the new list
4674 BOPAlgo_MakerVolume aMV2;
4675 aMV2.SetArguments(aLF);
4676 // no need to intersect this time
4677 aMV2.SetIntersect(Standard_False);
4678 aMV2.SetAvoidInternalShapes(Standard_True);
4679 aMV2.Perform(aPS.Next());
4680 bDone = ! aMV2.HasErrors();
4681 if (!bDone) {
4682 return bDone;
4683 }
4684 //
4685 const TopoDS_Shape& aResult2 = aMV2.Shape();
4686 if (aResult2.ShapeType() == TopAbs_SOLID) {
4687 return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
4688 }
4689 //
4690 TopExp_Explorer aExp(aResult2, TopAbs_FACE);
4691 bDone = aExp.More();
4692 if (!bDone) {
4693 return bDone;
4694 }
4695 //
4696 aLF.Clear();
4697 aDMFS.Clear();
4698 anAllocLoc->Reset();
4699
4700 // the result is non-manifold - resolve it comparing normal
4701 // directions of the offset faces and original faces
4702 for (; aExp.More(); aExp.Next())
4703 {
4704 const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
4705 const TopTools_ListOfShape* pLFOr = anOrigins.Seek(aF);
4706 if (!pLFOr)
4707 {
4708 Standard_ASSERT_INVOKE("BRepOffset_MakeOffset::BuildShellsCompleteInterSplit(): "
4709 "Origins map does not contain the split face");
4710 continue;
4711 }
4712 // Check orientation
4713 TopTools_ListIteratorOfListOfShape aItLOr(*pLFOr);
4714 for (; aItLOr.More(); aItLOr.Next())
4715 {
4716 const TopoDS_Face& aFOr = TopoDS::Face(aItLOr.Value());
4717 if (BRepOffset_Tool::CheckPlanesNormals(aF, aFOr))
4718 {
4719 aLF.Append(aF);
4720 break;
4721 }
4722 }
4723 }
4724 //
4725 // make solid from most outer faces with correct normal direction
4726 BOPAlgo_MakerVolume aMV3;
4727 aMV3.SetArguments(aLF);
4728 aMV3.SetIntersect(Standard_False);
4729 aMV3.SetAvoidInternalShapes(Standard_True);
4730 aMV3.Perform(aPS.Next());
4731 bDone = ! aMV3.HasErrors();
4732 if (!bDone) {
4733 return bDone;
4734 }
4735 //
4736 const TopoDS_Shape& aResult3 = aMV3.Shape();
4737 return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
4738 }
4739
4740 //=======================================================================
4741 //function : Generated
4742 //purpose :
4743 //=======================================================================
Generated(const TopoDS_Shape & theS)4744 const TopTools_ListOfShape& BRepOffset_MakeOffset::Generated (const TopoDS_Shape& theS)
4745 {
4746 myGenerated.Clear();
4747 const TopAbs_ShapeEnum aType = theS.ShapeType();
4748 switch (aType)
4749 {
4750 case TopAbs_VERTEX:
4751 {
4752 if (myAnalyse.HasAncestor (theS))
4753 {
4754 TopTools_MapOfShape aMFence;
4755 const TopTools_ListOfShape& aLA = myAnalyse.Ancestors (theS);
4756 TopTools_ListOfShape::Iterator itLA (aLA);
4757 for (; myGenerated.IsEmpty() && itLA.More(); itLA.Next())
4758 {
4759 const TopoDS_Shape& aE = itLA.Value();
4760 if (!myInitOffsetEdge.HasImage (aE))
4761 continue;
4762 TopTools_ListOfShape aLEIm;
4763 myInitOffsetEdge.LastImage (aE, aLEIm);
4764 TopTools_ListOfShape::Iterator itLEIm (aLEIm);
4765 for (; myGenerated.IsEmpty() && itLEIm.More(); itLEIm.Next())
4766 {
4767 TopoDS_Iterator itV (itLEIm.Value());
4768 for (; itV.More(); itV.Next())
4769 {
4770 if (!aMFence.Add (itV.Value()))
4771 {
4772 myGenerated.Append (itV.Value());
4773 break;
4774 }
4775 }
4776 }
4777 }
4778 }
4779 }
4780 Standard_FALLTHROUGH
4781 case TopAbs_EDGE:
4782 {
4783 if (myInitOffsetEdge.HasImage (theS))
4784 {
4785 myInitOffsetEdge.LastImage (theS, myGenerated);
4786 }
4787 }
4788 Standard_FALLTHROUGH
4789 case TopAbs_FACE:
4790 {
4791 TopoDS_Shape aS = theS;
4792 const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aS);
4793 if (aPlanface)
4794 aS = TopoDS::Face(*aPlanface);
4795
4796 if (!myFaces.Contains (aS) &&
4797 myInitOffsetFace.HasImage (aS))
4798 {
4799 myInitOffsetFace.LastImage (aS, myGenerated);
4800
4801 if (!myFaces.IsEmpty())
4802 {
4803 // Reverse generated shapes in case of small solids.
4804 // Useful only for faces without influence on others.
4805 TopTools_ListIteratorOfListOfShape it(myGenerated);
4806 for (; it.More(); it.Next())
4807 it.Value().Reverse();
4808 }
4809 }
4810 break;
4811 }
4812 case TopAbs_SOLID:
4813 {
4814 if (theS.IsSame (myShape))
4815 myGenerated.Append (myOffsetShape);
4816 break;
4817 }
4818 default:
4819 break;
4820 }
4821
4822 if (myResMap.IsEmpty())
4823 TopExp::MapShapes (myOffsetShape, myResMap);
4824
4825 for (TopTools_ListOfShape::Iterator it (myGenerated); it.More();)
4826 {
4827 if (myResMap.Contains (it.Value()))
4828 it.Next();
4829 else
4830 myGenerated.Remove (it);
4831 }
4832
4833 return myGenerated;
4834 }
4835
4836 //=======================================================================
4837 //function : Modified
4838 //purpose :
4839 //=======================================================================
Modified(const TopoDS_Shape & theShape)4840 const TopTools_ListOfShape& BRepOffset_MakeOffset::Modified (const TopoDS_Shape& theShape)
4841 {
4842 myGenerated.Clear();
4843
4844 if (theShape.ShapeType() == TopAbs_FACE)
4845 {
4846 TopoDS_Shape aS = theShape;
4847 const TopoDS_Shape* aPlanface = myFacePlanfaceMap.Seek(aS);
4848 if (aPlanface)
4849 aS = TopoDS::Face(*aPlanface);
4850
4851 if (myFaces.Contains (aS) &&
4852 myInitOffsetFace.HasImage (aS))
4853 {
4854 myInitOffsetFace.LastImage (aS, myGenerated);
4855
4856 if (!myFaces.IsEmpty())
4857 {
4858 // Reverse generated shapes in case of small solids.
4859 // Useful only for faces without influence on others.
4860 TopTools_ListIteratorOfListOfShape it(myGenerated);
4861 for (; it.More(); it.Next())
4862 it.Value().Reverse();
4863 }
4864 }
4865 }
4866
4867 return myGenerated;
4868 }
4869
4870 //=======================================================================
4871 //function : IsDeleted
4872 //purpose :
4873 //=======================================================================
IsDeleted(const TopoDS_Shape & theS)4874 Standard_Boolean BRepOffset_MakeOffset::IsDeleted (const TopoDS_Shape& theS)
4875 {
4876 if (myResMap.IsEmpty())
4877 TopExp::MapShapes (myOffsetShape, myResMap);
4878
4879 if (myResMap.Contains (theS))
4880 return Standard_False;
4881
4882 return Generated (theS).IsEmpty()
4883 && Modified (theS).IsEmpty();
4884 }
4885
4886 //=======================================================================
4887 //function : GetSubShapes
4888 //purpose :
4889 //=======================================================================
GetSubShapes(const TopoDS_Shape & theShape,const TopAbs_ShapeEnum theSSType,TopoDS_Shape & theResult)4890 Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
4891 const TopAbs_ShapeEnum theSSType,
4892 TopoDS_Shape& theResult)
4893 {
4894 TopExp_Explorer aExp(theShape, theSSType);
4895 if (!aExp.More()) {
4896 return Standard_False;
4897 }
4898 //
4899 TopoDS_Compound aResult;
4900 BRep_Builder().MakeCompound(aResult);
4901 //
4902 for (; aExp.More(); aExp.Next()) {
4903 const TopoDS_Shape& aSS = aExp.Current();
4904 BRep_Builder().Add(aResult, aSS);
4905 }
4906 theResult = aResult;
4907 return Standard_True;
4908 }
4909
4910 //=======================================================================
4911 //function : analyzeProgress
4912 //purpose :
4913 //=======================================================================
analyzeProgress(const Standard_Real theWhole,TColStd_Array1OfReal & theSteps) const4914 void BRepOffset_MakeOffset::analyzeProgress (const Standard_Real theWhole,
4915 TColStd_Array1OfReal& theSteps) const
4916 {
4917 theSteps.Init(0.0);
4918
4919 // Set, approximately, the proportions for each operation.
4920 // It is not a problem that the sum of the set values will not
4921 // be equal to 100%, as the values will be normalized.
4922 // The main point is to make the proportions valid relatively each other.
4923
4924 // Proportions will be different for different connection types
4925 Standard_Boolean isArc = (myJoin == GeomAbs_Arc);
4926 Standard_Boolean isPlanarIntCase = myInter && !isArc && myIsPlanar && !myThickening &&
4927 myFaces.IsEmpty() && IsSolid(myShape);
4928
4929 theSteps(PIOperation_CheckInputData) = 1.;
4930 theSteps(PIOperation_Analyse) = 2.;
4931 theSteps(PIOperation_BuildOffsetBy) = isPlanarIntCase ? 70. : (isArc ? 20. : 50.);
4932 theSteps(PIOperation_Intersection) = isPlanarIntCase ? 0. : (isArc ? 50. : 20.);
4933 if (myThickening)
4934 {
4935 theSteps(PIOperation_MakeMissingWalls) = 5.;
4936 }
4937 theSteps(PIOperation_MakeShells) = isPlanarIntCase ? 25. : 5.;
4938 theSteps(PIOperation_MakeSolid) = 5.;
4939 if (myIsPerformSewing && myThickening)
4940 {
4941 theSteps(PIOperation_Sewing) = 10.;
4942 }
4943
4944 normalizeSteps(theWhole, theSteps);
4945 }
4946
4947 //=======================================================================
4948 //function : IsPlanar
4949 //purpose : Checks if all the faces of the shape are planes
4950 //=======================================================================
IsPlanar()4951 Standard_Boolean BRepOffset_MakeOffset::IsPlanar()
4952 {
4953 Standard_Boolean aIsNonPlanarFound = Standard_False;
4954 BRep_Builder aBB;
4955
4956 TopExp_Explorer aExp(myShape, TopAbs_FACE);
4957 for (; aExp.More(); aExp.Next())
4958 {
4959 const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
4960 BRepAdaptor_Surface aBAS(aF, Standard_False);
4961 if (aBAS.GetType() == GeomAbs_Plane)
4962 continue;
4963
4964 if (myIsLinearizationAllowed)
4965 {
4966 //define the toleance
4967 Standard_Real aTolForFace = BRep_Tool::Tolerance(aF);
4968
4969 //try to linearize
4970 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
4971 GeomLib_IsPlanarSurface aPlanarityChecker(aSurf, Precision::Confusion());
4972 if (aPlanarityChecker.IsPlanar())
4973 {
4974 gp_Pln aPln = aPlanarityChecker.Plan();
4975 Handle(Geom_Plane) aPlane = new Geom_Plane(aPln);
4976 TopoDS_Face aPlanarFace;
4977 aBB.MakeFace(aPlanarFace, aPlane, aTolForFace);
4978 TopoDS_Face aFaceForward = aF;
4979 aFaceForward.Orientation(TopAbs_FORWARD);
4980 TopoDS_Iterator anItFace(aFaceForward);
4981 for (; anItFace.More(); anItFace.Next())
4982 {
4983 const TopoDS_Shape& aWire = anItFace.Value();
4984 aBB.Add(aPlanarFace, aWire);
4985 }
4986 RemoveSeamAndDegeneratedEdges(aPlanarFace, aFaceForward);
4987 myFacePlanfaceMap.Bind(aF, aPlanarFace);
4988 if (myFaces.Contains(aF))
4989 {
4990 myFaces.RemoveKey(aF);
4991 myFaces.Add(aPlanarFace);
4992 }
4993 }
4994 else
4995 aIsNonPlanarFound = Standard_True;
4996 }
4997 else
4998 aIsNonPlanarFound = Standard_True;
4999 }
5000
5001 return (!aIsNonPlanarFound);
5002 }
5003
5004 //=======================================================================
5005 //function : RemoveSeamAndDegeneratedEdges
5006 //purpose : Removes useless seam and degenerated edges from a face that becomes planar
5007 //=======================================================================
RemoveSeamAndDegeneratedEdges(const TopoDS_Face & theFace,const TopoDS_Face & theOldFace)5008 void RemoveSeamAndDegeneratedEdges(const TopoDS_Face& theFace,
5009 const TopoDS_Face& theOldFace)
5010 {
5011 TopoDS_Face aFace = theFace;
5012 aFace.Orientation(TopAbs_FORWARD);
5013
5014 Standard_Boolean aIsDegOrSeamFound = Standard_False;
5015 TopTools_SequenceOfShape aEseq;
5016 TopExp_Explorer anExplo(aFace, TopAbs_EDGE);
5017 for (; anExplo.More(); anExplo.Next())
5018 {
5019 const TopoDS_Edge& anEdge = TopoDS::Edge(anExplo.Current());
5020 if (BRep_Tool::Degenerated(anEdge) ||
5021 BRepTools::IsReallyClosed(anEdge, theOldFace))
5022 aIsDegOrSeamFound = Standard_True;
5023 else
5024 aEseq.Append(anEdge);
5025 }
5026
5027 if (!aIsDegOrSeamFound)
5028 return;
5029
5030 //Reconstruct wires
5031 BRep_Builder aBB;
5032 TopTools_ListOfShape aWlist;
5033 TopoDS_Iterator anItFace(aFace);
5034 for (; anItFace.More(); anItFace.Next())
5035 aWlist.Append(anItFace.Value());
5036
5037 aFace.Free(Standard_True);
5038 TopTools_ListIteratorOfListOfShape anItl(aWlist);
5039 for (; anItl.More(); anItl.Next())
5040 aBB.Remove(aFace, anItl.Value());
5041
5042 while (!aEseq.IsEmpty())
5043 {
5044 TopoDS_Wire aNewWire;
5045 aBB.MakeWire(aNewWire);
5046 TopoDS_Edge aCurEdge = TopoDS::Edge(aEseq(1));
5047 aBB.Add(aNewWire, aCurEdge);
5048 aEseq.Remove(1);
5049 TopoDS_Vertex aFirstVertex, aCurVertex;
5050 TopExp::Vertices(aCurEdge, aFirstVertex, aCurVertex, Standard_True); //with orientation
5051 while (!aCurVertex.IsSame(aFirstVertex))
5052 {
5053 TopoDS_Vertex aV1, aV2;
5054 Standard_Integer ind;
5055 for (ind = 1; ind <= aEseq.Length(); ind++)
5056 {
5057 aCurEdge = TopoDS::Edge(aEseq(ind));
5058 TopExp::Vertices(aCurEdge, aV1, aV2, Standard_True); //with orientation
5059 if (aV1.IsSame(aCurVertex))
5060 break;
5061 }
5062 if (ind > aEseq.Length()) //error occurred: wire is not closed
5063 break;
5064
5065 aBB.Add(aNewWire, aCurEdge);
5066 aEseq.Remove(ind);
5067 aCurVertex = aV2;
5068 }
5069
5070 aBB.Add(aFace, aNewWire);
5071 }
5072 }
5073
5074 //=======================================================================
5075 //function : IsSolid
5076 //purpose : Checks if the shape is solid
5077 //=======================================================================
IsSolid(const TopoDS_Shape & theS)5078 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
5079 {
5080 TopExp_Explorer aExp(theS, TopAbs_SOLID);
5081 return aExp.More();
5082 }
5083
5084 //=======================================================================
5085 //function : AppendToList
5086 //purpose : Add to a list only unique elements
5087 //=======================================================================
AppendToList(TopTools_ListOfShape & theList,const TopoDS_Shape & theShape)5088 void AppendToList(TopTools_ListOfShape& theList,
5089 const TopoDS_Shape& theShape)
5090 {
5091 TopTools_ListIteratorOfListOfShape aIt(theList);
5092 for (; aIt.More(); aIt.Next()) {
5093 const TopoDS_Shape& aS = aIt.Value();
5094 if (aS.IsSame(theShape)) {
5095 return;
5096 }
5097 }
5098 theList.Append(theShape);
5099 }
5100