1 // Created on: 2018-03-14
2 // Created by: Nikolai BUKHALOV
3 // Copyright (c) 1999-2018 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 
17 #include <BRepFill_AdvancedEvolved.hxx>
18 
19 #include <BRep_Builder.hxx>
20 #include <BRepFill_PipeShell.hxx>
21 #include <BRepFill_TransitionStyle.hxx>
22 #include <TopExp.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Edge.hxx>
25 #include <TopTools_ListOfShape.hxx>
26 #include <BOPAlgo_Tools.hxx>
27 #include <BRepLib_FindSurface.hxx>
28 #include <Geom_Plane.hxx>
29 #include <BRepAdaptor_Curve.hxx>
30 #include <BOPAlgo_MakerVolume.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <BOPAlgo_PaveFiller.hxx>
34 #include <math_MultipleVarFunctionWithHessian.hxx>
35 #include <Adaptor3d_CurveOnSurface.hxx>
36 #include <Adaptor2d_Curve2d.hxx>
37 #include <Adaptor3d_Surface.hxx>
38 #include <math_NewtonMinimum.hxx>
39 #include <BOPTools_AlgoTools.hxx>
40 #include <math_Matrix.hxx>
41 #include <math_Vector.hxx>
42 #include <BRepAdaptor_Surface.hxx>
43 #include <BRepTools_WireExplorer.hxx>
44 #include <BRepTools.hxx>
45 #include <BRepTopAdaptor_FClass2d.hxx>
46 #include <BOPAlgo_BuilderFace.hxx>
47 #include <BOPAlgo_BuilderFace.hxx>
48 #include <Geom2d_Line.hxx>
49 #include <BRepBuilderAPI_Copy.hxx>
50 #include <math_GlobOptMin.hxx>
51 #include <Geom_ConicalSurface.hxx>
52 #include <Extrema_ExtPC.hxx>
53 #include <BOPDS_DS.hxx>
54 #include <BRepLib.hxx>
55 #include <BRepExtrema_DistShapeShape.hxx>
56 #include <BRepLib_MakeFace.hxx>
57 #include <ShapeFix_Shape.hxx>
58 #include <BRepClass_FaceClassifier.hxx>
59 #include <BRepGProp_Face.hxx>
60 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
61 #include <BRep_TEdge.hxx>
62 #include <ShapeUpgrade_UnifySameDomain.hxx>
63 
64 #ifdef BRepFill_AdvancedEvolved_DEBUG
65 #include <BinTools.hxx>
66 #endif
67 
68 
69 static const Standard_Real aPipeLinearTolerance = 1.0e-4;
70 static const Standard_Real aPipeAngularTolerance = 1.0e-2;
71 
72 static Standard_Boolean ContainsInList(const TopTools_ListOfShape& theL,
73                                        const TopoDS_Shape& theObject);
74 
75 static void FindInternals(const TopoDS_Shape& theS,
76                           TopTools_ListOfShape& theLInt);
77 
78 static void RemoveInternalWires(const TopoDS_Shape& theShape);
79 
80 static void ProcessVertex(const TopoDS_Vertex& aV,
81                           const TopTools_ListOfShape& aLE,
82                           const TopTools_ListOfShape& aLF);
83 
84 static void ReduceVertexTolerance(const TopoDS_Shape& aS);
85 
86 //=======================================================================
87 //function : PerformBoolean
88 //purpose  :
89 //=======================================================================
PerformBoolean(const TopTools_ListOfShape & theArgsList,TopoDS_Shape & theResult) const90 Standard_Boolean BRepFill_AdvancedEvolved::PerformBoolean(const TopTools_ListOfShape& theArgsList,
91                                                           TopoDS_Shape& theResult) const
92 {
93   BOPAlgo_PaveFiller aPF;
94 
95   aPF.SetArguments(theArgsList);
96   aPF.SetRunParallel(myIsParallel);
97   aPF.SetFuzzyValue(myFuzzyValue);
98 
99   aPF.Perform();
100   if (aPF.HasErrors())
101   {
102     return Standard_False;
103   }
104 
105   BOPAlgo_Builder aBuilder;
106   aBuilder.SetArguments(theArgsList);
107 
108   aBuilder.SetRunParallel(myIsParallel);
109   aBuilder.PerformWithFiller(aPF);
110   if (aBuilder.HasErrors())
111   {
112     return Standard_False;
113   }
114 
115   theResult = aBuilder.Shape();
116   return Standard_True;
117 }
118 
119 //=======================================================================
120 //function : GetSpineAndProfile
121 //purpose  :
122 //=======================================================================
GetSpineAndProfile(const TopoDS_Wire & theSpine,const TopoDS_Wire & theProfile)123 void BRepFill_AdvancedEvolved::GetSpineAndProfile(const TopoDS_Wire& theSpine,
124                                                   const TopoDS_Wire& theProfile)
125 {
126   mySpine = theSpine;
127   myProfile = theProfile;
128 
129   TopTools_IndexedDataMapOfShapeListOfShape aMVEP;
130   TopExp::MapShapesAndAncestors(theProfile, TopAbs_VERTEX, TopAbs_EDGE, aMVEP);
131 
132   gp_Vec aN2;
133   gp_Pnt aLoc;
134 
135   for (Standard_Integer i = 1; i <= aMVEP.Size(); i++)
136   {
137     const TopoDS_Vertex &aVC = TopoDS::Vertex(aMVEP.FindKey(i));
138 
139     const TopTools_ListOfShape &aLE = aMVEP.FindFromIndex(i);
140 
141     if (aLE.Extent() < 2)
142       continue;
143 
144     const TopoDS_Edge &anE1 = TopoDS::Edge(aLE.First());
145     const TopoDS_Edge &anE2 = TopoDS::Edge(aLE.Last());
146 
147     const BRepAdaptor_Curve anAC1(anE1), anAC2(anE2);
148 
149     const Standard_Real aPar1 = BRep_Tool::Parameter(aVC, anE1);
150     const Standard_Real aPar2 = BRep_Tool::Parameter(aVC, anE2);
151 
152     gp_Pnt aP;
153     gp_Vec aT1, aT2;
154 
155     anAC1.D1(aPar1, aP, aT1);
156     anAC1.D1(aPar2, aP, aT2);
157 
158     aN2 = aT1.Crossed(aT2);
159 
160     if (aN2.SquareMagnitude() > Precision::SquareConfusion())
161     {
162       aLoc = BRep_Tool::Pnt(aVC);
163       break;
164     }
165   }
166 
167   BRepExtrema_DistShapeShape anExtr;
168   anExtr.LoadS1(theSpine);
169 
170   if (aN2.SquareMagnitude() > Precision::SquareConfusion())
171   {
172     const gp_Pln aPln(aLoc, aN2);
173     BRepLib_MakeFace aMF(aPln, theProfile);
174     if (!aMF.IsDone())
175       return;
176 
177     anExtr.LoadS2(aMF.Face());
178   }
179   else
180   {
181     anExtr.LoadS2(theProfile);
182   }
183 
184   if (!anExtr.Perform())
185     return;
186 
187   const Standard_Integer aNbSol = anExtr.NbSolution();
188   if (aNbSol < 1)
189     return;
190 
191   Standard_Real aDistMin = RealLast();
192   Standard_Integer anIdxMin = 0;
193 
194   for (Standard_Integer aSolId = 1; aSolId <= aNbSol; aSolId++)
195   {
196     const Standard_Real aD = anExtr.Value();
197     if (aD > aDistMin)
198       continue;
199 
200     aDistMin = aD;
201     anIdxMin = aSolId;
202   }
203 
204   BRepExtrema_SupportType anExtrType2 = anExtr.SupportTypeShape2(anIdxMin);
205 
206   if (aDistMin < Precision::Confusion())
207   {
208     anExtrType2 = BRepExtrema_IsInFace;
209   }
210 
211   switch (anExtrType2)
212   {
213     case BRepExtrema_IsInFace:
214       if (anExtr.SupportTypeShape1(anIdxMin) == BRepExtrema_IsVertex)
215       {
216         const TopoDS_Vertex aV = TopoDS::Vertex(anExtr.SupportOnShape1(anIdxMin));
217         TopTools_IndexedDataMapOfShapeListOfShape aMVES;
218         TopExp::MapShapesAndAncestors(theSpine, TopAbs_VERTEX, TopAbs_EDGE, aMVES);
219 
220         const TopTools_ListOfShape &aLE = aMVES.FindFromKey(aV);
221 
222         const TopoDS_Edge &anE1 = TopoDS::Edge(aLE.First());
223         const TopoDS_Edge &anE2 = TopoDS::Edge(aLE.Last());
224 
225         const BRepAdaptor_Curve anAC1(anE1), anAC2(anE2);
226 
227         const Standard_Real aPar1 = BRep_Tool::Parameter(aV, anE1);
228         const Standard_Real aPar2 = BRep_Tool::Parameter(aV, anE2);
229 
230         gp_Pnt aP;
231         gp_Vec aT1, aT2;
232 
233         anAC1.D1(aPar1, aP, aT1);
234         anAC1.D1(aPar2, aP, aT2);
235 
236         // Find minimal sine
237         const Standard_Real aSqT1 = Max(aT1.SquareMagnitude(), 1.0 / Precision::Infinite());
238         const Standard_Real aSqT2 = Max(aT2.SquareMagnitude(), 1.0 / Precision::Infinite());
239 
240         const Standard_Real aSqSin1 = aT1.CrossSquareMagnitude(aN2) / aSqT1;
241         const Standard_Real aSqSin2 = aT2.CrossSquareMagnitude(aN2) / aSqT2;
242 
243         if (aSqSin1 < aSqSin2)
244         {
245           if (aT1.Dot(aN2) > 0.0)
246           {
247             myProfile.Reverse();
248           }
249         }
250         else
251         {
252           if (aT2.Dot(aN2) > 0.0)
253           {
254             myProfile.Reverse();
255           }
256         }
257       }
258       else // if (... == BRepExtrema_IsOnEdge)
259       {
260         const TopoDS_Edge anE = TopoDS::Edge(anExtr.SupportOnShape1(anIdxMin));
261         const BRepAdaptor_Curve anAC(anE);
262         Standard_Real aPar;
263         anExtr.ParOnEdgeS1(anIdxMin, aPar);
264 
265         gp_Pnt aP;
266         gp_Vec aT1;
267         anAC.D1(aPar, aP, aT1);
268 
269         if (aT1.Dot(aN2) > 0.0)
270         {
271           myProfile.Reverse();
272         }
273       }
274       break;
275 
276     case BRepExtrema_IsOnEdge:
277     case BRepExtrema_IsVertex:
278     {
279       const BRepLib_MakeFace aMkFSpine(theSpine, Standard_True);
280       if (!aMkFSpine.IsDone())
281         return;
282 
283       const TopoDS_Face &aFSpine = aMkFSpine.Face();
284       const Handle(Geom_Plane) aPlnSpine = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aFSpine));
285       const gp_Vec aN1(aPlnSpine->Axis().Direction());
286       gp_Vec aTanV;
287 
288       if (anExtr.SupportTypeShape2(anIdxMin) == BRepExtrema_IsVertex)
289       {
290         const TopoDS_Vertex aV = TopoDS::Vertex(anExtr.SupportOnShape2(anIdxMin));
291         TopTools_IndexedDataMapOfShapeListOfShape aMVES;
292         TopExp::MapShapesAndAncestors(theProfile, TopAbs_VERTEX, TopAbs_EDGE, aMVES);
293 
294         const TopTools_ListOfShape &aLE = aMVES.FindFromKey(aV);
295 
296         const TopoDS_Edge &anE1 = TopoDS::Edge(aLE.First());
297         const TopoDS_Edge &anE2 = TopoDS::Edge(aLE.Last());
298 
299         const BRepAdaptor_Curve anAC1(anE1), anAC2(anE2);
300 
301         const Standard_Real aPar1 = BRep_Tool::Parameter(aV, anE1);
302         const Standard_Real aPar2 = BRep_Tool::Parameter(aV, anE2);
303 
304         gp_Pnt aP;
305         gp_Vec aT1, aT2;
306 
307         anAC1.D1(aPar1, aP, aT1);
308         anAC1.D1(aPar2, aP, aT2);
309 
310         // Find maximal cosine
311         Standard_Real aSqT1 = aT1.SquareMagnitude();
312         Standard_Real aSqT2 = aT2.SquareMagnitude();
313 
314         if (aSqT1 < Precision::SquareConfusion())
315           aSqT1 = RealLast();
316 
317         if (aSqT2 < Precision::SquareConfusion())
318           aSqT2 = RealLast();
319 
320         const Standard_Real aDP1 = aT1.Dot(aN1);
321         const Standard_Real aDP2 = aT2.Dot(aN1);
322 
323         if (aDP1*aDP1*aSqT2 > aDP2*aDP2*aSqT1)
324         {
325           //aDP1*aDP1/aSqT1 > aDP2*aDP2/aSqT2
326           aTanV = aT1;
327         }
328         else
329         {
330           aTanV = aT2;
331         }
332       }
333       else // if(anExtr.SupportTypeShape2(anIdxMin) == BRepExtrema_IsOnEdge)
334       {
335         const TopoDS_Edge anE = TopoDS::Edge(anExtr.SupportOnShape2(anIdxMin));
336         const BRepAdaptor_Curve anAC(anE);
337         Standard_Real aPar;
338         anExtr.ParOnEdgeS2(anIdxMin, aPar);
339 
340         gp_Pnt aP;
341         anAC.D1(aPar, aP, aTanV);
342       }
343 
344       //The point in the profile, which is the nearest to the spine
345       const gp_Pnt &aPnear = anExtr.PointOnShape2(anIdxMin);
346 
347       BRepClass_FaceClassifier aFClass(aFSpine, aPnear, Precision::Confusion());
348       if (aFClass.State() != TopAbs_OUT)
349       {
350         if (aN1.Dot(aTanV) < 0.0)
351         {
352           myProfile.Reverse();
353         }
354       }
355       else
356       {
357         if (aN1.Dot(aTanV) > 0.0)
358         {
359           myProfile.Reverse();
360         }
361       }
362     }
363     break;
364     default:
365       break;
366   }
367 }
368 
369 //=======================================================================
370 //function : IsLid
371 //purpose  :
372 //=======================================================================
IsLid(const TopoDS_Face & theF,const TopTools_IndexedMapOfShape & theMapOfLids) const373 Standard_Boolean BRepFill_AdvancedEvolved::IsLid(const TopoDS_Face& theF,
374                                                  const TopTools_IndexedMapOfShape& theMapOfLids) const
375 {
376   if (theMapOfLids.IsEmpty())
377     return Standard_False;
378 
379   const Handle(Geom_Plane) aPlnF = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(theF));
380 
381   if (aPlnF.IsNull())
382     return Standard_False;
383 
384   TopTools_IndexedMapOfShape::Iterator anItr(theMapOfLids);
385   for (; anItr.More(); anItr.Next())
386   {
387     const TopoDS_Face &aF = TopoDS::Face(anItr.Value());
388     const Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aF));
389 
390     if (aPlane == aPlnF)
391       return Standard_True;
392   }
393 
394   return Standard_False;
395 }
396 
397 //=======================================================================
398 //function : Perform
399 //purpose  :
400 //=======================================================================
Perform(const TopoDS_Wire & theSpine,const TopoDS_Wire & theProfile,const Standard_Real theTolerance,const Standard_Boolean theSolidReq)401 void BRepFill_AdvancedEvolved::Perform(const TopoDS_Wire& theSpine,
402                                        const TopoDS_Wire& theProfile,
403                                        const Standard_Real theTolerance,
404                                        const Standard_Boolean theSolidReq)
405 {
406   myErrorStatus = BRepFill_AdvancedEvolved_Empty;
407 
408   if (myFuzzyValue < Precision::Confusion())
409   {
410     myFuzzyValue = theTolerance;
411   }
412 
413 #ifdef BRepFill_AdvancedEvolved_DEBUG
414   char aBuff[10000];
415   Sprintf(aBuff, "%s%s", myDebugShapesPath, "spine.nbv");
416   BinTools::Write(theSpine, aBuff);
417   Sprintf(aBuff, "%s%s", myDebugShapesPath, "profile.nbv");
418   BinTools::Write(theProfile, aBuff);
419 
420   std::streamsize aPrecVal = std::cout.precision();
421 
422   std::cout.precision(15);
423 
424   std::cout << "++++ Dump of Spine" << std::endl;
425   BRepTools::Dump(theSpine, std::cout);
426   std::cout << "---- Dump of Spine" << std::endl;
427 
428   std::cout << "++++ Dump of Profile" << std::endl;
429   BRepTools::Dump(theProfile, std::cout);
430   std::cout << "---- Dump of Profile" << std::endl;
431 
432   std::cout.precision(aPrecVal);
433 #endif
434 
435   GetSpineAndProfile(theSpine, theProfile);
436 
437   myPipeShell.Nullify();
438   myTopBottom.Nullify();
439   myResult.Nullify();
440 
441 #ifdef BRepFill_AdvancedEvolved_DEBUG
442   std::cout << "Start Evolved. Toler = " << myFuzzyValue << std::endl;
443 #endif
444 
445   PerformSweep();
446 
447 #ifdef BRepFill_AdvancedEvolved_DEBUG
448   std::cout << "PerformSweep complete. Status = " << myErrorStatus << std::endl;
449 #endif
450 
451   GetLids();
452 
453 #ifdef BRepFill_AdvancedEvolved_DEBUG
454   std::cout << "GetLids complete. Status = " << myErrorStatus << std::endl;
455 #endif
456 
457   if (myErrorStatus != BRepFill_AdvancedEvolved_NotSolid)
458   {
459     return;
460   }
461 
462   myResult = myPipeShell;
463 
464   BuildSolid();
465 
466   if ((myErrorStatus != BRepFill_AdvancedEvolved_OK) || theSolidReq)
467   {
468     return;
469   }
470 
471   TopoDS_Shell aShell;
472   TopTools_IndexedMapOfShape aMFLids;
473   TopExp::MapShapes(myTopBottom, TopAbs_FACE, aMFLids);
474 
475   TopExp_Explorer anExp(myResult, TopAbs_FACE);
476   for (; anExp.More(); anExp.Next())
477   {
478     BRep_Builder aBB;
479     if (aShell.IsNull())
480       aBB.MakeShell(aShell);
481 
482     const TopoDS_Face &aF = TopoDS::Face(anExp.Current());
483     if (IsLid(aF, aMFLids))
484       continue;
485 
486     aBB.Add(aShell, aF);
487   }
488 
489   if (!aShell.IsNull())
490     myResult = aShell;
491 }
492 
493 //=======================================================================
494 //function : PerformSweep
495 //purpose  :
496 //=======================================================================
PerformSweep()497 void BRepFill_AdvancedEvolved::PerformSweep()
498 {
499   if (myErrorStatus != BRepFill_AdvancedEvolved_Empty)
500     return;
501 
502   myErrorStatus = BRepFill_AdvancedEvolved_SweepError;
503 
504   Handle(BRepFill_PipeShell) aPipe = new BRepFill_PipeShell(mySpine);
505   aPipe->SetTolerance(aPipeLinearTolerance, aPipeLinearTolerance, aPipeAngularTolerance);
506   aPipe->SetTransition(BRepFill_Round);
507   aPipe->Add(myProfile, Standard_False, Standard_False);
508 
509   if (aPipe->Build())
510   {
511     myErrorStatus = BRepFill_AdvancedEvolved_NoLids;
512     myPipeShell = aPipe->Shape();
513   }
514 }
515 
516 //=======================================================================
517 //function : GetLids
518 //purpose  :
519 //=======================================================================
GetLids()520 void BRepFill_AdvancedEvolved::GetLids()
521 {
522   if (myPipeShell.IsNull())
523     return;
524 
525   if (BRep_Tool::IsClosed(myProfile))
526   {
527     // No need in lids creation
528     myErrorStatus = BRepFill_AdvancedEvolved_NotSolid;
529     return;
530   }
531 
532   myErrorStatus = BRepFill_AdvancedEvolved_NoLids;
533 
534   BRepLib_FindSurface aFS(mySpine, -1.0, Standard_True);
535   const Handle(Geom_Plane) aSurf = Handle(Geom_Plane)::DownCast(aFS.Surface());
536 
537   if (aSurf.IsNull())
538   {
539     myErrorStatus = BRepFill_AdvancedEvolved_NotPlanarSpine;
540     return;
541   }
542 
543   //Square of the default angular tolerance in
544   //BOPAlgo_Tools::EdgesToWires(...) and BOPAlgo_Tools::WiresToFaces(...) methods
545   const Standard_Real aSqAnguarTol = 1.0e-16;
546   const gp_Dir &aNormal = aSurf->Position().Direction();
547 
548   // Obtain free-edges from myPipeShell. All edges must be planar
549   // and parallel to the plane of mySpine
550 
551   TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
552 
553   TopExp::MapShapesAndAncestors(myPipeShell, TopAbs_EDGE, TopAbs_FACE, aMapEF);
554 
555   TopTools_ListOfShape aLE;
556 
557   gp_Pnt aPtmp;
558   gp_Vec aTan;
559 
560   for (Standard_Integer i = 1; i <= aMapEF.Size(); i++)
561   {
562     TopTools_ListOfShape& aListF = aMapEF(i);
563 
564     if (aListF.Extent() != 1)
565       continue;
566 
567     const TopoDS_Edge &anE = TopoDS::Edge(aMapEF.FindKey(i));
568 
569     BRepAdaptor_Curve anAC(anE);
570     if (!anAC.Is3DCurve())
571     {
572       // We are not interested in degenerated edges.
573       continue;
574     }
575 
576     anAC.D1(0.5*(anAC.FirstParameter() + anAC.LastParameter()), aPtmp, aTan);
577 
578     const Standard_Real aSqModulus = aTan.SquareMagnitude();
579     if (aSqModulus < Precision::Confusion())
580       continue;
581 
582     const Standard_Real aDP = aTan.XYZ().Dot(aNormal.XYZ());
583     if (aDP*aDP>aSqModulus*aSqAnguarTol)
584     {
585       //Only planar edges are considered
586       continue;
587     }
588 
589     aLE.Append(anE);
590   }
591 
592   if (aLE.IsEmpty())
593   {
594     myErrorStatus = BRepFill_AdvancedEvolved_NotPlanarSpine;
595     return;
596   }
597 
598   // Split interfered edges
599   TopoDS_Shape aFreeEdges;
600   if (!PerformBoolean(aLE, aFreeEdges))
601   {
602     myErrorStatus = BRepFill_AdvancedEvolved_NotPlanarSpine;
603     return;
604   }
605 
606   // Collect all free edges to wires and create planar
607   // top and bottom lids from these wires.
608   BRep_Builder aBB;
609   TopoDS_Compound aCompW, aCompF;
610   aBB.MakeCompound(aCompW);
611   aBB.MakeCompound(aCompF);
612   aBB.MakeCompound(myTopBottom);
613   BOPAlgo_Tools::EdgesToWires(aFreeEdges, aCompW, Standard_True);
614   BOPAlgo_Tools::WiresToFaces(aCompW, aCompF);
615 
616   {
617     // Check orientation
618 
619     TopTools_IndexedMapOfShape aMapV;
620     TopExp::MapShapes(myPipeShell, TopAbs_VERTEX, aMapV);
621     TopExp_Explorer anExp(aCompF, TopAbs_FACE);
622     for (; anExp.More(); anExp.Next())
623     {
624       const TopoDS_Face aF = TopoDS::Face(anExp.Current());
625       const Handle(Geom_Plane) aPln = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aF));
626       const gp_XYZ &aNorm = aPln->Position().Direction().XYZ();
627       const gp_XYZ &aLocP = aPln->Position().Location().XYZ();
628 
629       Standard_Boolean isFound = Standard_False;
630 
631       for (Standard_Integer i = 1; i <= aMapV.Size(); i++)
632       {
633         const TopoDS_Vertex aV = TopoDS::Vertex(aMapV.FindKey(i));
634         const gp_XYZ aP = BRep_Tool::Pnt(aV).XYZ();
635 
636         const gp_XYZ aDelta = aP - aLocP;
637         const Standard_Real aSqD = aDelta.SquareModulus();
638 
639         if (aSqD < Precision::SquareConfusion())
640           continue;
641 
642         const Standard_Real aDP = aDelta.Dot(aNorm);
643 
644         if (aDP*aDP < aSqD*Precision::SquareConfusion())
645         {
646           // aP is in the plane
647           continue;
648         }
649 
650         if (aDP > 0.0)
651         {
652           aBB.Add(myTopBottom, aF.Reversed());
653         }
654         else
655         {
656           aBB.Add(myTopBottom, aF);
657         }
658 
659         isFound = Standard_True;
660         break;
661       }
662 
663       if (!isFound)
664       {
665         aBB.Add(myTopBottom, aF);
666       }
667     }
668   }
669 
670   myErrorStatus = BRepFill_AdvancedEvolved_NotSolid;
671 }
672 
673 //=======================================================================
674 //function : BuildSolid
675 //purpose  :
676 //=======================================================================
BuildSolid()677 void BRepFill_AdvancedEvolved::BuildSolid()
678 {
679   if (myErrorStatus != BRepFill_AdvancedEvolved_NotSolid)
680     return;
681 
682   myErrorStatus = BRepFill_AdvancedEvolved_NotVolume;
683 
684   TopTools_MapOfShape aMapF;
685   TopTools_ListOfShape aLF, aLSplits;
686   TopExp_Explorer anExpF;
687 
688 #ifdef BRepFill_AdvancedEvolved_DEBUG
689   char aBuff[10000];
690   Sprintf(aBuff, "%s%s", myDebugShapesPath, "shape2.nbv");
691   BinTools::Write(myPipeShell, aBuff);
692 #endif
693 
694   for (anExpF.Init(myPipeShell, TopAbs_FACE);
695        anExpF.More(); anExpF.Next())
696   {
697     const TopoDS_Face &aF = TopoDS::Face(anExpF.Current());
698     if (!aMapF.Add(aF))
699       continue;
700 
701     ReduceVertexTolerance(aF);
702     CheckSingularityAndAdd(aF, myFuzzyValue, aLF, aLSplits);
703   }
704 
705   {
706     TopTools_ListIteratorOfListOfShape anItrS(aLSplits);
707     for (; anItrS.More(); anItrS.Next())
708     {
709       const TopoDS_Face &aF = TopoDS::Face(anItrS.Value());
710       aLF.Append(aF);
711     }
712 
713 #ifdef BRepFill_AdvancedEvolved_DEBUG
714     BRep_Builder aBB;
715     TopoDS_Compound aDebComp;
716     aBB.MakeCompound(aDebComp);
717     TopTools_ListIteratorOfListOfShape anItrDeb(aLF);
718     for (; anItrDeb.More(); anItrDeb.Next())
719     {
720       const TopoDS_Face &aF = TopoDS::Face(anItrDeb.Value());
721       aBB.Add(aDebComp, aF);
722     }
723 
724     Sprintf(aBuff, "%s%s", myDebugShapesPath, "shape3.nbv");
725     BinTools::Write(aDebComp, aBuff);
726 #endif
727 
728     // Split interfered faces
729     PerformBoolean(aLF, myPipeShell);
730 #ifdef BRepFill_AdvancedEvolved_DEBUG
731     Sprintf(aBuff, "%s%s", myDebugShapesPath, "shape4.nbv");
732     BinTools::Write(myPipeShell, aBuff);
733 #endif
734   }
735 
736   aLF.Clear();
737   aMapF.Clear();
738   for (anExpF.Init(myPipeShell, TopAbs_FACE);
739        anExpF.More(); anExpF.Next())
740   {
741     const TopoDS_Face &aF = TopoDS::Face(anExpF.Current());
742     if (!aMapF.Add(aF))
743       continue;
744 
745     aLF.Append(aF);
746   }
747 
748   if (!myTopBottom.IsNull())
749   {
750     TopoDS_Iterator anItLids(myTopBottom);
751     for (; anItLids.More(); anItLids.Next())
752     {
753       const TopoDS_Face &aF = TopoDS::Face(anItLids.Value());
754       aLF.Append(aF);
755     }
756   }
757 
758 #ifdef BRepFill_AdvancedEvolved_DEBUG
759   BRep_Builder aBB;
760   TopoDS_Compound aDebComp;
761   aBB.MakeCompound(aDebComp);
762   TopTools_ListIteratorOfListOfShape anItrDeb(aLF);
763   for (; anItrDeb.More(); anItrDeb.Next())
764   {
765     const TopoDS_Face &aF = TopoDS::Face(anItrDeb.Value());
766     aBB.Add(aDebComp, aF);
767   }
768 
769   Sprintf(aBuff, "%s%s", myDebugShapesPath, "shape5.nbv");
770   BinTools::Write(aDebComp, aBuff);
771 #endif
772 
773   BOPAlgo_MakerVolume aMV;
774   aMV.SetArguments(aLF);
775   aMV.SetFuzzyValue(myFuzzyValue);
776   aMV.SetIntersect(Standard_True);
777   aMV.SetRunParallel(myIsParallel);
778   aMV.SetAvoidInternalShapes(Standard_True);
779   aMV.Perform();
780 
781   if (aMV.HasErrors())
782   {
783     return;
784   }
785 
786   myResult = aMV.Shape();
787 
788 #ifdef BRepFill_AdvancedEvolved_DEBUG
789   std::cout << "BuildSolid After VM." << std::endl;
790 #endif
791 
792   RemoveExcessSolids(aLSplits, myResult, aLF, aMV);
793 
794   UnifyShape();
795   RemoveInternalWires(myResult);
796 
797   myErrorStatus = BRepFill_AdvancedEvolved_OK;
798 }
799 
800 //=======================================================================
801 //function : UnifyShape
802 //purpose  :
803 //=======================================================================
UnifyShape()804 void BRepFill_AdvancedEvolved::UnifyShape()
805 {
806   ShapeUpgrade_UnifySameDomain aUnifier;
807 
808   aUnifier.Initialize(myResult, Standard_True, Standard_True, Standard_False);
809   aUnifier.SetSafeInputMode(Standard_True);
810   aUnifier.AllowInternalEdges(Standard_False);
811   aUnifier.SetLinearTolerance(aPipeLinearTolerance);
812   aUnifier.SetAngularTolerance(aPipeAngularTolerance);
813   aUnifier.Build();
814 
815   myResult = aUnifier.Shape();
816 
817 }
818 
819 //=======================================================================
820 //function : ExtractOuterSolid
821 //purpose  :
822 //=======================================================================
ExtractOuterSolid(TopoDS_Shape & theShape,TopTools_ListOfShape & theArgsList)823 void BRepFill_AdvancedEvolved::ExtractOuterSolid(TopoDS_Shape& theShape,
824                                                  TopTools_ListOfShape& theArgsList)
825 {
826   TopTools_IndexedDataMapOfShapeListOfShape aMapS;
827   TopExp::MapShapesAndAncestors(theShape, TopAbs_FACE, TopAbs_SOLID, aMapS);
828 
829   //theArgsList.Clear();
830   TopTools_ListOfShape aNewList;
831   const Standard_Integer aNbF = aMapS.Extent();
832   for (Standard_Integer i = 1; i <= aNbF; ++i)
833   {
834     if (aMapS(i).Extent() == 1)
835       aNewList.Append(aMapS.FindKey(i));
836   }
837 
838   if (aNewList.IsEmpty())
839     return;
840 
841   {
842     TopTools_ListIteratorOfListOfShape anItrF;
843 
844     Standard_Boolean isRemoved = Standard_True;
845     while (isRemoved)
846     {
847       isRemoved = Standard_False;
848       for (anItrF.Init(theArgsList); anItrF.More(); anItrF.Next())
849       {
850         const TopoDS_Face& aF = TopoDS::Face(anItrF.Value());
851         if (!ContainsInList(aNewList, aF))
852         {
853           theArgsList.Remove(aF);
854           isRemoved = Standard_True;
855           break;
856         }
857       }
858     }
859   }
860 
861   BOPAlgo_MakerVolume aMV;
862   aMV.SetArguments(aNewList);
863   aMV.SetIntersect(Standard_True);
864   aMV.SetRunParallel(myIsParallel);
865   aMV.SetAvoidInternalShapes(Standard_True);
866   aMV.Perform();
867 
868   if (aMV.HasErrors())
869   {
870     return;
871   }
872 
873   theShape = aMV.Shape();
874 }
875 
876 //=======================================================================
877 //function : RemoveExcessSolids
878 //purpose  :
879 //=======================================================================
RemoveExcessSolids(const TopTools_ListOfShape & theLSplits,const TopoDS_Shape & theShape,TopTools_ListOfShape & theArgsList,BOPAlgo_MakerVolume & theMV)880 void BRepFill_AdvancedEvolved::RemoveExcessSolids(const TopTools_ListOfShape& theLSplits,
881                                                   const TopoDS_Shape& theShape,
882                                                   TopTools_ListOfShape& theArgsList,
883                                                   BOPAlgo_MakerVolume& theMV)
884 {
885   if (myErrorStatus != BRepFill_AdvancedEvolved_NotVolume)
886     return;
887 
888   TopoDS_Shape aResShape = theShape;
889 
890   TopExp_Explorer anExpSo;
891   for (Standard_Integer i = 0; i < 2; i++)
892   {
893     anExpSo.Init(aResShape, TopAbs_SOLID);
894     if (!anExpSo.More())
895     {
896       // No any solids
897       myResult = aResShape;
898       return;
899     }
900 
901     anExpSo.Next();
902     if (!anExpSo.More())
903     {
904       // Only one solid has been generated
905       myResult = TopoDS::Solid(anExpSo.Current());
906       return;
907     }
908 
909     if (i != 0)
910       break;
911 
912     ExtractOuterSolid(aResShape, theArgsList);
913   }
914 
915   TopTools_ListOfShape aSolidList;
916 
917   //Look for all solids containing lids
918   {
919     anExpSo.Init(aResShape, TopAbs_SOLID);
920     for (; anExpSo.More(); anExpSo.Next())
921     {
922       const TopoDS_Solid &aSol = TopoDS::Solid(anExpSo.Current());
923       TopTools_IndexedMapOfShape aMapF;
924       TopExp::MapShapes(aSol, aMapF);
925 
926       Standard_Boolean areThereLids = Standard_False;
927       TopExp_Explorer anExpLids(myTopBottom, TopAbs_FACE);
928       for (; anExpLids.More(); anExpLids.Next())
929       {
930         areThereLids = Standard_True;
931         const TopoDS_Face &aFLid = TopoDS::Face(anExpLids.Current());
932         const Standard_Integer aFIdx = aMapF.FindIndex(aFLid);
933         if (aFIdx < 1)
934           continue;
935 
936         const TopoDS_Face &aFSol = TopoDS::Face(aMapF.FindKey(aFIdx));
937 
938         if (aFSol.IsEqual(aFLid))
939         {
940           aSolidList.Append(aSol);
941         }
942 
943         break;
944       }
945 
946       if (!areThereLids)
947         break;
948     }
949 
950     if (aSolidList.Extent() < 1)
951     {
952       myResult = aResShape;
953       return;
954     }
955 
956     if (aSolidList.Extent() == 1)
957     {
958       myResult = aSolidList.First();
959       return;
960     }
961 
962     if (aSolidList.Extent() > 0)
963     {
964       BRep_Builder aBB;
965       TopoDS_CompSolid aCompSol;
966       aBB.MakeCompSolid(aCompSol);
967       TopTools_ListIteratorOfListOfShape anItl(aSolidList);
968       for (; anItl.More(); anItl.Next())
969       {
970         const TopoDS_Solid &aSol = TopoDS::Solid(anItl.Value());
971         aBB.Add(aCompSol, aSol);
972       }
973 
974       aResShape = aCompSol;
975       aSolidList.Clear();
976     }
977   }
978 
979   {
980     // Remove Split faces from the list of arguments
981     TopTools_ListIteratorOfListOfShape anItl(theLSplits);
982     for (; anItl.More(); anItl.Next())
983     {
984       const TopoDS_Face &aF = TopoDS::Face(anItl.Value());
985       theArgsList.Remove(aF);
986     }
987 
988     // Create a list of invalid faces. The face is invalid if
989     // BOPAlgo_MakerVolume changes its orientation while creating solids.
990     // Faces from theLSplits are not checked.
991     TopTools_ListOfShape aListInvFaces;
992     for (anItl.Init(theArgsList); anItl.More(); anItl.Next())
993     {
994       const TopoDS_Face &aF = TopoDS::Face(anItl.Value());
995       for (TopTools_ListIteratorOfListOfShape anItM(theMV.Modified(aF));
996            anItM.More(); anItM.Next())
997       {
998         const TopoDS_Face &aFM = TopoDS::Face(anItM.Value());
999 
1000         if (aFM.Orientation() != aF.Orientation())
1001           aListInvFaces.Append(aFM);
1002       }
1003     }
1004 
1005     for (anExpSo.Init(aResShape, TopAbs_SOLID); anExpSo.More(); anExpSo.Next())
1006     {
1007       const TopoDS_Solid &aSo = TopoDS::Solid(anExpSo.Current());
1008       TopTools_IndexedMapOfShape aMapF;
1009       TopExp::MapShapes(aSo, TopAbs_FACE, aMapF);
1010       Standard_Boolean isToDelete = Standard_False;
1011 
1012       for (anItl.Init(aListInvFaces); anItl.More(); anItl.Next())
1013       {
1014         const TopoDS_Face &aF = TopoDS::Face(anItl.Value());
1015         if (aMapF.Contains(aF))
1016         {
1017           isToDelete = Standard_True;
1018           break;
1019         }
1020       }
1021 
1022       if (isToDelete)
1023       {
1024         continue;
1025       }
1026 
1027       for (anItl.Init(theArgsList); anItl.More(); anItl.Next())
1028       {
1029         const TopoDS_Face &aF = TopoDS::Face(anItl.Value());
1030         const Standard_Integer anIdx = aMapF.FindIndex(aF);
1031         if (anIdx == 0)
1032           continue;
1033 
1034         const TopoDS_Face &aF1 = TopoDS::Face(aMapF.FindKey(anIdx));
1035 
1036         // aF and aF1 are same shapes. Check if they are equal.
1037 
1038         if (!aF.IsEqual(aF1))
1039         {
1040           isToDelete = Standard_True;
1041           break;
1042         }
1043       }
1044 
1045       if (isToDelete)
1046       {
1047         continue;
1048       }
1049 
1050       aSolidList.Append(aSo);
1051     }
1052   }
1053 
1054   if (aSolidList.Extent() < 1)
1055   {
1056     myResult = aResShape;
1057     return;
1058   }
1059 
1060   if (aSolidList.Extent() == 1)
1061   {
1062     myResult = aSolidList.First();
1063     return;
1064   }
1065 
1066   BRep_Builder aBB;
1067   TopoDS_CompSolid aCmpSol;
1068   aBB.MakeCompSolid(aCmpSol);
1069 
1070   for (TopTools_ListIteratorOfListOfShape anItl(aSolidList); anItl.More(); anItl.Next())
1071   {
1072     const TopoDS_Solid &aSo = TopoDS::Solid(anItl.Value());
1073     aBB.Add(aCmpSol, aSo);
1074   }
1075 
1076   myResult = aCmpSol;
1077 }
1078 
1079 #if 0
1080 //=======================================================================
1081 //class : NormalFunc
1082 //purpose  : This function computes square modulus of the normal to the
1083 //            surface in every point of the curve myCOnS. It allows detecting
1084 //            whether the curve goes through the singular point(s).
1085 //            It will be useful in case(s) when the result after PipeShell
1086 //            algorithm contains only one face with single seam-edge. E.g.:
1087 //                Draw[]> ellipse cc 0 0 0 0 0 1 30 10
1088 //                Draw[]> mkedge ee cc
1089 //                Draw[]> wire ww ee
1090 //                Draw[]> polyline tw 0 25 -5 0 -20 10
1091 //                Draw[]> mksweep ww
1092 //                Draw[]> addsweep tw
1093 //                Draw[]> buildsweep r1 -R
1094 //
1095 //           It results in creation of shell with self-interfered face.
1096 //            However, "checkshape" does not detect any invalidities.
1097 //
1098 //           The algorithm "Evolved" must be improved to process such cases.
1099 //            Currently they are not processed and this function is useless.
1100 //=======================================================================
1101 class NormalFunc : public math_MultipleVarFunctionWithGradient
1102 {
1103 public:
1104   NormalFunc(const Adaptor3d_CurveOnSurface& theCOS) :myCOnS(theCOS)
1105   {
1106   }
1107 
1108   virtual Standard_Integer NbVariables() const Standard_OVERRIDE
1109   {
1110     return 1;
1111   }
1112 
1113   virtual Standard_Boolean Value(const math_Vector& X, Standard_Real& F) Standard_OVERRIDE;
1114   virtual Standard_Boolean Gradient(const math_Vector& X, math_Vector& G) Standard_OVERRIDE;
1115   virtual Standard_Boolean Values(const math_Vector& theX,
1116                                   Standard_Real& theF,
1117                                   math_Vector& theG) Standard_OVERRIDE
1118   {
1119     if (!Value(theX, theF))
1120     return Standard_False;
1121 
1122     if (!Gradient(theX, theG))
1123       return Standard_False;
1124 
1125     return Standard_True;
1126   };
1127 
1128   virtual Standard_Boolean Values(const math_Vector& theX,
1129                                   Standard_Real& theF,
1130                                   math_Vector& theG,
1131                                   math_Matrix& theH) Standard_OVERRIDE
1132   {
1133     if (!Values(theX, theF, theG))
1134     return Standard_False;
1135 
1136     theH(1, 1) = theG(1);
1137     return Standard_True;
1138   };
1139 
1140   Standard_Real FirstParameter() const
1141   {
1142     return myCOnS.FirstParameter();
1143   }
1144 
1145   Standard_Real LastParameter() const
1146   {
1147     return myCOnS.LastParameter();
1148   }
1149 
1150   gp_Pnt GetPoint(const Standard_Real theX)
1151   {
1152     const Handle(Adaptor2d_Curve2d) &aC = myCOnS.GetCurve();
1153     const Handle(Adaptor3d_Surface) &aS = myCOnS.GetSurface();
1154     const gp_Pnt2d aP2d(aC->Value(theX));
1155     return aS->Value(aP2d.X(), aP2d.Y());
1156   }
1157 
1158 protected:
1159 
1160   NormalFunc& operator=(NormalFunc&);
1161 
1162 private:
1163   const Adaptor3d_CurveOnSurface& myCOnS;
1164 };
1165 
1166 //=======================================================================
1167 //function : Value
1168 //purpose  : +aD1v_x^2*aD1u_y^2 + aD1v_x^2*aD1u_z^2 +
1169 //           +aD1v_y^2*aD1u_z^2 + aD1u_x^2*aD1v_y^2 +
1170 //           +aD1u_x^2*aD1v_z^2 + aD1u_y^2*aD1v_z^2 -
1171 //           -  2*(+aD1u_x*aD1v_x*aD1u_y*aD1v_y +
1172 //                 +aD1u_x*aD1v_x*aD1u_z*aD1v_z +
1173 //                 +aD1u_y*aD1v_y*aD1u_z*aD1v_z)
1174 //=======================================================================
1175 Standard_Boolean NormalFunc::Value(const math_Vector& theX, Standard_Real& theF)
1176 {
1177   const Handle(Adaptor2d_Curve2d) &aC = myCOnS.GetCurve();
1178   const Handle(Adaptor3d_Surface) &aS = myCOnS.GetSurface();
1179 
1180   const gp_Pnt2d aP2d(aC->Value(theX(1)));
1181   gp_Pnt aP3d;
1182   gp_Vec aD1u, aD1v;
1183   aS->D1(aP2d.X(), aP2d.Y(), aP3d, aD1u, aD1v);
1184 
1185   theF = aD1u.Crossed(aD1v).SquareMagnitude();
1186   return Standard_True;
1187 }
1188 
1189 //=======================================================================
1190 //function : Gradient
1191 //purpose  :
1192 //2 * ((aD1v_x*aD1u_y)*(aD1u_y*(aD2uv_x*aDc_x + aD2v_x*aDc_y) + aD1v_x*(aD2u_y*aDc_x + aD2uv_y*aDc_y)) +
1193 //     (aD1v_x*aD1u_z)*(aD1u_z*(aD2uv_x*aDc_x + aD2v_x*aDc_y) + aD1v_x*(aD2u_z*aDc_x + aD2uv_z*aDc_y)) +
1194 //     (aD1v_y*aD1u_z)*(aD1u_z*(aD2uv_y*aDc_x + aD2v_y*aDc_y) + aD1v_y*(aD2u_z*aDc_x + aD2uv_z*aDc_y)) +
1195 //     (aD1u_x*aD1v_y)*(aD1u_x*(aD2uv_y*aDc_x + aD2v_y*aDc_y) + aD1v_y*(aD2u_x*aDc_x + aD2uv_x*aDc_y)) +
1196 //     (aD1u_x*aD1v_z)*(aD1u_x*(aD2uv_z*aDc_x + aD2v_z*aDc_y) + aD1v_z*(aD2u_x*aDc_x + aD2uv_x*aDc_y)) +
1197 //     (aD1u_y*aD1v_z)*(aD1u_y*(aD2uv_z*aDc_x + aD2v_z*aDc_y) + aD1v_z*(aD2u_y*aDc_x + aD2uv_y*aDc_y)) -
1198 //
1199 //     (aD2u_x*aDc_x + aD2uv_x*aDc_y)*aD1v_x*aD1u_y*aD1v_y -
1200 //     aD1u_x*(aD2uv_x*aDc_x + aD2v_x*aDc_y)*aD1u_y*aD1v_y -
1201 //     aD1u_x*aD1v_x*(aD2u_y*aDc_x + aD2uv_y*aDc_y)*aD1v_y -
1202 //     aD1u_x*aD1v_x*aD1u_y*(aD2uv_y*aDc_x + aD2v_y*aDc_y) -
1203 //
1204 //     (aD2u_x*aDc_x + aD2uv_x*aDc_y)*aD1v_x*aD1u_z*aD1v_z -
1205 //     aD1u_x*(aD2uv_x*aDc_x + aD2v_x*aDc_y)*aD1u_z*aD1v_z -
1206 //     aD1u_x*aD1v_x*(aD2u_z*aDc_x + aD2uv_z*aDc_y)*aD1v_z -
1207 //     aD1u_x*aD1v_x*aD1u_z*(aD2uv_z*aDc_x + aD2v_z*aDc_y) -
1208 //
1209 //     (aD2u_y*aDc_x + aD2uv_y*aDc_y)*aD1v_y*aD1u_z*aD1v_z -
1210 //     aD1u_y*(aD2uv_y*aDc_x + aD2v_y*aDc_y)*aD1u_z*aD1v_z -
1211 //     aD1u_y*aD1v_y*(aD2u_z*aDc_x + aD2uv_z*aDc_y)*aD1v_z -
1212 //     aD1u_y*aD1v_y*aD1u_z*(aD2uv_z*aDc_x + aD2v_z*aDc_y))
1213 //=======================================================================
1214 Standard_Boolean NormalFunc::Gradient(const math_Vector& theX, math_Vector& theG)
1215 {
1216   const Handle(Adaptor2d_Curve2d) &aC = myCOnS.GetCurve();
1217   const Handle(Adaptor3d_Surface) &aS = myCOnS.GetSurface();
1218 
1219   gp_Pnt2d aP2d;
1220   gp_Vec2d aDc;
1221   aC->D1(theX(1), aP2d, aDc);
1222 
1223   gp_Pnt aP3d;
1224   gp_Vec aD1u, aD1v, aD2u, aD2v, aD2uv;
1225   aS->D2(aP2d.X(), aP2d.Y(), aP3d, aD1u, aD1v, aD2u, aD2v, aD2uv);
1226 
1227   theG(1) = (aD1v.X()*aD1u.Y())*(aD1u.Y()*(aD2uv.X()*aDc.X() + aD2v.X()*aDc.Y()) +
1228             aD1v.X()*(aD2u.Y()*aDc.X() + aD2uv.Y()*aDc.Y())) +
1229             (aD1v.X()*aD1u.Z())*(aD1u.Z()*(aD2uv.X()*aDc.X() +
1230             aD2v.X()*aDc.Y()) + aD1v.X()*(aD2u.Z()*aDc.X() + aD2uv.Z()*aDc.Y())) +
1231             (aD1v.Y()*aD1u.Z())*(aD1u.Z()*(aD2uv.Y()*aDc.X() + aD2v.Y()*aDc.Y()) +
1232             aD1v.Y()*(aD2u.Z()*aDc.X() + aD2uv.Z()*aDc.Y())) + (aD1u.X()*aD1v.Y())*
1233             (aD1u.X()*(aD2uv.Y()*aDc.X() + aD2v.Y()*aDc.Y()) + aD1v.Y()*(aD2u.X()*
1234             aDc.X() + aD2uv.X()*aDc.Y())) + (aD1u.X()*aD1v.Z())*(aD1u.X()*(aD2uv.Z()*
1235             aDc.X() + aD2v.Z()*aDc.Y()) + aD1v.Z()*(aD2u.X()*aDc.X() +
1236             aD2uv.X()*aDc.Y())) + (aD1u.Y()*aD1v.Z())*(aD1u.Y()*(aD2uv.Z()*aDc.X() +
1237             aD2v.Z()*aDc.Y()) + aD1v.Z()*(aD2u.Y()*aDc.X() + aD2uv.Y()*aDc.Y())) -
1238             (aD2u.X()*aDc.X() + aD2uv.X()*aDc.Y())*aD1v.X()*aD1u.Y()*aD1v.Y() -
1239             aD1u.X()*(aD2uv.X()*aDc.X() + aD2v.X()*aDc.Y())*aD1u.Y()*aD1v.Y() -
1240             aD1u.X()*aD1v.X()*(aD2u.Y()*aDc.X() + aD2uv.Y()*aDc.Y())*aD1v.Y() -
1241             aD1u.X()*aD1v.X()*aD1u.Y()*(aD2uv.Y()*aDc.X() + aD2v.Y()*aDc.Y()) -
1242             (aD2u.X()*aDc.X() + aD2uv.X()*aDc.Y())*aD1v.X()*aD1u.Z()*aD1v.Z() -
1243             aD1u.X()*(aD2uv.X()*aDc.X() + aD2v.X()*aDc.Y())*aD1u.Z()*aD1v.Z() -
1244             aD1u.X()*aD1v.X()*(aD2u.Z()*aDc.X() + aD2uv.Z()*aDc.Y())*aD1v.Z() -
1245             aD1u.X()*aD1v.X()*aD1u.Z()*(aD2uv.Z()*aDc.X() + aD2v.Z()*aDc.Y()) -
1246             (aD2u.Y()*aDc.X() + aD2uv.Y()*aDc.Y())*aD1v.Y()*aD1u.Z()*aD1v.Z() -
1247             aD1u.Y()*(aD2uv.Y()*aDc.X() + aD2v.Y()*aDc.Y())*aD1u.Z()*aD1v.Z() -
1248             aD1u.Y()*aD1v.Y()*(aD2u.Z()*aDc.X() + aD2uv.Z()*aDc.Y())*aD1v.Z() -
1249             aD1u.Y()*aD1v.Y()*aD1u.Z()*(aD2uv.Z()*aDc.X() + aD2v.Z()*aDc.Y());
1250 
1251   return Standard_True;
1252 }
1253 
1254 #endif
1255 //=======================================================================
1256 //function : RebuildFaces
1257 //purpose  : Creates a wires from theEdges and puts it to the new face
1258 //            which is empty-copied from theSourceFace.
1259 //=======================================================================
RebuildFaces(const TopTools_ListOfShape & theLE,const TopoDS_Face & theSourceFace,TopTools_ListOfShape & theList)1260 static void RebuildFaces(const TopTools_ListOfShape& theLE,
1261                          const TopoDS_Face& theSourceFace,
1262                          TopTools_ListOfShape& theList)
1263 {
1264   //build new faces
1265   BOPAlgo_BuilderFace aBF;
1266 
1267   TopoDS_Face aF = TopoDS::Face(theSourceFace.Oriented(TopAbs_FORWARD));
1268 
1269   aBF.SetFace(aF);
1270   aBF.SetShapes(theLE);
1271 
1272   aBF.Perform();
1273 
1274   const TopTools_ListOfShape& aLFR = aBF.Areas();
1275 
1276   if (aLFR.IsEmpty())
1277   {
1278     theList.Append(theSourceFace);
1279     return;
1280   }
1281 
1282   TopTools_ListIteratorOfListOfShape aItFR(aLFR);
1283   for (; aItFR.More(); aItFR.Next())
1284   {
1285     const TopoDS_Shape& aFR = TopoDS::Face(aItFR.Value());
1286     theList.Append(aFR);
1287   }
1288 }
1289 
1290 //=======================================================================
1291 //function : MakeEdgeDegenerated
1292 //purpose  : Returns TRUE if degenerated edge has been created.
1293 //           Every degenerated edge (to split) must be added in theLEdges twice
1294 //           with different orientations. Moreover, Degenerated edges cannot be shared.
1295 //           Therefore, make copy of them before adding.
1296 //=======================================================================
MakeEdgeDegenerated(const TopoDS_Vertex & theV,const TopoDS_Face & theFace,const gp_Pnt2d & thePf,const gp_Pnt2d & thePl,TopTools_ListOfShape & theLEdges)1297 static Standard_Boolean MakeEdgeDegenerated(const TopoDS_Vertex& theV,
1298                                             const TopoDS_Face& theFace,
1299                                             const gp_Pnt2d& thePf,
1300                                             const gp_Pnt2d& thePl,
1301                                             TopTools_ListOfShape& theLEdges)
1302 {
1303   BRepAdaptor_Surface anAS(theFace, Standard_False);
1304 
1305   const Standard_Real aTol = 2.0*BRep_Tool::Tolerance(theV);
1306   const Standard_Real aTolU = anAS.UResolution(aTol),
1307                       aTolV = anAS.VResolution(aTol);
1308 
1309   if ((Abs(thePf.X() - thePl.X()) < aTolU) && (Abs(thePf.Y() - thePl.Y()) < aTolV))
1310     return Standard_False;
1311 
1312   const TopoDS_Vertex aVf = TopoDS::Vertex(theV.Oriented(TopAbs_FORWARD)),
1313                       aVl = TopoDS::Vertex(theV.Oriented(TopAbs_REVERSED));
1314 
1315   const gp_XY aV = thePl.XY() - thePf.XY();
1316   const Handle(Geom2d_Line) aL1 = new Geom2d_Line(thePf, gp_Dir2d(aV));
1317   const Handle(Geom2d_Line) aL2 = new Geom2d_Line(thePl, gp_Dir2d(aV.Reversed()));
1318 
1319   BRep_Builder aBB;
1320   TopoDS_Edge anEdegen1, anEdegen2;
1321   aBB.MakeEdge(anEdegen1);
1322   aBB.MakeEdge(anEdegen2);
1323 
1324   aBB.UpdateEdge(anEdegen1, aL1, theFace, Precision::Confusion());
1325   aBB.UpdateEdge(anEdegen2, aL2, theFace, Precision::Confusion());
1326 
1327   anEdegen1.Orientation(TopAbs_FORWARD);
1328   anEdegen2.Orientation(TopAbs_FORWARD);
1329 
1330   aBB.Add(anEdegen1, aVf);
1331   aBB.Add(anEdegen1, aVl);
1332   aBB.Add(anEdegen2, aVf);
1333   aBB.Add(anEdegen2, aVl);
1334 
1335   aBB.Degenerated(anEdegen1, Standard_True);
1336   aBB.Degenerated(anEdegen2, Standard_True);
1337 
1338   const Standard_Real aLPar = aV.Modulus();
1339   aBB.Range(anEdegen1, 0.0, aLPar);
1340   aBB.Range(anEdegen2, 0.0, aLPar);
1341 
1342   theLEdges.Append(anEdegen1);
1343   theLEdges.Append(anEdegen2);
1344 
1345   return Standard_True;
1346 }
1347 
1348 //=======================================================================
1349 //function : InsertEDegenerated
1350 //purpose  :
1351 //=======================================================================
InsertEDegenerated(const TopoDS_Face & theFace,TopTools_ListOfShape & theLEdges)1352 static void InsertEDegenerated(const TopoDS_Face& theFace,
1353                                TopTools_ListOfShape& theLEdges)
1354 {
1355   BRep_Builder aBB;
1356   TopoDS_Wire aWir;
1357   aBB.MakeWire(aWir);
1358 
1359   TopTools_ListIteratorOfListOfShape anItr(theLEdges);
1360   for (; anItr.More(); anItr.Next())
1361   {
1362     const TopoDS_Edge &anE = TopoDS::Edge(anItr.Value());
1363     aBB.Add(aWir, anE);
1364   }
1365 
1366   TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
1367   TopExp::MapShapesAndUniqueAncestors(aWir, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1368 
1369   BRepTools_WireExplorer anExp(aWir, theFace);
1370 
1371   TopoDS_Edge anE1 = anExp.Current(), aFirstEdge, aLastEdge;
1372 
1373   if (anE1.IsNull())
1374   {
1375     // It is possible if aWir contains
1376     // only INTERNAL/EXTERNAL edges.
1377 
1378     return;
1379   }
1380 
1381   aFirstEdge = anE1;
1382   anExp.Next();
1383 
1384 # if 0
1385   if (!anExp.More())
1386   {
1387     // The wire contains only single edge.
1388     // But this edge can be closed itself (e.g. circle).
1389 
1390     TopoDS_Vertex aVf, aVl;
1391     TopExp::Vertices(anE1, aVf, aVl);
1392     if (!aVf.IsNull() && aVf.IsSame(aVl))
1393     {
1394       Standard_Real aF, aL;
1395       const Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface(anE1, theFace, aF, aL);
1396       aF = BRep_Tool::Parameter(aVf, anE1);
1397       aL = BRep_Tool::Parameter(aVl, anE1);
1398       const gp_Pnt2d aPf(aC->Value(aF)), aPl(aC->Value(aL));
1399 
1400       MakeEdgeDegenerated(aVf, theFace, aPf, aPl, theLEdges);
1401     }
1402 
1403     return;
1404   }
1405 #endif
1406 
1407   // Map containing all vertices of degenerated edges
1408   TopTools_MapOfShape aMapVofDE;
1409 
1410   {
1411     TopExp_Explorer anExpDE(aWir, TopAbs_EDGE);
1412     for (; anExpDE.More(); anExpDE.Next())
1413     {
1414       const TopoDS_Edge &anE = TopoDS::Edge(anExpDE.Current());
1415       if (!BRep_Tool::Degenerated(anE))
1416         continue;
1417 
1418       TopoDS_Vertex aV1, aV2;
1419       TopExp::Vertices(anE, aV1, aV2);
1420 
1421       // aV1 and aV2 are SAME vertices
1422 
1423       aMapVofDE.Add(aV1);
1424     }
1425   }
1426 
1427   for (; anExp.More(); anExp.Next())
1428   {
1429     const TopoDS_Edge& anE2 = anExp.Current();
1430     aLastEdge = anE2;
1431 #if 0
1432     if (anE1.IsSame(anE2))
1433     {
1434       //Exclude a gap between two seam-edges (e.g. cylinder without roofs).
1435       anE1 = anE2;
1436       continue;
1437     }
1438 #endif
1439 
1440     const TopoDS_Vertex &aVertCurr = anExp.CurrentVertex();
1441 
1442     if (aMapVofDE.Contains(aVertCurr))
1443     {
1444       // Necessary degenerated edge has already been created.
1445       anE1 = anE2;
1446       continue;
1447     }
1448 
1449     Standard_Real aF, aL;
1450     const Handle(Geom2d_Curve) aC1 = BRep_Tool::CurveOnSurface(anE1, theFace, aF, aL),
1451                                aC2 = BRep_Tool::CurveOnSurface(anE2, theFace, aF, aL);
1452     aF = BRep_Tool::Parameter(aVertCurr, anE1);
1453     aL = BRep_Tool::Parameter(aVertCurr, anE2);
1454     const gp_Pnt2d aPf(aC1->Value(aF)), aPl(aC2->Value(aL));
1455 
1456     if (MakeEdgeDegenerated(aVertCurr, theFace, aPf, aPl, theLEdges))
1457     {
1458       aMapVofDE.Add(aVertCurr);
1459       anE1 = anE2;
1460       continue;
1461     }
1462 
1463     const TopTools_ListOfShape *anEList = aMapVE.Seek(aVertCurr);
1464     if ((anEList != 0) && (anEList->Extent() <= 2))
1465     {
1466       anE1 = anE2;
1467       continue;
1468     }
1469 
1470     // Case like cone with apex. In 2D space all is OK
1471     // (therefore BRepTools_WireExplorer processes this case
1472     // correctly). But in 3D-space, we have several edges with
1473     // the same vertex. Cone apex must be plugged by degenerated edge.
1474 
1475     Standard_Boolean hasDegenerated = Standard_False;
1476     anItr.Init(*anEList);
1477     for (; anItr.More(); anItr.Next())
1478     {
1479       const TopoDS_Edge &anEdge = TopoDS::Edge(anItr.Value());
1480       if (BRep_Tool::Degenerated(anEdge))
1481       {
1482         hasDegenerated = Standard_True;
1483         break;
1484       }
1485     }
1486 
1487     if (hasDegenerated)
1488     {
1489       anE1 = anE2;
1490       continue;
1491     }
1492 
1493     // Look for the pair for anE1 and anE2 edges
1494     for (Standard_Integer i = 0; i < 2; i++)
1495     {
1496       const gp_Pnt2d &aPoint = i ? aPl : aPf;
1497       anItr.Init(*anEList);
1498       for (; anItr.More(); anItr.Next())
1499       {
1500         const TopoDS_Edge &anEdge = TopoDS::Edge(anItr.Value());
1501 
1502         if (anEdge.IsSame(anE1) || anEdge.IsSame(anE2))
1503           continue;
1504 
1505         const Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface(anEdge, theFace, aF, aL);
1506         aF = BRep_Tool::Parameter(aVertCurr, anEdge);
1507         const gp_Pnt2d aP(aC->Value(aF));
1508 
1509         if (MakeEdgeDegenerated(aVertCurr, theFace, aPoint, aP, theLEdges))
1510         {
1511           aMapVofDE.Add(aVertCurr);
1512           i = 2;
1513           break;
1514         }
1515       }
1516     }
1517 
1518     anE1 = anE2;
1519   }
1520 
1521   if (aFirstEdge.IsNull() || aLastEdge.IsNull())
1522     return;
1523 
1524 #if 0
1525   if (aFirstEdge.IsSame(aLastEdge))
1526   {
1527     //Exclude a gap between two seam-edges (e.g. cylinder without bottom-base).
1528 
1529     return;
1530   }
1531 #endif
1532 
1533   //TopExp::CommonVertex(...) does not work
1534   //if edges have more than one pair of common vertex
1535   //(e.g. two halves of circle). Here, we process this case.
1536   TopoDS_Vertex aV[4];
1537   TopExp::Vertices(aFirstEdge, aV[0], aV[1]);
1538   if (!aV[0].IsNull() && aV[0].IsSame(aV[1]))
1539   {
1540     // Possible reason is the NOT-CLOSED edge
1541     // has only single vertex and is covered by it.
1542     return;
1543   }
1544 
1545   TopExp::Vertices(aLastEdge, aV[2], aV[3]);
1546   if (!aV[2].IsNull() && aV[2].IsSame(aV[3]))
1547   {
1548     // Possible reason is the NOT-CLOSED edge
1549     // has only single vertex and is covered by it.
1550     return;
1551   }
1552 
1553   for (Standard_Integer anIDFE = 0; anIDFE < 2; anIDFE++)
1554   {
1555     for (Standard_Integer anIDLE = 2; anIDLE < 4; anIDLE++)
1556     {
1557       if (!aV[anIDFE].IsSame(aV[anIDLE]))
1558         continue;
1559 
1560       const NCollection_List<TopoDS_Shape> *anEList = aMapVE.Seek(aV[anIDFE]);
1561       if ((anEList != 0) && (anEList->Extent() > 2))
1562       {
1563         // Causes:
1564         //  1. Non-manifold topology.
1565         //  2. Case such as:
1566         //
1567         //        *************************
1568         //        *                       *
1569         //  seam  *                       *  seam
1570         //        *  edge1         edge2  *
1571         //        * ********    ********* *
1572         //       V1        V2   V3       V4
1573         //
1574         //
1575         //  V1 - vertex between edge1 and seam
1576         //  V4 - vertex between edge2 and seam
1577         //
1578         //  Indeed, V1 and V4 are same but they
1579         //  must not be joined.
1580 
1581         continue;
1582       }
1583 
1584       Standard_Real aF, aL;
1585       const Handle(Geom2d_Curve) aC1 = BRep_Tool::CurveOnSurface(aFirstEdge, theFace, aF, aL),
1586                                  aC2 = BRep_Tool::CurveOnSurface(aLastEdge, theFace, aF, aL);
1587       aF = BRep_Tool::Parameter(aV[anIDFE], aFirstEdge);
1588       aL = BRep_Tool::Parameter(aV[anIDLE], aLastEdge);
1589       const gp_Pnt2d aPf(aC1->Value(aF)), aPl(aC2->Value(aL));
1590 
1591       MakeEdgeDegenerated(aV[anIDFE], theFace, aPf, aPl, theLEdges);
1592     }
1593   }
1594 }
1595 
1596 //=======================================================================
1597 //function : CheckSingularityAndAdd
1598 //purpose  : Returns TRUE if theF has been split
1599 //=======================================================================
CheckSingularityAndAdd(const TopoDS_Face & theF,const Standard_Real theFuzzyToler,TopTools_ListOfShape & theListOfFaces,TopTools_ListOfShape & theListOfSplits) const1600 Standard_Boolean BRepFill_AdvancedEvolved::CheckSingularityAndAdd(const TopoDS_Face& theF,
1601                                                                   const Standard_Real theFuzzyToler,
1602                                                                   TopTools_ListOfShape& theListOfFaces,
1603                                                                   TopTools_ListOfShape& theListOfSplits) const
1604 {
1605   const BRepAdaptor_Surface anAS(theF, Standard_False);
1606   GeomAbs_SurfaceType aSType = anAS.GetType();
1607 
1608   if (aSType == GeomAbs_OffsetSurface)
1609   {
1610     aSType = anAS.BasisSurface()->GetType();
1611   }
1612 
1613   if (aSType == GeomAbs_Plane)
1614   {
1615     TopTools_MapOfShape aME;
1616     TopTools_ListOfShape aLE;
1617     TopExp_Explorer anExp(theF, TopAbs_EDGE);
1618     for (; anExp.More(); anExp.Next())
1619     {
1620       const TopoDS_Edge &anE = TopoDS::Edge(anExp.Current());
1621 
1622       if (aME.Add(anE))
1623         aLE.Append(anE);
1624     }
1625 
1626     // Split interfered edges
1627     BOPAlgo_PaveFiller aPF;
1628     aPF.SetArguments(aLE);
1629     aPF.SetRunParallel(myIsParallel);
1630 
1631     aPF.Perform();
1632     if (aPF.HasErrors())
1633     {
1634       theListOfFaces.Append(theF);
1635       return Standard_False;
1636     }
1637 
1638     const BOPDS_DS &aDS = aPF.DS();
1639     if (aDS.NbShapes() == aDS.NbSourceShapes())
1640     {
1641       //Interfered edges have not been detected
1642       theListOfFaces.Append(theF);
1643       return Standard_False;
1644     }
1645 
1646     BOPAlgo_Builder aBuilder;
1647     aBuilder.SetArguments(aLE);
1648     aBuilder.SetRunParallel(myIsParallel);
1649     aBuilder.PerformWithFiller(aPF);
1650     if (aBuilder.HasErrors())
1651     {
1652       theListOfFaces.Append(theF);
1653       return Standard_False;
1654     }
1655 
1656     const TopoDS_Shape& anEdges = aBuilder.Shape();
1657 
1658     BRep_Builder aBB;
1659     TopoDS_Compound aCompW, aCompF;
1660     aBB.MakeCompound(aCompW);
1661     aBB.MakeCompound(aCompF);
1662     BOPAlgo_Tools::EdgesToWires(anEdges, aCompW, Standard_True);
1663     BOPAlgo_Tools::WiresToFaces(aCompW, aCompF);
1664 
1665     aME.Clear();
1666     anExp.Init(aCompF, TopAbs_FACE);
1667     for (; anExp.More(); anExp.Next())
1668     {
1669       const TopoDS_Face &aF = TopoDS::Face(anExp.Current());
1670       theListOfSplits.Append(aF);
1671     }
1672 
1673     return Standard_True;
1674   }
1675 
1676   if ((aSType != GeomAbs_Cone) &&
1677       (aSType != GeomAbs_Sphere) &&
1678       (aSType != GeomAbs_BezierSurface) &&
1679       (aSType != GeomAbs_BSplineSurface) &&
1680       (aSType != GeomAbs_SurfaceOfRevolution))
1681   {
1682     theListOfFaces.Append(theF);
1683     return Standard_False;
1684   }
1685 
1686   BRep_Builder aBB;
1687 
1688   TopoDS_Compound aCWires;
1689   aBB.MakeCompound(aCWires);
1690 
1691   Standard_Boolean isSplit = Standard_False;
1692   TopTools_ListOfShape aListEdges;
1693 
1694   const TopoDS_Face aFace = TopoDS::Face(theF.Oriented(TopAbs_FORWARD));
1695 
1696   for (TopoDS_Iterator anExpW(aFace); anExpW.More(); anExpW.Next())
1697   {
1698     const TopoDS_Wire &aWir = TopoDS::Wire(anExpW.Value());
1699 
1700     TopTools_ListOfShape aLGF;
1701     TopExp_Explorer anEExp(aWir, TopAbs_EDGE);
1702     for (; anEExp.More(); anEExp.Next())
1703     {
1704       const TopoDS_Edge &anE = TopoDS::Edge(anEExp.Current());
1705       aLGF.Append(anE);
1706     }
1707 
1708     BOPAlgo_PaveFiller aPF;
1709     aPF.SetArguments(aLGF);
1710     aPF.SetFuzzyValue(theFuzzyToler);
1711     aPF.Perform();
1712 
1713     if (aPF.HasErrors())
1714     {
1715       continue;
1716     }
1717 
1718     const BOPDS_DS &aDS = aPF.DS();
1719     if (aDS.NbShapes() == aDS.NbSourceShapes())
1720     {
1721       //No new shapes have been created
1722       continue;
1723     }
1724 
1725     BOPAlgo_Builder aBuilder;
1726     aBuilder.SetArguments(aLGF);
1727     aBuilder.SetRunParallel(myIsParallel);
1728     aBuilder.SetNonDestructive(Standard_True);
1729     aBuilder.PerformWithFiller(aPF);
1730     if (aBuilder.HasErrors())
1731     {
1732       continue;
1733     }
1734 
1735     TopTools_ListOfShape aLE;
1736 #if 0
1737     // This fragment requires fixing the issue #29656
1738     TopTools_MapOfShape aMM;
1739     TopExp_Explorer anExpEB(aBAB.Shape(), TopAbs_EDGE);
1740     for (; anExpEB.More(); anExpEB.Next())
1741     {
1742       const TopoDS_Edge anEE = TopoDS::Edge(anExpEB.Current());
1743       if (!aMM.Add(anEE))
1744         continue;
1745 
1746       aLE.Append(anEE);
1747     }
1748 #else
1749     TopTools_ListIteratorOfListOfShape aBItr(aLGF);
1750     for (; aBItr.More(); aBItr.Next())
1751     {
1752       const TopoDS_Edge &aSh = TopoDS::Edge(aBItr.Value());
1753       const TopTools_ListOfShape &aLM = aBuilder.Modified(aSh);
1754       if (aLM.IsEmpty() || BRep_Tool::Degenerated(aSh))
1755       {
1756         aLE.Append(aSh);
1757         continue;
1758       }
1759 
1760       TopTools_ListIteratorOfListOfShape anItLM(aLM);
1761       for (; anItLM.More(); anItLM.Next())
1762       {
1763         const TopoDS_Edge &anEM = TopoDS::Edge(anItLM.Value());
1764         aLE.Append(anEM);
1765       }
1766     }
1767 #endif
1768 
1769     isSplit = Standard_True;
1770     InsertEDegenerated(aFace, aLE);
1771     aListEdges.Append(aLE);
1772   }
1773 
1774   if (!isSplit)
1775   {
1776     theListOfFaces.Append(theF);
1777     return Standard_False;
1778   }
1779 
1780   RebuildFaces(aListEdges, theF, theListOfSplits);
1781 
1782   TopTools_ListIteratorOfListOfShape anItrS(theListOfSplits);
1783   for (; anItrS.More(); anItrS.Next())
1784   {
1785     const TopoDS_Face &aF = TopoDS::Face(anItrS.Value());
1786     theListOfFaces.Append(aF.Oriented(theF.Orientation()));
1787   }
1788 
1789   return Standard_True;
1790 }
1791 
1792 //=======================================================================
1793 //function : ContainsInList
1794 //purpose  :
1795 //=======================================================================
ContainsInList(const TopTools_ListOfShape & theL,const TopoDS_Shape & theObject)1796 Standard_Boolean ContainsInList(const TopTools_ListOfShape& theL,
1797                                 const TopoDS_Shape& theObject)
1798 {
1799   TopTools_ListIteratorOfListOfShape anIt(theL);
1800   for (; anIt.More(); anIt.Next())
1801   {
1802     if (anIt.Value().IsSame(theObject))
1803     {
1804       return Standard_True;
1805     }
1806   }
1807   return Standard_False;
1808 }
1809 
1810 //=======================================================================
1811 // function: FindInternals
1812 // purpose: Looks for internal shapes inside the face or solid
1813 //=======================================================================
FindInternals(const TopoDS_Shape & theS,TopTools_ListOfShape & theLInt)1814 void FindInternals(const TopoDS_Shape& theS,
1815                    TopTools_ListOfShape& theLInt)
1816 {
1817   TopoDS_Iterator itS(theS);
1818   for (; itS.More(); itS.Next())
1819   {
1820     const TopoDS_Shape& aSS = itS.Value();
1821     if (aSS.Orientation() == TopAbs_INTERNAL)
1822       theLInt.Append(aSS);
1823     else
1824     {
1825       TopoDS_Iterator itSS(aSS);
1826       for (; itSS.More(); itSS.Next())
1827       {
1828         if (itSS.Value().Orientation() == TopAbs_INTERNAL)
1829         {
1830           theLInt.Append(aSS);
1831           break;
1832         }
1833       }
1834     }
1835   }
1836 }
1837 
1838 //=======================================================================
1839 // function: RemoveInternalWires
1840 // purpose: Removes internal wires from the faces
1841 //=======================================================================
RemoveInternalWires(const TopoDS_Shape & theShape)1842 void RemoveInternalWires(const TopoDS_Shape& theShape)
1843 {
1844   TopExp_Explorer anExpF(theShape, TopAbs_FACE);
1845   for (; anExpF.More(); anExpF.Next())
1846   {
1847     TopoDS_Face& aF = *(TopoDS_Face*) &anExpF.Current();
1848     TopTools_ListOfShape aLWToRemove;
1849     FindInternals(aF, aLWToRemove);
1850     if (aLWToRemove.Extent())
1851     {
1852       aF.Free(Standard_True);
1853       TopTools_ListIteratorOfListOfShape itR(aLWToRemove);
1854       for (; itR.More(); itR.Next())
1855       {
1856         BRep_Builder().Remove(aF, itR.Value());
1857       }
1858       aF.Free(Standard_False);
1859     }
1860   }
1861 }
1862 
1863 //=======================================================================
1864 //function : ProcessVertex
1865 //purpose  :
1866 //=======================================================================
ProcessVertex(const TopoDS_Vertex & aV,const TopTools_ListOfShape & aLE,const TopTools_ListOfShape & aLF)1867 void ProcessVertex(const TopoDS_Vertex& aV,
1868                    const TopTools_ListOfShape& aLE,
1869                    const TopTools_ListOfShape& aLF)
1870 {
1871   Standard_Real aTol, aD2, aTolMax2, aTolE, aParam;
1872   gp_Pnt aPC3D;
1873   gp_Pnt2d aPC2D;
1874   TopAbs_Orientation anOrV;
1875 
1876   TopTools_ListIteratorOfListOfShape anIt;
1877   TopExp_Explorer aVExp;
1878 
1879   BRep_ListIteratorOfListOfCurveRepresentation itcr;
1880   //
1881   aTolMax2 = -1.e6;
1882   //
1883   Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &aV.TShape());
1884   const gp_Pnt& aPV3D = TV->Pnt();
1885   aTol = BRep_Tool::Tolerance(aV);
1886   //
1887   anIt.Initialize(aLE);
1888   for (; anIt.More(); anIt.Next())
1889   {
1890     const TopoDS_Edge& aE = TopoDS::Edge(anIt.Value());
1891     //
1892     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
1893     const TopLoc_Location& Eloc = aE.Location();
1894     //
1895     aVExp.Init(aE, TopAbs_VERTEX);
1896     for (; aVExp.More(); aVExp.Next())
1897     {
1898       const TopoDS_Vertex& aVx = TopoDS::Vertex(aVExp.Current());
1899       //
1900       if (!aVx.IsSame(aV))
1901       {
1902         continue;
1903       }
1904       //
1905       anOrV = aVx.Orientation();
1906       if (!(anOrV == TopAbs_FORWARD || anOrV == TopAbs_REVERSED))
1907       {
1908         continue;
1909       }
1910       //
1911       const BRep_ListOfCurveRepresentation& aLCR = TE->Curves();
1912       itcr.Initialize(aLCR);
1913       for (; itcr.More(); itcr.Next())
1914       {
1915         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
1916         const TopLoc_Location& loc = cr->Location();
1917         TopLoc_Location L = (Eloc * loc).Predivided(aV.Location());
1918         //
1919         // 3D-Curve
1920         if (cr->IsCurve3D())
1921         {
1922           const Handle(Geom_Curve)& aC3D = cr->Curve3D();
1923           //
1924           if (aC3D.IsNull())
1925           {
1926             continue;
1927           }
1928           // 3D-point treatment
1929           aParam = BRep_Tool::Parameter(aVx, aE);
1930           aPC3D = aC3D->Value(aParam);
1931           aPC3D.Transform(L.Transformation());
1932           aD2 = aPV3D.SquareDistance(aPC3D);
1933           if (aD2 > aTolMax2)
1934           {
1935             aTolMax2 = aD2;
1936           }
1937           //
1938         }//if (cr->IsCurve3D())
1939         //
1940         // 2D-Curve
1941         else if (cr->IsCurveOnSurface())
1942         {
1943           const Handle(Geom2d_Curve)& aC2D = cr->PCurve();
1944           if (aC2D.IsNull())
1945           {
1946             continue;
1947           }
1948           // Surface
1949           const Handle(Geom_Surface)& aS = cr->Surface();
1950           //
1951           // 2D-point treatment
1952           aParam = BRep_Tool::Parameter(aVx, aE, aS, L);
1953           aPC2D = aC2D->Value(aParam);
1954           aS->D0(aPC2D.X(), aPC2D.Y(), aPC3D);
1955           aPC3D.Transform(L.Transformation());
1956           aD2 = aPV3D.SquareDistance(aPC3D);
1957           if (aD2 > aTolMax2)
1958           {
1959             aTolMax2 = aD2;
1960           }
1961         } //if (cr->IsCurveOnSurface())
1962 
1963       }//for (; itcr.More(); itcr.Next())
1964     }//for (; aVExp.More(); aVExp.Next())
1965   }//for (; anIt.More(); anIt.Next())
1966   //#########################################################
1967   //
1968   // Reducing
1969   if (aTolMax2<0.)
1970   {
1971     return;
1972   }
1973   //
1974   aTolMax2 = sqrt(aTolMax2);
1975   if (aTolMax2>aTol)
1976   {
1977     return;
1978   }
1979   //
1980   anIt.Initialize(aLE);
1981   for (; anIt.More(); anIt.Next())
1982   {
1983     const TopoDS_Edge& aE = TopoDS::Edge(anIt.Value());
1984 
1985     aTolE = BRep_Tool::Tolerance(aE);
1986     if (aTolMax2 < aTolE)
1987     {
1988       aTolMax2 = aTolE;
1989     }
1990   }
1991   //
1992   anIt.Initialize(aLF);
1993   for (; anIt.More(); anIt.Next())
1994   {
1995     const TopoDS_Face& aF = TopoDS::Face(anIt.Value());
1996 
1997     aTolE = BRep_Tool::Tolerance(aF);
1998     if (aTolMax2 < aTolE)
1999     {
2000       aTolMax2 = aTolE;
2001     }
2002   }
2003   //
2004   if (aTolMax2>aTol)
2005   {
2006     return;
2007   }
2008   //
2009   // Update Tolerance
2010   // with a small margin
2011   TV->Tolerance(aTolMax2 + aTolMax2 * 0.0001);
2012 }
2013 
2014 //=======================================================================
2015 //function : ReduceVertexTolerance
2016 //purpose  :
2017 //=======================================================================
ReduceVertexTolerance(const TopoDS_Shape & aS)2018 void ReduceVertexTolerance(const TopoDS_Shape& aS)
2019 {
2020   Standard_Integer i, aNbV;
2021   TopTools_IndexedDataMapOfShapeListOfShape aVEMap, aVFMap;
2022 
2023   TopExp::MapShapesAndUniqueAncestors(aS, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
2024   TopExp::MapShapesAndUniqueAncestors(aS, TopAbs_VERTEX, TopAbs_FACE, aVFMap);
2025 
2026   aNbV = aVEMap.Extent();
2027   for (i = 1; i <= aNbV; i++)
2028   {
2029     const TopoDS_Vertex& aV = TopoDS::Vertex(aVEMap.FindKey(i));
2030     const TopTools_ListOfShape& aLE = aVEMap(i);
2031     const TopTools_ListOfShape& aLF = aVFMap.FindFromKey(aV);
2032 
2033     ProcessVertex(aV, aLE, aLF);
2034   }
2035 }
2036