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