0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / BRepFill / BRepFill_AdvancedEvolved.cxx
CommitLineData
85843588 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_HCurve2d.hxx>
37#include <Adaptor3d_HSurface.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
69static const Standard_Real aPipeLinearTolerance = 1.0e-4;
70static const Standard_Real aPipeAngularTolerance = 1.0e-2;
71
72static Standard_Boolean ContainsInList(const TopTools_ListOfShape& theL,
73 const TopoDS_Shape& theObject);
74
75static void FindInternals(const TopoDS_Shape& theS,
76 TopTools_ListOfShape& theLInt);
77
78static void RemoveInternalWires(const TopoDS_Shape& theShape);
79
80static void ProcessVertex(const TopoDS_Vertex& aV,
81 const TopTools_ListOfShape& aLE,
82 const TopTools_ListOfShape& aLF);
83
84static void ReduceVertexTolerance(const TopoDS_Shape& aS);
85
86//=======================================================================
87//function : PerformBoolean
88//purpose :
89//=======================================================================
90Standard_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//=======================================================================
123void 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//=======================================================================
373Standard_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//=======================================================================
401void 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//=======================================================================
497void 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//=======================================================================
520void 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//=======================================================================
677void 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//=======================================================================
804void 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//=======================================================================
823void 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//=======================================================================
880void 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//=======================================================================
1101class NormalFunc : public math_MultipleVarFunctionWithGradient
1102{
1103public:
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_HCurve2d) &aC = myCOnS.GetCurve();
1153 const Handle(Adaptor3d_HSurface) &aS = myCOnS.GetSurface();
1154 const gp_Pnt2d aP2d(aC->Value(theX));
1155 return aS->Value(aP2d.X(), aP2d.Y());
1156 }
1157
1158protected:
1159
1160 NormalFunc& operator=(NormalFunc&);
1161
1162private:
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//=======================================================================
1175Standard_Boolean NormalFunc::Value(const math_Vector& theX, Standard_Real& theF)
1176{
1177 const Handle(Adaptor2d_HCurve2d) &aC = myCOnS.GetCurve();
1178 const Handle(Adaptor3d_HSurface) &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//=======================================================================
1214Standard_Boolean NormalFunc::Gradient(const math_Vector& theX, math_Vector& theG)
1215{
1216 const Handle(Adaptor2d_HCurve2d) &aC = myCOnS.GetCurve();
1217 const Handle(Adaptor3d_HSurface) &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//=======================================================================
1260static 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//=======================================================================
1297static 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//=======================================================================
1352static 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//=======================================================================
1600Standard_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//=======================================================================
1796Standard_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//=======================================================================
1814void 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//=======================================================================
1842void 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//=======================================================================
1867void 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 TV->Tolerance(aTolMax2);
2011}
2012
2013//=======================================================================
2014//function : ReduceVertexTolerance
2015//purpose :
2016//=======================================================================
2017void ReduceVertexTolerance(const TopoDS_Shape& aS)
2018{
2019 Standard_Integer i, aNbV;
2020 TopTools_IndexedDataMapOfShapeListOfShape aVEMap, aVFMap;
2021
2022 TopExp::MapShapesAndUniqueAncestors(aS, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
2023 TopExp::MapShapesAndUniqueAncestors(aS, TopAbs_VERTEX, TopAbs_FACE, aVFMap);
2024
2025 aNbV = aVEMap.Extent();
2026 for (i = 1; i <= aNbV; i++)
2027 {
2028 const TopoDS_Vertex& aV = TopoDS::Vertex(aVEMap.FindKey(i));
2029 const TopTools_ListOfShape& aLE = aVEMap(i);
2030 const TopTools_ListOfShape& aLF = aVFMap.FindFromKey(aV);
2031
2032 ProcessVertex(aV, aLE, aLF);
2033 }
2034}