X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IMeasureOperations.cxx;h=7bfc35b5f19243ae780e2a1823a8ec67b8d441a0;hb=9f730900596e9412f431c23b2bd985063814a750;hp=5a191cd6bcc4c13e09edb0441532a901eb37a0d3;hpb=4e4b3762fc1215eb520840fe65eaeeea0854eff8;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index 5a191cd6b..7bfc35b5f 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -20,105 +20,81 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include - #include +#include +#include + +#include +#include +#include +#include #include -#include -#include -#include + +#include +#include #include -#include +#include +#include #include -#include #include -#include - #include -#include -#include // OCCT Includes -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include -#include #include #include #include #include +#include +#include +#include #include #include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include +#include +#include #include #include - -#include - -#include -#include - #include #include - +#include #include #include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC +#include + //============================================================================= /*! * Constructor */ //============================================================================= -GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID) -: GEOM_IOperations(theEngine, theDocID) +GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine) +: GEOM_IOperations(theEngine) { MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations"); } @@ -163,7 +139,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape int geom_type = theShape->GetType(); // check if it's advanced shape - if ( geom_type > ADVANCED_BASE ) { + if ( geom_type > USER_TYPE ) { SetErrorCode(OK); return SK_ADVANCED; } @@ -172,14 +148,48 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape GEOMAlgo_ShapeInfoFiller aSF; aSF.SetShape(aShape); aSF.Perform(); + Standard_Integer iErr = aSF.ErrorStatus(); + if (iErr) { SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller"); return SK_NO_SHAPE; } const GEOMAlgo_ShapeInfo& anInfo = aSF.Info(); - // Interprete results + // specific processing for some "advanced" objects + switch ( geom_type ) { + case GEOM_MARKER: + // local coordinate system + // (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz + + TopoDS_Face aFace = TopoDS::Face( aShape ); + Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) ); + gp_Pnt aC = aPlane->Pln().Location(); + gp_Ax3 anAx3 = aPlane->Pln().Position(); + + theDoubles->Append(aC.X()); + theDoubles->Append(aC.Y()); + theDoubles->Append(aC.Z()); + + gp_Dir aD = anAx3.XDirection(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + aD = anAx3.YDirection(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + aD = anAx3.Direction(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + + SetErrorCode(OK); + return SK_LCS; + } + + // Interpret results TopAbs_ShapeEnum aType = anInfo.Type(); switch (aType) { @@ -560,35 +570,22 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aD.X()); theDoubles->Append(aD.Y()); theDoubles->Append(aD.Z()); + + if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE) + { + // (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices + aKind = SK_PLANAR; + + theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE)); + theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX)); + } } break; default: - if (anInfo.KindOfShape() == GEOMAlgo_KS_PLANE) { - // (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices - - aKind = SK_PLANAR; - - gp_Pnt aC = anInfo.Location(); - theDoubles->Append(aC.X()); - theDoubles->Append(aC.Y()); - theDoubles->Append(aC.Z()); - - gp_Ax3 anAx3 = anInfo.Position(); - gp_Dir aD = anAx3.Direction(); - theDoubles->Append(aD.X()); - theDoubles->Append(aD.Y()); - theDoubles->Append(aD.Z()); - - theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE)); - theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX)); - } - else { - // ??? geompy.kind.FACE nb_edges nb_vertices _surface_type_id_ - // (+) geompy.kind.FACE nb_edges nb_vertices - - theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE)); - theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX)); - } + // ??? geompy.kind.FACE nb_edges nb_vertices _surface_type_id_ + // (+) geompy.kind.FACE nb_edges nb_vertices + theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE)); + theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX)); } } break; @@ -749,6 +746,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP.Z()); } break; + default:; } SetErrorCode(OK); @@ -784,9 +782,7 @@ void GEOMImpl_IMeasureOperations::GetPosition } try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape); @@ -799,9 +795,8 @@ void GEOMImpl_IMeasureOperations::GetPosition aDirZ.Coord(Zx, Zy, Zz); aDirX.Coord(Xx, Xy, Xz); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -821,7 +816,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass if (theShape.IsNull()) return NULL; //Add a new CentreOfMass object - Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG); + Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG); //Add a new CentreOfMass function Handle(GEOM_Function) aFunction = @@ -840,17 +835,14 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass //Compute the CentreOfMass value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Measure driver failed to compute centre of mass"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -868,7 +860,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass //============================================================================= Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex (Handle(GEOM_Object) theShape, - Standard_Integer theIndex) + Standard_Integer theIndex, + Standard_Boolean theUseOri) { SetErrorCode(KO); @@ -878,7 +871,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex if (aRefShape.IsNull()) return NULL; //Add a new Vertex object - Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT); + Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT); //Add a function Handle(GEOM_Function) aFunction = @@ -891,25 +884,26 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex GEOMImpl_IMeasure aCI (aFunction); aCI.SetBase(aRefShape); aCI.SetIndex(theIndex); + aCI.SetUseOri(theUseOri); //Compute try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vertex by index driver failed."); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } //Make a Python command - GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")"; + GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" + << theShape << ", " + << theIndex << ", " + << theUseOri << ")"; SetErrorCode(OK); return aVertex; @@ -929,7 +923,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal if (theFace.IsNull()) return NULL; //Add a new Normale object - Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GetDocID(), GEOM_VECTOR); + Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR); //Add a new Normale function Handle(GEOM_Function) aFunction = @@ -953,17 +947,14 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal //Compute the Normale value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Measure driver failed to compute normake of face"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -985,6 +976,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal */ //============================================================================= void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance, Standard_Real& theLength, Standard_Real& theSurfArea, Standard_Real& theVolume) @@ -1004,28 +996,26 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha //Compute the parameters GProp_GProps LProps, SProps; + Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif - BRepGProp::LinearProperties(aShape, LProps); + BRepGProp::LinearProperties(aShape, LProps, Standard_True); theLength = LProps.Mass(); - BRepGProp::SurfaceProperties(aShape, SProps); + BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True); theSurfArea = SProps.Mass(); theVolume = 0.0; if (aShape.ShapeType() < TopAbs_SHELL) { for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) { GProp_GProps VProps; - BRepGProp::VolumeProperties(Exp.Current(), VProps); + BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True); theVolume += VProps.Mass(); } } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1061,18 +1051,16 @@ void GEOMImpl_IMeasureOperations::GetInertia GProp_GProps System; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (aShape.ShapeType() == TopAbs_VERTEX || aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) { - BRepGProp::LinearProperties(aShape, System); + BRepGProp::LinearProperties(aShape, System, Standard_True); } else if (aShape.ShapeType() == TopAbs_FACE || aShape.ShapeType() == TopAbs_SHELL) { - BRepGProp::SurfaceProperties(aShape, System); + BRepGProp::SurfaceProperties(aShape, System, Standard_True); } else { - BRepGProp::VolumeProperties(aShape, System); + BRepGProp::VolumeProperties(aShape, System, Standard_True); } gp_Mat I = System.MatrixOfInertia(); @@ -1091,9 +1079,8 @@ void GEOMImpl_IMeasureOperations::GetInertia GProp_PrincipalProps Pr = System.PrincipalProperties(); Pr.Moments(Ix,Iy,Iz); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1129,9 +1116,7 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox Bnd_Box B; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif BRepBuilderAPI_Copy aCopyTool (aShape); if (!aCopyTool.IsDone()) { SetErrorCode("GetBoundingBox Error: Bad shape detected"); @@ -1154,9 +1139,8 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1177,7 +1161,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox if (theShape.IsNull()) return NULL; //Add a new BoundingBox object - Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX); + Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX); //Add a new BoundingBox function const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE); @@ -1197,17 +1181,14 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox //Compute the BoundingBox value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Measure driver failed to compute a bounding box"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -1256,9 +1237,7 @@ void GEOMImpl_IMeasureOperations::GetTolerance FaceMax = EdgeMax = VertMax = -RealLast(); try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif for (TopExp_Explorer ExF (aShape, TopAbs_FACE); ExF.More(); ExF.Next()) { TopoDS_Face Face = TopoDS::Face(ExF.Current()); T = BRep_Tool::Tolerance(Face); @@ -1284,9 +1263,8 @@ void GEOMImpl_IMeasureOperations::GetTolerance VertMin = T; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1298,11 +1276,12 @@ void GEOMImpl_IMeasureOperations::GetTolerance * CheckShape */ //============================================================================= -bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, - const Standard_Boolean theIsCheckGeom, - TCollection_AsciiString& theDump) +bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, + const Standard_Boolean theIsCheckGeom, + std::list &theErrors) { SetErrorCode(KO); + theErrors.clear(); if (theShape.IsNull()) return false; @@ -1318,20 +1297,16 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, //Compute the parameters bool isValid = false; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif BRepCheck_Analyzer ana (aShape, theIsCheckGeom); if (ana.IsValid()) { - theDump.Clear(); isValid = true; } else { - StructuralDump(ana, aShape, theDump); + FillErrors(ana, aShape, theErrors); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return false; } @@ -1339,6 +1314,223 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, return isValid; } +//============================================================================= +/*! + * PrintShapeErrors + */ +//============================================================================= +TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors + (Handle(GEOM_Object) theShape, + const std::list &theErrors) +{ + TCollection_AsciiString aDump; + + if (theShape.IsNull()) { + return aDump; + } + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + + if (aRefShape.IsNull()) { + return aDump; + } + + TopoDS_Shape aShape = aRefShape->GetValue(); + + if (aShape.IsNull()) { + SetErrorCode("The Objects has NULL Shape"); + return aDump; + } + + if (!theErrors.empty()) { + // The shape is not valid. Prepare errors for dump. + TopTools_IndexedMapOfShape anIndices; + std::list::const_iterator anIter = theErrors.begin(); + Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo; + nbv = nbe = nbw = nbf = nbs = nbo = 0; + + // Map sub-shapes and their indices + TopExp::MapShapes(aShape, anIndices); + + const Standard_Integer aNbSubShapes = anIndices.Extent(); + TColStd_MapOfInteger aMapPbInd; + + aDump += " -- The Shape has problems :\n"; + aDump += " Check Count\n"; + aDump += " ------------------------------------------------\n"; + + for (; anIter != theErrors.end(); anIter++) { + Standard_Integer aNbShapes = anIter->incriminated.size(); + + switch(anIter->error) { + case BRepCheck_InvalidPointOnCurve: + aDump += " Invalid Point on Curve ................... "; + break; + case BRepCheck_InvalidPointOnCurveOnSurface: + aDump += " Invalid Point on CurveOnSurface .......... "; + break; + case BRepCheck_InvalidPointOnSurface: + aDump += " Invalid Point on Surface ................. "; + break; + case BRepCheck_No3DCurve: + aDump += " No 3D Curve .............................. "; + break; + case BRepCheck_Multiple3DCurve: + aDump += " Multiple 3D Curve ........................ "; + break; + case BRepCheck_Invalid3DCurve: + aDump += " Invalid 3D Curve ......................... "; + break; + case BRepCheck_NoCurveOnSurface: + aDump += " No Curve on Surface ...................... "; + break; + case BRepCheck_InvalidCurveOnSurface: + aDump += " Invalid Curve on Surface ................. "; + break; + case BRepCheck_InvalidCurveOnClosedSurface: + aDump += " Invalid Curve on closed Surface .......... "; + break; + case BRepCheck_InvalidSameRangeFlag: + aDump += " Invalid SameRange Flag ................... "; + break; + case BRepCheck_InvalidSameParameterFlag: + aDump += " Invalid SameParameter Flag ............... "; + break; + case BRepCheck_InvalidDegeneratedFlag: + aDump += " Invalid Degenerated Flag ................. "; + break; + case BRepCheck_FreeEdge: + aDump += " Free Edge ................................ "; + break; + case BRepCheck_InvalidMultiConnexity: + aDump += " Invalid MultiConnexity ................... "; + break; + case BRepCheck_InvalidRange: + aDump += " Invalid Range ............................ "; + break; + case BRepCheck_EmptyWire: + aDump += " Empty Wire ............................... "; + break; + case BRepCheck_RedundantEdge: + aDump += " Redundant Edge ........................... "; + break; + case BRepCheck_SelfIntersectingWire: + aDump += " Self Intersecting Wire ................... "; + break; + case BRepCheck_NoSurface: + aDump += " No Surface ............................... "; + break; + case BRepCheck_InvalidWire: + aDump += " Invalid Wire ............................. "; + break; + case BRepCheck_RedundantWire: + aDump += " Redundant Wire ........................... "; + break; + case BRepCheck_IntersectingWires: + aDump += " Intersecting Wires ....................... "; + break; + case BRepCheck_InvalidImbricationOfWires: + aDump += " Invalid Imbrication of Wires ............. "; + break; + case BRepCheck_EmptyShell: + aDump += " Empty Shell .............................. "; + break; + case BRepCheck_RedundantFace: + aDump += " Redundant Face ........................... "; + break; + case BRepCheck_UnorientableShape: + aDump += " Unorientable Shape ....................... "; + break; + case BRepCheck_NotClosed: + aDump += " Not Closed ............................... "; + break; + case BRepCheck_NotConnected: + aDump += " Not Connected ............................ "; + break; + case BRepCheck_SubshapeNotInShape: + aDump += " Sub-shape not in Shape ................... "; + break; + case BRepCheck_BadOrientation: + aDump += " Bad Orientation .......................... "; + break; + case BRepCheck_BadOrientationOfSubshape: + aDump += " Bad Orientation of Sub-shape ............. "; + break; + case BRepCheck_InvalidToleranceValue: + aDump += " Invalid Tolerance Value .................. "; + break; + case BRepCheck_CheckFail: + aDump += " Check Shape Failure ...................... "; + break; + default: + break; + } + + aDump += TCollection_AsciiString(aNbShapes) + "\n"; + + // Count types of shape. + std::list::const_iterator aShIter = anIter->incriminated.begin(); + + for (; aShIter != anIter->incriminated.end(); aShIter++) { + const Standard_Integer anIndex = *aShIter; + + if (anIndex > 0 && anIndex <= aNbSubShapes && aMapPbInd.Add(anIndex)) { + const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex); + const TopAbs_ShapeEnum aType = aSubShape.ShapeType(); + + switch (aType) { + case TopAbs_VERTEX : nbv++; break; + case TopAbs_EDGE : nbe++; break; + case TopAbs_WIRE : nbw++; break; + case TopAbs_FACE : nbf++; break; + case TopAbs_SHELL : nbs++; break; + case TopAbs_SOLID : nbo++; break; + default : break; + } + } + } + } + + const Standard_Integer aNbFaultyShapes = nbv + nbe + nbw + nbf + nbs + nbo; + aDump += " ------------------------------------------------\n"; + aDump += "*** Shapes with problems : "; + aDump += TCollection_AsciiString(aNbFaultyShapes) + "\n"; + + if (nbv > 0) { + aDump += "VERTEX : "; + if (nbv < 10) aDump += " "; + aDump += TCollection_AsciiString(nbv) + "\n"; + } + if (nbe > 0) { + aDump += "EDGE : "; + if (nbe < 10) aDump += " "; + aDump += TCollection_AsciiString(nbe) + "\n"; + } + if (nbw > 0) { + aDump += "WIRE : "; + if (nbw < 10) aDump += " "; + aDump += TCollection_AsciiString(nbw) + "\n"; + } + if (nbf > 0) { + aDump += "FACE : "; + if (nbf < 10) aDump += " "; + aDump += TCollection_AsciiString(nbf) + "\n"; + } + if (nbs > 0) { + aDump += "SHELL : "; + if (nbs < 10) aDump += " "; + aDump += TCollection_AsciiString(nbs) + "\n"; + } + if (nbo > 0) { + aDump += "SOLID : "; + if (nbo < 10) aDump += " "; + aDump += TCollection_AsciiString(nbo) + "\n"; + } + } + + return aDump; +} + //============================================================================= /*! * CheckSelfIntersections @@ -1346,10 +1538,10 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, //============================================================================= bool GEOMImpl_IMeasureOperations::CheckSelfIntersections (Handle(GEOM_Object) theShape, + const SICheckLevel theCheckLevel, Handle(TColStd_HSequenceOfInteger)& theIntersections) { SetErrorCode(KO); - bool isGood = false; if (theIntersections.IsNull()) theIntersections = new TColStd_HSequenceOfInteger; @@ -1357,17 +1549,15 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections theIntersections->Clear(); if (theShape.IsNull()) - return isGood; + return false; Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return isGood; + if (aRefShape.IsNull()) return false; TopoDS_Shape aShape = aRefShape->GetValue(); - if (aShape.IsNull()) return isGood; + if (aShape.IsNull()) return false; // 0. Prepare data - BRep_Builder aBB; - TopoDS_Compound aCS; TopoDS_Shape aScopy; // GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy); @@ -1376,37 +1566,31 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aScopy, anIndices); - aBB.MakeCompound(aCS); - aBB.Add(aCS, aScopy); - - BOPCol_ListOfShape aLCS; + TopTools_ListOfShape aLCS; aLCS.Append(aScopy); // BOPAlgo_CheckerSI aCSI; // checker of self-interferences aCSI.SetArguments(aLCS); + aCSI.SetLevelOfCheck(theCheckLevel); // 1. Launch the checker aCSI.Perform(); - Standard_Integer iErr = aCSI.ErrorStatus(); - if (iErr) { - return false; // Error - } + Standard_Boolean iErr = aCSI.HasErrors(); - isGood = true; // Standard_Integer aNbS, n1, n2; - BOPDS_MapIteratorMapOfPassKey aItMPK; + BOPDS_MapIteratorOfMapOfPair aItMPK; // // 2. Take the shapes from DS const BOPDS_DS& aDS = aCSI.DS(); aNbS=aDS.NbShapes(); // // 3. Get the pairs of interfered shapes - const BOPDS_MapOfPassKey& aMPK=aDS.Interferences(); + const BOPDS_MapOfPair& aMPK=aDS.Interferences(); aItMPK.Initialize(aMPK); for (; aItMPK.More(); aItMPK.Next()) { - const BOPDS_PassKey& aPK=aItMPK.Value(); - aPK.Ids(n1, n2); + const BOPDS_Pair& aPK=aItMPK.Value(); + aPK.Indices(n1, n2); // if (n1 > aNbS || n2 > aNbS){ return false; // Error @@ -1416,99 +1600,286 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections theIntersections->Append(anIndices.FindIndex(aS1)); theIntersections->Append(anIndices.FindIndex(aS2)); - isGood = false; } - SetErrorCode(OK); - return isGood; + if (!iErr) { + SetErrorCode(OK); + } + + return theIntersections->IsEmpty(); } //============================================================================= /*! - * IsGoodForSolid + * CheckSelfIntersectionsFast */ //============================================================================= -TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape) +bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast + (Handle(GEOM_Object) theShape, + float theDeflection, double theTolerance, + Handle(TColStd_HSequenceOfInteger)& theIntersections) { SetErrorCode(KO); - TCollection_AsciiString aRes = ""; + if (theIntersections.IsNull()) + theIntersections = new TColStd_HSequenceOfInteger; + else + theIntersections->Clear(); - if (theShape.IsNull()) { - aRes = "WRN_NULL_OBJECT_OR_SHAPE"; - } - else { - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) { - aRes = "WRN_NULL_OBJECT_OR_SHAPE"; - } - else { - TopoDS_Shape aShape = aRefShape->GetValue(); - if (aShape.IsNull()) { - aRes = "WRN_NULL_OBJECT_OR_SHAPE"; - } - else { - if (aShape.ShapeType() == TopAbs_COMPOUND) { - TopoDS_Iterator It (aShape, Standard_True, Standard_True); - if (It.More()) aShape = It.Value(); - } - if (aShape.ShapeType() == TopAbs_SHELL) { - BRepCheck_Shell chkShell (TopoDS::Shell(aShape)); - if (chkShell.Closed() == BRepCheck_NotClosed) { - aRes = "WRN_SHAPE_UNCLOSED"; - } - } - else { - aRes = "WRN_SHAPE_NOT_SHELL"; - } - } + if (theShape.IsNull()) + return false; + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return false; + + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) return false; + + // Prepare data + TopoDS_Shape aScopy; + + GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy); + GEOMUtils::MeshShape(aScopy, theDeflection); + + // Map sub-shapes and their indices + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aScopy, anIndices); + + // Checker of fast interferences + BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance); + + // Launch the checker + aTool.Perform(); + + const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements(); + + std::set processed; + + for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) { + Standard_Integer idxLeft = it.Key(); + if (processed.count(idxLeft) > 0) continue; // already added + processed.insert(idxLeft); + const TColStd_PackedMapOfInteger& overlaps = it.Value(); + for (TColStd_MapIteratorOfPackedMapOfInteger subit(overlaps); subit.More(); subit.Next()) { + Standard_Integer idxRight = subit.Key(); + if (processed.count(idxRight) > 0) continue; // already added + const TopoDS_Shape& aS1 = aTool.GetSubShape(idxLeft); + const TopoDS_Shape& aS2 = aTool.GetSubShape(idxRight); + theIntersections->Append(anIndices.FindIndex(aS1)); + theIntersections->Append(anIndices.FindIndex(aS2)); } } - if (aRes.IsEmpty()) + if (aTool.IsDone()) SetErrorCode(OK); - return aRes; + return theIntersections->IsEmpty(); } //============================================================================= /*! - * WhatIs + * CheckBOPArguments */ //============================================================================= -TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape) +bool GEOMImpl_IMeasureOperations::CheckBOPArguments + (const Handle(GEOM_Object) &theShape) { SetErrorCode(KO); - TCollection_AsciiString Astr; - - if (theShape.IsNull()) return Astr; + if (theShape.IsNull()) { + return false; + } Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return Astr; + + if (aRefShape.IsNull()) { + return false; + } TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { - SetErrorCode("The Objects has NULL Shape"); - return Astr; + return false; } //Compute the parameters - if (aShape.ShapeType() == TopAbs_EDGE) { - if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) { - Astr = Astr + " It is a degenerated edge \n"; - } - } + bool isValid = GEOMUtils::CheckBOPArguments(aShape); - Astr = Astr + " Number of sub-shapes : \n"; + SetErrorCode(OK); + + return isValid; +} + +//============================================================================= +/*! + * FastIntersect + */ +//============================================================================= +bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, + double theTolerance, float theDeflection, + Handle(TColStd_HSequenceOfInteger)& theIntersections1, + Handle(TColStd_HSequenceOfInteger)& theIntersections2) +{ + SetErrorCode(KO); + bool isGood = false; + + if (theIntersections1.IsNull()) + theIntersections1 = new TColStd_HSequenceOfInteger; + else + theIntersections1->Clear(); + + if (theIntersections2.IsNull()) + theIntersections2 = new TColStd_HSequenceOfInteger; + else + theIntersections2->Clear(); + + if (theShape1.IsNull() || theShape2.IsNull()) { + SetErrorCode("Objects have NULL Shape"); + return isGood; + } + + if (theShape1 == theShape2) { + SetErrorCode("Objects are equal"); + return isGood; + } + Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction(); + Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction(); + if (aRefShape1.IsNull() || aRefShape2.IsNull()) return isGood; + + TopoDS_Shape aShape1 = aRefShape1->GetValue(); + TopoDS_Shape aShape2 = aRefShape2->GetValue(); + if (aShape1.IsNull() || aShape2.IsNull()) return isGood; + + // 0. Prepare data + TopoDS_Shape aScopy1, aScopy2; + GEOMAlgo_AlgoTools::CopyShape(aShape1, aScopy1); + GEOMAlgo_AlgoTools::CopyShape(aShape2, aScopy2); + + GEOMUtils::MeshShape(aScopy1, theDeflection); + GEOMUtils::MeshShape(aScopy2, theDeflection); + // + // Map sub-shapes and their indices + TopTools_IndexedMapOfShape anIndices1, anIndices2; + TopExp::MapShapes(aScopy1, anIndices1); + TopExp::MapShapes(aScopy2, anIndices2); + + TopTools_ListOfShape aLCS1, aLCS2; + aLCS1.Append(aScopy1); aLCS2.Append(aScopy2); + // + BRepExtrema_ShapeProximity aBSP; // checker of fast interferences + aBSP.LoadShape1(aScopy1); aBSP.LoadShape2(aScopy2); + aBSP.SetTolerance((theTolerance <= 0.) ? 0.0 : theTolerance); + + // 1. Launch the checker + aBSP.Perform(); + + // 2. Get sets of IDs of overlapped faces + for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) + { + const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key()); + theIntersections1->Append(anIndices1.FindIndex(aS1)); + } + + for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) + { + const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key()); + theIntersections2->Append(anIndices2.FindIndex(aS2)); + } + + isGood = !theIntersections1->IsEmpty() && !theIntersections1->IsEmpty(); + + if (aBSP.IsDone()) + SetErrorCode(OK); + + return isGood; +} + +//============================================================================= +/*! + * IsGoodForSolid + */ +//============================================================================= +TCollection_AsciiString GEOMImpl_IMeasureOperations::IsGoodForSolid (Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + TCollection_AsciiString aRes = ""; + + if (theShape.IsNull()) { + aRes = "WRN_NULL_OBJECT_OR_SHAPE"; + } + else { + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) { + aRes = "WRN_NULL_OBJECT_OR_SHAPE"; + } + else { + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { + aRes = "WRN_NULL_OBJECT_OR_SHAPE"; + } + else { + if (aShape.ShapeType() == TopAbs_COMPOUND) { + TopoDS_Iterator It (aShape, Standard_True, Standard_True); + if (It.More()) aShape = It.Value(); + } + if (aShape.ShapeType() == TopAbs_SHELL) { + BRepCheck_Shell chkShell (TopoDS::Shell(aShape)); + if (chkShell.Closed() == BRepCheck_NotClosed) { + aRes = "WRN_SHAPE_UNCLOSED"; + } + } + else { + aRes = "WRN_SHAPE_NOT_SHELL"; + } + } + } + } + + if (aRes.IsEmpty()) + SetErrorCode(OK); + + return aRes; +} + +//============================================================================= +/*! + * WhatIs + */ +//============================================================================= +TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + TCollection_AsciiString Astr; + + if (theShape.IsNull()) return Astr; + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return Astr; + + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { + SetErrorCode("The Objects has NULL Shape"); + return Astr; + } + + //Compute the parameters + if (aShape.ShapeType() == TopAbs_EDGE) { + if (BRep_Tool::Degenerated(TopoDS::Edge(aShape))) { + Astr = Astr + " It is a degenerated edge \n"; + } + } + + Astr = Astr + " Number of sub-shapes : \n"; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif - int iType, nbTypes [TopAbs_SHAPE]; - for (iType = 0; iType < TopAbs_SHAPE; ++iType) + int iType, nbTypes [TopAbs_SHAPE], nbFlatType [TopAbs_SHAPE]; + for (iType = 0; iType < TopAbs_SHAPE; ++iType) { nbTypes[iType] = 0; + nbFlatType[iType] = 0; + } nbTypes[aShape.ShapeType()]++; TopTools_MapOfShape aMapOfShape; @@ -1518,12 +1889,16 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) TopTools_ListIteratorOfListOfShape itL (aListOfShape); for (; itL.More(); itL.Next()) { - TopoDS_Iterator it (itL.Value()); + TopoDS_Shape sp = itL.Value(); + TopoDS_Iterator it (sp); for (; it.More(); it.Next()) { TopoDS_Shape s = it.Value(); if (aMapOfShape.Add(s)) { aListOfShape.Append(s); nbTypes[s.ShapeType()]++; + if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) { + nbFlatType[s.ShapeType()]++; + } } } } @@ -1536,11 +1911,26 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) Astr = Astr + " SOLID : " + TCollection_AsciiString(nbTypes[TopAbs_SOLID]) + "\n"; Astr = Astr + " COMPSOLID : " + TCollection_AsciiString(nbTypes[TopAbs_COMPSOLID]) + "\n"; Astr = Astr + " COMPOUND : " + TCollection_AsciiString(nbTypes[TopAbs_COMPOUND]) + "\n"; - Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()); + Astr = Astr + " SHAPE : " + TCollection_AsciiString(aMapOfShape.Extent()) + "\n"; + + if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){ + Astr = Astr + " --------------------- \n Flat content : \n"; + if (nbFlatType[TopAbs_VERTEX] > 0) + Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n"; + if (nbFlatType[TopAbs_EDGE] > 0) + Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n"; + if (nbFlatType[TopAbs_WIRE] > 0) + Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n"; + if (nbFlatType[TopAbs_FACE] > 0) + Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n"; + if (nbFlatType[TopAbs_SHELL] > 0) + Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n"; + if (nbFlatType[TopAbs_SOLID] > 0) + Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n"; + } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return Astr; } @@ -1616,7 +2006,7 @@ GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape project.NbPoints() > 0 && project.LowerDistance() <= tolerance ) { - Quantity_Parameter u, v; + Standard_Real u, v; project.LowerDistanceParameters(u, v); gp_Pnt2d uv( u, v ); BRepClass_FaceClassifier FC ( face, uv, tolerance ); @@ -1698,9 +2088,7 @@ GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1, //Compute the parameters try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif gp_Pnt aPnt1, aPnt2; @@ -1713,9 +2101,8 @@ GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1, return MinDist; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return MinDist; } @@ -1750,27 +2137,13 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) // Compute the extremities try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif // skl 30.06.2008 // additional workaround for bugs 19899, 19908 and 19910 from Mantis - gp_Pnt P1, P2; - double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2); - if (dist > -1.0) { - nbSolutions = 1; - - theDoubles->Append(P1.X()); - theDoubles->Append(P1.Y()); - theDoubles->Append(P1.Z()); - theDoubles->Append(P2.X()); - theDoubles->Append(P2.Y()); - theDoubles->Append(P2.Z()); - - SetErrorCode(OK); - return nbSolutions; - } + gp_Pnt P1s, P2s; + double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s); + bool singularBetter = dist >= 0; BRepExtrema_DistShapeShape dst (aShape1, aShape2); if (dst.IsDone()) { @@ -1781,19 +2154,35 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) for (int i = 1; i <= nbSolutions; i++) { P1 = dst.PointOnShape1(i); P2 = dst.PointOnShape2(i); - + theDoubles->Append(P1.X()); theDoubles->Append(P1.Y()); theDoubles->Append(P1.Z()); theDoubles->Append(P2.X()); theDoubles->Append(P2.Y()); theDoubles->Append(P2.Z()); + + Standard_Real Dist = P1.Distance(P2); + singularBetter = singularBetter && dist < Dist; } } + + if (singularBetter) { + if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal; + else theDoubles->Clear(); + + nbSolutions = 1; + + theDoubles->Append(P1s.X()); + theDoubles->Append(P1s.Y()); + theDoubles->Append(P1s.Z()); + theDoubles->Append(P2s.X()); + theDoubles->Append(P2s.Y()); + theDoubles->Append(P2s.Z()); + } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return nbSolutions; } @@ -1826,9 +2215,7 @@ void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape } try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif gp_Pnt aPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) ); theX = aPnt.X(); theY = aPnt.Y(); @@ -1836,10 +2223,9 @@ void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode( aFail->GetMessageString() ); + SetErrorCode( aFail.GetMessageString() ); } } @@ -1878,9 +2264,7 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine } try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif TopoDS_Edge E1 = TopoDS::Edge(aLine1); TopoDS_Edge E2 = TopoDS::Edge(aLine2); @@ -1911,10 +2295,9 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + SetErrorCode(aFail.GetMessageString()); } return anAngle; @@ -1956,9 +2339,7 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Objec } try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif TopoDS_Edge aE1 = TopoDS::Edge(aVec1); TopoDS_Edge aE2 = TopoDS::Edge(aVec2); @@ -1978,16 +2359,83 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Objec SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + SetErrorCode(aFail.GetMessageString()); } return anAngle; } +//============================================================================= +/*! + * PatchFace + */ + //============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE); + Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL; + + GEOMImpl_IPatchFace aPI(aFunction); + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aPI.SetShape(aRefShape); + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + + // Perform + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("patch face driver failed"); + return NULL; + } + + // Get result compound and collect all faces into result sequence + TopoDS_Shape aResCompound = aFunction->GetValue(); + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aResCompound, anIndices); + + Handle(TColStd_HArray1OfInteger) anArray; + for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next()) + { + TopoDS_Shape aValue = anExpW.Value(); + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); + + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray); + if (!anObj.IsNull()) + { + aSeq->Append(anObj); + } + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aSeq; + } + + //Make a Python command + GEOM::TPythonDump(aFunction, true) + << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")"; + + SetErrorCode(OK); + return aSeq; +} + //============================================================================= /*! * CurveCurvatureByParam @@ -2018,17 +2466,14 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam //Compute curvature try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif GeomLProp_CLProps Prop = GeomLProp_CLProps (aCurve, aP, 2, Precision::Confusion()); aRes = fabs(Prop.Curvature()); SetErrorCode(OK); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2072,9 +2517,7 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint //Compute curvature try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif GeomAPI_ProjectPointOnCurve PPCurve(aPoint, aCurve, aFP, aLP); if(PPCurve.NbPoints()>0) { GeomLProp_CLProps Prop = GeomLProp_CLProps @@ -2083,9 +2526,8 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint SetErrorCode(OK); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2115,9 +2557,7 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures if (aSurf.IsNull()) return aRes; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif GeomLProp_SLProps Prop = GeomLProp_SLProps (aSurf, theUParam, theVParam, 2, Precision::Confusion()); if(Prop.IsCurvatureDefined()) { @@ -2137,9 +2577,8 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures SetErrorCode(OK); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2297,362 +2736,735 @@ Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false); } +//============================================================================= +/*! + * SurfaceCurvatureByPointAndDirection + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection + (Handle(GEOM_Object) theSurf, + Handle(GEOM_Object) thePoint, + Handle(GEOM_Object) theDirection) +{ + SetErrorCode(KO); + + if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL; -//======================================================================= -//function : StructuralDump -//purpose : Structural (data exchange) style of output. -//======================================================================= -void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna, - const TopoDS_Shape& theShape, - TCollection_AsciiString& theDump) + Handle(GEOM_Function) aSurf = theSurf->GetLastFunction(); + Handle(GEOM_Function) aPoint = thePoint->GetLastFunction(); + Handle(GEOM_Function) aDirection = theDirection->GetLastFunction(); + if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL; + + //Add a new CurvatureVector object + //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC); + Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR); + + //Add a new CurvatureVector function + Handle(GEOM_Function) aFunction = + aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL; + + GEOMImpl_IMeasure aCI (aFunction); + aCI.SetBase(aSurf); + aCI.SetPoint(aPoint); + aCI.SetDirection(aDirection); + + //Compute the CurvatureVector + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Measure driver failed to compute a surface curvature"); + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf + << ", " << thePoint << ", " << theDirection << ")"; + + SetErrorCode(OK); + return aCV; +} + +//============================================================================= +/*! + * SelfIntersected2D + * Find all self-intersected 2D curves. + * \param theChecks list of failed checks, contains type of check and failed shapes + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list& theChecks) { - Standard_Integer i; - theDump.Clear(); - theDump += " -- The Shape has problems :\n"; - theDump += " Check Count\n"; - theDump += " ------------------------------------------------\n"; - - Standard_Integer last_stat = (Standard_Integer)BRepCheck_CheckFail; - Handle(TColStd_HArray1OfInteger) NbProblems = - new TColStd_HArray1OfInteger(1, last_stat); - for (i = 1; i <= last_stat; i++) - NbProblems->SetValue(i,0); - - Handle(TopTools_HSequenceOfShape) sl; - sl = new TopTools_HSequenceOfShape(); - TopTools_DataMapOfShapeListOfShape theMap; - theMap.Clear(); - GetProblemShapes(theAna, theShape, sl, NbProblems, theMap); - theMap.Clear(); - - Standard_Integer count = 0; - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurve); - if (count > 0) { - theDump += " Invalid Point on Curve ................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnCurveOnSurface); - if (count > 0) { - theDump += " Invalid Point on CurveOnSurface .......... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidPointOnSurface); - if (count > 0) { - theDump += " Invalid Point on Surface ................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_No3DCurve); - if (count > 0) { - theDump += " No 3D Curve .............................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_Multiple3DCurve); - if (count > 0) { - theDump += " Multiple 3D Curve ........................ "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_Invalid3DCurve); - if (count > 0) { - theDump += " Invalid 3D Curve ......................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_NoCurveOnSurface); - if (count > 0) { - theDump += " No Curve on Surface ...................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnSurface); - if (count > 0) { - theDump += " Invalid Curve on Surface ................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidCurveOnClosedSurface); - if (count > 0) { - theDump += " Invalid Curve on closed Surface .......... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameRangeFlag); - if (count > 0) { - theDump += " Invalid SameRange Flag ................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidSameParameterFlag); - if (count > 0) { - theDump += " Invalid SameParameter Flag ............... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidDegeneratedFlag); - if (count > 0) { - theDump += " Invalid Degenerated Flag ................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_FreeEdge); - if (count > 0) { - theDump += " Free Edge ................................ "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidMultiConnexity); - if (count > 0) { - theDump += " Invalid MultiConnexity ................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidRange); - if (count > 0) { - theDump += " Invalid Range ............................ "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyWire); - if (count > 0) { - theDump += " Empty Wire ............................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantEdge); - if (count > 0) { - theDump += " Redundant Edge ........................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_SelfIntersectingWire); - if (count > 0) { - theDump += " Self Intersecting Wire ................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_NoSurface); - if (count > 0) { - theDump += " No Surface ............................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidWire); - if (count > 0) { - theDump += " Invalid Wire ............................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantWire); - if (count > 0) { - theDump += " Redundant Wire ........................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_IntersectingWires); - if (count > 0) { - theDump += " Intersecting Wires ....................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_InvalidImbricationOfWires); - if (count > 0) { - theDump += " Invalid Imbrication of Wires ............. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_EmptyShell); - if (count > 0) { - theDump += " Empty Shell .............................. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_RedundantFace); - if (count > 0) { - theDump += " Redundant Face ........................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_UnorientableShape); - if (count > 0) { - theDump += " Unorientable Shape ....................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_NotClosed); - if (count > 0) { - theDump += " Not Closed ............................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_NotConnected); - if (count > 0) { - theDump += " Not Connected ............................ "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_SubshapeNotInShape); - if (count > 0) { - theDump += " Sub-shape not in Shape .................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientation); - if (count > 0) { - theDump += " Bad Orientation .......................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_BadOrientationOfSubshape); - if (count > 0) { - theDump += " Bad Orientation of Sub-shape .............. "; - theDump += TCollection_AsciiString(count) + "\n"; - } - count = NbProblems->Value((Standard_Integer)BRepCheck_CheckFail); - if (count > 0) { - theDump += " checkshape failure ....................... "; - theDump += TCollection_AsciiString(count) + "\n"; - } - - theDump += " ------------------------------------------------\n"; - theDump += "*** Shapes with problems : "; - theDump += TCollection_AsciiString(sl->Length()) + "\n"; - - Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo; - nbv = nbe = nbw = nbf = nbs = nbo = 0; - - for (i = 1; i <= sl->Length(); i++) { - TopoDS_Shape shi = sl->Value(i); - TopAbs_ShapeEnum sti = shi.ShapeType(); - switch (sti) { - case TopAbs_VERTEX : nbv++; break; - case TopAbs_EDGE : nbe++; break; - case TopAbs_WIRE : nbw++; break; - case TopAbs_FACE : nbf++; break; - case TopAbs_SHELL : nbs++; break; - case TopAbs_SOLID : nbo++; break; - default : break; + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D"); + + std::list aSelfInters2D; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface) + aSelfInters2D.push_back(anIter->FailedShapes); } } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aSelfInters2D; + } - if (nbv > 0) { - theDump += "VERTEX : "; - if (nbv < 10) theDump += " "; - theDump += TCollection_AsciiString(nbv) + "\n"; + SetErrorCode(OK); + return aSelfInters2D; +} + +namespace +{ + static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes, + const int theShapeType1, + const int theShapeType2) + { + if (theShapeType1 == -1 && theShapeType2 == -1) + return true; + + TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull() + ? TopAbs_SHAPE + : theShapes.first->GetValue().ShapeType(); + TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull() + ? TopAbs_SHAPE + : theShapes.second->GetValue().ShapeType(); + + if (theShapeType1 == -1) + return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2; + else if (theShapeType2 == -1) + return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1; + return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) || + (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1); + } +} // namespace + +//============================================================================= +/*! + * InterferingSubshapes + * Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned. + * \param theChecks list of failed checks, contains type of check and failed shapes + * \param theShapeType1 Type of shape. + * \param theShapeType2 Type of shape. + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::InterferingSubshapes + (const std::list& theChecks, + const int theShapeType1, + const int theShapeType2) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes"); + + std::list anInterfer; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect && + checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2)) + anInterfer.push_back(anIter->FailedShapes); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return anInterfer; + } + + SetErrorCode(OK); + return anInterfer; +} + +//============================================================================= +/*! + * SmallEdges + * Find edges, which are fully covered by tolerances of vertices. + * \param theChecks list of failed checks, contains type of check and failed shapes + */ + //============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges( + const std::list& theChecks) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::smallEdges"); + + Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge) + aSmallEdges->Append(anIter->FailedShapes.first); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + SetErrorCode(OK); + return aSmallEdges; +} + +//============================================================================= +/*! + * DistantShapes + * find remote objects (sub-shape on a shape). + * \param theShape Shape for check. + * \param theShapeType Type of shape. + * \param theSubShapeType Type of sub-shape. + * \param theTolerance tolerance. + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::DistantShapes + (const std::list& theChecks, + const int theShapeType, + const int theSubShapeType, + double theTolerance) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::distantShapes"); + + std::list aDistShapes; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first; + Handle(GEOM_Object) aShape = anIter->FailedShapes.second; + if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) && + aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) && + aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType)) + { + gp_XYZ aP1, aP2; + Standard_Real aDist = Precision::Infinite(); + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface) + aDist = ComputeTolerance(aSubShape, aShape); + if (aDist > theTolerance) + aDistShapes.push_back(anIter->FailedShapes); + } + } } - if (nbe > 0) { - theDump += "EDGE : "; - if (nbe < 10) theDump += " "; - theDump += TCollection_AsciiString(nbe) + "\n"; + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aDistShapes; } - if (nbw > 0) { - theDump += "WIRE : "; - if (nbw < 10) theDump += " "; - theDump += TCollection_AsciiString(nbw) + "\n"; + + SetErrorCode(OK); + return aDistShapes; +} + +//============================================================================= +/*! + * CheckConformityShape + * Perform analyse of shape and find imperfections in the shape. + * \param theShape Shape for analyse. + */ + //============================================================================= +void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list& theChecks) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::checkShape"); + + Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY); + Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE); + if (aFunction.IsNull()) return; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return; + + GEOMImpl_IConformity aCI(aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return; + + aCI.SetShape(aRefShape); + + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("Failed: checkShape"); + return; + } + Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS); + Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices(); + if (aRes.IsNull()) + return; + + for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex) + { + std::pair aPair; + Handle(TColStd_HArray1OfInteger) anArray; + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, aRes->Value(anIndex, 1)); + + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray); + if (!anObj.IsNull()) + aPair.first = anObj; + + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, aRes->Value(anIndex, 2)); + + anObj = GetEngine()->AddSubShape(theShape, anArray); + if (!anObj.IsNull()) + aPair.second = anObj; + theChecks.push_back({ aTypesChecks->Value(anIndex), aPair }); + } } - if (nbf > 0) { - theDump += "FACE : "; - if (nbf < 10) theDump += " "; - theDump += TCollection_AsciiString(nbf) + "\n"; + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return; } - if (nbs > 0) { - theDump += "SHELL : "; - if (nbs < 10) theDump += " "; - theDump += TCollection_AsciiString(nbs) + "\n"; + + SetErrorCode(OK); + return; +} + +//============================================================================= +/*! + * UpdateTolerance + * Compute possible tolerance for the shape, minimize tolerance of shape as well + * as tolerance of sub-shapes as much as possible + * \param theShape Shape for compute tolerance. + */ + //============================================================================= +double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance"); + + double aResTol = -1; + Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY); + Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL); + if (aFunction.IsNull()) return aResTol; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol; + + GEOMImpl_IConformity aCI(aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return aResTol; + + aCI.SetShape(aRefShape); + + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("Failed: updateTolerance"); + return aResTol; + } + aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE); } - if (nbo > 0) { - theDump += "SOLID : "; - if (nbo < 10) theDump += " "; - theDump += TCollection_AsciiString(nbo) + "\n"; + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aResTol; } + + SetErrorCode(OK); + return aResTol; } +//============================================================================= +/*! + * ComputeTolerance + * Compute distance from the edge to the face. + */ + //============================================================================= +double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge, + Handle(GEOM_Object) theFace) +{ + double aMaxDist = Precision::Infinite(); + if (theEdge.IsNull() || theFace.IsNull()) + return aMaxDist; + + Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction(); + Handle(GEOM_Function) aRefFace = theFace->GetLastFunction(); + if (aRefEdge.IsNull() || aRefFace.IsNull()) + return aMaxDist; + + TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue()); + TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue()); + if (aEdge.IsNull() || aFace.IsNull()) + return aMaxDist; + + double aParam = 0.0; + BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam); + return aMaxDist; +} + +//======================================================================= +//function : FillErrorsSub +//purpose : Fill the errors list of subshapes on shape. +//======================================================================= +void GEOMImpl_IMeasureOperations::FillErrorsSub + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + const TopAbs_ShapeEnum theSubType, + TopTools_DataMapOfIntegerListOfShape &theMapErrors) const +{ + TopExp_Explorer anExp(theShape, theSubType); + TopTools_MapOfShape aMapSubShapes; + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aSubShape = anExp.Current(); + + if (aMapSubShapes.Add(aSubShape)) { + const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape); + + for (aRes->InitContextIterator(); + aRes->MoreShapeInContext(); + aRes->NextShapeInContext()) { + if (aRes->ContextualShape().IsSame(theShape)) { + BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape()); + + if (itl.Value() != BRepCheck_NoError) { + // Add all errors for theShape and its sub-shape. + for (;itl.More(); itl.Next()) { + const Standard_Integer aStat = (Standard_Integer)itl.Value(); + + if (!theMapErrors.IsBound(aStat)) { + TopTools_ListOfShape anEmpty; + + theMapErrors.Bind(aStat, anEmpty); + } + + TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat); + + theShapes.Append(aSubShape); + theShapes.Append(theShape); + } + } + } + + break; + } + } + } +} //======================================================================= -//function : GetProblemShapes -// purpose : for StructuralDump +//function : FillErrors +//purpose : Fill the errors list. //======================================================================= -void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer& theAna, - const TopoDS_Shape& theShape, - Handle(TopTools_HSequenceOfShape)& sl, - Handle(TColStd_HArray1OfInteger)& NbProblems, - TopTools_DataMapOfShapeListOfShape& theMap) +void GEOMImpl_IMeasureOperations::FillErrors + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + TopTools_DataMapOfIntegerListOfShape &theMapErrors, + TopTools_MapOfShape &theMapShapes) const { - for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) { - GetProblemShapes(theAna, iter.Value(), sl, NbProblems, theMap); - } - TopAbs_ShapeEnum styp = theShape.ShapeType(); - BRepCheck_ListIteratorOfListOfStatus itl; - TopTools_ListOfShape empty; - if (!theMap.IsBound(theShape)) { - theMap.Bind(theShape,empty); - - if (!theAna.Result(theShape).IsNull()) { - itl.Initialize(theAna.Result(theShape)->Status()); - // !!! May be, we have to print all the problems, not only the first one ? + if (theMapShapes.Add(theShape)) { + // Fill errors of child shapes. + for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) { + FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes); + } + + // Fill errors of theShape. + const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape); + + if (!aRes.IsNull()) { + BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status()); + if (itl.Value() != BRepCheck_NoError) { - sl->Append(theShape); - BRepCheck_Status stat = itl.Value(); - NbProblems->SetValue((Standard_Integer)stat, - NbProblems->Value((Standard_Integer)stat) + 1); + // Add all errors for theShape. + for (;itl.More(); itl.Next()) { + const Standard_Integer aStat = (Standard_Integer)itl.Value(); + + if (!theMapErrors.IsBound(aStat)) { + TopTools_ListOfShape anEmpty; + + theMapErrors.Bind(aStat, anEmpty); + } + + theMapErrors.ChangeFind(aStat).Append(theShape); + } } } + + // Add errors of subshapes on theShape. + const TopAbs_ShapeEnum aType = theShape.ShapeType(); + + switch (aType) { + case TopAbs_EDGE: + FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors); + break; + case TopAbs_FACE: + FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors); + FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors); + FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors); + break; + case TopAbs_SOLID: + FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors); + break; + default: + break; + } } +} - switch (styp) { - case TopAbs_EDGE: - GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap); - break; - case TopAbs_FACE: - GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_WIRE, theMap); - GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_EDGE, theMap); - GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_VERTEX, theMap); - break; - case TopAbs_SHELL: - break; - case TopAbs_SOLID: - GetProblemSub(theAna, theShape, sl, NbProblems, TopAbs_SHELL, theMap); - break; - default: - break; +//======================================================================= +//function : FillErrors +//purpose : Fill the errors list. +//======================================================================= +void GEOMImpl_IMeasureOperations::FillErrors + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + std::list &theErrors) const +{ + // Fill the errors map. + TopTools_DataMapOfIntegerListOfShape aMapErrors; + TopTools_MapOfShape aMapShapes; + + FillErrors(theAna, theShape, aMapErrors, aMapShapes); + + // Map sub-shapes and their indices + TopTools_IndexedMapOfShape anIndices; + + TopExp::MapShapes(theShape, anIndices); + + TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors); + + for (; aMapIter.More(); aMapIter.Next()) { + ShapeError anError; + + anError.error = (BRepCheck_Status)aMapIter.Key(); + + TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value()); + TopTools_MapOfShape aMapUnique; + + for (; aListIter.More(); aListIter.Next()) { + const TopoDS_Shape &aShape = aListIter.Value(); + + if (aMapUnique.Add(aShape)) { + const Standard_Integer anIndex = anIndices.FindIndex(aShape); + + anError.incriminated.push_back(anIndex); + } + } + + if (!anError.incriminated.empty()) { + theErrors.push_back(anError); + } } } //======================================================================= -//function : Contains +//function : ShapeProximityCalculator +//purpose : returns an object to compute the proximity value +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator + (Handle(GEOM_Object) theShape1, + Handle(GEOM_Object) theShape2) +{ + SetErrorCode(KO); + + if (theShape1.IsNull() || theShape2.IsNull()) + return NULL; + + Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction(); + Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction(); + if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull()) + return NULL; + + Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY); + if (aProximityCalc.IsNull()) + return NULL; + + Handle(GEOM_Function) aProximityFuncCoarse = + aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE); + //Check if the function is set correctly + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return NULL; + + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); + aProximity.SetShapes(aShapeFunc1, aShapeFunc2); + + //Make a Python command + GEOM::TPythonDump pd (aProximityFuncCoarse); + pd << "p = geompy.ShapeProximity()\n"; + pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")"; + + SetErrorCode(OK); + return aProximityCalc; +} + +//======================================================================= +//function : SetShapeSampling +//purpose : set number sample points to compute the coarse proximity +//======================================================================= +void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator, + Handle(GEOM_Object) theShape, + const Standard_Integer theNbSamples) +{ + SetErrorCode(KO); + if (theShape.IsNull() || + theCalculator.IsNull() || + theCalculator->GetNbFunctions() <= 0 || + theNbSamples <= 0) + return ; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return ; + + Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction(); + if (aShapeFunc.IsNull()) + return ; + + GEOMImpl_IProximity aProximity(aProximityFuncCoarse); + Handle(GEOM_Function) aShape1, aShape2; + aProximity.GetShapes(aShape1, aShape2); + if (aShape1->GetValue() == aShapeFunc->GetValue()) + aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples); + else if (aShape2->GetValue() == aShapeFunc->GetValue()) + aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples); + + //Make a Python command + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << + "p.setSampling(" << theShape << ", " << theNbSamples << ")"; + + SetErrorCode(OK); +} + +//======================================================================= +//function : GetCoarseProximity +//purpose : compute coarse proximity //======================================================================= -static Standard_Boolean Contains (const TopTools_ListOfShape& L, - const TopoDS_Shape& S) +Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator, + bool doPythonDump) { - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(L); it.More(); it.Next()) { - if (it.Value().IsSame(S)) { - return Standard_True; + SetErrorCode(KO); + if (theCalculator.IsNull()) + return -1; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() || + aProximityFuncCoarse->GetType() != PROXIMITY_COARSE) + return -1; + + // Perform + // We have to recompute the function each time, + // because the number of samples can be changed + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) { + SetErrorCode("shape proximity driver failed"); + return -1; } } - return Standard_False; + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return -1; + } + + //Make a Python command + if (doPythonDump) + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()"; + + SetErrorCode(OK); + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); + return aProximity.GetValue(); } //======================================================================= -//function : GetProblemSub -// purpose : for StructuralDump +//function : GetPreciseProximity +//purpose : compute precise proximity //======================================================================= -void GEOMImpl_IMeasureOperations::GetProblemSub (const BRepCheck_Analyzer& theAna, - const TopoDS_Shape& theShape, - Handle(TopTools_HSequenceOfShape)& sl, - Handle(TColStd_HArray1OfInteger)& NbProblems, - const TopAbs_ShapeEnum Subtype, - TopTools_DataMapOfShapeListOfShape& theMap) +Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator) { - BRepCheck_ListIteratorOfListOfStatus itl; - TopExp_Explorer exp; - for (exp.Init(theShape, Subtype); exp.More(); exp.Next()) { - const TopoDS_Shape& sub = exp.Current(); - - const Handle(BRepCheck_Result)& res = theAna.Result(sub); - for (res->InitContextIterator(); - res->MoreShapeInContext(); - res->NextShapeInContext()) { - if (res->ContextualShape().IsSame(theShape) && !Contains(theMap(sub), theShape)) { - theMap(sub).Append(theShape); - itl.Initialize(res->StatusOnShape()); - - if (itl.Value() != BRepCheck_NoError) { - Standard_Integer ii = 0; - - for (ii = 1; ii <= sl->Length(); ii++) - if (sl->Value(ii).IsSame(sub)) break; - - if (ii > sl->Length()) { - sl->Append(sub); - BRepCheck_Status stat = itl.Value(); - NbProblems->SetValue((Standard_Integer)stat, - NbProblems->Value((Standard_Integer)stat) + 1); - } - for (ii = 1; ii <= sl->Length(); ii++) - if (sl->Value(ii).IsSame(theShape)) break; - if (ii > sl->Length()) { - sl->Append(theShape); - BRepCheck_Status stat = itl.Value(); - NbProblems->SetValue((Standard_Integer)stat, - NbProblems->Value((Standard_Integer)stat) + 1); - } - } - break; - } + SetErrorCode(KO); + if (theCalculator.IsNull()) + return -1; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2); + if (aProximityFuncFine.IsNull()) + aProximityFuncFine = theCalculator->AddFunction + (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE); + + //Check if the functions are set correctly + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() || + aProximityFuncFine.IsNull() || + aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return -1; + + // perform coarse computation beforehand + GetCoarseProximity(theCalculator, /*doPythonDump=*/false); + + // transfer parameters from the coarse to precise calculator + GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse); + Handle(GEOM_Function) aShape1, aShape2; + aCoarseProximity.GetShapes(aShape1, aShape2); + if (aShape1.IsNull() || aShape2.IsNull()) + return -1; + gp_Pnt aProxPnt1, aProxPnt2; + Standard_Integer intStatus1, intStatus2; + aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2); + aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2); + Standard_Real aResultValue = aCoarseProximity.GetValue(); + + GEOMImpl_IProximity aFineProximity (aProximityFuncFine); + aFineProximity.SetShapes(aShape1, aShape2); + aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2); + aFineProximity.SetStatusOfPoints(intStatus1, intStatus2); + aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised + + // Perform + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aProximityFuncFine)) { + SetErrorCode("shape proximity driver failed"); + return -1; } } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return -1; + } + + aResultValue = aFineProximity.GetValue(); + aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2); + + //Make a Python command + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()"; + + SetErrorCode(OK); + return aResultValue; }