0028259: Method MakeBlocksCnx is duplicated in two different places in BOPAlgo
[occt.git] / src / BOPTools / BOPTools_AlgoTools.cxx
CommitLineData
4e57c75e 1// Created by: Peter KURNEV
973c2be1 2// Copyright (c) 2010-2014 OPEN CASCADE SAS
4e57c75e 3// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6//
973c2be1 7// This file is part of Open CASCADE Technology software library.
4e57c75e 8//
d5f74e42 9// This library is free software; you can redistribute it and/or modify it under
10// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 11// by the Free Software Foundation, with special exception defined in the file
12// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13// distribution for complete text of the license and disclaimer of any warranty.
4e57c75e 14//
973c2be1 15// Alternatively, this file may be used under the terms of Open CASCADE
16// commercial license or contractual agreement.
4e57c75e 17
42cf5bc1 18
19#include <BOPCol_IndexedMapOfShape.hxx>
20#include <BOPCol_MapOfShape.hxx>
77a11d3d 21#include <BOPCol_MapOfOrientedShape.hxx>
42cf5bc1 22#include <BOPTools.hxx>
23#include <BOPTools_AlgoTools.hxx>
24#include <BOPTools_AlgoTools2D.hxx>
25#include <BOPTools_AlgoTools3D.hxx>
26#include <BOPTools_CoupleOfShape.hxx>
27#include <BOPTools_ListOfCoupleOfShape.hxx>
28#include <BRep_Builder.hxx>
29#include <BRep_Tool.hxx>
30#include <BRepAdaptor_Curve2d.hxx>
31#include <BRepAdaptor_Surface.hxx>
32#include <BRepClass3d_SolidClassifier.hxx>
33#include <BRepLib.hxx>
4e57c75e 34#include <Geom2d_Curve.hxx>
42cf5bc1 35#include <Geom2dInt_Geom2dCurveTool.hxx>
36#include <Geom_Curve.hxx>
df017cc9 37#include <Geom_Plane.hxx>
42cf5bc1 38#include <Geom_Surface.hxx>
4e57c75e 39#include <Geom_TrimmedCurve.hxx>
4e57c75e 40#include <GeomAPI_ProjectPointOnSurf.hxx>
42cf5bc1 41#include <gp_Cone.hxx>
42#include <gp_Cylinder.hxx>
43#include <gp_Lin.hxx>
44#include <gp_Pnt.hxx>
45#include <gp_Pnt2d.hxx>
46#include <gp_Sphere.hxx>
47#include <gp_Torus.hxx>
48#include <gp_XYZ.hxx>
49#include <IntTools_Context.hxx>
50#include <IntTools_Curve.hxx>
51#include <IntTools_Range.hxx>
52#include <IntTools_ShrunkRange.hxx>
53#include <IntTools_Tools.hxx>
54#include <Precision.hxx>
4e57c75e 55#include <TopAbs_Orientation.hxx>
42cf5bc1 56#include <TopExp.hxx>
57#include <TopExp_Explorer.hxx>
77a11d3d 58#include <TopoDS.hxx>
4e57c75e 59#include <TopoDS_Compound.hxx>
60#include <TopoDS_CompSolid.hxx>
42cf5bc1 61#include <TopoDS_Edge.hxx>
62#include <TopoDS_Face.hxx>
63#include <TopoDS_Shape.hxx>
4e57c75e 64#include <TopoDS_Shell.hxx>
42cf5bc1 65#include <TopoDS_Solid.hxx>
66#include <TopoDS_Vertex.hxx>
4e57c75e 67#include <TopoDS_Wire.hxx>
b0fbc579 68#include <NCollection_Array1.hxx>
69#include <algorithm>
42cf5bc1 70
71//
4e57c75e 72static
73 Standard_Real AngleWithRef(const gp_Dir& theD1,
74 const gp_Dir& theD2,
75 const gp_Dir& theDRef);
4e57c75e 76
77static
78 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
79 const BOPCol_ListOfShape& thLF,
80 BOPTools_ListOfCoupleOfShape& theLCFF,
1e143abb 81 Handle(IntTools_Context)& theContext);
4e57c75e 82static
83 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
84 const TopoDS_Face& aF);
85
bb58e462 86static
18c06690 87 Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
88 const TopoDS_Face& aF,
89 const gp_Pnt& aP,
90 const Standard_Real aT,
91 const gp_Dir& aDTgt,
92 const Standard_Boolean theSmallFaces,
93 gp_Dir& aDN,
94 gp_Dir& aDB,
95 Handle(IntTools_Context)& theContext,
96 GeomAPI_ProjectPointOnSurf& aProjPL,
97 const Standard_Real aDt);
bb58e462 98static
f56518cd 99 Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
df017cc9 100 const gp_Pnt& aP,
df017cc9 101 gp_Dir& aDB,
102 gp_Pnt& aPOut,
1e143abb 103 Handle(IntTools_Context)& theContext,
f56518cd 104 GeomAPI_ProjectPointOnSurf& aProjPL,
393598eb 105 const Standard_Real aDt,
106 const Standard_Real aTolE);
f56518cd 107static
108 Standard_Real MinStep3D(const TopoDS_Edge& theE1,
109 const TopoDS_Face& theF1,
110 const BOPTools_ListOfCoupleOfShape& theLCS,
18c06690 111 const gp_Pnt& aP,
112 Handle(IntTools_Context)& theContext,
113 Standard_Boolean& theSmallFaces);
4e57c75e 114
07ef8bdf 115
b0fbc579 116
117//=======================================================================
4e57c75e 118// function: MakeConnexityBlocks
119// purpose:
120//=======================================================================
edfa30de 121void BOPTools_AlgoTools::MakeConnexityBlocks
505abfb8 122 (const TopoDS_Shape& theS,
123 const TopAbs_ShapeEnum theType1,
124 const TopAbs_ShapeEnum theType2,
125 BOPCol_ListOfShape& theLCB)
4e57c75e 126{
edfa30de 127 // Map shapes to find connected elements
128 BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS;
129 BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aDMSLS);
130 // Fence map
131 BOPCol_MapOfShape aMFence;
132 Standard_Integer i;
4e57c75e 133 BRep_Builder aBB;
4e57c75e 134 //
edfa30de 135 TopExp_Explorer aExp(theS, theType2);
136 for (; aExp.More(); aExp.Next()) {
137 const TopoDS_Shape& aS = aExp.Current();
138 if (!aMFence.Add(aS)) {
4e57c75e 139 continue;
140 }
edfa30de 141 // The block
142 BOPCol_IndexedMapOfShape aMBlock;
143 TopoDS_Compound aBlock;
144 aBB.MakeCompound(aBlock);
145 // Start the block
146 aMBlock.Add(aS);
147 aBB.Add(aBlock, aS);
148 // Look for connected parts
149 for (i = 1; i <= aMBlock.Extent(); ++i) {
150 const TopoDS_Shape& aS1 = aMBlock(i);
151 TopExp_Explorer aExpSS(aS1, theType1);
152 for (; aExpSS.More(); aExpSS.Next()) {
153 const TopoDS_Shape& aSubS = aExpSS.Current();
154 const BOPCol_ListOfShape& aLS = aDMSLS.FindFromKey(aSubS);
155 BOPCol_ListIteratorOfListOfShape aItLS(aLS);
156 for (; aItLS.More(); aItLS.Next()) {
157 const TopoDS_Shape& aS2 = aItLS.Value();
158 if (aMFence.Add(aS2)) {
159 aMBlock.Add(aS2);
160 aBB.Add(aBlock, aS2);
4e57c75e 161 }
edfa30de 162 }
4e57c75e 163 }
4e57c75e 164 }
edfa30de 165 // Add the block into result
166 theLCB.Append(aBlock);
167 }
4e57c75e 168}
169//=======================================================================
77a11d3d 170// function: OrientEdgesOnWire
171// purpose: Reorient edges on wire for correct ordering
172//=======================================================================
173void BOPTools_AlgoTools::OrientEdgesOnWire(TopoDS_Shape& theWire)
174{
175 // make vertex-edges connexity map
176 BOPCol_IndexedDataMapOfShapeListOfShape aVEMap;
177 BOPTools::MapShapesAndAncestors(theWire, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
178 //
179 if (aVEMap.IsEmpty()) {
180 return;
181 }
182 //
183 BRep_Builder aBB;
184 // new wire
185 TopoDS_Wire aWire;
186 aBB.MakeWire(aWire);
187 // fence map
188 BOPCol_MapOfOrientedShape aMFence;
189 //
190 TopoDS_Iterator aIt(theWire);
191 for (; aIt.More(); aIt.Next()) {
192 const TopoDS_Edge& aEC = TopoDS::Edge(aIt.Value());
193 if (!aMFence.Add(aEC)) {
194 continue;
195 }
196 //
197 // add edge to a wire as it is
198 aBB.Add(aWire, aEC);
199 //
200 TopoDS_Vertex aV1, aV2;
201 TopExp::Vertices(aEC, aV1, aV2, Standard_True);
202 //
203 if (aV1.IsSame(aV2)) {
204 // closed edge, go to the next edge
205 continue;
206 }
207 //
208 // orient the adjacent edges
209 for (Standard_Integer i = 0; i < 2; ++i) {
210 TopoDS_Shape aVC = !i ? aV1 : aV2;
211 //
212 for (;;) {
213 const BOPCol_ListOfShape& aLE = aVEMap.FindFromKey(aVC);
214 if (aLE.Extent() != 2) {
215 // free vertex or multi-connexity, go to the next edge
216 break;
217 }
218 //
219 Standard_Boolean bStop = Standard_True;
220 //
221 BOPCol_ListIteratorOfListOfShape aItLE(aLE);
222 for (; aItLE.More(); aItLE.Next()) {
223 const TopoDS_Edge& aEN = TopoDS::Edge(aItLE.Value());
224 if (aMFence.Contains(aEN)) {
225 continue;
226 }
227 //
228 TopoDS_Vertex aVN1, aVN2;
229 TopExp::Vertices(aEN, aVN1, aVN2, Standard_True);
230 if (aVN1.IsSame(aVN2)) {
231 // closed edge, go to the next edge
232 break;
233 }
234 //
235 // change orientation if necessary and go to the next edges
236 if ((!i && aVC.IsSame(aVN2)) || (i && aVC.IsSame(aVN1))) {
237 aBB.Add(aWire, aEN);
238 }
239 else {
240 aBB.Add(aWire, aEN.Reversed());
241 }
242 aMFence.Add(aEN);
243 aVC = aVC.IsSame(aVN1) ? aVN2 : aVN1;
244 bStop = Standard_False;
245 break;
246 }
247 //
248 if (bStop) {
249 break;
250 }
251 }
252 }
253 }
254 //
255 theWire = aWire;
256}
257//=======================================================================
4e57c75e 258// function: OrientFacesOnShell
259// purpose:
260//=======================================================================
744511c8 261void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
4e57c75e 262{
263 Standard_Boolean bIsProcessed1, bIsProcessed2;
264 Standard_Integer i, aNbE, aNbF, j;
265 TopAbs_Orientation anOrE1, anOrE2;
266 TopoDS_Face aF1x, aF2x;
267 TopoDS_Shape aShellNew;
268 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
269 BOPCol_IndexedMapOfShape aProcessedFaces;
270 BRep_Builder aBB;
271 //
272 BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
273 //
505abfb8 274 BOPTools::MapShapesAndAncestors(aShell,
275 TopAbs_EDGE, TopAbs_FACE,
276 aEFMap);
4e57c75e 277 aNbE=aEFMap.Extent();
278 //
279 // One seam edge in aEFMap contains 2 equivalent faces.
280 for (i=1; i<=aNbE; ++i) {
281 BOPCol_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
282 aNbF=aLF.Extent();
283 if (aNbF>1) {
284 BOPCol_ListOfShape aLFTmp;
285 BOPCol_IndexedMapOfShape aFM;
286 //
287 BOPCol_ListIteratorOfListOfShape anIt(aLF);
288 for (; anIt.More(); anIt.Next()) {
289 const TopoDS_Shape& aF=anIt.Value();
290 if (!aFM.Contains(aF)) {
291 aFM.Add(aF);
292 aLFTmp.Append(aF);
293 }
294 }
295 aLF.Clear();
296 aLF=aLFTmp;
297 }
298 }
299 //
300 // Do
301 for (i=1; i<=aNbE; ++i) {
302 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
303 if (BRep_Tool::Degenerated(aE)) {
304 continue;
305 }
306 //
307 const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
308 aNbF=aLF.Extent();
309 if (aNbF!=2) {
310 continue;
311 }
312 //
313 TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
314 TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
315 //
316 bIsProcessed1=aProcessedFaces.Contains(aF1);
317 bIsProcessed2=aProcessedFaces.Contains(aF2);
318 if (bIsProcessed1 && bIsProcessed2) {
319 continue;
320 }
321
322 if (!bIsProcessed1 && !bIsProcessed2) {
323 aProcessedFaces.Add(aF1);
324 aBB.Add(aShellNew, aF1);
325 bIsProcessed1=!bIsProcessed1;
326 }
327 //
328 aF1x=aF1;
329 if (bIsProcessed1) {
330 j=aProcessedFaces.FindIndex(aF1);
331 aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
332 }
333 //
334 aF2x=aF2;
335 if (bIsProcessed2) {
336 j=aProcessedFaces.FindIndex(aF2);
337 aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
338 }
339 //
340 anOrE1=Orientation(aE, aF1x);
341 anOrE2=Orientation(aE, aF2x);
342 //
343 if (bIsProcessed1 && !bIsProcessed2) {
344 if (anOrE1==anOrE2) {
345 if (!BRep_Tool::IsClosed(aE, aF1) &&
346 !BRep_Tool::IsClosed(aE, aF2)) {
347 aF2.Reverse();
348 }
349 }
350 aProcessedFaces.Add(aF2);
351 aBB.Add(aShellNew, aF2);
352 }
353 else if (!bIsProcessed1 && bIsProcessed2) {
354 if (anOrE1==anOrE2) {
355 if (!BRep_Tool::IsClosed(aE, aF1) &&
356 !BRep_Tool::IsClosed(aE, aF2)) {
357 aF1.Reverse();
358 }
359 }
360 aProcessedFaces.Add(aF1);
361 aBB.Add(aShellNew, aF1);
362 }
363 }
364 //
365 //
366 for (i=1; i<=aNbE; ++i) {
367 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
368 if (BRep_Tool::Degenerated(aE)) {
369 continue;
370 }
371 //
372 const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
373 aNbF=aLF.Extent();
374 if (aNbF!=2) {
375 BOPCol_ListIteratorOfListOfShape anIt(aLF);
376 for(; anIt.More(); anIt.Next()) {
377 const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
378 if (!aProcessedFaces.Contains(aF)) {
379 aProcessedFaces.Add(aF);
380 aBB.Add(aShellNew, aF);
381 }
382 }
383 }
384 }
385 aShell=aShellNew;
386}
387//=======================================================================
388//function : Orientation
389//purpose :
390//=======================================================================
744511c8 391TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
bb58e462 392 const TopoDS_Face& aF)
4e57c75e 393{
394 TopAbs_Orientation anOr=TopAbs_INTERNAL;
395
396 TopExp_Explorer anExp;
397 anExp.Init(aF, TopAbs_EDGE);
398 for (; anExp.More(); anExp.Next()) {
399 const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
400 if (anEF1.IsSame(anE)) {
401 anOr=anEF1.Orientation();
402 break;
403 }
404 }
405 return anOr;
406}
4e57c75e 407//=======================================================================
408// function: MakeConnexityBlock.
409// purpose:
410//=======================================================================
505abfb8 411void BOPTools_AlgoTools::MakeConnexityBlock
412 (BOPCol_ListOfShape& theLFIn,
413 BOPCol_IndexedMapOfShape& theMEAvoid,
414 BOPCol_ListOfShape& theLCB,
415 const Handle(NCollection_BaseAllocator)& theAllocator)
4e57c75e 416{
417 Standard_Integer aNbF, aNbAdd1, aNbAdd, i;
418 TopExp_Explorer aExp;
419 BOPCol_ListIteratorOfListOfShape aIt;
420 //
421 BOPCol_IndexedMapOfShape aMCB(100, theAllocator);
422 BOPCol_IndexedMapOfShape aMAdd(100, theAllocator);
423 BOPCol_IndexedMapOfShape aMAdd1(100, theAllocator);
424 BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
425 //
426 // 1. aMEF
427 aNbF=theLFIn.Extent();
428 aIt.Initialize(theLFIn);
429 for (; aIt.More(); aIt.Next()) {
430 const TopoDS_Shape& aF=aIt.Value();
431 BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
432 }
433 //
434 // 2. aMCB
435 const TopoDS_Shape& aF1=theLFIn.First();
436 aMAdd.Add(aF1);
437 //
302f96fb 438 for(;;) {
4e57c75e 439 aMAdd1.Clear();
440 aNbAdd = aMAdd.Extent();
441 for (i=1; i<=aNbAdd; ++i) {
442 const TopoDS_Shape& aF=aMAdd(i);
443 //
444 //aMAdd1.Clear();
445 aExp.Init(aF, TopAbs_EDGE);
446 for (; aExp.More(); aExp.Next()) {
447 const TopoDS_Shape& aE=aExp.Current();
448 if (theMEAvoid.Contains(aE)){
449 continue;
450 }
451 //
452 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
453 aIt.Initialize(aLF);
454 for (; aIt.More(); aIt.Next()) {
455 const TopoDS_Shape& aFx=aIt.Value();
456 if (aFx.IsSame(aF)) {
457 continue;
458 }
459 if (aMCB.Contains(aFx)) {
460 continue;
461 }
462 aMAdd1.Add(aFx);
463 }
464 }//for (; aExp.More(); aExp.Next()){
465 aMCB.Add(aF);
466 }// for (i=1; i<=aNbAdd; ++i) {
467 //
468 aNbAdd1=aMAdd1.Extent();
469 if (!aNbAdd1) {
470 break;
471 }
472 //
473 aMAdd.Clear();
474 for (i=1; i<=aNbAdd1; ++i) {
475 const TopoDS_Shape& aFAdd=aMAdd1(i);
476 aMAdd.Add(aFAdd);
477 }
478 //
479 }//while(1) {
480
481 //
482 aNbF=aMCB.Extent();
483 for (i=1; i<=aNbF; ++i) {
484 const TopoDS_Shape& aF=aMCB(i);
485 theLCB.Append(aF);
486 }
487}
488//=======================================================================
489// function: ComputeStateByOnePoint
490// purpose:
491//=======================================================================
505abfb8 492TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint
493 (const TopoDS_Shape& theS,
494 const TopoDS_Solid& theRef,
495 const Standard_Real theTol,
1e143abb 496 Handle(IntTools_Context)& theContext)
4e57c75e 497{
498 TopAbs_State aState;
499 TopAbs_ShapeEnum aType;
500 //
501 aState=TopAbs_UNKNOWN;
502 aType=theS.ShapeType();
503 if (aType==TopAbs_VERTEX) {
504 const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
505 aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
506 }
507 else if (aType==TopAbs_EDGE) {
508 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
509 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
510 }
511 return aState;
512}
513
514//=======================================================================
515// function: ComputeState
516// purpose:
517//=======================================================================
505abfb8 518TopAbs_State BOPTools_AlgoTools::ComputeState
519 (const TopoDS_Face& theF,
520 const TopoDS_Solid& theRef,
521 const Standard_Real theTol,
522 BOPCol_IndexedMapOfShape& theBounds,
1e143abb 523 Handle(IntTools_Context)& theContext)
4e57c75e 524{
525 TopAbs_State aState;
526 TopExp_Explorer aExp;
527 TopoDS_Edge aE1;
528 gp_Pnt2d aP2D;
529 gp_Pnt aP3D;
530 //
531 aState=TopAbs_UNKNOWN;
532 //
533 aExp.Init(theF, TopAbs_EDGE);
534 for (; aExp.More(); aExp.Next()) {
535 const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
536 if (BRep_Tool::Degenerated(aSE)) {
537 continue;
538 }
539 //
540 if (!theBounds.Contains(aSE)) {
541 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
505abfb8 542 aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol,
543 theContext);
4e57c75e 544 return aState;
545 }
546 if (aE1.IsNull()) {
547 aE1=(*(TopoDS_Edge*)(&aSE));
548 }
549 }
550 // !!<- process edges that are all on theRef
551 if (!aE1.IsNull()) {
505abfb8 552 BOPTools_AlgoTools3D::PointNearEdge(aE1, theF,
553 aP2D, aP3D, theContext);
554 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
555 theContext);
4e57c75e 556 }
557 //
558 return aState;
559}
560//=======================================================================
561// function: ComputeState
562// purpose:
563//=======================================================================
505abfb8 564TopAbs_State BOPTools_AlgoTools::ComputeState
565 (const TopoDS_Vertex& theV,
566 const TopoDS_Solid& theRef,
567 const Standard_Real theTol,
1e143abb 568 Handle(IntTools_Context)& theContext)
4e57c75e 569{
570 TopAbs_State aState;
571 gp_Pnt aP3D;
572 //
573 aP3D=BRep_Tool::Pnt(theV);
505abfb8 574 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
575 theContext);
4e57c75e 576 return aState;
577}
578//=======================================================================
579// function: ComputeState
580// purpose:
581//=======================================================================
505abfb8 582TopAbs_State BOPTools_AlgoTools::ComputeState
583 (const TopoDS_Edge& theE,
584 const TopoDS_Solid& theRef,
585 const Standard_Real theTol,
1e143abb 586 Handle(IntTools_Context)& theContext)
4e57c75e 587{
588 Standard_Real aT1, aT2, aT = 0.;
589 TopAbs_State aState;
590 Handle(Geom_Curve) aC3D;
591 gp_Pnt aP3D;
592 //
593 aC3D = BRep_Tool::Curve(theE, aT1, aT2);
594 //
595 if(aC3D.IsNull()) {
596 //it means that we are in degenerated edge
597 const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
598 if(aV.IsNull()){
599 return TopAbs_UNKNOWN;
600 }
601 aP3D=BRep_Tool::Pnt(aV);
602 }
603 else {//usual case
604 Standard_Boolean bF2Inf, bL2Inf;
605 Standard_Real dT=10.;
606 //
607 bF2Inf = Precision::IsNegativeInfinite(aT1);
608 bL2Inf = Precision::IsPositiveInfinite(aT2);
609 //
610 if (bF2Inf && !bL2Inf) {
611 aT=aT2-dT;
612 }
613 else if (!bF2Inf && bL2Inf) {
614 aT=aT1+dT;
615 }
616 else if (bF2Inf && bL2Inf) {
617 aT=0.;
618 }
619 else {
620 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
621 }
622 aC3D->D0(aT, aP3D);
623 }
624 //
505abfb8 625 aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol,
626 theContext);
4e57c75e 627 //
628 return aState;
629}
630//=======================================================================
631// function: ComputeState
632// purpose:
633//=======================================================================
505abfb8 634TopAbs_State BOPTools_AlgoTools::ComputeState
635 (const gp_Pnt& theP,
636 const TopoDS_Solid& theRef,
637 const Standard_Real theTol,
1e143abb 638 Handle(IntTools_Context)& theContext)
4e57c75e 639{
640 TopAbs_State aState;
641 //
642 BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
643 aSC.Perform(theP, theTol);
644 //
645 aState=aSC.State();
646 //
647 return aState;
648}
649//=======================================================================
650//function : IsInternalFace
651//purpose :
652//=======================================================================
dde68833 653Standard_Boolean BOPTools_AlgoTools::IsInternalFace
744511c8 654 (const TopoDS_Face& theFace,
655 const TopoDS_Solid& theSolid,
656 BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
657 const Standard_Real theTol,
1e143abb 658 Handle(IntTools_Context)& theContext)
4e57c75e 659{
744511c8 660 Standard_Boolean bDegenerated;
661 Standard_Integer aNbF, iRet, iFound;
4e57c75e 662 TopAbs_Orientation aOr;
744511c8 663 TopoDS_Edge aE1;
4e57c75e 664 TopExp_Explorer aExp;
665 BOPCol_ListIteratorOfListOfShape aItF;
666 //
744511c8 667 // For all invoked functions: [::IsInternalFace(...)]
668 // the returned value iRet means:
669 // iRet=0; - state is not IN
670 // iRet=1; - state is IN
671 // iRet=2; - state can not be found by the method of angles
672 //
673 // For this function the returned value iRet means:
674 // iRet=0; - state is not IN
675 // iRet=1; - state is IN
4e57c75e 676 //
744511c8 677 iRet=0;
4e57c75e 678 // 1 Try to find an edge from theFace in theMEF
744511c8 679 iFound=0;
4e57c75e 680 aExp.Init(theFace, TopAbs_EDGE);
681 for(; aExp.More(); aExp.Next()) {
682 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
683 if (!theMEF.Contains(aE)) {
684 continue;
685 }
686 //
744511c8 687 ++iFound;
688 //
4e57c75e 689 aOr=aE.Orientation();
690 if (aOr==TopAbs_INTERNAL) {
691 continue;
692 }
693 bDegenerated=BRep_Tool::Degenerated(aE);
694 if (bDegenerated){
695 continue;
696 }
697 // aE
698 BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
699 aNbF=aLF.Extent();
700 if (!aNbF) {
dde68833 701 return iRet != 0; // it can not be so
4e57c75e 702 }
744511c8 703 //
4e57c75e 704 else if (aNbF==1) {
705 // aE is internal edge on aLF.First()
706 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
744511c8 707 BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
708 if (aE1.Orientation()!=TopAbs_INTERNAL) {
bb58e462 709 iRet=2;
710 break;
744511c8 711 }
712 //
505abfb8 713 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1,
714 theContext);
744511c8 715 break;
4e57c75e 716 }
744511c8 717 //
4e57c75e 718 else if (aNbF==2) {
719 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
720 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
721 //
722 if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
723 // treat as it was for 1 face
505abfb8 724 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
725 theContext);
bb58e462 726 break;
4e57c75e 727 }
728 }
744511c8 729 //
4e57c75e 730 if (aNbF%2) {
dde68833 731 return Standard_False; // it can not be so
4e57c75e 732 }
733 else { // aNbF=2,4,6,8,...
505abfb8 734 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF,
735 theContext);
744511c8 736 break;
4e57c75e 737 }
738 }//for(; aExp.More(); aExp.Next()) {
739 //
744511c8 740 if (!iFound) {
741 // the face has no shared edges with the solid
742 iRet=2;
743 }
744 //
745 if (iRet!=2) {
dde68833 746 return iRet == 1;
744511c8 747 }
748 //
4e57c75e 749 //========================================
750 // 2. Classify face using classifier
751 //
752 TopAbs_State aState;
753 BOPCol_IndexedMapOfShape aBounds;
754 //
744511c8 755 BOPTools::MapShapes(theSolid, TopAbs_EDGE, aBounds);
756 //
505abfb8 757 aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid,
758 theTol, aBounds, theContext);
dde68833 759 return aState == TopAbs_IN;
4e57c75e 760}
761//=======================================================================
762//function : IsInternalFace
763//purpose :
764//=======================================================================
505abfb8 765Standard_Integer BOPTools_AlgoTools::IsInternalFace
766 (const TopoDS_Face& theFace,
767 const TopoDS_Edge& theEdge,
768 BOPCol_ListOfShape& theLF,
1e143abb 769 Handle(IntTools_Context)& theContext)
4e57c75e 770{
744511c8 771 Standard_Integer aNbF, iRet;
4e57c75e 772 //
744511c8 773 iRet=0;
4e57c75e 774 //
775 aNbF=theLF.Extent();
776 if (aNbF==2) {
777 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
778 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
505abfb8 779 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
780 theContext);
744511c8 781 return iRet;
4e57c75e 782 }
783 //
784 else {
785 BOPTools_ListOfCoupleOfShape aLCFF;
786 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
787 //
788 FindFacePairs(theEdge, theLF, aLCFF, theContext);
789 //
790 aIt.Initialize(aLCFF);
791 for (; aIt.More(); aIt.Next()) {
792 BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
793 //
794 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
795 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
505abfb8 796 iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2,
797 theContext);
744511c8 798 if (iRet) {
799 return iRet;
4e57c75e 800 }
801 }
802 }
744511c8 803 return iRet;
4e57c75e 804}
805//=======================================================================
806//function : IsInternalFace
807//purpose :
808//=======================================================================
744511c8 809Standard_Integer BOPTools_AlgoTools::IsInternalFace
810 (const TopoDS_Face& theFace,
811 const TopoDS_Edge& theEdge,
812 const TopoDS_Face& theFace1,
813 const TopoDS_Face& theFace2,
1e143abb 814 Handle(IntTools_Context)& theContext)
4e57c75e 815{
816 Standard_Boolean bRet;
744511c8 817 Standard_Integer iRet;
4e57c75e 818 TopoDS_Edge aE1, aE2;
819 TopoDS_Face aFOff;
820 BOPTools_ListOfCoupleOfShape theLCSOff;
821 BOPTools_CoupleOfShape aCS1, aCS2;
822 //
823 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
824 if (aE1.Orientation()==TopAbs_INTERNAL) {
825 aE2=aE1;
826 aE1.Orientation(TopAbs_FORWARD);
827 aE2.Orientation(TopAbs_REVERSED);
828 }
829 else if (theFace1==theFace2) {
830 aE2=aE1;
831 aE1.Orientation(TopAbs_FORWARD);
832 aE2.Orientation(TopAbs_REVERSED);
833 }
834 else {
835 BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
836 }
837 //
838 aCS1.SetShape1(theEdge);
839 aCS1.SetShape2(theFace);
840 theLCSOff.Append(aCS1);
841 //
842 aCS2.SetShape1(aE2);
843 aCS2.SetShape2(theFace2);
844 theLCSOff.Append(aCS2);
845 //
744511c8 846 bRet=GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
4e57c75e 847 //
744511c8 848 iRet=0; // theFace is not internal
849 if (theFace.IsEqual(aFOff)) {
850 // theFace is internal
851 iRet=1;
852 if (!bRet) {
853 // theFace seems to be internal
854 iRet=2;
855 }
856 }
857 return iRet;
4e57c75e 858}
859//=======================================================================
860//function : GetFaceOff
861//purpose :
862//=======================================================================
744511c8 863Standard_Boolean BOPTools_AlgoTools::GetFaceOff
864 (const TopoDS_Edge& theE1,
865 const TopoDS_Face& theF1,
866 BOPTools_ListOfCoupleOfShape& theLCSOff,
867 TopoDS_Face& theFOff,
1e143abb 868 Handle(IntTools_Context)& theContext)
4e57c75e 869{
18c06690 870 Standard_Boolean bRet, bIsComputed;
f56518cd 871 Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin, aDt3D;
59f52058 872 Standard_Real aUmin, aUsup, aVmin, aVsup, aPA;
4e57c75e 873 gp_Pnt aPn1, aPn2, aPx;
df017cc9 874 gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
4e57c75e 875 gp_Vec aVTgt;
df017cc9 876 TopAbs_Orientation aOr;
4e57c75e 877 Handle(Geom_Curve)aC3D;
bb58e462 878 Handle(Geom_Plane) aPL;
4e57c75e 879 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
bb58e462 880 GeomAPI_ProjectPointOnSurf aProjPL;
4e57c75e 881 //
59f52058 882 aPA=Precision::Angular();
4e57c75e 883 aAngleMin=100.;
884 aTwoPI=M_PI+M_PI;
885 aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
4e57c75e 886 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
887 aC3D->D0(aT, aPx);
df017cc9 888 //
4e57c75e 889 BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
df017cc9 890 gp_Dir aDTgt(aVTgt), aDTgt2;
891 aOr = theE1.Orientation();
892 //
bb58e462 893 aPL = new Geom_Plane(aPx, aDTgt);
894 aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
895 aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
896 //
18c06690 897 Standard_Boolean bSmallFaces = Standard_False;
898 aDt3D = MinStep3D(theE1, theF1, theLCSOff, aPx, theContext, bSmallFaces);
899 bIsComputed = GetFaceDir(theE1, theF1, aPx, aT, aDTgt, bSmallFaces,
900 aDN1, aDBF, theContext, aProjPL, aDt3D);
901 if (!bIsComputed) {
902#ifdef OCCT_DEBUG
903 cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << endl;
904#endif
905 }
df017cc9 906 //
4e57c75e 907 aDTF=aDN1^aDBF;
908 //
744511c8 909 bRet=Standard_True;
4e57c75e 910 aIt.Initialize(theLCSOff);
911 for (; aIt.More(); aIt.Next()) {
912 const BOPTools_CoupleOfShape& aCS=aIt.Value();
913 const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
914 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
915 //
df017cc9 916 aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
18c06690 917 bIsComputed = GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, bSmallFaces, aDN2,
918 aDBF2, theContext, aProjPL, aDt3D);
919 if (!bIsComputed) {
920#ifdef OCCT_DEBUG
921 cout << "BOPTools_AlgoTools::GetFaceOff(): incorrect computation of bi-normal direction." << endl;
922#endif
923 }
4e57c75e 924 //Angle
925 aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
926 //
927 if(aAngle<0.) {
928 aAngle=aTwoPI+aAngle;
929 }
df017cc9 930 //
59f52058 931 if (aAngle<aPA) {
df017cc9 932 if (aF2==theF1) {
933 aAngle=M_PI;
934 }
935 else if (aF2.IsSame(theF1)) {
936 aAngle=aTwoPI;
937 }
938 }
939 //
59f52058 940 if (fabs(aAngle-aAngleMin)<aPA) {
941 // the minimal angle can not be found
942 bRet=Standard_False;
943 }
944 //
4e57c75e 945 if (aAngle<aAngleMin){
946 aAngleMin=aAngle;
947 theFOff=aF2;
948 }
744511c8 949 else if (aAngle==aAngleMin) {
950 // the minimal angle can not be found
951 bRet=Standard_False;
952 }
4e57c75e 953 }
744511c8 954 return bRet;
4e57c75e 955}
956//=======================================================================
957//function : GetEdgeOff
958//purpose :
959//=======================================================================
bb58e462 960Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
961 const TopoDS_Face& theF2,
962 TopoDS_Edge& theE2)
4e57c75e 963{
964 Standard_Boolean bFound;
965 TopAbs_Orientation aOr1, aOr1C, aOr2;
966 TopExp_Explorer anExp;
967 //
968 bFound=Standard_False;
969 aOr1=theE1.Orientation();
970 aOr1C=TopAbs::Reverse(aOr1);
971 //
972 anExp.Init(theF2, TopAbs_EDGE);
973 for (; anExp.More(); anExp.Next()) {
974 const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
975 if (aEF2.IsSame(theE1)) {
976 aOr2=aEF2.Orientation();
977 if (aOr2==aOr1C) {
978 theE2=aEF2;
979 bFound=!bFound;
980 return bFound;
981 }
982 }
983 }
984 return bFound;
985}
986
987//=======================================================================
988//function : AreFacesSameDomain
989//purpose :
990//=======================================================================
505abfb8 991Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain
992 (const TopoDS_Face& theF1,
993 const TopoDS_Face& theF2,
0d0481c7 994 Handle(IntTools_Context)& theContext,
995 const Standard_Real theFuzz)
4e57c75e 996{
997 Standard_Boolean bFlag;
e656bcbe 998 Standard_Integer iErr;
4e57c75e 999 Standard_Real aTolF1, aTolF2, aTol;
1000 gp_Pnt2d aP2D;
1001 gp_Pnt aP;
1002 TopoDS_Face aF1, aF2;
1003 TopoDS_Edge aE1;
1004 TopExp_Explorer aExp;
0d0481c7 1005 Standard_Real aFuzz1 = (theFuzz > Precision::Confusion() ? theFuzz : Precision::Confusion());
4e57c75e 1006 //
1007 bFlag=Standard_False;
1008 //
1009 aF1=theF1;
1010 aF1.Orientation(TopAbs_FORWARD);
1011 aF2=theF2;
1012 aF2.Orientation(TopAbs_FORWARD);
1013 //
1014 aTolF1=BRep_Tool::Tolerance(aF1);
1015 // 1
4e57c75e 1016 aExp.Init(aF1, TopAbs_EDGE);
1017 for (; aExp.More(); aExp.Next()) {
1018 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
1019 if (!BRep_Tool::Degenerated(aE1)) {
4e57c75e 1020 Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
0d0481c7 1021 if (aTolE > aTolF1) {
1022 aTolF1 = aTolE;
1023 }
4e57c75e 1024 }
1025 }
4e57c75e 1026 // 2
1027 aTolF2=BRep_Tool::Tolerance(aF2);
0d0481c7 1028 aTol = aTolF1 + aTolF2 + aFuzz1;
4e57c75e 1029 //
505abfb8 1030 iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D,
1031 theContext);
e656bcbe 1032 if (!iErr) {
1033 bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
1034 }
4e57c75e 1035 //
1036 return bFlag;
1037}
1038
1039//=======================================================================
1040//function : CheckSameGeom
1041//purpose :
1042//=======================================================================
505abfb8 1043Standard_Boolean BOPTools_AlgoTools::CheckSameGeom
1044 (const TopoDS_Face& theF1,
1045 const TopoDS_Face& theF2,
1e143abb 1046 Handle(IntTools_Context)& theContext)
4e57c75e 1047{
1048 Standard_Boolean bRet;
1049 Standard_Real aTolF1, aTolF2, aTol;
1050 gp_Pnt2d aP2D;
1051 gp_Pnt aP;
1052 TopExp_Explorer aExp;
1053 //
1054 bRet=Standard_False;
1055 aExp.Init(theF1, TopAbs_EDGE);
1056 for (; aExp.More(); aExp.Next()) {
1057 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
1058 if (!BRep_Tool::Degenerated(aE)) {
1059 aTolF1=BRep_Tool::Tolerance(theF1);
1060 aTolF2=BRep_Tool::Tolerance(theF2);
1061 aTol=aTolF1+aTolF2;
1062 BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
1063 bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
1064 break;
1065 }
1066 }
1067 return bRet;
1068}
1069//=======================================================================
1070// function: Sense
1071// purpose:
1072//=======================================================================
bb58e462 1073Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
51db0179 1074 const TopoDS_Face& theF2,
1075 const Handle(IntTools_Context)& theContext)
4e57c75e 1076{
1077 Standard_Integer iSense=0;
1078 gp_Dir aDNF1, aDNF2;
1079 TopoDS_Edge aE1, aE2;
1080 TopExp_Explorer aExp;
1081 //
1082 aExp.Init(theF1, TopAbs_EDGE);
1083 for (; aExp.More(); aExp.Next()) {
1084 aE1=(*(TopoDS_Edge*)(&aExp.Current()));
1085 if (!BRep_Tool::Degenerated(aE1)) {
1086 if (!BRep_Tool::IsClosed(aE1, theF1)) {
1087 break;
1088 }
1089 }
1090 }
1091 //
1092 aExp.Init(theF2, TopAbs_EDGE);
1093 for (; aExp.More(); aExp.Next()) {
1094 aE2=(*(TopoDS_Edge*)(&aExp.Current()));
1095 if (!BRep_Tool::Degenerated(aE2)) {
1096 if (!BRep_Tool::IsClosed(aE2, theF2)) {
1097 if (aE2.IsSame(aE1)) {
1098 iSense=1;
1099 break;
1100 }
1101 }
1102 }
1103 }
1104 //
1105 if (!iSense) {
1106 return iSense;
1107 }
1108 //
51db0179 1109 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1, theContext);
1110 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2, theContext);
4e57c75e 1111 //
1112 iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
1113 //
1114 return iSense;
1115}
1116//=======================================================================
1117// function: IsSplitToReverse
1118// purpose:
1119//=======================================================================
505abfb8 1120Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1121 (const TopoDS_Shape& theSp,
1122 const TopoDS_Shape& theSr,
1e143abb 1123 Handle(IntTools_Context)& theContext)
4e57c75e 1124{
1125 Standard_Boolean bRet;
1126 TopAbs_ShapeEnum aType;
1127 //
1128 bRet=Standard_False;
1129 //
1130 aType=theSp.ShapeType();
1131 switch (aType) {
1132 case TopAbs_EDGE: {
1133 const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
1134 const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
1135 bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
1136 }
1137 break;
1138 //
1139 case TopAbs_FACE: {
1140 const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
1141 const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
1142 bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
1143 }
1144 break;
1145 //
1146 default:
1147 break;
1148 }
1149 return bRet;
1150}
1151//=======================================================================
1152//function :IsSplitToReverse
1153//purpose :
1154//=======================================================================
505abfb8 1155Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1156 (const TopoDS_Face& theFSp,
1157 const TopoDS_Face& theFSr,
1e143abb 1158 Handle(IntTools_Context)& theContext)
4e57c75e 1159{
6fd4ffd9 1160 // Compare surfaces
1161 Handle(Geom_Surface) aSFSp = BRep_Tool::Surface(theFSp);
1162 Handle(Geom_Surface) aSFOr = BRep_Tool::Surface(theFSr);
1163 if (aSFSp == aSFOr) {
1164 return theFSp.Orientation() != theFSr.Orientation();
4e57c75e 1165 }
1166 //
6fd4ffd9 1167 Standard_Boolean bDone = Standard_False;
1168 // Find the point inside the split face
1169 gp_Pnt aPFSp;
1170 gp_Pnt2d aP2DFSp;
1171 //
1172 // Error status
1173 Standard_Integer iErr;
1174 // Use the hatcher to find the point in the middle of the face
1175 iErr = BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1176 if (iErr) {
1177 // Hatcher has failed to find a point.
1178 // Try to get the point near some not closed and
1179 // not degenerated edge on the split face.
1180 TopExp_Explorer anExp(theFSp, TopAbs_EDGE);
1181 for (; anExp.More(); anExp.Next()) {
1182 const TopoDS_Edge& aESp = (*(TopoDS_Edge*)(&anExp.Current()));
1183 if (!BRep_Tool::Degenerated(aESp) && !BRep_Tool::IsClosed(aESp, theFSp)) {
1184 iErr = BOPTools_AlgoTools3D::PointNearEdge
1185 (aESp, theFSp, aP2DFSp, aPFSp, theContext);
1186 if (!iErr) {
1187 break;
1188 }
4e57c75e 1189 }
1190 }
4e57c75e 1191 //
6fd4ffd9 1192 if (!anExp.More()) {
1193 // The point has not been found.
1194 return bDone;
5b98e25d 1195 }
4e57c75e 1196 }
6fd4ffd9 1197 //
1198 // Compute normal direction of the split face
1199 gp_Dir aDNFSp;
1200 bDone = BOPTools_AlgoTools3D::GetNormalToSurface
1201 (aSFSp, aP2DFSp.X(), aP2DFSp.Y(), aDNFSp);
1202 if (!bDone) {
1203 return bDone;
4e57c75e 1204 }
1205 //
6fd4ffd9 1206 if (theFSp.Orientation() == TopAbs_REVERSED){
1207 aDNFSp.Reverse();
4e57c75e 1208 }
1209 //
6fd4ffd9 1210 // Project the point from the split face on the original face
1211 // to find its UV coordinates
1212 GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(theFSr);
1213 aProjector.Perform(aPFSp);
1214 bDone = (aProjector.NbPoints() > 0);
1215 if (!bDone) {
1216 return bDone;
4e57c75e 1217 }
6fd4ffd9 1218 // UV coordinates of the point on the original face
1219 Standard_Real aU, aV;
1220 aProjector.LowerDistanceParameters(aU, aV);
4e57c75e 1221 //
6fd4ffd9 1222 // Compute normal direction for the original face in this point
1223 gp_Dir aDNFOr;
1224 bDone = BOPTools_AlgoTools3D::GetNormalToSurface(aSFOr, aU, aV, aDNFOr);
1225 if (!bDone) {
1226 return bDone;
4e57c75e 1227 }
1228 //
6fd4ffd9 1229 if (theFSr.Orientation() == TopAbs_REVERSED) {
1230 aDNFOr.Reverse();
1231 }
4e57c75e 1232 //
6fd4ffd9 1233 // compare the normals
1234 Standard_Real aCos = aDNFSp*aDNFOr;
1235 return (aCos < 0.);
4e57c75e 1236}
1237//=======================================================================
1238//function :IsSplitToReverse
1239//purpose :
1240//=======================================================================
505abfb8 1241Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
1242 (const TopoDS_Edge& aEF1,
1243 const TopoDS_Edge& aEF2,
1e143abb 1244 Handle(IntTools_Context)& theContext)
4e57c75e 1245{
1246 Standard_Boolean bRet, bIsDegenerated;
1247 //
1248 bRet=Standard_False;
1249 bIsDegenerated=(BRep_Tool::Degenerated(aEF1) ||
1250 BRep_Tool::Degenerated(aEF2));
1251 if (bIsDegenerated) {
1252 return bRet;
1253 }
1254 //
1255 Standard_Real a, b;
1256 TopAbs_Orientation aOrE, aOrSp;
1257 Handle(Geom_Curve)aC1, aC2;
1258 //
1259 aC2=BRep_Tool::Curve(aEF2, a, b);
1260 aC1=BRep_Tool::Curve(aEF1, a, b);
1261 //
1262 if (aC1==aC2) {
1263 aOrE=aEF2.Orientation();
1264 aOrSp=aEF1.Orientation();
1265 bRet=(aOrE!=aOrSp);
1266 return bRet;
1267 }
1268 //
1269 Standard_Real aT1, aT2, aScPr;
1270 gp_Vec aV1, aV2;
1271 gp_Pnt aP;
1272 //
1273 aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
1274 aC1->D0(aT1, aP);
1275 BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
1276 gp_Dir aDT1(aV1);
1277 //
1278 theContext->ProjectPointOnEdge(aP, aEF2, aT2);
1279 //
1280 BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
1281 gp_Dir aDT2(aV2);
1282 //
1283 aScPr=aDT1*aDT2;
1284 bRet=(aScPr<0.);
1285 //
1286 return bRet;
1287}
1288
1289//=======================================================================
1290//function : IsHole
1291//purpose :
1292//=======================================================================
bb58e462 1293Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1294 const TopoDS_Shape& aFace)
4e57c75e 1295{
1296 Standard_Boolean bIsHole;
1297 Standard_Integer i, aNbS;
1298 Standard_Real aT1, aT2, aS;
96a95605 1299 Standard_Real aU1, aU, dU;
4e57c75e 1300 Standard_Real aX1, aY1, aX0, aY0;
1301 TopAbs_Orientation aOr;
1302
1303 gp_Pnt2d aP2D0, aP2D1;
1304 Handle(Geom2d_Curve) aC2D;
1305 TopoDS_Face aF, aFF;
1306 TopoDS_Iterator aItW;
1307 //
1308 bIsHole=Standard_False;
1309 //
1310 aF=(*(TopoDS_Face *)(&aFace));
1311 aFF=aF;
1312 aFF.Orientation(TopAbs_FORWARD);
1313 //
1314 aS=0.;
1315 aItW.Initialize(aW);
1316 for (; aItW.More(); aItW.Next()) {
1317 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1318 aOr=aE.Orientation();
1319 if (!(aOr==TopAbs_FORWARD ||
1320 aOr==TopAbs_REVERSED)) {
1321 continue;
1322 }
1323 //
1324 aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1325 if (aC2D.IsNull()) {
1326 break; //xx
1327 }
1328 //
1329 BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1330 aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1331 if (aNbS>2) {
1332 aNbS*=4;
1333 }
1334 //
1335 dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1336 aU =aT1;
1337 aU1=aT1;
4e57c75e 1338 if (aOr==TopAbs_REVERSED) {
1339 aU =aT2;
1340 aU1=aT2;
4e57c75e 1341 dU=-dU;
1342 }
1343 //
94f71cad 1344 aBAC2D.D0(aU, aP2D0);
4e57c75e 1345 for(i=2; i<=aNbS; i++) {
1346 aU=aU1+(i-1)*dU;
94f71cad 1347 aBAC2D.D0(aU, aP2D1);
4e57c75e 1348 aP2D0.Coord(aX0, aY0);
1349 aP2D1.Coord(aX1, aY1);
1350 //
1351 aS=aS+(aY0+aY1)*(aX1-aX0);
1352 //
1353 aP2D0=aP2D1;
1354 }
1355 }//for (; aItW.More(); aItW.Next()) {
1356 bIsHole=(aS>0.);
1357 return bIsHole;
1358}
1359
1360//=======================================================================
1361// function: MakeContainer
1362// purpose:
1363//=======================================================================
bb58e462 1364void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1365 TopoDS_Shape& theC)
4e57c75e 1366{
1367 BRep_Builder aBB;
1368 //
1369 switch(theType) {
1370 case TopAbs_COMPOUND:{
1371 TopoDS_Compound aC;
1372 aBB.MakeCompound(aC);
1373 theC=aC;
1374 }
1375 break;
1376 //
1377 case TopAbs_COMPSOLID:{
1378 TopoDS_CompSolid aCS;
1379 aBB.MakeCompSolid(aCS);
1380 theC=aCS;
1381 }
1382 break;
1383 //
1384 case TopAbs_SOLID:{
1385 TopoDS_Solid aSolid;
1386 aBB.MakeSolid(aSolid);
1387 theC=aSolid;
1388 }
1389 break;
1390 //
1391 //
1392 case TopAbs_SHELL:{
1393 TopoDS_Shell aShell;
1394 aBB.MakeShell(aShell);
1395 theC=aShell;
1396 }
1397 break;
1398 //
1399 case TopAbs_WIRE: {
1400 TopoDS_Wire aWire;
1401 aBB.MakeWire(aWire);
1402 theC=aWire;
1403 }
1404 break;
1405 //
1406 default:
1407 break;
1408 }
1409}
1410//=======================================================================
1411// function: MakePCurve
1412// purpose:
1413//=======================================================================
bb58e462 1414void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1415 const TopoDS_Face& aF1,
1416 const TopoDS_Face& aF2,
1417 const IntTools_Curve& aIC,
1418 const Standard_Boolean bPC1,
51db0179 1419 const Standard_Boolean bPC2,
1420 const Handle(IntTools_Context)& theContext)
4e57c75e 1421
1422{
1423 Standard_Integer i;
1424 Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1425 Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1426 TopoDS_Face aFFWD;
1427 BRep_Builder aBB;
1428 Standard_Boolean bPC;
1429 //
1430 aTolE=BRep_Tool::Tolerance(aE);
1431 //
1432 const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
505abfb8 1433 Handle(Geom_TrimmedCurve)aC3DETrim=
1434 new Geom_TrimmedCurve(aC3DE, aT1, aT2);
4e57c75e 1435 //
1436 for (i=0; i<2; ++i) {
1437 bPC = !i ? bPC1 : bPC2;
1438 if (!bPC) {
1439 continue;
1440 }
1441 //
1442 if (!i) {
1443 aFFWD=aF1;
1444 aC2Dx1=aIC.FirstCurve2d();
1445 }
1446 else {
1447 aFFWD=aF2;
1448 aC2Dx1=aIC.SecondCurve2d();
1449 }
1450 //
1451 aFFWD.Orientation(TopAbs_FORWARD);
1452 //
1453 aC2D=aC2Dx1;
1454 if (aC2D.IsNull()) {
51db0179 1455 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD, theContext);
4e57c75e 1456 BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D,
1457 aOutFirst, aOutLast,
51db0179 1458 aOutTol, theContext);
4e57c75e 1459 }
1460 //
1461 if (aC3DE->IsPeriodic()) {
505abfb8 1462 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2, aC2D,
51db0179 1463 aC2DA, theContext);
4e57c75e 1464 }
1465 else {
505abfb8 1466 BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D,
51db0179 1467 aC2DA, theContext);
4e57c75e 1468 }
1469 //
1470 aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1471 //BRepLib::SameParameter(aE);
1472 }
1473 BRepLib::SameParameter(aE);
1474}
1475//=======================================================================
1476// function: MakeEdge
1477// purpose:
1478//=======================================================================
bb58e462 1479void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1480 const TopoDS_Vertex& theV1,
1481 const Standard_Real theT1,
1482 const TopoDS_Vertex& theV2,
1483 const Standard_Real theT2,
1484 const Standard_Real theTolR3D,
1485 TopoDS_Edge& theE)
4e57c75e 1486{
4e57c75e 1487 BRep_Builder aBB;
0d0481c7 1488 Standard_Real aNeedTol = theTolR3D + 1e-12;
1489 //
1490 aBB.UpdateVertex(theV1, aNeedTol);
1491 aBB.UpdateVertex(theV2, aNeedTol);
4e57c75e 1492 //
505abfb8 1493 BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2,
1494 theE);
4e57c75e 1495 //
1496 aBB.UpdateEdge(theE, theTolR3D);
4e57c75e 1497}
1498//=======================================================================
1499// function: ComputeVV
1500// purpose:
1501//=======================================================================
bb58e462 1502Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
1503 const gp_Pnt& aP2,
1504 const Standard_Real aTolP2)
4e57c75e 1505{
1506 Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1507 gp_Pnt aP1;
1508 //
1509 aTolV1=BRep_Tool::Tolerance(aV1);
1510
3510db62 1511 aTolSum = aTolV1 + aTolP2 + Precision::Confusion();
4e57c75e 1512 aTolSum2=aTolSum*aTolSum;
1513 //
1514 aP1=BRep_Tool::Pnt(aV1);
1515 //
1516 aD2=aP1.SquareDistance(aP2);
1517 if (aD2>aTolSum2) {
1518 return 1;
1519 }
1520 return 0;
1521}
1522//=======================================================================
1523// function: ComputeVV
1524// purpose:
1525//=======================================================================
bb58e462 1526Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1,
0d0481c7 1527 const TopoDS_Vertex& aV2,
1528 const Standard_Real aFuzz)
4e57c75e 1529{
1530 Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1531 gp_Pnt aP1, aP2;
0d0481c7 1532 Standard_Real aFuzz1 = (aFuzz > Precision::Confusion() ? aFuzz : Precision::Confusion());
4e57c75e 1533 //
1534 aTolV1=BRep_Tool::Tolerance(aV1);
1535 aTolV2=BRep_Tool::Tolerance(aV2);
0d0481c7 1536 aTolSum=aTolV1+aTolV2+aFuzz1;
4e57c75e 1537 aTolSum2=aTolSum*aTolSum;
1538 //
1539 aP1=BRep_Tool::Pnt(aV1);
1540 aP2=BRep_Tool::Pnt(aV2);
1541 //
1542 aD2=aP1.SquareDistance(aP2);
1543 if (aD2>aTolSum2) {
1544 return 1;
1545 }
1546 return 0;
1547}
1548//=======================================================================
1549// function: MakeVertex
1550// purpose :
1551//=======================================================================
3510db62 1552void BOPTools_AlgoTools::MakeVertex(const BOPCol_ListOfShape& aLV,
bb58e462 1553 TopoDS_Vertex& aVnew)
4e57c75e 1554{
07ef8bdf 1555 Standard_Integer aNb = aLV.Extent();
1556 if (aNb == 1)
138ac530 1557 aVnew=*((TopoDS_Vertex*)(&aLV.First()));
07ef8bdf 1558 else if (aNb > 1)
1559 {
1560 Standard_Real aNTol;
1561 gp_Pnt aNC;
1562 BRepLib::BoundingVertex(aLV, aNC, aNTol);
4e57c75e 1563 BRep_Builder aBB;
07ef8bdf 1564 aBB.MakeVertex(aVnew, aNC, aNTol);
4e57c75e 1565 }
1566}
1567//=======================================================================
1568//function : GetEdgeOnFace
1569//purpose :
1570//=======================================================================
505abfb8 1571Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace
1572(const TopoDS_Edge& theE1,
1573 const TopoDS_Face& theF2,
1574 TopoDS_Edge& theE2)
4e57c75e 1575{
1576 Standard_Boolean bFound;
1577 TopoDS_Iterator aItF, aItW;
1578 //
1579 bFound=Standard_False;
1580 //
1581 aItF.Initialize(theF2);
1582 for (; aItF.More(); aItF.Next()) {
1583 const TopoDS_Shape& aW=aItF.Value();
1584 aItW.Initialize(aW);
1585 for (; aItW.More(); aItW.Next()) {
1586 const TopoDS_Shape& aE=aItW.Value();
1587 if (aE.IsSame(theE1)) {
1588 theE2=(*(TopoDS_Edge*)(&aE));
1589 bFound=!bFound;
1590 return bFound;
1591 }
1592 }
1593 }
1594 return bFound;
1595}
1596//=======================================================================
1597//function : FindFacePairs
1598//purpose :
1599//=======================================================================
1600Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1601 const BOPCol_ListOfShape& thLF,
1602 BOPTools_ListOfCoupleOfShape& theLCFF,
1e143abb 1603 Handle(IntTools_Context)& theContext)
4e57c75e 1604{
1605 Standard_Boolean bFound;
1606 Standard_Integer i, aNbCEF;
1d47d8d0 1607 TopAbs_Orientation aOr, aOrC = TopAbs_FORWARD;
4e57c75e 1608 BOPCol_MapOfShape aMFP;
1609 TopoDS_Face aF1, aF2;
1610 TopoDS_Edge aEL, aE1;
1611 BOPCol_ListIteratorOfListOfShape aItLF;
1612 BOPTools_CoupleOfShape aCEF, aCFF;
1613 BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1614 BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1615 //
1616 bFound=Standard_True;
1617 //
1618 // Preface aLCEF
1619 aItLF.Initialize(thLF);
1620 for (; aItLF.More(); aItLF.Next()) {
1621 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1622 //
1623 bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1624 if (!bFound) {
1625 return bFound; // it can not be so
1626 }
1627 //
1628 aCEF.SetShape1(aEL);
1629 aCEF.SetShape2(aFL);
1630 aLCEF.Append(aCEF);
1631 }
1632 //
1633 aNbCEF=aLCEF.Extent();
1634 while(aNbCEF) {
1635 //
1636 // aLCEFx
1637 aLCEFx.Clear();
1638 aIt.Initialize(aLCEF);
1639 for (i=0; aIt.More(); aIt.Next(), ++i) {
1640 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1641 const TopoDS_Shape& aEx=aCSx.Shape1();
1642 const TopoDS_Shape& aFx=aCSx.Shape2();
1643 //
1644 aOr=aEx.Orientation();
1645 //
1646 if (!i) {
1647 aOrC=TopAbs::Reverse(aOr);
1648 aE1=(*(TopoDS_Edge*)(&aEx));
1649 aF1=(*(TopoDS_Face*)(&aFx));
1650 aMFP.Add(aFx);
1651 continue;
1652 }
1653 //
1654 if (aOr==aOrC) {
1655 aLCEFx.Append(aCSx);
1656 aMFP.Add(aFx);
1657 }
1658 }
1659 //
1660 // F2
1661 BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1662 //
1663 aCFF.SetShape1(aF1);
1664 aCFF.SetShape2(aF2);
1665 theLCFF.Append(aCFF);
1666 //
1667 aMFP.Add(aF1);
1668 aMFP.Add(aF2);
1669 //
1670 // refine aLCEF
1671 aLCEFx.Clear();
1672 aLCEFx=aLCEF;
1673 aLCEF.Clear();
1674 aIt.Initialize(aLCEFx);
1675 for (; aIt.More(); aIt.Next()) {
1676 const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1677 const TopoDS_Shape& aFx=aCSx.Shape2();
1678 if (!aMFP.Contains(aFx)) {
1679 aLCEF.Append(aCSx);
1680 }
1681 }
1682 //
1683 aNbCEF=aLCEF.Extent();
1684 }//while(aNbCEF) {
1685 //
1686 return bFound;
1687}
1688//=======================================================================
1689//function : AngleWithRef
1690//purpose :
1691//=======================================================================
1692Standard_Real AngleWithRef(const gp_Dir& theD1,
1693 const gp_Dir& theD2,
1694 const gp_Dir& theDRef)
1695{
1696 Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1697 gp_XYZ aXYZ;
1698 //
1699 aHalfPI=0.5*M_PI;
1700 //
1701 const gp_XYZ& aXYZ1=theD1.XYZ();
1702 const gp_XYZ& aXYZ2=theD2.XYZ();
1703 aXYZ=aXYZ1.Crossed(aXYZ2);
1704 aSinus=aXYZ.Modulus();
1705 aCosinus=theD1*theD2;
1706 //
1707 aBeta=0.;
1708 if (aSinus>=0.) {
1709 aBeta=aHalfPI*(1.-aCosinus);
1710 }
1711 else {
1712 aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1713 }
1714 //
1715 aScPr=aXYZ.Dot(theDRef.XYZ());
1716 if (aScPr<0.) {
1717 aBeta=-aBeta;
1718 }
1719 return aBeta;
1720}
1721//=======================================================================
4e57c75e 1722// function: IsBlockInOnFace
1723// purpose:
1724//=======================================================================
505abfb8 1725Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace
1726 (const IntTools_Range& aShrR,
1727 const TopoDS_Face& aF,
1728 const TopoDS_Edge& aE1,
1e143abb 1729 Handle(IntTools_Context)& aContext)
4e57c75e 1730{
1731 Standard_Boolean bFlag;
1732 Standard_Real f1, l1, ULD, VLD;
1733 gp_Pnt2d aP2D;
1734 gp_Pnt aP11, aP12;
1735 //
1736 aShrR.Range(f1, l1);
1737 Standard_Real dt=0.0075, k;//dt=0.001, k;
1738 k=dt*(l1-f1);
1739 f1=f1+k;
1740 l1=l1-k;
1741 //
1742 // Treatment P11
1743 BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1744 //
1745 GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1746 aProjector.Perform(aP11);
1747 //
1748 bFlag=aProjector.IsDone();
1749 if (!bFlag) {
1750 return bFlag;
1751 }
1752
1753 aProjector.LowerDistanceParameters(ULD, VLD);
1754 aP2D.SetCoord(ULD, VLD);
1755 //
1756 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1757 //
1758 if (!bFlag) {
1759 return bFlag;
1760 }
1761 //
1762 // Treatment P12
1763 BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1764 //
1765 aProjector.Perform(aP12);
1766 //
1767 bFlag=aProjector.IsDone();
1768 if (!bFlag) {
1769 return bFlag;
1770 }
1771
1772 aProjector.LowerDistanceParameters(ULD, VLD);
1773 aP2D.SetCoord(ULD, VLD);
1774 //
1775 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1776 //
1777 if (!bFlag) {
1778 return bFlag;
1779 }
1780 //
1781 // Treatment intemediate
1782 Standard_Real m1, aTolF, aTolE, aTol, aDist;
1783 m1=IntTools_Tools::IntermediatePoint(f1, l1);
1784 BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1785 //
1786 aProjector.Perform(aP12);
1787 //
1788 bFlag=aProjector.IsDone();
1789 if (!bFlag) {
1790 return bFlag;
1791 }
1792 //
1793 aTolE=BRep_Tool::Tolerance(aE1);
1794 aTolF=BRep_Tool::Tolerance(aF);
1795 aTol=aTolE+aTolF;
1796 aDist=aProjector.LowerDistance();
1797 if (aDist > aTol){
1798 return Standard_False;
1799 }
1800
1801 aProjector.LowerDistanceParameters(ULD, VLD);
1802 aP2D.SetCoord(ULD, VLD);
1803 //
1804 bFlag=aContext->IsPointInOnFace (aF, aP2D);
1805 //
1806 if (!bFlag) {
1807 return bFlag;
1808 }
1809 return bFlag;
1810}
1811
1812//=======================================================================
4e57c75e 1813//function : IsMicroEdge
1814//purpose :
1815//=======================================================================
505abfb8 1816Standard_Boolean BOPTools_AlgoTools::IsMicroEdge
1817 (const TopoDS_Edge& aE,
01b5b3df 1818 const Handle(IntTools_Context)& aCtx,
1819 const Standard_Boolean bCheckSplittable)
4e57c75e 1820{
1821 Standard_Boolean bRet;
4e57c75e 1822 Standard_Real aT1, aT2, aTmp;
1823 Handle(Geom_Curve) aC3D;
1824 TopoDS_Vertex aV1, aV2;
1825 //
1826 bRet=(BRep_Tool::Degenerated(aE) ||
1827 !BRep_Tool::IsGeometric(aE));
1828 if (bRet) {
1829 return bRet;
1830 }
1831 //
1832 aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1833 TopExp::Vertices(aE, aV1, aV2);
1834 aT1=BRep_Tool::Parameter(aV1, aE);
1835 aT2=BRep_Tool::Parameter(aV2, aE);
1836 if (aT2<aT1) {
1837 aTmp=aT1;
1838 aT1=aT2;
1839 aT2=aTmp;
1840 }
1841 //
1e143abb 1842 IntTools_ShrunkRange aSR;
505abfb8 1843 aSR.SetContext(aCtx);
1844 aSR.SetData(aE, aT1, aT2, aV1, aV2);
4e57c75e 1845 aSR.Perform();
01b5b3df 1846 bRet = !aSR.IsDone();
1847 if (!bRet && bCheckSplittable) {
1848 bRet = !aSR.IsSplittable();
1849 }
4e57c75e 1850 //
1851 return bRet;
1852}
1853
4e57c75e 1854//=======================================================================
df017cc9 1855//function : GetFaceDir
1856//purpose : Get binormal direction for the face in the point aP
1857//=======================================================================
18c06690 1858Standard_Boolean GetFaceDir(const TopoDS_Edge& aE,
1859 const TopoDS_Face& aF,
1860 const gp_Pnt& aP,
1861 const Standard_Real aT,
1862 const gp_Dir& aDTgt,
1863 const Standard_Boolean theSmallFaces,
1864 gp_Dir& aDN,
1865 gp_Dir& aDB,
1866 Handle(IntTools_Context)& theContext,
1867 GeomAPI_ProjectPointOnSurf& aProjPL,
1868 const Standard_Real aDt)
df017cc9 1869{
393598eb 1870 Standard_Real aTolE;
1871 gp_Pnt aPx;
1872 //
51db0179 1873 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN, theContext);
df017cc9 1874 if (aF.Orientation()==TopAbs_REVERSED){
1875 aDN.Reverse();
1876 }
393598eb 1877 //
18c06690 1878 aTolE=BRep_Tool::Tolerance(aE);
df017cc9 1879 aDB = aDN^aDTgt;
1880 //
18c06690 1881 // do not try to look for the point in the small face by intersecting
1882 // it with the circle because, most likely, the intersection point will
1883 // be out of the face
1884 Standard_Boolean bFound = !theSmallFaces &&
1885 FindPointInFace(aF, aP, aDB, aPx, theContext, aProjPL, aDt, aTolE);
1886 if (!bFound) {
1887 // if the first method did not succeed, try to use hatcher to find the point
1888 bFound = BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
1889 (aE, aF, aT, aDt, aPx, aDN, theContext);
bb58e462 1890 aProjPL.Perform(aPx);
1891 aPx = aProjPL.NearestPoint();
1892 gp_Vec aVec(aP, aPx);
1893 aDB.SetXYZ(aVec.XYZ());
4e57c75e 1894 }
18c06690 1895 //
1896 return bFound;
df017cc9 1897}
df017cc9 1898//=======================================================================
1899//function : FindPointInFace
18c06690 1900//purpose : Find a point in the face in direction of <aDB>.
1901// To get this point the method intersects the circle with radius
1902// <aDt> built in point <aP> with normal perpendicular to <aDB>.
df017cc9 1903//=======================================================================
f56518cd 1904Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
bb58e462 1905 const gp_Pnt& aP,
1906 gp_Dir& aDB,
1907 gp_Pnt& aPOut,
1e143abb 1908 Handle(IntTools_Context)& theContext,
f56518cd 1909 GeomAPI_ProjectPointOnSurf& aProjPL,
393598eb 1910 const Standard_Real aDt,
1911 const Standard_Real aTolE)
df017cc9 1912{
1913 Standard_Integer aNbItMax;
b9f6147d 1914 Standard_Real aDist, aDTol, aPM, anEps;
df017cc9 1915 Standard_Boolean bRet;
393598eb 1916 gp_Pnt aP1, aPS;
4e57c75e 1917 //
59495dbe 1918 aDTol = Precision::Angular();
1919 aPM = aP.XYZ().Modulus();
1920 if (aPM > 1000.) {
1921 aDTol = 5.e-16 * aPM;
1922 }
df017cc9 1923 bRet = Standard_False;
f56518cd 1924 aNbItMax = 15;
b9f6147d 1925 anEps = Precision::SquareConfusion();
4e57c75e 1926 //
df017cc9 1927 GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
4e57c75e 1928 //
393598eb 1929 aPS=aP;
1930 aProj.Perform(aPS);
1931 if (!aProj.IsDone()) {
1932 return bRet;
1933 }
1934 aPS=aProj.NearestPoint();
1935 aProjPL.Perform(aPS);
1936 aPS=aProjPL.NearestPoint();
1937 //
1938 aPS.SetXYZ(aPS.XYZ()+2.*aTolE*aDB.XYZ());
b9f6147d 1939 aProj.Perform(aPS);
393598eb 1940 if (!aProj.IsDone()) {
1941 return bRet;
1942 }
1943 aPS=aProj.NearestPoint();
1944 aProjPL.Perform(aPS);
1945 aPS=aProjPL.NearestPoint();
1946 //
df017cc9 1947 do {
393598eb 1948 aP1.SetXYZ(aPS.XYZ()+aDt*aDB.XYZ());
df017cc9 1949 //
1950 aProj.Perform(aP1);
1951 if (!aProj.IsDone()) {
1952 return bRet;
1953 }
1954 aPOut = aProj.NearestPoint();
1955 aDist = aProj.LowerDistance();
1956 //
bb58e462 1957 aProjPL.Perform(aPOut);
1958 aPOut = aProjPL.NearestPoint();
1959 //
393598eb 1960 gp_Vec aV(aPS, aPOut);
b9f6147d 1961 if (aV.SquareMagnitude() < anEps) {
1962 return bRet;
1963 }
df017cc9 1964 aDB.SetXYZ(aV.XYZ());
59495dbe 1965 } while (aDist > aDTol && --aNbItMax);
4e57c75e 1966 //
59495dbe 1967 bRet = aDist < aDTol;
df017cc9 1968 return bRet;
4e57c75e 1969}
30ecd5f8 1970//=======================================================================
f56518cd 1971//function : MinStep3D
1972//purpose :
1973//=======================================================================
1974Standard_Real MinStep3D(const TopoDS_Edge& theE1,
1975 const TopoDS_Face& theF1,
1976 const BOPTools_ListOfCoupleOfShape& theLCS,
18c06690 1977 const gp_Pnt& aP,
1978 Handle(IntTools_Context)& theContext,
1979 Standard_Boolean& theSmallFaces)
f56518cd 1980{
18c06690 1981 Standard_Real aDt, aTolE, aTolF, aDtMax, aDtMin;
f56518cd 1982 //
18c06690 1983 // add the current pair of edge/face for checking as well
1984 BOPTools_CoupleOfShape aCS1;
f56518cd 1985 aCS1.SetShape1(theE1);
1986 aCS1.SetShape2(theF1);
18c06690 1987 //
1988 BOPTools_ListOfCoupleOfShape aLCS = theLCS;
f56518cd 1989 aLCS.Append(aCS1);
1990 //
1991 aTolE = BRep_Tool::Tolerance(theE1);
1992 aDtMax = -1.;
1993 aDtMin = 5.e-6;
1994 //
18c06690 1995 BOPTools_ListIteratorOfListOfCoupleOfShape aIt(aLCS);
f56518cd 1996 for (; aIt.More(); aIt.Next()) {
1997 const BOPTools_CoupleOfShape& aCS = aIt.Value();
1998 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
1999 //
2000 aTolF = BRep_Tool::Tolerance(aF);
2001 aDt = 2*(aTolE + aTolF);
18c06690 2002 if (aDt > aDtMax) {
2003 aDtMax = aDt;
2004 }
f56518cd 2005 //
18c06690 2006 // try to compute the minimal 3D step
2007 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2008 Standard_Real aR = 0.;
f56518cd 2009 GeomAbs_SurfaceType aSType = aBAS.GetType();
b9f6147d 2010 switch (aSType) {
2011 case GeomAbs_Cylinder: {
f56518cd 2012 aR = aBAS.Cylinder().Radius();
b9f6147d 2013 break;
f56518cd 2014 }
b9f6147d 2015 case GeomAbs_Cone: {
f56518cd 2016 gp_Lin aL(aBAS.Cone().Axis());
2017 aR = aL.Distance(aP);
b9f6147d 2018 break;
f56518cd 2019 }
b9f6147d 2020 case GeomAbs_Sphere: {
2021 aDtMin = Max(aDtMin, 5.e-4);
f56518cd 2022 aR = aBAS.Sphere().Radius();
b9f6147d 2023 break;
f56518cd 2024 }
b9f6147d 2025 case GeomAbs_Torus: {
f56518cd 2026 aR = aBAS.Torus().MajorRadius();
b9f6147d 2027 break;
f56518cd 2028 }
b9f6147d 2029 default:
2030 aDtMin = Max(aDtMin, 5.e-4);
2031 break;
f56518cd 2032 }
2033 //
2034 if (aR > 100.) {
b9f6147d 2035 Standard_Real d = 10*Precision::PConfusion();
2036 aDtMin = Max(aDtMin, sqrt(d*d + 2*d*aR));
f56518cd 2037 }
f56518cd 2038 }
2039 //
2040 if (aDtMax < aDtMin) {
2041 aDtMax = aDtMin;
2042 }
2043 //
18c06690 2044 // check if the computed 3D step is too big for any of the faces in the list
2045 aIt.Initialize(aLCS);
2046 for (; aIt.More(); aIt.Next()) {
2047 const BOPTools_CoupleOfShape& aCS = aIt.Value();
2048 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
2049 //
2050 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(aF);
2051 //
2052 Standard_Real aUMin, aUMax, aVMin, aVMax;
2053 theContext->UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
2054 //
2055 Standard_Real aDU = aUMax - aUMin;
2056 if (aDU > 0.) {
2057 Standard_Real aURes = aBAS.UResolution(aDtMax);
2058 if (2*aURes > aDU) {
2059 break;
2060 }
2061 }
2062 //
2063 Standard_Real aDV = aVMax - aVMin;
2064 if (aDV > 0.) {
2065 Standard_Real aVRes = aBAS.VResolution(aDtMax);
2066 if (2*aVRes > aDV) {
2067 break;
2068 }
2069 }
2070 }
2071 //
2072 theSmallFaces = aIt.More();
2073 //
f56518cd 2074 return aDtMax;
2075}
2076//=======================================================================
30ecd5f8 2077//function : IsOpenShell
2078//purpose :
2079//=======================================================================
505abfb8 2080Standard_Boolean BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
30ecd5f8 2081{
2082 Standard_Boolean bRet;
2083 Standard_Integer i, aNbE, aNbF;
2084 TopAbs_Orientation aOrF;
2085 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
2086 BOPCol_ListIteratorOfListOfShape aItLS;
2087 //
2088 bRet=Standard_False;
2089 //
2090 BOPTools::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
2091 //
2092 aNbE=aMEF.Extent();
2093 for (i=1; i<=aNbE; ++i) {
2094 const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
2095 if (BRep_Tool::Degenerated(aE)) {
2096 continue;
2097 }
2098 //
2099 aNbF=0;
2100 const BOPCol_ListOfShape& aLF=aMEF(i);
2101 aItLS.Initialize(aLF);
2102 for (; aItLS.More(); aItLS.Next()) {
2103 const TopoDS_Shape& aF=aItLS.Value();
2104 aOrF=aF.Orientation();
2105 if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
505abfb8 2106 continue;
30ecd5f8 2107 }
2108 ++aNbF;
2109 }
2110 //
2111 if (aNbF==1) {
2112 bRet=!bRet; // True
2113 break;
2114 }
2115 }
2116 //
2117 return bRet;
2118}
2119//=======================================================================
2120//function : IsInvertedSolid
2121//purpose :
2122//=======================================================================
393598eb 2123Standard_Boolean BOPTools_AlgoTools::IsInvertedSolid
2124 (const TopoDS_Solid& aSolid)
30ecd5f8 2125{
2126 Standard_Real aTolS;
2127 TopAbs_State aState;
2128 BRepClass3d_SolidClassifier aSC(aSolid);
2129 //
2130 aTolS=1.e-7;
2131 aSC.PerformInfinitePoint(aTolS);
2132 aState=aSC.State();
2133 return (aState==TopAbs_IN);
2134}