mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-07-30 13:05:50 +03:00
540 lines
16 KiB
C++
540 lines
16 KiB
C++
// Created on: 1995-12-08
|
|
// Created by: Jacques GOUSSARD
|
|
// Copyright (c) 1995-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <BRepCheck_Analyzer.hxx>
|
|
|
|
#include <BRepCheck_Edge.hxx>
|
|
#include <BRepCheck_Face.hxx>
|
|
#include <BRepCheck_ListIteratorOfListOfStatus.hxx>
|
|
#include <BRepCheck_Result.hxx>
|
|
#include <BRepCheck_Shell.hxx>
|
|
#include <BRepCheck_Solid.hxx>
|
|
#include <BRepCheck_Vertex.hxx>
|
|
#include <BRepCheck_Wire.hxx>
|
|
#include <NCollection_Array1.hxx>
|
|
#include <NCollection_Shared.hxx>
|
|
#include <OSD_Parallel.hxx>
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <Standard_Failure.hxx>
|
|
#include <Standard_Mutex.hxx>
|
|
#include <Standard_NullObject.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
|
|
//! Functor for multi-threaded execution.
|
|
class BRepCheck_ParallelAnalyzer
|
|
{
|
|
public:
|
|
BRepCheck_ParallelAnalyzer (NCollection_Array1< NCollection_Array1<TopoDS_Shape> >& theArray,
|
|
const BRepCheck_IndexedDataMapOfShapeResult& theMap)
|
|
: myArray (theArray),
|
|
myMap (theMap)
|
|
{
|
|
//
|
|
}
|
|
|
|
void operator() (const Standard_Integer theVectorIndex) const
|
|
{
|
|
TopExp_Explorer exp;
|
|
for (Standard_Integer aShapeIter = myArray[theVectorIndex].Lower();
|
|
aShapeIter <= myArray[theVectorIndex].Upper(); ++aShapeIter)
|
|
{
|
|
const TopoDS_Shape& aShape = myArray[theVectorIndex][aShapeIter];
|
|
const TopAbs_ShapeEnum aType = aShape.ShapeType();
|
|
const Handle(BRepCheck_Result)& aResult = myMap.FindFromKey (aShape);
|
|
switch (aType)
|
|
{
|
|
case TopAbs_VERTEX:
|
|
{
|
|
// modified by NIZHNY-MKK Wed May 19 16:56:16 2004.BEGIN
|
|
// There is no need to check anything.
|
|
// if (aShape.IsSame(S)) {
|
|
// myMap(S)->Blind();
|
|
// }
|
|
// modified by NIZHNY-MKK Wed May 19 16:56:23 2004.END
|
|
break;
|
|
}
|
|
case TopAbs_EDGE:
|
|
{
|
|
try
|
|
{
|
|
Handle(BRepCheck_Edge) aResEdge = Handle(BRepCheck_Edge)::DownCast(aResult);
|
|
const BRepCheck_Status ste = aResEdge->CheckPolygonOnTriangulation (TopoDS::Edge (aShape));
|
|
if (ste != BRepCheck_NoError)
|
|
{
|
|
aResEdge->SetStatus (ste);
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
|
|
TopTools_MapOfShape MapS;
|
|
for (exp.Init (aShape, TopAbs_VERTEX); exp.More(); exp.Next())
|
|
{
|
|
const TopoDS_Shape& aVertex = exp.Current();
|
|
Handle(BRepCheck_Result) aResOfVertex = myMap.FindFromKey (aVertex);
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
if (MapS.Add (aVertex))
|
|
{
|
|
aResOfVertex->InContext (aShape);
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
|
|
if (!aResOfVertex.IsNull())
|
|
{
|
|
aResOfVertex->SetFailStatus (aVertex);
|
|
aResOfVertex->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case TopAbs_WIRE:
|
|
{
|
|
break;
|
|
}
|
|
case TopAbs_FACE:
|
|
{
|
|
TopTools_MapOfShape MapS;
|
|
for (exp.Init (aShape, TopAbs_VERTEX); exp.More(); exp.Next())
|
|
{
|
|
Handle(BRepCheck_Result) aFaceVertexRes = myMap.FindFromKey (exp.Current());
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
if (MapS.Add (exp.Current()))
|
|
{
|
|
aFaceVertexRes->InContext (aShape);
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
if (!aFaceVertexRes.IsNull())
|
|
{
|
|
aFaceVertexRes->SetFailStatus (exp.Current());
|
|
aFaceVertexRes->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Boolean performwire = Standard_True;
|
|
Standard_Boolean isInvalidTolerance = Standard_False;
|
|
MapS.Clear();
|
|
for (exp.Init (aShape, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
const Handle(BRepCheck_Result)& aFaceEdgeRes = myMap.FindFromKey (exp.Current());
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
if (MapS.Add (exp.Current()))
|
|
{
|
|
aFaceEdgeRes->InContext (aShape);
|
|
|
|
if (performwire)
|
|
{
|
|
Standard_Mutex::Sentry aLock (aFaceEdgeRes->GetMutex());
|
|
if (aFaceEdgeRes->IsStatusOnShape(aShape))
|
|
{
|
|
BRepCheck_ListIteratorOfListOfStatus itl (aFaceEdgeRes->StatusOnShape (aShape));
|
|
for (; itl.More(); itl.Next())
|
|
{
|
|
const BRepCheck_Status ste = itl.Value();
|
|
if (ste == BRepCheck_NoCurveOnSurface ||
|
|
ste == BRepCheck_InvalidCurveOnSurface ||
|
|
ste == BRepCheck_InvalidRange ||
|
|
ste == BRepCheck_InvalidCurveOnClosedSurface)
|
|
{
|
|
performwire = Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
if (!aFaceEdgeRes.IsNull())
|
|
{
|
|
aFaceEdgeRes->SetFailStatus (exp.Current());
|
|
aFaceEdgeRes->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Boolean orientofwires = performwire;
|
|
for (exp.Init (aShape, TopAbs_WIRE); exp.More(); exp.Next())
|
|
{
|
|
const Handle(BRepCheck_Result)& aFaceWireRes = myMap.FindFromKey (exp.Current());
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
aFaceWireRes->InContext (aShape);
|
|
|
|
if (orientofwires)
|
|
{
|
|
Standard_Mutex::Sentry aLock (aFaceWireRes->GetMutex());
|
|
if (aFaceWireRes->IsStatusOnShape (aShape))
|
|
{
|
|
const BRepCheck_ListOfStatus& aStatusList = aFaceWireRes->StatusOnShape (aShape);
|
|
BRepCheck_ListIteratorOfListOfStatus itl (aStatusList);
|
|
for (; itl.More(); itl.Next())
|
|
{
|
|
BRepCheck_Status ste = itl.Value();
|
|
if (ste != BRepCheck_NoError)
|
|
{
|
|
orientofwires = Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
if (!aFaceWireRes.IsNull())
|
|
{
|
|
aFaceWireRes->SetFailStatus (exp.Current());
|
|
aFaceWireRes->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
const Handle(BRepCheck_Face) aFaceRes = Handle(BRepCheck_Face)::DownCast(aResult);
|
|
if (isInvalidTolerance)
|
|
{
|
|
aFaceRes->SetStatus (BRepCheck_InvalidToleranceValue);
|
|
}
|
|
else if (performwire)
|
|
{
|
|
if (orientofwires)
|
|
{
|
|
aFaceRes->OrientationOfWires (Standard_True);// on enregistre
|
|
}
|
|
else
|
|
{
|
|
aFaceRes->SetUnorientable();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aFaceRes->SetUnorientable();
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
|
|
for (exp.Init (aShape, TopAbs_WIRE); exp.More(); exp.Next())
|
|
{
|
|
Handle(BRepCheck_Result) aFaceCatchRes = myMap.FindFromKey (exp.Current());
|
|
if (!aFaceCatchRes.IsNull())
|
|
{
|
|
aFaceCatchRes->SetFailStatus (exp.Current());
|
|
aFaceCatchRes->SetFailStatus (aShape);
|
|
aResult->SetFailStatus (exp.Current());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case TopAbs_SHELL:
|
|
{
|
|
break;
|
|
}
|
|
case TopAbs_SOLID:
|
|
{
|
|
exp.Init (aShape, TopAbs_SHELL);
|
|
for (; exp.More(); exp.Next())
|
|
{
|
|
const TopoDS_Shape& aShell = exp.Current();
|
|
Handle(BRepCheck_Result) aSolidRes = myMap.FindFromKey (aShell);
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
aSolidRes->InContext (aShape);
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
(void)anException;
|
|
if (!aResult.IsNull())
|
|
{
|
|
aResult->SetFailStatus (aShape);
|
|
}
|
|
if (!aSolidRes.IsNull())
|
|
{
|
|
aSolidRes->SetFailStatus (exp.Current());
|
|
aSolidRes->SetFailStatus (aShape);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
BRepCheck_ParallelAnalyzer& operator=(const BRepCheck_ParallelAnalyzer&) Standard_DELETE;
|
|
|
|
private:
|
|
NCollection_Array1< NCollection_Array1<TopoDS_Shape> >& myArray;
|
|
const BRepCheck_IndexedDataMapOfShapeResult& myMap;
|
|
};
|
|
|
|
//=======================================================================
|
|
//function : Init
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepCheck_Analyzer::Init (const TopoDS_Shape& theShape,
|
|
const Standard_Boolean B)
|
|
{
|
|
if (theShape.IsNull())
|
|
{
|
|
throw Standard_NullObject ("BRepCheck_Analyzer::Init() - NULL shape");
|
|
}
|
|
|
|
myShape = theShape;
|
|
myMap.Clear();
|
|
Put (theShape, B);
|
|
Perform();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Put
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepCheck_Analyzer::Put (const TopoDS_Shape& theShape,
|
|
const Standard_Boolean B)
|
|
{
|
|
if (myMap.Contains (theShape))
|
|
{
|
|
return;
|
|
}
|
|
|
|
Handle(BRepCheck_Result) HR;
|
|
switch (theShape.ShapeType())
|
|
{
|
|
case TopAbs_VERTEX:
|
|
HR = new BRepCheck_Vertex (TopoDS::Vertex (theShape));
|
|
break;
|
|
case TopAbs_EDGE:
|
|
HR = new BRepCheck_Edge (TopoDS::Edge (theShape));
|
|
Handle(BRepCheck_Edge)::DownCast(HR)->GeometricControls (B);
|
|
Handle(BRepCheck_Edge)::DownCast(HR)->SetExactMethod(myIsExact);
|
|
break;
|
|
case TopAbs_WIRE:
|
|
HR = new BRepCheck_Wire (TopoDS::Wire (theShape));
|
|
Handle(BRepCheck_Wire)::DownCast(HR)->GeometricControls (B);
|
|
break;
|
|
case TopAbs_FACE:
|
|
HR = new BRepCheck_Face (TopoDS::Face (theShape));
|
|
Handle(BRepCheck_Face)::DownCast(HR)->GeometricControls (B);
|
|
break;
|
|
case TopAbs_SHELL:
|
|
HR = new BRepCheck_Shell (TopoDS::Shell (theShape));
|
|
break;
|
|
case TopAbs_SOLID:
|
|
HR = new BRepCheck_Solid (TopoDS::Solid (theShape));
|
|
break;
|
|
case TopAbs_COMPSOLID:
|
|
case TopAbs_COMPOUND:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!HR.IsNull())
|
|
{
|
|
HR->SetParallel (myIsParallel);
|
|
}
|
|
myMap.Add (theShape, HR);
|
|
|
|
for (TopoDS_Iterator theIterator (theShape); theIterator.More(); theIterator.Next())
|
|
{
|
|
Put (theIterator.Value(), B); // performs minimum on each shape
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose :
|
|
//=======================================================================
|
|
void BRepCheck_Analyzer::Perform()
|
|
{
|
|
const Standard_Integer aMapSize = myMap.Size();
|
|
const Standard_Integer aMinTaskSize = 10;
|
|
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
|
|
const Standard_Integer aNbThreads = aThreadPool->NbThreads();
|
|
Standard_Integer aNbTasks = aNbThreads * 10;
|
|
Standard_Integer aTaskSize = (Standard_Integer)Ceiling ((double)aMapSize / aNbTasks);
|
|
if (aTaskSize < aMinTaskSize)
|
|
{
|
|
aTaskSize = aMinTaskSize;
|
|
aNbTasks = (Standard_Integer)Ceiling ((double)aMapSize / aTaskSize);
|
|
}
|
|
|
|
NCollection_Array1< NCollection_Array1<TopoDS_Shape> > aArrayOfArray (0, aNbTasks - 1);
|
|
for (Standard_Integer anI = 1; anI <= aMapSize; ++anI)
|
|
{
|
|
Standard_Integer aVectIndex = (anI-1) / aTaskSize;
|
|
Standard_Integer aShapeIndex = (anI-1) % aTaskSize;
|
|
if (aShapeIndex == 0)
|
|
{
|
|
Standard_Integer aVectorSize = aTaskSize;
|
|
Standard_Integer aTailSize = aMapSize - aVectIndex * aTaskSize;
|
|
if (aTailSize < aTaskSize)
|
|
{
|
|
aVectorSize = aTailSize;
|
|
}
|
|
aArrayOfArray[aVectIndex].Resize (0, aVectorSize - 1, Standard_False);
|
|
}
|
|
aArrayOfArray[aVectIndex][aShapeIndex] = myMap.FindKey (anI);
|
|
}
|
|
|
|
BRepCheck_ParallelAnalyzer aParallelAnalyzer (aArrayOfArray, myMap);
|
|
OSD_Parallel::For (0, aArrayOfArray.Size(), aParallelAnalyzer, !myIsParallel);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : IsValid
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepCheck_Analyzer::IsValid(const TopoDS_Shape& S) const
|
|
{
|
|
if (!myMap.FindFromKey (S).IsNull())
|
|
{
|
|
BRepCheck_ListIteratorOfListOfStatus itl;
|
|
itl.Initialize (myMap.FindFromKey (S)->Status());
|
|
if (itl.Value() != BRepCheck_NoError) { // a voir
|
|
return Standard_False;
|
|
}
|
|
}
|
|
|
|
for(TopoDS_Iterator theIterator(S);theIterator.More();theIterator.Next()) {
|
|
if (!IsValid(theIterator.Value())) {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
|
|
switch (S.ShapeType()) {
|
|
case TopAbs_EDGE:
|
|
{
|
|
return ValidSub(S,TopAbs_VERTEX);
|
|
}
|
|
// break;
|
|
case TopAbs_FACE:
|
|
{
|
|
Standard_Boolean valid = ValidSub(S,TopAbs_WIRE);
|
|
valid = valid && ValidSub(S,TopAbs_EDGE);
|
|
valid = valid && ValidSub(S,TopAbs_VERTEX);
|
|
return valid;
|
|
}
|
|
|
|
// break;
|
|
case TopAbs_SHELL:
|
|
// return ValidSub(S,TopAbs_FACE);
|
|
break;
|
|
case TopAbs_SOLID:
|
|
// return ValidSub(S,TopAbs_EDGE);
|
|
// break;
|
|
return ValidSub(S,TopAbs_SHELL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ValidSub
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean BRepCheck_Analyzer::ValidSub
|
|
(const TopoDS_Shape& S,
|
|
const TopAbs_ShapeEnum SubType) const
|
|
{
|
|
BRepCheck_ListIteratorOfListOfStatus itl;
|
|
TopExp_Explorer exp;
|
|
for (exp.Init(S,SubType);exp.More(); exp.Next()) {
|
|
// for (TopExp_Explorer exp(S,SubType);exp.More(); exp.Next()) {
|
|
const Handle(BRepCheck_Result)& RV = myMap.FindFromKey(exp.Current());
|
|
for (RV->InitContextIterator();
|
|
RV->MoreShapeInContext();
|
|
RV->NextShapeInContext()) {
|
|
if (RV->ContextualShape().IsSame(S)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!RV->MoreShapeInContext()) break;
|
|
|
|
for (itl.Initialize(RV->StatusOnShape()); itl.More(); itl.Next()) {
|
|
if (itl.Value() != BRepCheck_NoError) {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
}
|
|
return Standard_True ;
|
|
}
|