b311480e |
1 | // Created on: 1995-12-08 |
2 | // Created by: Jacques GOUSSARD |
3 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
42cf5bc1 |
17 | #include <BRepCheck_Analyzer.hxx> |
000c21fa |
18 | |
7fd59977 |
19 | #include <BRepCheck_Edge.hxx> |
7fd59977 |
20 | #include <BRepCheck_Face.hxx> |
42cf5bc1 |
21 | #include <BRepCheck_ListIteratorOfListOfStatus.hxx> |
22 | #include <BRepCheck_Result.hxx> |
7fd59977 |
23 | #include <BRepCheck_Shell.hxx> |
949df2b6 |
24 | #include <BRepCheck_Solid.hxx> |
42cf5bc1 |
25 | #include <BRepCheck_Vertex.hxx> |
26 | #include <BRepCheck_Wire.hxx> |
000c21fa |
27 | #include <NCollection_Array1.hxx> |
28 | #include <NCollection_Shared.hxx> |
29 | #include <OSD_Parallel.hxx> |
42cf5bc1 |
30 | #include <Standard_ErrorHandler.hxx> |
31 | #include <Standard_Failure.hxx> |
000c21fa |
32 | #include <Standard_Mutex.hxx> |
42cf5bc1 |
33 | #include <Standard_NullObject.hxx> |
7fd59977 |
34 | #include <TopExp_Explorer.hxx> |
7fd59977 |
35 | #include <TopoDS.hxx> |
42cf5bc1 |
36 | #include <TopoDS_Iterator.hxx> |
37 | #include <TopoDS_Shape.hxx> |
38 | #include <TopTools_MapOfShape.hxx> |
949df2b6 |
39 | |
000c21fa |
40 | //! Functor for multi-threaded execution. |
41 | class BRepCheck_ParallelAnalyzer |
7fd59977 |
42 | { |
000c21fa |
43 | public: |
44 | BRepCheck_ParallelAnalyzer (NCollection_Array1< NCollection_Array1<TopoDS_Shape> >& theArray, |
45 | const BRepCheck_IndexedDataMapOfShapeResult& theMap) |
46 | : myArray (theArray), |
47 | myMap (theMap) |
48 | { |
49 | // |
7fd59977 |
50 | } |
000c21fa |
51 | |
52 | void operator() (const Standard_Integer theVectorIndex) const |
52d45841 |
53 | { |
000c21fa |
54 | TopExp_Explorer exp; |
55 | for (Standard_Integer aShapeIter = myArray[theVectorIndex].Lower(); |
56 | aShapeIter <= myArray[theVectorIndex].Upper(); ++aShapeIter) |
52d45841 |
57 | { |
000c21fa |
58 | const TopoDS_Shape& aShape = myArray[theVectorIndex][aShapeIter]; |
59 | const TopAbs_ShapeEnum aType = aShape.ShapeType(); |
60 | const Handle(BRepCheck_Result)& aResult = myMap.FindFromKey (aShape); |
61 | switch (aType) |
52d45841 |
62 | { |
000c21fa |
63 | case TopAbs_VERTEX: |
52d45841 |
64 | { |
000c21fa |
65 | // modified by NIZHNY-MKK Wed May 19 16:56:16 2004.BEGIN |
66 | // There is no need to check anything. |
67 | // if (aShape.IsSame(S)) { |
68 | // myMap(S)->Blind(); |
69 | // } |
70 | // modified by NIZHNY-MKK Wed May 19 16:56:23 2004.END |
71 | break; |
52d45841 |
72 | } |
000c21fa |
73 | case TopAbs_EDGE: |
52d45841 |
74 | { |
000c21fa |
75 | try |
52d45841 |
76 | { |
000c21fa |
77 | Handle(BRepCheck_Edge) aResEdge = Handle(BRepCheck_Edge)::DownCast(aResult); |
78 | const BRepCheck_Status ste = aResEdge->CheckPolygonOnTriangulation (TopoDS::Edge (aShape)); |
79 | if (ste != BRepCheck_NoError) |
80 | { |
81 | aResEdge->SetStatus (ste); |
82 | } |
52d45841 |
83 | } |
000c21fa |
84 | catch (Standard_Failure const& anException) |
52d45841 |
85 | { |
000c21fa |
86 | (void)anException; |
87 | if (!aResult.IsNull()) |
88 | { |
89 | aResult->SetFailStatus (aShape); |
90 | } |
52d45841 |
91 | } |
52d45841 |
92 | |
000c21fa |
93 | TopTools_MapOfShape MapS; |
94 | for (exp.Init (aShape, TopAbs_VERTEX); exp.More(); exp.Next()) |
52d45841 |
95 | { |
000c21fa |
96 | const TopoDS_Shape& aVertex = exp.Current(); |
97 | Handle(BRepCheck_Result) aResOfVertex = myMap.FindFromKey (aVertex); |
98 | try |
99 | { |
100 | OCC_CATCH_SIGNALS |
101 | if (MapS.Add (aVertex)) |
102 | { |
103 | aResOfVertex->InContext (aShape); |
104 | } |
105 | } |
106 | catch (Standard_Failure const& anException) |
52d45841 |
107 | { |
000c21fa |
108 | (void)anException; |
109 | if (!aResult.IsNull()) |
52d45841 |
110 | { |
000c21fa |
111 | aResult->SetFailStatus (aShape); |
52d45841 |
112 | } |
113 | |
000c21fa |
114 | if (!aResOfVertex.IsNull()) |
52d45841 |
115 | { |
000c21fa |
116 | aResOfVertex->SetFailStatus (aVertex); |
117 | aResOfVertex->SetFailStatus (aShape); |
52d45841 |
118 | } |
119 | } |
120 | } |
000c21fa |
121 | break; |
52d45841 |
122 | } |
000c21fa |
123 | case TopAbs_WIRE: |
124 | { |
125 | break; |
52d45841 |
126 | } |
000c21fa |
127 | case TopAbs_FACE: |
52d45841 |
128 | { |
000c21fa |
129 | TopTools_MapOfShape MapS; |
130 | for (exp.Init (aShape, TopAbs_VERTEX); exp.More(); exp.Next()) |
52d45841 |
131 | { |
000c21fa |
132 | Handle(BRepCheck_Result) aFaceVertexRes = myMap.FindFromKey (exp.Current()); |
133 | try |
52d45841 |
134 | { |
000c21fa |
135 | OCC_CATCH_SIGNALS |
136 | if (MapS.Add (exp.Current())) |
52d45841 |
137 | { |
000c21fa |
138 | aFaceVertexRes->InContext (aShape); |
52d45841 |
139 | } |
140 | } |
000c21fa |
141 | catch (Standard_Failure const& anException) |
52d45841 |
142 | { |
000c21fa |
143 | (void)anException; |
144 | if (!aResult.IsNull()) |
145 | { |
146 | aResult->SetFailStatus (aShape); |
147 | } |
148 | if (!aFaceVertexRes.IsNull()) |
52d45841 |
149 | { |
000c21fa |
150 | aFaceVertexRes->SetFailStatus (exp.Current()); |
151 | aFaceVertexRes->SetFailStatus (aShape); |
52d45841 |
152 | } |
153 | } |
154 | } |
000c21fa |
155 | |
156 | Standard_Boolean performwire = Standard_True; |
157 | Standard_Boolean isInvalidTolerance = Standard_False; |
158 | MapS.Clear(); |
159 | for (exp.Init (aShape, TopAbs_EDGE); exp.More(); exp.Next()) |
52d45841 |
160 | { |
000c21fa |
161 | const Handle(BRepCheck_Result)& aFaceEdgeRes = myMap.FindFromKey (exp.Current()); |
162 | try |
163 | { |
164 | OCC_CATCH_SIGNALS |
165 | if (MapS.Add (exp.Current())) |
166 | { |
167 | aFaceEdgeRes->InContext (aShape); |
52d45841 |
168 | |
000c21fa |
169 | if (performwire) |
170 | { |
171 | Standard_Mutex::Sentry aLock (aFaceEdgeRes->GetMutex()); |
172 | if (aFaceEdgeRes->IsStatusOnShape(aShape)) |
173 | { |
174 | BRepCheck_ListIteratorOfListOfStatus itl (aFaceEdgeRes->StatusOnShape (aShape)); |
175 | for (; itl.More(); itl.Next()) |
176 | { |
177 | const BRepCheck_Status ste = itl.Value(); |
178 | if (ste == BRepCheck_NoCurveOnSurface || |
179 | ste == BRepCheck_InvalidCurveOnSurface || |
180 | ste == BRepCheck_InvalidRange || |
181 | ste == BRepCheck_InvalidCurveOnClosedSurface) |
182 | { |
183 | performwire = Standard_False; |
184 | break; |
185 | } |
186 | } |
187 | } |
188 | } |
189 | } |
190 | } |
191 | catch (Standard_Failure const& anException) |
192 | { |
193 | (void)anException; |
194 | if (!aResult.IsNull()) |
195 | { |
196 | aResult->SetFailStatus (aShape); |
197 | } |
198 | if (!aFaceEdgeRes.IsNull()) |
199 | { |
200 | aFaceEdgeRes->SetFailStatus (exp.Current()); |
201 | aFaceEdgeRes->SetFailStatus (aShape); |
202 | } |
203 | } |
204 | } |
52d45841 |
205 | |
000c21fa |
206 | Standard_Boolean orientofwires = performwire; |
207 | for (exp.Init (aShape, TopAbs_WIRE); exp.More(); exp.Next()) |
52d45841 |
208 | { |
000c21fa |
209 | const Handle(BRepCheck_Result)& aFaceWireRes = myMap.FindFromKey (exp.Current()); |
210 | try |
211 | { |
212 | OCC_CATCH_SIGNALS |
213 | aFaceWireRes->InContext (aShape); |
214 | |
215 | if (orientofwires) |
216 | { |
217 | Standard_Mutex::Sentry aLock (aFaceWireRes->GetMutex()); |
218 | if (aFaceWireRes->IsStatusOnShape (aShape)) |
219 | { |
220 | const BRepCheck_ListOfStatus& aStatusList = aFaceWireRes->StatusOnShape (aShape); |
221 | BRepCheck_ListIteratorOfListOfStatus itl (aStatusList); |
222 | for (; itl.More(); itl.Next()) |
223 | { |
224 | BRepCheck_Status ste = itl.Value(); |
225 | if (ste != BRepCheck_NoError) |
226 | { |
227 | orientofwires = Standard_False; |
228 | break; |
229 | } |
230 | } |
231 | } |
232 | } |
233 | } |
234 | catch (Standard_Failure const& anException) |
235 | { |
236 | (void)anException; |
237 | if (!aResult.IsNull()) |
238 | { |
239 | aResult->SetFailStatus (aShape); |
240 | } |
241 | if (!aFaceWireRes.IsNull()) |
242 | { |
243 | aFaceWireRes->SetFailStatus (exp.Current()); |
244 | aFaceWireRes->SetFailStatus (aShape); |
245 | } |
246 | } |
52d45841 |
247 | } |
52d45841 |
248 | |
000c21fa |
249 | try |
52d45841 |
250 | { |
000c21fa |
251 | OCC_CATCH_SIGNALS |
252 | const Handle(BRepCheck_Face) aFaceRes = Handle(BRepCheck_Face)::DownCast(aResult); |
253 | if (isInvalidTolerance) |
254 | { |
255 | aFaceRes->SetStatus (BRepCheck_InvalidToleranceValue); |
256 | } |
257 | else if (performwire) |
258 | { |
259 | if (orientofwires) |
260 | { |
261 | aFaceRes->OrientationOfWires (Standard_True);// on enregistre |
262 | } |
263 | else |
264 | { |
265 | aFaceRes->SetUnorientable(); |
266 | } |
267 | } |
268 | else |
269 | { |
270 | aFaceRes->SetUnorientable(); |
271 | } |
52d45841 |
272 | } |
000c21fa |
273 | catch (Standard_Failure const& anException) |
52d45841 |
274 | { |
000c21fa |
275 | (void)anException; |
276 | if (!aResult.IsNull()) |
277 | { |
278 | aResult->SetFailStatus (aShape); |
279 | } |
280 | |
281 | for (exp.Init (aShape, TopAbs_WIRE); exp.More(); exp.Next()) |
282 | { |
283 | Handle(BRepCheck_Result) aFaceCatchRes = myMap.FindFromKey (exp.Current()); |
284 | if (!aFaceCatchRes.IsNull()) |
285 | { |
286 | aFaceCatchRes->SetFailStatus (exp.Current()); |
287 | aFaceCatchRes->SetFailStatus (aShape); |
288 | aResult->SetFailStatus (exp.Current()); |
289 | } |
290 | } |
52d45841 |
291 | } |
000c21fa |
292 | break; |
52d45841 |
293 | } |
000c21fa |
294 | case TopAbs_SHELL: |
52d45841 |
295 | { |
000c21fa |
296 | break; |
52d45841 |
297 | } |
000c21fa |
298 | case TopAbs_SOLID: |
52d45841 |
299 | { |
000c21fa |
300 | exp.Init (aShape, TopAbs_SHELL); |
301 | for (; exp.More(); exp.Next()) |
52d45841 |
302 | { |
000c21fa |
303 | const TopoDS_Shape& aShell = exp.Current(); |
304 | Handle(BRepCheck_Result) aSolidRes = myMap.FindFromKey (aShell); |
305 | try |
306 | { |
307 | OCC_CATCH_SIGNALS |
308 | aSolidRes->InContext (aShape); |
309 | } |
310 | catch (Standard_Failure const& anException) |
311 | { |
312 | (void)anException; |
313 | if (!aResult.IsNull()) |
314 | { |
315 | aResult->SetFailStatus (aShape); |
316 | } |
317 | if (!aSolidRes.IsNull()) |
318 | { |
319 | aSolidRes->SetFailStatus (exp.Current()); |
320 | aSolidRes->SetFailStatus (aShape); |
321 | } |
322 | } |
52d45841 |
323 | } |
000c21fa |
324 | break; |
325 | } |
326 | default: |
327 | { |
328 | break; |
52d45841 |
329 | } |
7fd59977 |
330 | } |
331 | } |
000c21fa |
332 | } |
52d45841 |
333 | |
000c21fa |
334 | private: |
bec59435 |
335 | BRepCheck_ParallelAnalyzer& operator=(const BRepCheck_ParallelAnalyzer&) Standard_DELETE; |
000c21fa |
336 | |
bec59435 |
337 | private: |
000c21fa |
338 | NCollection_Array1< NCollection_Array1<TopoDS_Shape> >& myArray; |
339 | const BRepCheck_IndexedDataMapOfShapeResult& myMap; |
340 | }; |
341 | |
342 | //======================================================================= |
343 | //function : Init |
344 | //purpose : |
345 | //======================================================================= |
346 | void BRepCheck_Analyzer::Init (const TopoDS_Shape& theShape, |
0ffecc2f |
347 | const Standard_Boolean B) |
000c21fa |
348 | { |
349 | if (theShape.IsNull()) |
350 | { |
351 | throw Standard_NullObject ("BRepCheck_Analyzer::Init() - NULL shape"); |
352 | } |
353 | |
354 | myShape = theShape; |
355 | myMap.Clear(); |
0ffecc2f |
356 | Put (theShape, B); |
357 | Perform(); |
000c21fa |
358 | } |
359 | |
360 | //======================================================================= |
361 | //function : Put |
362 | //purpose : |
363 | //======================================================================= |
364 | void BRepCheck_Analyzer::Put (const TopoDS_Shape& theShape, |
0ffecc2f |
365 | const Standard_Boolean B) |
000c21fa |
366 | { |
367 | if (myMap.Contains (theShape)) |
368 | { |
369 | return; |
370 | } |
371 | |
372 | Handle(BRepCheck_Result) HR; |
373 | switch (theShape.ShapeType()) |
374 | { |
375 | case TopAbs_VERTEX: |
376 | HR = new BRepCheck_Vertex (TopoDS::Vertex (theShape)); |
377 | break; |
378 | case TopAbs_EDGE: |
379 | HR = new BRepCheck_Edge (TopoDS::Edge (theShape)); |
380 | Handle(BRepCheck_Edge)::DownCast(HR)->GeometricControls (B); |
0ffecc2f |
381 | Handle(BRepCheck_Edge)::DownCast(HR)->SetExactMethod(myIsExact); |
000c21fa |
382 | break; |
383 | case TopAbs_WIRE: |
384 | HR = new BRepCheck_Wire (TopoDS::Wire (theShape)); |
385 | Handle(BRepCheck_Wire)::DownCast(HR)->GeometricControls (B); |
386 | break; |
387 | case TopAbs_FACE: |
388 | HR = new BRepCheck_Face (TopoDS::Face (theShape)); |
389 | Handle(BRepCheck_Face)::DownCast(HR)->GeometricControls (B); |
390 | break; |
391 | case TopAbs_SHELL: |
392 | HR = new BRepCheck_Shell (TopoDS::Shell (theShape)); |
393 | break; |
394 | case TopAbs_SOLID: |
395 | HR = new BRepCheck_Solid (TopoDS::Solid (theShape)); |
396 | break; |
397 | case TopAbs_COMPSOLID: |
398 | case TopAbs_COMPOUND: |
399 | break; |
400 | default: |
401 | break; |
402 | } |
403 | |
404 | if (!HR.IsNull()) |
405 | { |
0ffecc2f |
406 | HR->SetParallel (myIsParallel); |
000c21fa |
407 | } |
408 | myMap.Add (theShape, HR); |
409 | |
410 | for (TopoDS_Iterator theIterator (theShape); theIterator.More(); theIterator.Next()) |
411 | { |
0ffecc2f |
412 | Put (theIterator.Value(), B); // performs minimum on each shape |
000c21fa |
413 | } |
414 | } |
415 | |
416 | //======================================================================= |
417 | //function : Perform |
418 | //purpose : |
419 | //======================================================================= |
0ffecc2f |
420 | void BRepCheck_Analyzer::Perform() |
000c21fa |
421 | { |
422 | const Standard_Integer aMapSize = myMap.Size(); |
423 | const Standard_Integer aMinTaskSize = 10; |
424 | const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool(); |
425 | const Standard_Integer aNbThreads = aThreadPool->NbThreads(); |
426 | Standard_Integer aNbTasks = aNbThreads * 10; |
427 | Standard_Integer aTaskSize = (Standard_Integer)Ceiling ((double)aMapSize / aNbTasks); |
428 | if (aTaskSize < aMinTaskSize) |
429 | { |
430 | aTaskSize = aMinTaskSize; |
431 | aNbTasks = (Standard_Integer)Ceiling ((double)aMapSize / aTaskSize); |
432 | } |
433 | |
434 | NCollection_Array1< NCollection_Array1<TopoDS_Shape> > aArrayOfArray (0, aNbTasks - 1); |
435 | for (Standard_Integer anI = 1; anI <= aMapSize; ++anI) |
436 | { |
437 | Standard_Integer aVectIndex = (anI-1) / aTaskSize; |
438 | Standard_Integer aShapeIndex = (anI-1) % aTaskSize; |
439 | if (aShapeIndex == 0) |
52d45841 |
440 | { |
000c21fa |
441 | Standard_Integer aVectorSize = aTaskSize; |
442 | Standard_Integer aTailSize = aMapSize - aVectIndex * aTaskSize; |
443 | if (aTailSize < aTaskSize) |
444 | { |
445 | aVectorSize = aTailSize; |
446 | } |
447 | aArrayOfArray[aVectIndex].Resize (0, aVectorSize - 1, Standard_False); |
949df2b6 |
448 | } |
000c21fa |
449 | aArrayOfArray[aVectIndex][aShapeIndex] = myMap.FindKey (anI); |
450 | } |
7fd59977 |
451 | |
000c21fa |
452 | BRepCheck_ParallelAnalyzer aParallelAnalyzer (aArrayOfArray, myMap); |
0ffecc2f |
453 | OSD_Parallel::For (0, aArrayOfArray.Size(), aParallelAnalyzer, !myIsParallel); |
000c21fa |
454 | } |
7fd59977 |
455 | |
456 | //======================================================================= |
457 | //function : IsValid |
458 | //purpose : |
459 | //======================================================================= |
460 | |
461 | Standard_Boolean BRepCheck_Analyzer::IsValid(const TopoDS_Shape& S) const |
462 | { |
000c21fa |
463 | if (!myMap.FindFromKey (S).IsNull()) |
464 | { |
7fd59977 |
465 | BRepCheck_ListIteratorOfListOfStatus itl; |
000c21fa |
466 | itl.Initialize (myMap.FindFromKey (S)->Status()); |
7fd59977 |
467 | if (itl.Value() != BRepCheck_NoError) { // a voir |
468 | return Standard_False; |
469 | } |
470 | } |
471 | |
472 | for(TopoDS_Iterator theIterator(S);theIterator.More();theIterator.Next()) { |
473 | if (!IsValid(theIterator.Value())) { |
474 | return Standard_False; |
475 | } |
476 | } |
477 | |
478 | switch (S.ShapeType()) { |
479 | case TopAbs_EDGE: |
480 | { |
481 | return ValidSub(S,TopAbs_VERTEX); |
482 | } |
483 | // break; |
484 | case TopAbs_FACE: |
485 | { |
486 | Standard_Boolean valid = ValidSub(S,TopAbs_WIRE); |
487 | valid = valid && ValidSub(S,TopAbs_EDGE); |
488 | valid = valid && ValidSub(S,TopAbs_VERTEX); |
489 | return valid; |
490 | } |
491 | |
492 | // break; |
493 | case TopAbs_SHELL: |
494 | // return ValidSub(S,TopAbs_FACE); |
495 | break; |
496 | case TopAbs_SOLID: |
497 | // return ValidSub(S,TopAbs_EDGE); |
498 | // break; |
499 | return ValidSub(S,TopAbs_SHELL); |
500 | break; |
501 | default: |
502 | break; |
503 | } |
504 | |
505 | return Standard_True; |
506 | } |
507 | |
508 | //======================================================================= |
509 | //function : ValidSub |
510 | //purpose : |
511 | //======================================================================= |
512 | |
513 | Standard_Boolean BRepCheck_Analyzer::ValidSub |
514 | (const TopoDS_Shape& S, |
515 | const TopAbs_ShapeEnum SubType) const |
516 | { |
517 | BRepCheck_ListIteratorOfListOfStatus itl; |
518 | TopExp_Explorer exp; |
519 | for (exp.Init(S,SubType);exp.More(); exp.Next()) { |
520 | // for (TopExp_Explorer exp(S,SubType);exp.More(); exp.Next()) { |
000c21fa |
521 | const Handle(BRepCheck_Result)& RV = myMap.FindFromKey(exp.Current()); |
7fd59977 |
522 | for (RV->InitContextIterator(); |
949df2b6 |
523 | RV->MoreShapeInContext(); |
524 | RV->NextShapeInContext()) { |
7fd59977 |
525 | if (RV->ContextualShape().IsSame(S)) { |
949df2b6 |
526 | break; |
7fd59977 |
527 | } |
528 | } |
529 | |
530 | if(!RV->MoreShapeInContext()) break; |
531 | |
532 | for (itl.Initialize(RV->StatusOnShape()); itl.More(); itl.Next()) { |
533 | if (itl.Value() != BRepCheck_NoError) { |
949df2b6 |
534 | return Standard_False; |
7fd59977 |
535 | } |
536 | } |
537 | } |
538 | return Standard_True ; |
539 | } |