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