4e57c75e |
1 | // Created by: Peter KURNEV |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
4e57c75e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
4e57c75e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
4e57c75e |
14 | |
42cf5bc1 |
15 | |
16 | #include <BOPAlgo_Tools.hxx> |
e6ae74fd |
17 | |
18 | #include <gp_Pnt.hxx> |
19 | #include <gp_Vec.hxx> |
20 | #include <gp_Dir.hxx> |
21 | #include <gp_Pln.hxx> |
22 | #include <gp_Circ.hxx> |
23 | #include <gp_Elips.hxx> |
24 | #include <gp_Hypr.hxx> |
25 | #include <gp_Parab.hxx> |
26 | |
27 | #include <Standard_ErrorHandler.hxx> |
28 | #include <Standard_Failure.hxx> |
29 | |
30 | #include <TopoDS.hxx> |
31 | #include <TopoDS_Edge.hxx> |
32 | |
33 | #include <BOPCol_MapOfShape.hxx> |
34 | #include <BOPCol_IndexedMapOfShape.hxx> |
42cf5bc1 |
35 | #include <BOPCol_IndexedMapOfInteger.hxx> |
e6ae74fd |
36 | #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx> |
37 | |
38 | #include <TopExp_Explorer.hxx> |
39 | |
40 | #include <BRepAdaptor_Curve.hxx> |
41 | |
42 | #include <BRepBuilderAPI_MakeFace.hxx> |
43 | |
44 | #include <BRep_Tool.hxx> |
45 | #include <BRep_Builder.hxx> |
46 | |
47 | #include <GeomAPI_ProjectPointOnCurve.hxx> |
48 | #include <GeomAPI_ProjectPointOnSurf.hxx> |
49 | |
50 | #include <BOPAlgo_Builder.hxx> |
51 | #include <BOPAlgo_BuilderFace.hxx> |
52 | |
4e57c75e |
53 | #include <BOPDS_CommonBlock.hxx> |
54 | #include <BOPDS_DataMapOfPaveBlockListOfPaveBlock.hxx> |
42cf5bc1 |
55 | #include <BOPDS_DS.hxx> |
56 | #include <BOPDS_IndexedMapOfPaveBlock.hxx> |
57 | #include <BOPDS_MapOfPaveBlock.hxx> |
58 | #include <BOPDS_PaveBlock.hxx> |
e6ae74fd |
59 | |
60 | #include <BOPTools.hxx> |
61 | #include <BOPTools_AlgoTools.hxx> |
62 | #include <BOPTools_AlgoTools2D.hxx> |
63 | |
3510db62 |
64 | #include <IntTools_Context.hxx> |
e6ae74fd |
65 | |
66 | typedef NCollection_IndexedDataMap |
67 | <TopoDS_Shape, gp_Dir, TopTools_ShapeMapHasher> BOPAlgo_IndexedDataMapOfShapeDir; |
68 | typedef NCollection_IndexedDataMap |
69 | <TopoDS_Shape, gp_Pln, TopTools_ShapeMapHasher> BOPAlgo_IndexedDataMapOfShapePln; |
70 | |
71 | static |
72 | void MakeWires(const BOPCol_IndexedMapOfShape& theEdges, |
73 | TopoDS_Compound& theWires, |
74 | const Standard_Boolean theCheckUniquePlane, |
75 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
76 | BOPCol_MapOfShape& theMEdgesNoUniquePlane); |
77 | |
78 | static |
79 | Standard_Boolean FindPlane(const BRepAdaptor_Curve& theCurve, |
80 | gp_Pln& thePlane); |
81 | |
82 | static |
83 | Standard_Boolean FindPlane(const TopoDS_Shape& theWire, |
84 | gp_Pln& thePlane, |
85 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
86 | BOPCol_MapOfShape& theMEdgesNoUniquePlane); |
87 | |
88 | static |
89 | Standard_Boolean FindEdgeTangent(const TopoDS_Edge& theEdge, |
90 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
91 | gp_Dir& theTgt); |
92 | |
93 | static |
94 | Standard_Boolean FindEdgeTangent(const BRepAdaptor_Curve& theCurve, |
95 | gp_Vec& theTangent); |
4e57c75e |
96 | |
97 | //======================================================================= |
98 | //function : MakeBlocksCnx |
99 | //purpose : |
100 | //======================================================================= |
3510db62 |
101 | void BOPAlgo_Tools::MakeBlocksCnx(const BOPCol_IndexedDataMapOfIntegerListOfInteger& aMILI, |
102 | BOPCol_DataMapOfIntegerListOfInteger& aMBlocks, |
103 | const Handle(NCollection_BaseAllocator)& aAllocator) |
4e57c75e |
104 | { |
105 | Standard_Integer aNbV, nV, aNbVS, nVP, nVx, aNbVP, aNbEC, k, i, j; |
106 | BOPCol_ListIteratorOfListOfInteger aItLI; |
107 | // |
108 | BOPCol_MapOfInteger aMVS(100, aAllocator); |
109 | BOPCol_IndexedMapOfInteger aMEC(100, aAllocator); |
110 | BOPCol_IndexedMapOfInteger aMVP(100, aAllocator); |
111 | BOPCol_IndexedMapOfInteger aMVAdd(100, aAllocator); |
112 | // |
113 | aNbV=aMILI.Extent(); |
114 | // |
115 | for (k=0,i=1; i<=aNbV; ++i) { |
116 | aNbVS=aMVS.Extent(); |
117 | if (aNbVS==aNbV) { |
118 | break; |
119 | } |
120 | // |
121 | nV = aMILI.FindKey(i); |
122 | if (aMVS.Contains(nV)){ |
123 | continue; |
124 | } |
125 | aMVS.Add(nV); |
126 | // |
127 | aMEC.Clear(); |
128 | aMVP.Clear(); |
129 | aMVAdd.Clear(); |
130 | // |
131 | aMVP.Add(nV); |
302f96fb |
132 | for(;;) { |
4e57c75e |
133 | aNbVP=aMVP.Extent(); |
134 | for (j=1; j<=aNbVP; ++j) { |
135 | nVP=aMVP(j); |
136 | const BOPCol_ListOfInteger& aLV=aMILI.FindFromKey(nVP); |
137 | aItLI.Initialize(aLV); |
138 | for (; aItLI.More(); aItLI.Next()) { |
139 | nVx=aItLI.Value(); |
140 | if (aMEC.Contains(nVx)) { |
141 | continue; |
142 | } |
143 | // |
144 | aMVS.Add(nVx); |
145 | aMEC.Add(nVx); |
146 | aMVAdd.Add(nVx); |
147 | } |
148 | } |
149 | // |
150 | aNbVP=aMVAdd.Extent(); |
151 | if (!aNbVP) { |
152 | break; // from while(1) |
153 | } |
154 | // |
155 | aMVP.Clear(); |
156 | for (j=1; j<=aNbVP; ++j) { |
157 | aMVP.Add(aMVAdd(j)); |
158 | } |
159 | aMVAdd.Clear(); |
160 | }//while(1) { |
161 | // |
162 | BOPCol_ListOfInteger aLIx(aAllocator); |
163 | // |
164 | aNbEC = aMEC.Extent(); |
165 | for (j=1; j<=aNbEC; ++j) { |
166 | nVx=aMEC(j); |
167 | aLIx.Append(nVx); |
168 | } |
169 | // |
170 | aMBlocks.Bind(k, aLIx); |
171 | ++k; |
172 | }//for (k=0,i=1; i<=aNbV; ++i) |
173 | aMVAdd.Clear(); |
174 | aMVP.Clear(); |
175 | aMEC.Clear(); |
176 | aMVS.Clear(); |
177 | } |
178 | //======================================================================= |
179 | //function : FillMap |
180 | //purpose : |
181 | //======================================================================= |
3510db62 |
182 | void BOPAlgo_Tools::FillMap(const Standard_Integer n1, |
183 | const Standard_Integer n2, |
184 | BOPCol_IndexedDataMapOfIntegerListOfInteger& aMILI, |
185 | const Handle(NCollection_BaseAllocator)& aAllocator) |
4e57c75e |
186 | { |
187 | if (aMILI.Contains(n1)) { |
188 | BOPCol_ListOfInteger& aLI=aMILI.ChangeFromKey(n1); |
189 | aLI.Append(n2); |
190 | } |
191 | else { |
192 | BOPCol_ListOfInteger aLI(aAllocator); |
193 | aLI.Append(n2); |
194 | aMILI.Add(n1, aLI); |
195 | } |
196 | if (aMILI.Contains(n2)) { |
197 | BOPCol_ListOfInteger& aLI=aMILI.ChangeFromKey(n2); |
198 | aLI.Append(n1); |
199 | } |
200 | else { |
201 | BOPCol_ListOfInteger aLI(aAllocator); |
202 | aLI.Append(n1); |
203 | aMILI.Add(n2, aLI); |
204 | } |
205 | } |
206 | //======================================================================= |
207 | //function : FillMap |
208 | //purpose : |
209 | //======================================================================= |
3510db62 |
210 | void BOPAlgo_Tools::FillMap(const Handle(BOPDS_PaveBlock)& aPB1, |
211 | const Handle(BOPDS_PaveBlock)& aPB2, |
212 | BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& aMPBLPB, |
213 | const Handle(NCollection_BaseAllocator)& aAllocator) |
4e57c75e |
214 | { |
215 | if (aMPBLPB.Contains(aPB1)) { |
216 | BOPDS_ListOfPaveBlock& aLPB=aMPBLPB.ChangeFromKey(aPB1); |
217 | aLPB.Append(aPB2); |
218 | } |
219 | else { |
220 | BOPDS_ListOfPaveBlock aLPB(aAllocator); |
221 | aLPB.Append(aPB2); |
222 | aMPBLPB.Add(aPB1, aLPB); |
223 | } |
224 | if (aMPBLPB.Contains(aPB2)) { |
225 | BOPDS_ListOfPaveBlock& aLPB=aMPBLPB.ChangeFromKey(aPB2); |
226 | aLPB.Append(aPB1); |
227 | } |
228 | else { |
229 | BOPDS_ListOfPaveBlock aLPB(aAllocator); |
230 | aLPB.Append(aPB1); |
231 | aMPBLPB.Add(aPB2, aLPB); |
232 | } |
233 | } |
234 | //======================================================================= |
235 | //function : FillMap |
236 | //purpose : |
237 | //======================================================================= |
3510db62 |
238 | void BOPAlgo_Tools::FillMap(const Handle(BOPDS_PaveBlock)& aPB, |
239 | const Standard_Integer nF, |
240 | BOPDS_IndexedDataMapOfPaveBlockListOfInteger& aMPBLI, |
241 | const Handle(NCollection_BaseAllocator)& aAllocator) |
4e57c75e |
242 | { |
243 | if (aMPBLI.Contains(aPB)) { |
244 | BOPCol_ListOfInteger& aLI=aMPBLI.ChangeFromKey(aPB); |
245 | aLI.Append(nF); |
246 | } |
247 | else { |
248 | BOPCol_ListOfInteger aLI(aAllocator); |
249 | aLI.Append(nF); |
250 | aMPBLI.Add(aPB, aLI); |
251 | } |
252 | } |
253 | //======================================================================= |
254 | //function : MakeBlocks |
255 | //purpose : |
256 | //======================================================================= |
3510db62 |
257 | void BOPAlgo_Tools::MakeBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& aMILI, |
258 | BOPDS_DataMapOfIntegerListOfPaveBlock& aMBlocks, |
259 | const Handle(NCollection_BaseAllocator)& aAllocator) |
4e57c75e |
260 | { |
261 | Standard_Integer aNbV, aNbVS, aNbVP, aNbEC, k, i, j; |
262 | BOPDS_ListIteratorOfListOfPaveBlock aItLI; |
263 | // |
264 | BOPDS_MapOfPaveBlock aMVS(100, aAllocator); |
265 | BOPDS_IndexedMapOfPaveBlock aMEC(100, aAllocator); |
266 | BOPDS_IndexedMapOfPaveBlock aMVP(100, aAllocator); |
267 | BOPDS_IndexedMapOfPaveBlock aMVAdd(100, aAllocator); |
268 | // |
269 | aNbV=aMILI.Extent(); |
270 | // |
271 | for (k=0, i=1; i<=aNbV; ++i) { |
272 | aNbVS=aMVS.Extent(); |
273 | if (aNbVS==aNbV) { |
274 | break; |
275 | } |
276 | // |
277 | const Handle(BOPDS_PaveBlock)& nV=aMILI.FindKey(i); |
278 | if (aMVS.Contains(nV)){ |
279 | continue; |
280 | } |
281 | aMVS.Add(nV); |
282 | // |
283 | aMEC.Clear(); |
284 | aMVP.Clear(); |
285 | aMVAdd.Clear(); |
286 | // |
287 | aMVP.Add(nV); |
302f96fb |
288 | for(;;) { |
4e57c75e |
289 | aNbVP=aMVP.Extent(); |
290 | for (j=1; j<=aNbVP; ++j) { |
291 | const Handle(BOPDS_PaveBlock)& nVP=aMVP(j); |
292 | const BOPDS_ListOfPaveBlock& aLV=aMILI.FindFromKey(nVP); |
293 | aItLI.Initialize(aLV); |
294 | for (; aItLI.More(); aItLI.Next()) { |
295 | const Handle(BOPDS_PaveBlock)& nVx=aItLI.Value(); |
296 | if (aMEC.Contains(nVx)) { |
297 | continue; |
298 | } |
299 | // |
300 | aMVS.Add(nVx); |
301 | aMEC.Add(nVx); |
302 | aMVAdd.Add(nVx); |
303 | } |
304 | } |
305 | // |
306 | aNbVP=aMVAdd.Extent(); |
307 | if (!aNbVP) { |
308 | break; // from while(1) |
309 | } |
310 | // |
311 | aMVP.Clear(); |
312 | for (j=1; j<=aNbVP; ++j) { |
313 | aMVP.Add(aMVAdd(j)); |
314 | } |
315 | aMVAdd.Clear(); |
316 | }//while(1) { |
317 | // |
318 | BOPDS_ListOfPaveBlock aLIx(aAllocator); |
319 | // |
320 | aNbEC = aMEC.Extent(); |
321 | for (j=1; j<=aNbEC; ++j) { |
322 | const Handle(BOPDS_PaveBlock)& nVx=aMEC(j); |
323 | aLIx.Append(nVx); |
324 | } |
325 | // |
326 | aMBlocks.Bind(k, aLIx); |
327 | ++k; |
328 | }//for (k=0, i=1; i<=aNbV; ++i) |
329 | aMVAdd.Clear(); |
330 | aMVP.Clear(); |
331 | aMEC.Clear(); |
332 | aMVS.Clear(); |
333 | } |
334 | //======================================================================= |
335 | //function : PerformCommonBlocks |
336 | //purpose : |
337 | //======================================================================= |
3510db62 |
338 | void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& aMPBLPB, |
339 | const Handle(NCollection_BaseAllocator)& aAllocator, |
340 | BOPDS_PDS& pDS) |
4e57c75e |
341 | { |
342 | Standard_Integer aNbCB; |
343 | // |
344 | aNbCB=aMPBLPB.Extent(); |
345 | if (!aNbCB) { |
346 | return; |
347 | } |
348 | // |
349 | Standard_Integer aNbPB, aNbBlocks, k; |
350 | BOPDS_ListIteratorOfListOfPaveBlock aItLPB; |
351 | Handle(BOPDS_CommonBlock) aCB; |
352 | BOPDS_DataMapOfIntegerListOfPaveBlock aMBlocks(100, aAllocator); |
353 | // |
354 | BOPAlgo_Tools::MakeBlocks(aMPBLPB, aMBlocks, aAllocator); |
355 | // |
356 | aNbBlocks = aMBlocks.Extent(); |
357 | for (k=0; k<aNbBlocks; ++k) { |
358 | const BOPDS_ListOfPaveBlock& aLPB=aMBlocks.Find(k); |
359 | aNbPB=aLPB.Extent(); |
360 | if (aNbPB>1) { |
361 | aCB=new BOPDS_CommonBlock; |
362 | // |
363 | aItLPB.Initialize(aLPB); |
364 | for (; aItLPB.More(); aItLPB.Next()) { |
365 | const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value(); |
366 | aCB->AddPaveBlock(aPBx); |
367 | } |
368 | // |
369 | aItLPB.Initialize(aLPB); |
370 | for (; aItLPB.More(); aItLPB.Next()) { |
371 | const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value(); |
5a77460e |
372 | pDS->SetCommonBlock(aPBx, aCB); |
4e57c75e |
373 | } |
374 | }//if (aNbPB>1) { |
375 | } |
376 | } |
377 | //======================================================================= |
378 | //function : PerformCommonBlocks |
379 | //purpose : |
380 | //======================================================================= |
3510db62 |
381 | void BOPAlgo_Tools::PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& aMPBLI, |
382 | const Handle(NCollection_BaseAllocator)& ,//aAllocator |
383 | BOPDS_PDS& pDS) |
4e57c75e |
384 | { |
385 | Standard_Integer nF, i, aNb; |
386 | BOPCol_ListIteratorOfListOfInteger aItLI; |
387 | Handle(BOPDS_PaveBlock) aPB; |
388 | Handle(BOPDS_CommonBlock) aCB; |
389 | // |
390 | aNb=aMPBLI.Extent(); |
391 | for (i=1; i<=aNb; ++i) { |
392 | aPB=aMPBLI.FindKey(i); |
5a77460e |
393 | if (pDS->IsCommonBlock(aPB)) { |
394 | aCB=pDS->CommonBlock(aPB); |
4e57c75e |
395 | } |
396 | else { |
397 | aCB=new BOPDS_CommonBlock; |
398 | aCB->AddPaveBlock(aPB); |
399 | } |
400 | // |
401 | const BOPCol_ListOfInteger& aLI=aMPBLI.FindFromKey(aPB); |
3510db62 |
402 | BOPCol_ListOfInteger aNewFaces; |
403 | const BOPCol_ListOfInteger& anOldFaces = aCB->Faces(); |
4e57c75e |
404 | aItLI.Initialize(aLI); |
405 | for (; aItLI.More(); aItLI.Next()) { |
406 | nF=aItLI.Value(); |
3510db62 |
407 | // the both lists aLI and anOldFaces are expected to be short, |
408 | // so we can allow to run nested loop here |
409 | BOPCol_ListIteratorOfListOfInteger it(anOldFaces); |
410 | for (; it.More(); it.Next()) { |
411 | if (it.Value() == nF) |
412 | break; |
413 | } |
414 | if (!it.More()) { |
415 | aNewFaces.Append(nF); |
416 | } |
4e57c75e |
417 | } |
3510db62 |
418 | aCB->AppendFaces(aNewFaces); |
5a77460e |
419 | pDS->SetCommonBlock(aPB, aCB); |
4e57c75e |
420 | } |
421 | } |
3510db62 |
422 | //======================================================================= |
423 | //function : ComputeToleranceOfCB |
424 | //purpose : |
425 | //======================================================================= |
426 | Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB |
427 | (const Handle(BOPDS_CommonBlock)& theCB, |
428 | const BOPDS_PDS theDS, |
429 | const Handle(IntTools_Context)& theContext) |
430 | { |
431 | Standard_Real aTolMax = 0.; |
432 | if (theCB.IsNull()) { |
433 | return aTolMax; |
434 | } |
435 | // |
436 | const Handle(BOPDS_PaveBlock)& aPBR = theCB->PaveBlock1(); |
437 | Standard_Integer nE = aPBR->OriginalEdge(); |
438 | const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&theDS->Shape(nE); |
439 | aTolMax = BRep_Tool::Tolerance(aEOr); |
440 | // |
441 | const BOPDS_ListOfPaveBlock& aLPB = theCB->PaveBlocks(); |
442 | const BOPCol_ListOfInteger& aLFI = theCB->Faces(); |
443 | // |
444 | if ((aLPB.Extent() < 2) && aLFI.IsEmpty()) { |
445 | return aTolMax; |
446 | } |
447 | // |
448 | const Standard_Integer aNbPnt = 11; |
449 | Standard_Real aTol, aT, aT1, aT2, aDt; |
450 | gp_Pnt aP; |
451 | // |
452 | const Handle(Geom_Curve)& aC3D = BRep_Tool::Curve(aEOr, aT1, aT2); |
453 | // |
454 | aPBR->Range(aT1, aT2); |
455 | aDt = (aT2 - aT1) / (aNbPnt + 1); |
456 | // |
457 | // compute max tolerance for common blocks on edges |
458 | if (aLPB.Extent() > 1) { |
459 | // compute max distance between edges |
460 | BOPDS_ListIteratorOfListOfPaveBlock aItPB; |
461 | GeomAPI_ProjectPointOnCurve aProjPC; |
462 | // |
463 | aItPB.Initialize(aLPB); |
464 | for (; aItPB.More(); aItPB.Next()) { |
465 | const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value(); |
466 | if (aPB == aPBR) { |
467 | continue; |
468 | } |
469 | // |
470 | nE = aPB->OriginalEdge(); |
471 | const TopoDS_Edge& aE = *(TopoDS_Edge*)&theDS->Shape(nE); |
472 | aTol = BRep_Tool::Tolerance(aE); |
473 | // |
474 | aProjPC = theContext->ProjPC(aE); |
475 | // |
476 | aT = aT1; |
477 | for (Standard_Integer i=1; i <= aNbPnt; i++) { |
478 | aT += aDt; |
479 | aC3D->D0(aT, aP); |
480 | aProjPC.Perform(aP); |
481 | if (aProjPC.NbPoints()) { |
482 | Standard_Real aTolNew = aTol + aProjPC.LowerDistance(); |
483 | if (aTolNew > aTolMax) { |
484 | aTolMax = aTolNew; |
485 | } |
486 | } |
487 | } |
488 | } |
489 | } |
490 | // |
491 | // compute max tolerance for common blocks on faces |
492 | if (aLFI.Extent()) { |
493 | Standard_Integer nF; |
494 | GeomAPI_ProjectPointOnSurf aProjPS; |
495 | BOPCol_ListIteratorOfListOfInteger aItLI; |
496 | // |
497 | aItLI.Initialize(aLFI); |
498 | for (; aItLI.More(); aItLI.Next()) { |
499 | nF = aItLI.Value(); |
500 | const TopoDS_Face& aF = *(TopoDS_Face*)&theDS->Shape(nF); |
501 | aTol = BRep_Tool::Tolerance(aF); |
502 | // |
503 | aProjPS = theContext->ProjPS(aF); |
504 | // |
505 | aT = aT1; |
506 | for (Standard_Integer i=1; i <= aNbPnt; i++) { |
507 | aT += aDt; |
508 | aC3D->D0(aT, aP); |
509 | aProjPS.Perform(aP); |
510 | if (aProjPS.NbPoints()) { |
511 | Standard_Real aTolNew = aTol + aProjPS.LowerDistance(); |
512 | if (aTolNew > aTolMax) { |
513 | aTolMax = aTolNew; |
514 | } |
515 | } |
516 | } |
517 | } |
518 | } |
519 | // |
520 | return aTolMax; |
521 | } |
e6ae74fd |
522 | |
523 | //======================================================================= |
524 | //function : EdgesToWires |
525 | //purpose : |
526 | //======================================================================= |
527 | Standard_Integer BOPAlgo_Tools::EdgesToWires(const TopoDS_Shape& theEdges, |
528 | TopoDS_Shape& theWires, |
529 | const Standard_Boolean theShared, |
530 | const Standard_Real theAngTol) |
531 | { |
532 | Standard_Integer iErr = 0; |
533 | // |
534 | // 1. Check the input edges |
535 | // |
536 | // List of edges to process |
537 | BOPCol_ListOfShape aLE; |
538 | // |
539 | TopExp_Explorer aExp(theEdges, TopAbs_EDGE); |
540 | for (; aExp.More(); aExp.Next()) { |
541 | const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current()); |
542 | if (!BRep_Tool::Degenerated(aE) && BRep_Tool::IsGeometric(aE)) { |
543 | aLE.Append(aExp.Current()); |
544 | } |
545 | } |
546 | // |
547 | if (aLE.IsEmpty()) { |
548 | // no edges to process |
549 | iErr = 1; |
550 | return iErr; |
551 | } |
552 | // |
553 | BRep_Builder aBB; |
554 | TopoDS_Compound aRWires; |
555 | aBB.MakeCompound(aRWires); |
556 | // |
557 | if (aLE.Extent() == 1) { |
558 | TopoDS_Wire aWire; |
559 | aBB.MakeWire(aWire); |
560 | aBB.Add(aWire, aLE.First()); |
561 | aBB.Add(aRWires, aWire); |
562 | theWires = aRWires; |
563 | return iErr; |
564 | } |
565 | // |
566 | // 2. Make compound of shared edges |
567 | TopoDS_Shape aSEdges; |
568 | // |
569 | if (!theShared) { |
570 | // intersect the edges if necessary |
571 | BOPAlgo_Builder aGF; |
572 | aGF.SetArguments(aLE); |
573 | aGF.Perform(); |
574 | if (aGF.ErrorStatus()) { |
575 | // unable to share the edges |
576 | iErr = 2; |
577 | return iErr; |
578 | } |
579 | // |
580 | aSEdges = aGF.Shape(); |
581 | } |
582 | else { |
583 | aBB.MakeCompound(TopoDS::Compound(aSEdges)); |
584 | BOPCol_ListIteratorOfListOfShape aItLE(aLE); |
585 | for (; aItLE.More(); aItLE.Next()) { |
586 | aBB.Add(aSEdges, aItLE.Value()); |
587 | } |
588 | } |
589 | // |
590 | // 3. Find edges located in the same planes and make wires from them. |
591 | // If the plane cannot be found for a single edge, then it is necessary |
592 | // to find all pairs of connected edges with the same cross product. |
593 | |
594 | // Try to compute the plane in which the edge is located |
595 | BOPAlgo_IndexedDataMapOfShapePln aDMEdgePln; |
596 | // Compute the tangent direction for the edges for which the plane is not defined |
597 | BOPAlgo_IndexedDataMapOfShapeDir aDMEdgeTgt; |
598 | // |
599 | // edges for which the plane is not found |
600 | BOPCol_MapOfShape aMEdgesNoUniquePlane; |
601 | // |
602 | // edges for which the plane cannot be found on a single edge |
603 | TopoDS_Compound aLEdges; |
604 | aBB.MakeCompound(aLEdges); |
605 | // |
606 | aExp.Init(aSEdges, TopAbs_EDGE); |
607 | for (; aExp.More(); aExp.Next()) { |
608 | const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current()); |
609 | BRepAdaptor_Curve aBAC(aE); |
610 | // |
611 | gp_Pln aPln; |
612 | if (FindPlane(aBAC, aPln)) { |
613 | aDMEdgePln.Add(aE, aPln); |
614 | } |
615 | else { |
616 | gp_Vec aVT; |
617 | if (FindEdgeTangent(aBAC, aVT)) { |
618 | aDMEdgeTgt.Add(aE, gp_Dir(aVT)); |
619 | aBB.Add(aLEdges, aE); |
620 | aMEdgesNoUniquePlane.Add(aE); |
621 | } |
622 | } |
623 | } |
624 | // |
625 | typedef NCollection_List<gp_Dir> BOPAlgo_ListOfDir; |
626 | // |
627 | // to avoid processing of the same edges in the same plane store |
628 | // the processed planes into a list and use it as a fence map |
629 | BOPAlgo_ListOfDir aLPFence; |
630 | // |
631 | // used edges |
632 | BOPCol_MapOfShape aMEFence; |
633 | // |
634 | // look for a planes on the single edges |
635 | Standard_Integer i, j, aNbPlanes = aDMEdgePln.Extent(), aNbEdges = aDMEdgeTgt.Extent(); |
636 | for (i = 1; i <= aNbPlanes; ++i) { |
637 | const TopoDS_Shape& aEI = aDMEdgePln.FindKey(i); |
638 | if (!aMEFence.Add(aEI)) { |
639 | continue; |
640 | } |
641 | // |
642 | const gp_Pln& aPlnI = aDMEdgePln(i); |
643 | const gp_Dir& aDI = aPlnI.Position().Direction(); |
644 | // |
645 | aLPFence.Append(aDI); |
646 | // |
647 | BOPCol_IndexedMapOfShape aMEPln; |
648 | aMEPln.Add(aEI); |
649 | // |
650 | BOPCol_IndexedMapOfShape aMV; |
651 | BOPTools::MapShapes(aEI, TopAbs_VERTEX, aMV); |
652 | // |
653 | // look for other edges with the plane parallel to current one |
654 | for (j = i + 1; j <= aNbPlanes; ++j) { |
655 | const gp_Dir& aDJ = aDMEdgePln(j).Position().Direction(); |
656 | if (aDI.IsParallel(aDJ, theAngTol)) { |
657 | const TopoDS_Shape& aEJ = aDMEdgePln.FindKey(j); |
658 | aMEPln.Add(aEJ); |
659 | aMEFence.Add(aEJ); |
660 | BOPTools::MapShapes(aEJ, TopAbs_VERTEX, aMV); |
661 | } |
662 | } |
663 | // |
664 | // look for all other edges located in the plane parallel to current one |
665 | TopoDS_Compound aCEPln; |
666 | aBB.MakeCompound(aCEPln); |
667 | // |
668 | for (j = 1; j <= aNbEdges; ++j) { |
669 | const gp_Dir& aDJ = aDMEdgeTgt(j); |
670 | if (aDI.IsNormal(aDJ, theAngTol)) { |
671 | aBB.Add(aCEPln, aDMEdgeTgt.FindKey(j)); |
672 | } |
673 | } |
674 | // |
675 | // make blocks of these edges and check blocks to be connected |
676 | // to any of the already added edges or forming a wire themselves |
677 | BOPCol_ListOfShape aLCBE; |
678 | BOPTools_AlgoTools::MakeConnexityBlocks(aCEPln, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); |
679 | // |
680 | // make wire from each block |
681 | BOPCol_ListIteratorOfListOfShape aItLCB(aLCBE); |
682 | for (; aItLCB.More(); aItLCB.Next()) { |
683 | const TopoDS_Shape& aCBE = aItLCB.Value(); |
684 | // |
685 | // check connectivity |
686 | TopExp_Explorer aExpV(aCBE, TopAbs_VERTEX); |
687 | for (; aExpV.More(); aExpV.Next()) { |
688 | if (aMV.Contains(aExpV.Current())) { |
689 | break; |
690 | } |
691 | } |
692 | // |
693 | Standard_Boolean bAddBlock = aExpV.More(); |
694 | if (!bAddBlock) { |
695 | // check if the edges are forming a wire |
696 | gp_Pln aPln; |
697 | bAddBlock = FindPlane(aCBE, aPln, aDMEdgeTgt, aMEdgesNoUniquePlane); |
698 | } |
699 | // |
700 | if (bAddBlock) { |
701 | // add edges |
702 | for (TopoDS_Iterator aItE(aCBE); aItE.More(); aItE.Next()) { |
703 | aMEPln.Add(aItE.Value()); |
704 | } |
705 | } |
706 | } |
707 | // |
708 | MakeWires(aMEPln, aRWires, Standard_False, aDMEdgeTgt, aMEdgesNoUniquePlane); |
709 | } |
710 | // |
711 | // make connection map from vertices to edges to find the connected pairs |
712 | BOPCol_IndexedDataMapOfShapeListOfShape aDMVE; |
713 | BOPTools::MapShapesAndAncestors(aLEdges, TopAbs_VERTEX, TopAbs_EDGE, aDMVE); |
714 | // |
715 | // find planes for connected edges |
716 | Standard_Integer aNbV = aDMVE.Extent(); |
717 | for (i = 1; i <= aNbV; ++i) { |
718 | const BOPCol_ListOfShape& aLEI = aDMVE(i); |
719 | if (aLEI.Extent() < 2) { |
720 | continue; |
721 | } |
722 | // |
723 | BOPCol_ListIteratorOfListOfShape aItLEI1(aLEI); |
724 | for (; aItLEI1.More(); aItLEI1.Next()) { |
725 | const TopoDS_Shape& aEI1 = aItLEI1.Value(); |
726 | const gp_Dir& aDI1 = aDMEdgeTgt.FindFromKey(aEI1); |
727 | // |
728 | BOPCol_ListIteratorOfListOfShape aItLEI2(aLEI); |
729 | for (; aItLEI2.More(); aItLEI2.Next()) { |
730 | const TopoDS_Shape& aEI2 = aItLEI2.Value(); |
731 | if (aEI2.IsSame(aEI1)) { |
732 | continue; |
733 | } |
734 | // |
735 | const gp_Dir& aDI2 = aDMEdgeTgt.FindFromKey(aEI2); |
736 | // |
737 | if (aDI1.IsParallel(aDI2, theAngTol)) { |
738 | continue; |
739 | } |
740 | // |
741 | gp_Dir aDNI = aDI1^aDI2; |
742 | // |
743 | // check if this normal direction has not been checked yet |
744 | BOPAlgo_ListOfDir::Iterator aItLPln(aLPFence); |
745 | for (; aItLPln.More(); aItLPln.Next()) { |
746 | if (aDNI.IsParallel(aItLPln.Value(), theAngTol)) { |
747 | break; |
748 | } |
749 | } |
750 | if (aItLPln.More()) { |
751 | continue; |
752 | } |
753 | // |
754 | aLPFence.Append(aDNI); |
755 | // |
756 | // find all other edges in the plane parallel to current one |
757 | BOPCol_IndexedMapOfShape aMEPln; |
758 | aMEPln.Add(aEI1); |
759 | aMEPln.Add(aEI2); |
760 | // |
761 | // iterate on all other edges to find all edges lying in the plane parallel to current one |
762 | for (j = 1; j <= aNbEdges; ++j) { |
763 | const gp_Dir& aDJ = aDMEdgeTgt(j); |
764 | if (aDNI.IsNormal(aDJ, theAngTol)) { |
765 | aMEPln.Add(aDMEdgeTgt.FindKey(j)); |
766 | } |
767 | } |
768 | // |
769 | MakeWires(aMEPln, aRWires, Standard_True, aDMEdgeTgt, aMEdgesNoUniquePlane); |
770 | } // for (; aItLEI2.More(); aItLEI2.Next()) { |
771 | } // for (; aItLEI1.More(); aItLEI1.Next()) { |
772 | } // for (i = 1; i < aNb; ++i) { |
773 | // |
774 | // 4. Find unused edges and make wires from them |
775 | BOPCol_IndexedMapOfShape aMEAlone, aMEUsed; |
776 | BOPTools::MapShapes(aRWires, TopAbs_EDGE, aMEUsed); |
777 | // |
778 | for (i = 1; i <= aNbEdges; ++i) { |
779 | const TopoDS_Shape& aE = aDMEdgeTgt.FindKey(i); |
780 | if (!aMEUsed.Contains(aE)) { |
781 | aMEAlone.Add(aE); |
782 | } |
783 | } |
784 | // |
785 | MakeWires(aMEAlone, aRWires, Standard_False, aDMEdgeTgt, aMEdgesNoUniquePlane); |
786 | // |
787 | theWires = aRWires; |
788 | // |
789 | return iErr; |
790 | } |
791 | |
792 | //======================================================================= |
793 | //function : WiresToFaces |
794 | //purpose : |
795 | //======================================================================= |
796 | Standard_Boolean BOPAlgo_Tools::WiresToFaces(const TopoDS_Shape& theWires, |
797 | TopoDS_Shape& theFaces, |
798 | const Standard_Real theAngTol) |
799 | { |
800 | BRep_Builder aBB; |
801 | BOPCol_MapOfShape aMFence; |
802 | TopoDS_Compound aRFaces; |
803 | aBB.MakeCompound(aRFaces); |
804 | // |
805 | const Standard_Real aMax = 1.e+8; |
806 | // |
807 | // map to store the tangent vectors for the edges |
808 | BOPAlgo_IndexedDataMapOfShapeDir aDMEdgeTgt; |
809 | // maps to store the planes found for the wires |
810 | BOPAlgo_IndexedDataMapOfShapePln aDMWirePln; |
811 | // map to store the tolerance for the wire |
812 | NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> aDMWireTol; |
813 | // edges for which the plane is not found |
814 | BOPCol_MapOfShape aMEdgesNoUniquePlane; |
815 | // |
816 | // Find planes for the wires |
817 | TopExp_Explorer aExpW(theWires, TopAbs_WIRE); |
818 | for (; aExpW.More(); aExpW.Next()) { |
819 | const TopoDS_Wire& aWire = TopoDS::Wire(aExpW.Current()); |
820 | gp_Pln aPlane; |
821 | if (FindPlane(aWire, aPlane, aDMEdgeTgt, aMEdgesNoUniquePlane)) { |
822 | aDMWirePln.Add(aWire, aPlane); |
823 | // find tolerance for the wire - max tolerance of its edges |
824 | aDMWireTol.Bind(aWire, BRep_Tool::MaxTolerance(aWire, TopAbs_EDGE)); |
825 | } |
826 | } |
827 | // |
828 | Standard_Integer i, j, aNb = aDMWirePln.Extent(); |
829 | for (i = 1; i <= aNb; ++i) { |
830 | const TopoDS_Shape& aWireI = aDMWirePln.FindKey(i); |
831 | if (aMFence.Contains(aWireI)) { |
832 | continue; |
833 | } |
834 | // |
835 | const gp_Pln& aPlnI = aDMWirePln(i); |
836 | // |
837 | BOPCol_ListOfShape aLW; |
838 | aLW.Append(aWireI); |
839 | aMFence.Add(aWireI); |
840 | // |
841 | Standard_Real aTolI = aDMWireTol.Find(aWireI); |
842 | // |
843 | // Find other wires in the same plane |
844 | for (j = i + 1; j <= aNb; ++j) { |
845 | const TopoDS_Shape& aWireJ = aDMWirePln.FindKey(j); |
846 | if (aMFence.Contains(aWireJ)) { |
847 | continue; |
848 | } |
849 | // |
850 | // check if the planes are the same |
851 | const gp_Pln& aPlnJ = aDMWirePln(j); |
852 | // check direction of the planes |
853 | if (!aPlnI.Position().Direction().IsParallel(aPlnJ.Position().Direction(), theAngTol)) { |
854 | continue; |
855 | } |
856 | // check distance between the planes |
857 | Standard_Real aDist = aPlnI.Distance(aPlnJ.Location()); |
858 | Standard_Real aTolJ = aDMWireTol.Find(aWireJ); |
859 | if (aDist > (aTolI + aTolJ)) { |
860 | continue; |
861 | } |
862 | // |
863 | aLW.Append(aWireJ); |
864 | aMFence.Add(aWireJ); |
865 | } |
866 | // |
867 | // Take the edges to build the face |
868 | BOPCol_ListOfShape aLE; |
869 | BOPCol_ListIteratorOfListOfShape aItLW(aLW); |
870 | for (; aItLW.More(); aItLW.Next()) { |
871 | TopoDS_Iterator aItE(aItLW.Value()); |
872 | for (; aItE.More(); aItE.Next()) { |
873 | aLE.Append(aItE.Value().Oriented(TopAbs_FORWARD)); |
874 | aLE.Append(aItE.Value().Oriented(TopAbs_REVERSED)); |
875 | } |
876 | } |
877 | // |
878 | // build planar face |
879 | TopoDS_Face aFF = BRepBuilderAPI_MakeFace |
880 | (aPlnI, -aMax, aMax, -aMax, aMax).Face(); |
881 | aFF.Orientation(TopAbs_FORWARD); |
882 | // |
883 | try { |
884 | OCC_CATCH_SIGNALS |
885 | // |
886 | // build pcurves for edges on this face |
887 | BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane(aLE, aFF); |
888 | // |
889 | // split the face with the edges |
890 | BOPAlgo_BuilderFace aBF; |
891 | aBF.SetShapes(aLE); |
892 | aBF.SetFace(aFF); |
893 | aBF.Perform(); |
894 | if (aBF.ErrorStatus()) { |
895 | continue; |
896 | } |
897 | // |
898 | const BOPCol_ListOfShape& aLFSp = aBF.Areas(); |
899 | BOPCol_ListIteratorOfListOfShape aItLF(aLFSp); |
900 | for (; aItLF.More(); aItLF.Next()) { |
901 | const TopoDS_Shape& aFSp = aItLF.ChangeValue(); |
902 | aBB.Add(aRFaces, aFSp); |
903 | } |
904 | } |
905 | catch (Standard_Failure) { |
906 | continue; |
907 | } |
908 | } |
909 | // |
910 | // fix tolerances of the resulting faces |
911 | BOPCol_IndexedMapOfShape aMEmpty; |
912 | BOPTools_AlgoTools::CorrectTolerances(aRFaces, aMEmpty, 0.05, Standard_False); |
913 | BOPTools_AlgoTools::CorrectShapeTolerances(aRFaces, aMEmpty, Standard_False); |
914 | // |
915 | theFaces = aRFaces; |
916 | TopoDS_Iterator aItF(theFaces); |
917 | return aItF.More(); |
918 | } |
919 | |
920 | //======================================================================= |
921 | //function : MakeWires |
922 | //purpose : Makes wires from the separate blocks of the given edges |
923 | //======================================================================= |
924 | void MakeWires(const BOPCol_IndexedMapOfShape& theEdges, |
925 | TopoDS_Compound& theWires, |
926 | const Standard_Boolean theCheckUniquePlane, |
927 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
928 | BOPCol_MapOfShape& theMEdgesNoUniquePlane) |
929 | { |
930 | TopoDS_Compound aCE; |
931 | BRep_Builder().MakeCompound(aCE); |
932 | Standard_Integer i, aNbE = theEdges.Extent(); |
933 | for (i = 1; i <= aNbE; ++i) { |
934 | BRep_Builder().Add(aCE, theEdges(i)); |
935 | } |
936 | // |
937 | BOPCol_ListOfShape aLCBE; |
938 | BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); |
939 | // |
940 | // make wire from each block |
941 | BOPCol_ListIteratorOfListOfShape aItLCB(aLCBE); |
942 | for (; aItLCB.More(); aItLCB.Next()) { |
943 | const TopoDS_Shape& aCBE = aItLCB.Value(); |
944 | // |
945 | if (theCheckUniquePlane) { |
946 | gp_Pln aPln; |
947 | if (!FindPlane(aCBE, aPln, theDMEdgeTgt, theMEdgesNoUniquePlane)) { |
948 | continue; |
949 | } |
950 | } |
951 | // |
952 | TopoDS_Wire aWire; |
953 | BRep_Builder().MakeWire(aWire); |
954 | for (TopoDS_Iterator aItE(aCBE); aItE.More(); aItE.Next()) { |
955 | BRep_Builder().Add(aWire, aItE.Value()); |
956 | } |
957 | // |
958 | BRep_Builder().Add(theWires, aWire); |
959 | } |
960 | } |
961 | |
962 | //======================================================================= |
963 | //function : FindEdgeTangent |
964 | //purpose : Finds the tangent for the edge using the map |
965 | //======================================================================= |
966 | Standard_Boolean FindEdgeTangent(const TopoDS_Edge& theEdge, |
967 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
968 | gp_Dir& theTgt) |
969 | { |
970 | gp_Dir *pDTE = theDMEdgeTgt.ChangeSeek(theEdge); |
971 | if (!pDTE) { |
972 | gp_Vec aVTE; |
973 | BRepAdaptor_Curve aBAC(theEdge); |
974 | if (!FindEdgeTangent(aBAC, aVTE)) { |
975 | return Standard_False; |
976 | } |
977 | pDTE = &theDMEdgeTgt(theDMEdgeTgt.Add(theEdge, gp_Dir(aVTE))); |
978 | } |
979 | theTgt = *pDTE; |
980 | return Standard_True; |
981 | } |
982 | |
983 | //======================================================================= |
984 | //function : FindEdgeTangent |
985 | //purpose : Finds the tangent for the edge |
986 | //======================================================================= |
987 | Standard_Boolean FindEdgeTangent(const BRepAdaptor_Curve& theCurve, |
988 | gp_Vec& theTangent) |
989 | { |
990 | if (!theCurve.Is3DCurve()) { |
991 | return Standard_False; |
992 | } |
993 | // for the line the tangent is defined by the direction |
994 | if (theCurve.GetType() == GeomAbs_Line) { |
995 | theTangent = theCurve.Line().Position().Direction(); |
996 | return Standard_True; |
997 | } |
998 | // |
999 | // for other curves take D1 and check for its length |
1000 | Standard_Real aT, aT1(theCurve.FirstParameter()), aT2(theCurve.LastParameter()); |
1001 | const Standard_Integer aNbP = 11; |
1002 | const Standard_Real aDt = (aT2 - aT1) / aNbP; |
1003 | // |
1004 | for (aT = aT1 + aDt; aT <= aT2; aT += aDt) { |
1005 | gp_Pnt aP; |
1006 | theCurve.D1(aT, aP, theTangent); |
1007 | if (theTangent.Magnitude() > Precision::Confusion()) { |
1008 | return Standard_True; |
1009 | } |
1010 | } |
1011 | // |
1012 | return Standard_False; |
1013 | } |
1014 | |
1015 | //======================================================================= |
1016 | //function : FindPlane |
1017 | //purpose : Finds the plane in which the edge is located |
1018 | //======================================================================= |
1019 | Standard_Boolean FindPlane(const BRepAdaptor_Curve& theCurve, |
1020 | gp_Pln& thePlane) |
1021 | { |
1022 | if (!theCurve.Is3DCurve()) { |
1023 | return Standard_False; |
1024 | } |
1025 | // |
1026 | Standard_Boolean bFound = Standard_True; |
1027 | gp_Vec aVN; |
1028 | switch (theCurve.GetType()) { |
1029 | case GeomAbs_Line: |
1030 | return Standard_False; |
1031 | case GeomAbs_Circle: |
1032 | aVN = theCurve.Circle().Position().Direction(); |
1033 | break; |
1034 | case GeomAbs_Ellipse: |
1035 | aVN = theCurve.Ellipse().Position().Direction(); |
1036 | break; |
1037 | case GeomAbs_Hyperbola: |
1038 | aVN = theCurve.Hyperbola().Position().Direction(); |
1039 | break; |
1040 | case GeomAbs_Parabola: |
1041 | aVN = theCurve.Parabola().Position().Direction(); |
1042 | break; |
1043 | default: { |
1044 | // for all other types of curve compute two tangent vectors |
1045 | // on the curve and cross them |
1046 | bFound = Standard_False; |
1047 | Standard_Real aT, aT1(theCurve.FirstParameter()), aT2(theCurve.LastParameter()); |
1048 | const Standard_Integer aNbP = 11; |
1049 | const Standard_Real aDt = (aT2 - aT1) / aNbP; |
1050 | // |
1051 | aT = aT1; |
1052 | gp_Pnt aP1; |
1053 | gp_Vec aV1; |
1054 | theCurve.D1(aT, aP1, aV1); |
1055 | // |
1056 | for (aT = aT1 + aDt; aT <= aT2; aT += aDt) { |
1057 | gp_Pnt aP2; |
1058 | gp_Vec aV2; |
1059 | theCurve.D1(aT, aP2, aV2); |
1060 | // |
1061 | aVN = aV1^aV2; |
1062 | if (aVN.Magnitude() > Precision::Confusion()) { |
1063 | bFound = Standard_True; |
1064 | break; |
1065 | } |
1066 | } |
1067 | break; |
1068 | } |
1069 | } |
1070 | // |
1071 | if (bFound) { |
1072 | thePlane = gp_Pln(theCurve.Value(theCurve.FirstParameter()), gp_Dir(aVN)); |
1073 | } |
1074 | return bFound; |
1075 | } |
1076 | |
1077 | //======================================================================= |
1078 | //function : FindPlane |
1079 | //purpose : Finds the plane in which the wire is located |
1080 | //======================================================================= |
1081 | Standard_Boolean FindPlane(const TopoDS_Shape& theWire, |
1082 | gp_Pln& thePlane, |
1083 | BOPAlgo_IndexedDataMapOfShapeDir& theDMEdgeTgt, |
1084 | BOPCol_MapOfShape& theMEdgesNoUniquePlane) |
1085 | { |
1086 | TopExp_Explorer aExpE1(theWire, TopAbs_EDGE); |
1087 | if (!aExpE1.More()) { |
1088 | return Standard_False; |
1089 | } |
1090 | // |
1091 | // try to find two not parallel edges in wire to get normal of the plane |
1092 | for (; aExpE1.More(); aExpE1.Next()) { |
1093 | // get the first edge in the wire |
1094 | const TopoDS_Edge& aE1 = TopoDS::Edge(aExpE1.Current()); |
1095 | // |
1096 | // find tangent for the first edge |
1097 | gp_Dir aDTE1; |
1098 | if (!FindEdgeTangent(aE1, theDMEdgeTgt, aDTE1)) { |
1099 | continue; |
1100 | } |
1101 | // |
1102 | // find the other edge not parallel to the first one |
1103 | TopExp_Explorer aExpE2(theWire, TopAbs_EDGE); |
1104 | for (; aExpE2.More(); aExpE2.Next()) { |
1105 | const TopoDS_Edge& aE2 = TopoDS::Edge(aExpE2.Current()); |
1106 | if (aE1.IsSame(aE2)) { |
1107 | continue; |
1108 | } |
1109 | // |
1110 | // find tangent for the second edge |
1111 | gp_Dir aDTE2; |
1112 | if (!FindEdgeTangent(aE2, theDMEdgeTgt, aDTE2)) { |
1113 | continue; |
1114 | } |
1115 | // |
1116 | if (aDTE1.IsParallel(aDTE2, Precision::Angular())) { |
1117 | continue; |
1118 | } |
1119 | // |
1120 | gp_Dir aDN = aDTE1^aDTE2; |
1121 | // |
1122 | TopoDS_Iterator aItV(aE1); |
1123 | thePlane = gp_Pln(BRep_Tool::Pnt(TopoDS::Vertex(aItV.Value())), aDN); |
1124 | return Standard_True; |
1125 | } |
1126 | } |
1127 | // |
1128 | // try to compute normal on the single edge |
1129 | aExpE1.Init(theWire, TopAbs_EDGE); |
1130 | for (; aExpE1.More(); aExpE1.Next()) { |
1131 | const TopoDS_Edge& aE = TopoDS::Edge(aExpE1.Current()); |
1132 | if (theMEdgesNoUniquePlane.Contains(aE)) { |
1133 | continue; |
1134 | } |
1135 | BRepAdaptor_Curve aBAC(aE); |
1136 | if (FindPlane(aBAC, thePlane)) { |
1137 | return Standard_True; |
1138 | } |
1139 | theMEdgesNoUniquePlane.Add(aE); |
1140 | } |
1141 | return Standard_False; |
1142 | } |