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