4e57c75e |
1 | // Created on: 2004-09-02 |
2 | // Copyright (c) 2004-2012 OPEN CASCADE SAS |
3 | // |
4 | // The content of this file is subject to the Open CASCADE Technology Public |
5 | // License Version 6.5 (the "License"). You may not use the content of this file |
6 | // except in compliance with the License. Please obtain a copy of the License |
7 | // at http://www.opencascade.org and read it completely before using this file. |
8 | // |
9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
11 | // |
12 | // The Original Code and all software distributed under the License is |
13 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
14 | // Initial Developer hereby disclaims all such warranties, including without |
15 | // limitation, any warranties of merchantability, fitness for a particular |
16 | // purpose or non-infringement. Please see the License for the specific terms |
17 | // and conditions governing the rights and limitations under the License. |
18 | |
19 | #include <BOPAlgo_ArgumentAnalyzer.ixx> |
20 | |
21 | #include <Standard_ErrorHandler.hxx> |
22 | #include <Standard_Failure.hxx> |
23 | #include <TopExp.hxx> |
24 | #include <TopExp_Explorer.hxx> |
25 | #include <BRep_Builder.hxx> |
26 | #include <BRep_Tool.hxx> |
27 | #include <BRepExtrema_DistShapeShape.hxx> |
28 | #include <gp_Pnt.hxx> |
29 | #include <TopoDS_Iterator.hxx> |
30 | #include <TopoDS.hxx> |
31 | #include <TopoDS_Vertex.hxx> |
32 | #include <TopoDS_Edge.hxx> |
33 | #include <TopoDS_Wire.hxx> |
34 | #include <TopoDS_Shell.hxx> |
35 | #include <TopoDS_Solid.hxx> |
36 | #include <BOPCol_ListOfShape.hxx> |
37 | #include <BOPCol_SequenceOfShape.hxx> |
38 | #include <BOPCol_MapOfShape.hxx> |
39 | |
40 | #include <TColStd_Array2OfBoolean.hxx> |
41 | |
42 | #include <IntTools_Range.hxx> |
43 | #include <IntTools_EdgeEdge.hxx> |
44 | #include <IntTools_CommonPrt.hxx> |
45 | |
46 | #include <BOPAlgo_Operation.hxx> |
47 | #include <BOPAlgo_CheckerSI.hxx> |
48 | #include <BOPAlgo_BuilderFace.hxx> |
49 | |
50 | #include <BOPDS_DS.hxx> |
51 | #include <BOPDS_VectorOfInterfVV.hxx> |
52 | #include <BOPDS_VectorOfInterfVE.hxx> |
53 | #include <BOPDS_VectorOfInterfEE.hxx> |
54 | #include <BOPDS_VectorOfInterfVF.hxx> |
55 | #include <BOPDS_VectorOfInterfEF.hxx> |
56 | #include <BOPDS_VectorOfInterfFF.hxx> |
57 | |
58 | #include <BOPInt_Context.hxx> |
59 | |
60 | #include <BOPTools_AlgoTools3D.hxx> |
61 | #include <BOPTools_AlgoTools.hxx> |
62 | #include <BOPCol_ListOfShape.hxx> |
63 | |
64 | // ================================================================================ |
65 | // function: Constructor |
66 | // purpose: |
67 | // ================================================================================ |
68 | BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() : |
69 | myStopOnFirst(Standard_False), |
70 | myOperation(BOPAlgo_UNKNOWN), |
71 | myArgumentTypeMode(Standard_False), |
72 | mySelfInterMode(Standard_False), |
73 | mySmallEdgeMode(Standard_False), |
74 | myRebuildFaceMode(Standard_False), |
75 | myTangentMode(Standard_False), |
76 | myMergeVertexMode(Standard_False), |
77 | myMergeEdgeMode(Standard_False), |
78 | myEmpty1(Standard_False), |
79 | myEmpty2(Standard_False) |
80 | // myMergeFaceMode(Standard_False) |
81 | { |
82 | } |
83 | |
84 | // ================================================================================ |
85 | // function: SetShape1 |
86 | // purpose: |
87 | // ================================================================================ |
88 | void BOPAlgo_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape) |
89 | { |
90 | myShape1 = TheShape; |
91 | } |
92 | |
93 | // ================================================================================ |
94 | // function: SetShape2 |
95 | // purpose: |
96 | // ================================================================================ |
97 | void BOPAlgo_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape) |
98 | { |
99 | myShape2 = TheShape; |
100 | } |
101 | |
102 | // ================================================================================ |
103 | // function: GetShape1 |
104 | // purpose: |
105 | // ================================================================================ |
106 | const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape1() const |
107 | { |
108 | return myShape1; |
109 | } |
110 | |
111 | // ================================================================================ |
112 | // function: GetShape2 |
113 | // purpose: |
114 | // ================================================================================ |
115 | const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape2() const |
116 | { |
117 | return myShape2; |
118 | } |
119 | |
120 | // ================================================================================ |
121 | // function: OperationType |
122 | // purpose: |
123 | // ================================================================================ |
124 | BOPAlgo_Operation& BOPAlgo_ArgumentAnalyzer::OperationType() |
125 | { |
126 | return myOperation; |
127 | } |
128 | |
129 | // ================================================================================ |
130 | // function: StopOnFirstFaulty |
131 | // purpose: |
132 | // ================================================================================ |
133 | Standard_Boolean & BOPAlgo_ArgumentAnalyzer::StopOnFirstFaulty() |
134 | { |
135 | return myStopOnFirst; |
136 | } |
137 | |
138 | // ================================================================================ |
139 | // function: Prepare |
140 | // purpose: |
141 | // ================================================================================ |
142 | void BOPAlgo_ArgumentAnalyzer::Prepare() |
143 | { |
144 | Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull(); |
145 | if (!isS1) { |
146 | myEmpty1 = BOPTools_AlgoTools3D::IsEmptyShape(myShape1); |
147 | } |
148 | if (!isS2) { |
149 | myEmpty2 = BOPTools_AlgoTools3D::IsEmptyShape(myShape2); |
150 | } |
151 | } |
152 | // ================================================================================ |
153 | // function: Perform |
154 | // purpose: |
155 | // ================================================================================ |
156 | void BOPAlgo_ArgumentAnalyzer::Perform() |
157 | { |
158 | try { |
159 | OCC_CATCH_SIGNALS |
160 | myResult.Clear(); |
161 | |
162 | Prepare(); |
163 | |
164 | if(myArgumentTypeMode) { |
165 | TestTypes(); |
166 | } |
167 | |
168 | if(mySelfInterMode) { |
169 | TestSelfInterferences(); |
170 | } |
171 | |
172 | if(mySmallEdgeMode) { |
173 | if(!(!myResult.IsEmpty() && myStopOnFirst)) |
174 | TestSmallEdge(); |
175 | } |
176 | |
177 | if(myRebuildFaceMode) { |
178 | if(!(!myResult.IsEmpty() && myStopOnFirst)) |
179 | TestRebuildFace(); |
180 | } |
181 | |
182 | if(myTangentMode) { |
183 | if(!(!myResult.IsEmpty() && myStopOnFirst)) |
184 | TestTangent(); |
185 | } |
186 | |
187 | if(myMergeVertexMode) { |
188 | if(!(!myResult.IsEmpty() && myStopOnFirst)) |
189 | TestMergeVertex(); |
190 | } |
191 | |
192 | if(myMergeEdgeMode) { |
193 | if(!(!myResult.IsEmpty() && myStopOnFirst)) |
194 | TestMergeEdge(); |
195 | } |
196 | } |
197 | catch(Standard_Failure) { |
198 | BOPAlgo_CheckResult aResult; |
199 | aResult.SetCheckStatus(BOPAlgo_CheckUnknown); |
200 | myResult.Append(aResult); |
201 | } |
202 | } |
203 | |
204 | // ================================================================================ |
205 | // function: HasFaulty |
206 | // purpose: |
207 | // ================================================================================ |
208 | Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const |
209 | { |
210 | return ( !myResult.IsEmpty()); |
211 | } |
212 | |
213 | // ================================================================================ |
214 | // function: GetCheckResult |
215 | // purpose: |
216 | // ================================================================================ |
217 | const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const |
218 | { |
219 | return myResult; |
220 | } |
221 | |
222 | // ================================================================================ |
223 | // function: TestTypes |
224 | // purpose: |
225 | // ================================================================================ |
226 | void BOPAlgo_ArgumentAnalyzer::TestTypes() |
227 | { |
228 | Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull(); |
229 | |
230 | if(isS1 && isS2) { |
231 | BOPAlgo_CheckResult aResult; |
232 | aResult.SetCheckStatus(BOPAlgo_BadType); |
233 | myResult.Append(aResult); |
234 | return; |
235 | } |
236 | |
237 | //single shape check |
238 | if((isS1 && !isS2) || (!isS1 && isS2)) { |
239 | Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1; |
240 | |
241 | if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) { |
242 | const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1; |
243 | BOPAlgo_CheckResult aResult; |
244 | aResult.SetShape1(aS); |
245 | aResult.SetCheckStatus(BOPAlgo_BadType); |
246 | myResult.Append(aResult); |
247 | return; |
248 | } |
249 | } |
250 | // two shapes check (begin) |
251 | else { |
252 | if(myEmpty1 || myEmpty2) { |
253 | BOPAlgo_CheckResult aResult; |
254 | if(myEmpty1 && myEmpty2) { |
255 | aResult.SetShape1(myShape1); |
256 | aResult.SetShape2(myShape2); |
257 | } |
258 | else { |
259 | const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2; |
260 | if(myEmpty1) |
261 | aResult.SetShape1(aS); |
262 | else |
263 | aResult.SetShape2(aS); |
264 | } |
265 | aResult.SetCheckStatus(BOPAlgo_BadType); |
266 | myResult.Append(aResult); |
267 | return; |
268 | } |
269 | // |
270 | Standard_Integer aDim1, aDim2; |
271 | Standard_Boolean bBadTypes = Standard_False; |
272 | // |
273 | aDim1 = BOPTools_AlgoTools::Dimension(myShape1); |
274 | aDim2 = BOPTools_AlgoTools::Dimension(myShape2); |
275 | if (aDim1 < aDim2) { |
276 | if (myOperation == BOPAlgo_FUSE || |
277 | myOperation == BOPAlgo_CUT21) { |
278 | bBadTypes = Standard_True; |
279 | } |
280 | } |
281 | else if (aDim1 > aDim2) { |
282 | if (myOperation == BOPAlgo_FUSE || |
283 | myOperation == BOPAlgo_CUT) { |
284 | bBadTypes = Standard_True; |
285 | } |
286 | } |
287 | if (bBadTypes) { |
288 | BOPAlgo_CheckResult aResult; |
289 | aResult.SetShape1(myShape1); |
290 | aResult.SetShape2(myShape2); |
291 | aResult.SetCheckStatus(BOPAlgo_BadType); |
292 | myResult.Append(aResult); |
293 | } |
294 | } |
295 | } |
296 | |
297 | // ================================================================================ |
298 | // function: TestSelfInterferences |
299 | // purpose: |
300 | // ================================================================================ |
301 | void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences() |
302 | { |
303 | Standard_Integer ii = 0, j; |
304 | Standard_Boolean bSelfInt; |
305 | |
306 | for(ii = 0; ii < 2; ii++) { |
307 | TopoDS_Shape aS = (ii == 0) ? myShape1 : myShape2; |
308 | |
309 | if(aS.IsNull()) |
310 | continue; |
311 | |
312 | Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2; |
313 | if (bIsEmpty) { |
314 | continue; |
315 | } |
316 | |
317 | BOPAlgo_CheckerSI aChecker; |
318 | BOPCol_ListOfShape anArgs; |
319 | anArgs.Append(aS); |
320 | aChecker.SetArguments(anArgs); |
321 | // |
322 | aChecker.Perform(); |
323 | Standard_Integer iErr = aChecker.ErrorStatus(); |
324 | // |
325 | const BOPDS_PDS& theDS = aChecker.PDS(); |
326 | BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV(); |
327 | BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE(); |
328 | BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE(); |
329 | BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF(); |
330 | BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF(); |
331 | BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF(); |
332 | // |
333 | Standard_Integer aNb[6] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), |
334 | aVFs.Extent(), aEFs.Extent(), aFFs.Extent()}; |
335 | // |
4e57c75e |
336 | for (Standard_Integer aTypeInt = 0; aTypeInt < 6; ++aTypeInt) { |
337 | for (Standard_Integer i = 0; i < aNb[aTypeInt]; ++i) { |
338 | BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) : |
339 | ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) : |
340 | ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) : |
341 | ((aTypeInt==3) ? (BOPDS_Interf*)(&aVFs(i)) : |
342 | ((aTypeInt==4) ? (BOPDS_Interf*)(&aEFs(i)) : (BOPDS_Interf*)(&aFFs(i)))))); |
343 | // |
344 | Standard_Integer nI1 = aInt->Index1(); |
345 | Standard_Integer nI2 = aInt->Index2(); |
346 | if (nI1 == nI2) { |
347 | continue; |
348 | } |
349 | // |
f1419025 |
350 | if (aTypeInt == 4) { |
351 | BOPDS_InterfEF& aEF=aEFs(i); |
352 | if (aEF.CommonPart().Type()==TopAbs_SHAPE) { |
353 | continue; |
354 | } |
355 | } |
356 | // |
4e57c75e |
357 | const TopoDS_Shape& aS1 = theDS->Shape(nI1); |
358 | const TopoDS_Shape& aS2 = theDS->Shape(nI2); |
359 | // |
360 | if (aTypeInt == 5) { |
361 | bSelfInt = Standard_False; |
362 | BOPDS_InterfFF& aFF = aFFs(i); |
363 | BOPDS_VectorOfPoint& aVP=aFF.ChangePoints(); |
364 | Standard_Integer aNbP=aVP.Extent(); |
365 | BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves(); |
366 | Standard_Integer aNbC=aVC.Extent(); |
367 | if (!aNbP && !aNbC) { |
368 | continue; |
369 | } |
370 | for (j=0; j<aNbC; ++j) { |
371 | BOPDS_Curve& aNC=aVC(j); |
372 | BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks(); |
373 | if (aLPBC.Extent()) { |
374 | bSelfInt = Standard_True; |
375 | break; |
376 | } |
377 | } |
378 | if (!bSelfInt) { |
379 | continue; |
380 | } |
381 | } |
382 | // |
383 | BOPAlgo_CheckResult aResult; |
384 | if(ii == 0) |
385 | aResult.SetShape1(myShape1); |
386 | else |
387 | aResult.SetShape2(myShape2); |
388 | |
389 | if(ii == 0) { |
390 | aResult.AddFaultyShape1(aS1); |
391 | aResult.AddFaultyShape1(aS2); |
392 | } |
393 | else { |
394 | aResult.AddFaultyShape2(aS1); |
395 | aResult.AddFaultyShape2(aS2); |
396 | } |
397 | aResult.SetCheckStatus(BOPAlgo_SelfIntersect); |
398 | myResult.Append(aResult); |
399 | } |
400 | } |
401 | if (iErr) { |
402 | BOPAlgo_CheckResult aResult; |
403 | if(ii == 0) |
404 | aResult.SetShape1(myShape1); |
405 | else |
406 | aResult.SetShape2(myShape2); |
407 | |
408 | if(ii == 0) { |
409 | aResult.AddFaultyShape1(myShape1); |
410 | } |
411 | else { |
412 | aResult.AddFaultyShape2(myShape2); |
413 | } |
414 | aResult.SetCheckStatus(BOPAlgo_OperationAborted); |
415 | myResult.Append(aResult); |
416 | } |
417 | } |
418 | |
419 | } |
420 | |
421 | // ================================================================================ |
422 | // function: TestSmallEdge |
423 | // purpose: |
424 | // ================================================================================ |
425 | void BOPAlgo_ArgumentAnalyzer::TestSmallEdge() |
426 | { |
427 | Standard_Integer i = 0; |
428 | BRepExtrema_DistShapeShape aDist; |
429 | Handle(BOPInt_Context) aCtx; |
430 | // |
431 | aCtx = new BOPInt_Context; |
432 | |
433 | for(i = 0; i < 2; i++) { |
434 | TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2; |
435 | |
436 | if(aS.IsNull()) |
437 | continue; |
438 | |
439 | TopExp_Explorer anExp(aS, TopAbs_EDGE); |
440 | |
441 | for(; anExp.More(); anExp.Next()) { |
442 | TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current()); |
443 | |
444 | if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) { |
445 | Standard_Boolean bKeepResult = Standard_True; |
446 | |
447 | if(myOperation == BOPAlgo_SECTION) { |
448 | TopoDS_Shape anOtherS = (i == 0) ? myShape2 : myShape1; |
449 | |
450 | if(!anOtherS.IsNull()) { |
451 | aDist.LoadS2(anOtherS); |
452 | |
453 | Standard_Boolean bVertexIsOnShape = Standard_False; |
454 | Standard_Integer ii = 0; |
455 | TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX); |
456 | |
457 | for(; anExpV.More(); anExpV.Next()) { |
458 | TopoDS_Shape aV = anExpV.Current(); |
459 | |
460 | aDist.LoadS1(aV); |
461 | aDist.Perform(); |
462 | |
463 | if(aDist.IsDone()) { |
464 | |
465 | for(ii = 1; ii <= aDist.NbSolution(); ii++) { |
466 | Standard_Real aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aV)); |
467 | TopoDS_Shape aSupportShape = aDist.SupportOnShape2(ii); |
468 | |
469 | switch(aSupportShape.ShapeType()) { |
470 | case TopAbs_VERTEX: { |
471 | aTolerance += BRep_Tool::Tolerance(TopoDS::Vertex(aSupportShape)); |
472 | break; |
473 | } |
474 | case TopAbs_EDGE: { |
475 | aTolerance += BRep_Tool::Tolerance(TopoDS::Edge(aSupportShape)); |
476 | break; |
477 | } |
478 | case TopAbs_FACE: { |
479 | aTolerance += BRep_Tool::Tolerance(TopoDS::Face(aSupportShape)); |
480 | break; |
481 | } |
482 | default: |
483 | break; |
484 | } |
485 | |
486 | if(aDist.Value() < aTolerance) { |
487 | bVertexIsOnShape = Standard_True; |
488 | break; |
489 | } |
490 | } |
491 | } |
492 | } |
493 | |
494 | if(!bVertexIsOnShape) { |
495 | bKeepResult = Standard_False; |
496 | } |
497 | } |
498 | } |
499 | |
500 | if(bKeepResult) { |
501 | BOPAlgo_CheckResult aResult; |
502 | |
503 | if(i == 0) { |
504 | aResult.SetShape1(myShape1); |
505 | aResult.AddFaultyShape1(anEdge); |
506 | } |
507 | else { |
508 | aResult.SetShape2(myShape2); |
509 | aResult.AddFaultyShape2(anEdge); |
510 | } |
511 | |
512 | aResult.SetCheckStatus(BOPAlgo_TooSmallEdge); |
513 | myResult.Append(aResult); |
514 | |
515 | if(myStopOnFirst) { |
516 | return; |
517 | } |
518 | } |
519 | } |
520 | } |
521 | } |
522 | } |
523 | |
524 | // ================================================================================ |
525 | // function: TestRebuildFace |
526 | // purpose: |
527 | // ================================================================================ |
528 | void BOPAlgo_ArgumentAnalyzer::TestRebuildFace() |
529 | { |
530 | if((myOperation == BOPAlgo_SECTION) || |
531 | (myOperation == BOPAlgo_UNKNOWN)) |
532 | return; |
533 | Standard_Integer i = 0; |
534 | |
535 | for(i = 0; i < 2; i++) { |
536 | TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2; |
537 | |
538 | if(aS.IsNull()) |
539 | continue; |
540 | |
541 | TopExp_Explorer anExp(aS, TopAbs_FACE); |
542 | BOPCol_ListOfShape aLS; |
543 | |
544 | for(; anExp.More(); anExp.Next()) { |
545 | TopoDS_Face aFace = TopoDS::Face(anExp.Current()); |
546 | |
547 | TopoDS_Face aFF = aFace; |
548 | aFF.Orientation(TopAbs_FORWARD); |
549 | TopExp_Explorer anExpE(aFF, TopAbs_EDGE); |
550 | Standard_Integer nbstartedges = 0; |
551 | aLS.Clear(); |
552 | // |
553 | for(; anExpE.More(); anExpE.Next()) { |
554 | const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current())); |
555 | TopAbs_Orientation anOriE=aE.Orientation(); |
556 | // |
557 | if (anOriE==TopAbs_INTERNAL) { |
558 | TopoDS_Edge aEE=aE; |
559 | aEE.Orientation(TopAbs_FORWARD); |
560 | aLS.Append(aEE); |
561 | aEE.Orientation(TopAbs_REVERSED); |
562 | aLS.Append(aEE); |
563 | } |
564 | else { |
565 | aLS.Append(aE); |
566 | } |
567 | nbstartedges++; |
568 | } |
569 | BOPAlgo_BuilderFace aBF; |
570 | aBF.SetFace(aFace); |
571 | aBF.SetShapes(aLS); |
572 | aBF.Perform(); |
573 | const BOPCol_ListOfShape& aLF = aBF.Areas(); |
574 | Standard_Boolean bBadFace = Standard_False; |
575 | |
576 | if(aLF.Extent() != 1) { |
577 | bBadFace = Standard_True; |
578 | } |
579 | else { |
580 | Standard_Integer nbedgeused = 0; |
581 | anExpE.Init(aLF.First(), TopAbs_EDGE); |
582 | |
583 | for(; anExpE.More(); anExpE.Next(), nbedgeused++); |
584 | |
585 | if(nbstartedges != nbedgeused) { |
586 | bBadFace = Standard_True; |
587 | } |
588 | } |
589 | |
590 | if(bBadFace) { |
591 | BOPAlgo_CheckResult aResult; |
592 | |
593 | if(i == 0) { |
594 | aResult.SetShape1(myShape1); |
595 | aResult.AddFaultyShape1(aFace); |
596 | } |
597 | else { |
598 | aResult.SetShape2(myShape2); |
599 | aResult.AddFaultyShape2(aFace); |
600 | } |
601 | |
602 | aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace); |
603 | myResult.Append(aResult); |
604 | |
605 | if(myStopOnFirst) { |
606 | return; |
607 | } |
608 | } |
609 | } |
610 | } |
611 | } |
612 | |
613 | // ================================================================================ |
614 | // function: TestTangent |
615 | // purpose: |
616 | // ================================================================================ |
617 | void BOPAlgo_ArgumentAnalyzer::TestTangent() |
618 | { |
619 | // not implemented |
620 | } |
621 | |
622 | // ================================================================================ |
623 | // function: TestMergeSubShapes |
624 | // purpose: |
625 | // ================================================================================ |
626 | void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) |
627 | { |
628 | if(myShape1.IsNull() || myShape2.IsNull()) |
629 | return; |
630 | |
631 | if (myEmpty1 || myEmpty2) |
632 | return; |
633 | |
634 | BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown; |
635 | |
636 | switch(theType) { |
637 | case TopAbs_VERTEX: { |
638 | aStatus = BOPAlgo_IncompatibilityOfVertex; |
639 | break; |
640 | } |
641 | case TopAbs_EDGE: { |
642 | aStatus = BOPAlgo_IncompatibilityOfEdge; |
643 | break; |
644 | } |
645 | case TopAbs_FACE: { |
646 | aStatus = BOPAlgo_IncompatibilityOfFace; |
647 | break; |
648 | } |
649 | default: |
650 | return; |
651 | } |
652 | TopExp_Explorer anExp1(myShape1, theType); |
653 | TopExp_Explorer anExp2(myShape2, theType); |
654 | BOPCol_SequenceOfShape aSeq1, aSeq2; |
655 | BOPCol_MapOfShape aMap1, aMap2; |
656 | |
657 | for(; anExp1.More(); anExp1.Next()) { |
658 | TopoDS_Shape aS1 = anExp1.Current(); |
659 | |
660 | if(aMap1.Contains(aS1)) |
661 | continue; |
662 | aSeq1.Append(aS1); |
663 | aMap1.Add(aS1); |
664 | } |
665 | |
666 | for(; anExp2.More(); anExp2.Next()) { |
667 | TopoDS_Shape aS2 = anExp2.Current(); |
668 | if(aMap2.Contains(aS2)) |
669 | continue; |
670 | aSeq2.Append(aS2); |
671 | aMap2.Add(aS2); |
672 | } |
673 | |
674 | TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length()); |
675 | Standard_Integer i = 0, j = 0; |
676 | for(i = 1; i <= aSeq1.Length(); i++) |
677 | for(j = 1; j <= aSeq2.Length(); j++) |
678 | anArrayOfFlag.SetValue(i, j, Standard_False); |
679 | |
680 | for(i = 1; i <= aSeq1.Length(); i++) { |
681 | TopoDS_Shape aS1 = aSeq1.Value(i); |
682 | BOPCol_ListOfShape aListOfS2; |
683 | Standard_Integer nbs = 0; |
684 | |
685 | for(j = 1; j <= aSeq2.Length(); j++) { |
686 | TopoDS_Shape aS2 = aSeq2.Value(j); |
687 | Standard_Boolean bIsEqual = Standard_False; |
688 | |
689 | if(theType == TopAbs_VERTEX) { |
690 | |
691 | TopoDS_Vertex aV1 = TopoDS::Vertex(aS1); |
692 | TopoDS_Vertex aV2 = TopoDS::Vertex(aS2); |
693 | gp_Pnt aP1 = BRep_Tool::Pnt(aV1); |
694 | gp_Pnt aP2 = BRep_Tool::Pnt(aV2); |
695 | Standard_Real aDist = aP1.Distance(aP2); |
696 | |
697 | if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) { |
698 | bIsEqual = Standard_True; |
699 | } |
700 | } |
701 | else if(theType == TopAbs_EDGE) { |
702 | Standard_Integer aDiscretize = 30; |
703 | Standard_Real aDeflection = 0.01; |
704 | TopoDS_Edge aE1 = TopoDS::Edge(aS1); |
705 | TopoDS_Edge aE2 = TopoDS::Edge(aS2); |
706 | |
707 | IntTools_EdgeEdge aEE; |
708 | aEE.SetEdge1 (aE1); |
709 | aEE.SetEdge2 (aE2); |
710 | aEE.SetTolerance1 (BRep_Tool::Tolerance(aE1)); |
711 | aEE.SetTolerance2 (BRep_Tool::Tolerance(aE2)); |
712 | aEE.SetDiscretize (aDiscretize); |
713 | aEE.SetDeflection (aDeflection); |
714 | |
715 | Standard_Real f = 0., l = 0.; |
716 | BRep_Tool::Range(aE1, f, l); |
717 | aEE.SetRange1(f, l); |
718 | |
719 | BRep_Tool::Range(aE2, f, l); |
720 | aEE.SetRange2(f, l); |
721 | |
722 | aEE.Perform(); |
723 | |
724 | if (aEE.IsDone()) { |
725 | const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts(); |
726 | Standard_Integer ii = 0; |
727 | |
728 | for (ii = 1; ii <= aCPrts.Length(); ii++) { |
729 | const IntTools_CommonPrt& aCPart = aCPrts(ii); |
730 | |
731 | if (aCPart.Type() == TopAbs_EDGE) { |
732 | bIsEqual = Standard_True; |
733 | } |
734 | } |
735 | } |
736 | } |
737 | else if(theType == TopAbs_FACE) { |
738 | // not yet implemented! |
739 | } |
740 | |
741 | if(bIsEqual) { |
742 | anArrayOfFlag.SetValue(i, j, Standard_True ); |
743 | aListOfS2.Append(aS2); |
744 | nbs++; |
745 | } |
746 | } |
747 | |
748 | if(nbs > 1) { |
749 | BOPAlgo_CheckResult aResult; |
750 | |
751 | aResult.SetShape1(myShape1); |
752 | aResult.SetShape2(myShape2); |
753 | aResult.AddFaultyShape1(aS1); |
754 | BOPCol_ListIteratorOfListOfShape anIt(aListOfS2); |
755 | |
756 | for(; anIt.More(); anIt.Next()) { |
757 | aResult.AddFaultyShape2(anIt.Value()); |
758 | } |
759 | |
760 | aResult.SetCheckStatus(aStatus); |
761 | myResult.Append(aResult); |
762 | |
763 | if(myStopOnFirst) { |
764 | return; |
765 | } |
766 | } |
767 | } |
768 | |
769 | for(i = 1; i <= aSeq2.Length(); i++) { |
770 | TopoDS_Shape aS2 = aSeq2.Value(i); |
771 | BOPCol_ListOfShape aListOfS1; |
772 | Standard_Integer nbs = 0; |
773 | |
774 | for(j = 1; j <= aSeq1.Length(); j++) { |
775 | TopoDS_Shape aS1 = aSeq1.Value(j); |
776 | |
777 | if(anArrayOfFlag.Value(j, i)) { |
778 | aListOfS1.Append(aS1); |
779 | nbs++; |
780 | } |
781 | } |
782 | |
783 | if(nbs > 1) { |
784 | BOPAlgo_CheckResult aResult; |
785 | |
786 | aResult.SetShape1(myShape1); |
787 | aResult.SetShape2(myShape2); |
788 | BOPCol_ListIteratorOfListOfShape anIt(aListOfS1); |
789 | |
790 | for(; anIt.More(); anIt.Next()) { |
791 | aResult.AddFaultyShape1(anIt.Value()); |
792 | } |
793 | aResult.AddFaultyShape2(aS2); |
794 | |
795 | aResult.SetCheckStatus(aStatus); |
796 | myResult.Append(aResult); |
797 | |
798 | if(myStopOnFirst) { |
799 | return; |
800 | } |
801 | } |
802 | } |
803 | } |
804 | |
805 | // ================================================================================ |
806 | // function: TestMergeVertex |
807 | // purpose: |
808 | // ================================================================================ |
809 | void BOPAlgo_ArgumentAnalyzer::TestMergeVertex() |
810 | { |
811 | TestMergeSubShapes(TopAbs_VERTEX); |
812 | } |
813 | |
814 | // ================================================================================ |
815 | // function: TestMergeEdge |
816 | // purpose: |
817 | // ================================================================================ |
818 | void BOPAlgo_ArgumentAnalyzer::TestMergeEdge() |
819 | { |
820 | TestMergeSubShapes(TopAbs_EDGE); |
821 | } |
822 | |
823 | // ================================================================================ |
824 | // function: TestMergeFace |
825 | // purpose: |
826 | // ================================================================================ |
827 | // void BOPAlgo_ArgumentAnalyzer::TestMergeFace() |
828 | // { |
829 | // not implemented |
830 | // } |