0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / BRepCheck / BRepCheck_Analyzer.cxx
CommitLineData
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.
41class BRepCheck_ParallelAnalyzer
7fd59977 42{
000c21fa 43public:
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 334private:
bec59435 335 BRepCheck_ParallelAnalyzer& operator=(const BRepCheck_ParallelAnalyzer&) Standard_DELETE;
000c21fa 336
bec59435 337private:
000c21fa 338 NCollection_Array1< NCollection_Array1<TopoDS_Shape> >& myArray;
339 const BRepCheck_IndexedDataMapOfShapeResult& myMap;
340};
341
342//=======================================================================
343//function : Init
344//purpose :
345//=======================================================================
346void 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//=======================================================================
364void 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 420void 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
461Standard_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
513Standard_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}