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