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 | |
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 | //======================================================================= |
90 | 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 | //======================================================================= |
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 | //======================================================================= |
373 | 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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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_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 | |
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_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 | //======================================================================= |
1214 | Standard_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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
1600 | 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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | //======================================================================= |
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 | TV->Tolerance(aTolMax2); |
2011 | } |
2012 | |
2013 | //======================================================================= |
2014 | //function : ReduceVertexTolerance |
2015 | //purpose : |
2016 | //======================================================================= |
2017 | void 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 | } |