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