X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IMeasureOperations.cxx;h=fb2320ea5cef74e4d237a89c1b6be2ba9d7a1005;hb=ed87a1f7c81ec39992aff1f463d73dc81e5791e0;hp=df3a87a49963a3490934fa56f6eac236c9d82f20;hpb=8180539548a5038e52445454e88c1a170ee64e56;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index df3a87a49..fb2320ea5 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 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 @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,108 +18,56 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // 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 -#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 //============================================================================= @@ -173,7 +121,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; } @@ -765,69 +713,6 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape return aKind; } -//============================================================================= -/*! Get LCS, corresponding to the given shape. - * Origin of the LCS is situated at the shape's center of mass. - * Axes of the LCS are obtained from shape's location or, - * if the shape is a planar face, from position of its plane. - */ -//============================================================================= -gp_Ax3 GEOMImpl_IMeasureOperations::GetPosition (const TopoDS_Shape& theShape) -{ - gp_Ax3 aResult; - - if (theShape.IsNull()) - return aResult; - - // Axes - aResult.Transform(theShape.Location().Transformation()); - if (theShape.ShapeType() == TopAbs_FACE) { - Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape)); - if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) { - Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS); - gp_Pln aPln = aGPlane->Pln(); - aResult = aPln.Position(); - // In case of reverse orinetation of the face invert the plane normal - // (the face's normal does not mathc the plane's normal in this case) - if(theShape.Orientation() == TopAbs_REVERSED) - { - gp_Dir Vx = aResult.XDirection(); - gp_Dir N = aResult.Direction().Mirrored(Vx); - gp_Pnt P = aResult.Location(); - aResult = gp_Ax3(P, N, Vx); - } - } - } - - // Origin - gp_Pnt aPnt; - - TopAbs_ShapeEnum aShType = theShape.ShapeType(); - - if (aShType == TopAbs_VERTEX) { - aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape)); - } - else { - if (aShType == TopAbs_COMPOUND) { - aShType = GEOMImpl_IShapesOperations::GetTypeOfSimplePart(theShape); - } - - GProp_GProps aSystem; - if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) - BRepGProp::LinearProperties(theShape, aSystem); - else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL) - BRepGProp::SurfaceProperties(theShape, aSystem); - else - BRepGProp::VolumeProperties(theShape, aSystem); - - aPnt = aSystem.CentreOfMass(); - } - - aResult.SetLocation(aPnt); - - return aResult; -} - //============================================================================= /*! * GetPosition @@ -857,11 +742,9 @@ void GEOMImpl_IMeasureOperations::GetPosition } try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif - gp_Ax3 anAx3 = GetPosition(aShape); + gp_Ax3 anAx3 = GEOMUtils::GetPosition(aShape); gp_Pnt anOri = anAx3.Location(); gp_Dir aDirZ = anAx3.Direction(); @@ -913,9 +796,7 @@ 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; @@ -967,9 +848,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex //Compute try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vertex by index driver failed."); return NULL; @@ -1026,9 +905,7 @@ 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; @@ -1078,9 +955,7 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha //Compute the parameters GProp_GProps LProps, SProps; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif BRepGProp::LinearProperties(aShape, LProps); theLength = LProps.Mass(); @@ -1134,9 +1009,7 @@ 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) { @@ -1180,6 +1053,7 @@ void GEOMImpl_IMeasureOperations::GetInertia //============================================================================= void GEOMImpl_IMeasureOperations::GetBoundingBox (Handle(GEOM_Object) theShape, + const Standard_Boolean precise, Standard_Real& Xmin, Standard_Real& Xmax, Standard_Real& Ymin, Standard_Real& Ymax, Standard_Real& Zmin, Standard_Real& Zmax) @@ -1201,9 +1075,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"); @@ -1216,6 +1088,14 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox BRepTools::Clean(aShape); BRepBndLib::Add(aShape, B); + + if (precise) { + if (!GEOMUtils::PreciseBoundingBox(aShape, B)) { + SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised"); + return; + } + } + B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); } catch (Standard_Failure) { @@ -1227,6 +1107,67 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox SetErrorCode(OK); } +//============================================================================= +/*! + * GetBoundingBox + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox + (Handle(GEOM_Object) theShape, + const Standard_Boolean precise) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + //Add a new BoundingBox object + Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX); + + //Add a new BoundingBox function + const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE); + Handle(GEOM_Function) aFunction = + aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL; + + GEOMImpl_IMeasure aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aCI.SetBase(aRefShape); + + //Compute the BoundingBox value + try { + OCC_CATCH_SIGNALS; + 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()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump aPd(aFunction); + + aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape; + + if (precise) { + aPd << ", True"; + } + + aPd << ")"; + + SetErrorCode(OK); + return aBnd; +} + //============================================================================= /*! * GetTolerance @@ -1257,9 +1198,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); @@ -1299,11 +1238,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; @@ -1319,15 +1259,12 @@ 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) { @@ -1340,6 +1277,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 @@ -1347,6 +1501,7 @@ 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); @@ -1367,52 +1522,44 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections if (aShape.IsNull()) return isGood; // 0. Prepare data - BRep_Builder aBB; - TopoDS_Compound aCS; TopoDS_Shape aScopy; - NMTDS_Tools::CopyShape(aShape, aScopy); - + // + GEOMAlgo_AlgoTools::CopyShape(aShape, aScopy); + // // Map sub-shapes and their indices TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aScopy, anIndices); - aBB.MakeCompound(aCS); - aBB.Add(aCS, aScopy); - - NMTTools_CheckerSI aCSI; // checker of self-interferences - aCSI.SetCompositeShape(aCS); + BOPCol_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.StopStatus(); - if (iErr) { - return false; // Error - } + Standard_Integer iErr = aCSI.ErrorStatus(); isGood = true; - + // + Standard_Integer aNbS, n1, n2; + BOPDS_MapIteratorMapOfPassKey aItMPK; + // // 2. Take the shapes from DS - const NMTDS_ShapesDataStructure& aDS = *(aCSI.DS()); - Standard_Integer aNbS = aDS.NumberOfShapesOfTheObject(); - + const BOPDS_DS& aDS = aCSI.DS(); + aNbS=aDS.NbShapes(); + // // 3. Get the pairs of interfered shapes - NMTDS_PInterfPool pIP = aCSI.IP(); - //const NMTDS_ListOfPassKeyBoolean& aLPKB = pIP->Get(); - const NMTDS_ListOfPairBoolean& aLPKB = pIP->Get(); - - Standard_Integer n1, n2; - //NMTDS_ListIteratorOfListOfPassKeyBoolean aIt; - NMTDS_ListIteratorOfListOfPairBoolean aIt; - - aIt.Initialize(aLPKB); - for (; aIt.More(); aIt.Next()) { - //const NMTDS_PassKeyBoolean& aPKB = aIt.Value(); - const NMTDS_PairBoolean& aPKB = aIt.Value(); - aPKB.Ids(n1, n2); - - if (n1 > aNbS || n2 > aNbS) + const BOPDS_MapOfPassKey& aMPK=aDS.Interferences(); + aItMPK.Initialize(aMPK); + for (; aItMPK.More(); aItMPK.Next()) { + const BOPDS_PassKey& aPK=aItMPK.Value(); + aPK.Ids(n1, n2); + // + if (n1 > aNbS || n2 > aNbS){ return false; // Error - + } const TopoDS_Shape& aS1 = aDS.Shape(n1); const TopoDS_Shape& aS2 = aDS.Shape(n2); @@ -1421,7 +1568,10 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections isGood = false; } - SetErrorCode(OK); + if (!iErr) { + SetErrorCode(OK); + } + return isGood; } @@ -1505,12 +1655,12 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) 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; @@ -1520,12 +1670,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()]++; + } } } } @@ -1538,7 +1692,23 @@ 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(); @@ -1550,339 +1720,121 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) return Astr; } - -//======================================================================= -//function : CheckSingularCase -//purpose : auxilary for GetMinDistance() -// workaround for bugs 19899, 19908 and 19910 from Mantis -//======================================================================= -static double CheckSingularCase(const TopoDS_Shape& aSh1, - const TopoDS_Shape& aSh2, - gp_Pnt& Ptmp1, gp_Pnt& Ptmp2) -{ - bool IsChange1 = false; - double AddDist1 = 0.0; - TopExp_Explorer anExp; - TopoDS_Shape tmpSh1, tmpSh2; - int nbf = 0; - for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh1 = anExp.Current(); - } - if(nbf==1) { - TopoDS_Shape sh = aSh1; - while(sh.ShapeType()==TopAbs_COMPOUND) { - TopoDS_Iterator it(sh); - sh = it.Value(); - } - Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh1)); - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { - if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) { - // non solid case - double U1,U2,V1,V2; - // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88 - //S->Bounds(U1,U2,V1,V2); changed by - ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2); - // end of changes for 020677 (dmv) - Handle(Geom_RectangularTrimmedSurface) TrS1 = - new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2); - Handle(Geom_RectangularTrimmedSurface) TrS2 = - new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2); - BRep_Builder B; - TopoDS_Face F1,F2; - TopoDS_Compound Comp; - B.MakeCompound(Comp); - B.MakeFace(F1,TrS1,1.e-7); - B.Add(Comp,F1); - B.MakeFace(F2,TrS2,1.e-7); - B.Add(Comp,F2); - Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - sfs->Init(Comp); - sfs->SetPrecision(1.e-6); - sfs->SetMaxTolerance(1.0); - sfs->Perform(); - tmpSh1 = sfs->Shape(); - IsChange1 = true; - } - else { - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) { - Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S); - gp_Pnt PC = SS->Location(); - BRep_Builder B; - TopoDS_Vertex V; - B.MakeVertex(V,PC,1.e-7); - tmpSh1 = V; - AddDist1 = SS->Radius(); - IsChange1 = true; - } - else { - Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S); - gp_Ax3 ax3 = TS->Position(); - Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius()); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C,1.e-7); - tmpSh1 = E; - AddDist1 = TS->MinorRadius(); - IsChange1 = true; - } - } - } - else - tmpSh1 = aSh1; - } - else - tmpSh1 = aSh1; - bool IsChange2 = false; - double AddDist2 = 0.0; - nbf = 0; - for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh2 = anExp.Current(); - } - if(nbf==1) { - TopoDS_Shape sh = aSh2; - while(sh.ShapeType()==TopAbs_COMPOUND) { - TopoDS_Iterator it(sh); - sh = it.Value(); - } - Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh2)); - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { - if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) { - // non solid case - double U1,U2,V1,V2; - //S->Bounds(U1,U2,V1,V2); - ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh2),U1,U2,V1,V2); - Handle(Geom_RectangularTrimmedSurface) TrS1 = - new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2); - Handle(Geom_RectangularTrimmedSurface) TrS2 = - new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2); - BRep_Builder B; - TopoDS_Face F1,F2; - TopoDS_Compound Comp; - B.MakeCompound(Comp); - B.MakeFace(F1,TrS1,1.e-7); - B.Add(Comp,F1); - B.MakeFace(F2,TrS2,1.e-7); - B.Add(Comp,F2); - Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - sfs->Init(Comp); - sfs->SetPrecision(1.e-6); - sfs->SetMaxTolerance(1.0); - sfs->Perform(); - tmpSh2 = sfs->Shape(); - IsChange2 = true; - } - else { - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) { - Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S); - gp_Pnt PC = SS->Location(); - BRep_Builder B; - TopoDS_Vertex V; - B.MakeVertex(V,PC,1.e-7); - tmpSh2 = V; - AddDist2 = SS->Radius(); - IsChange2 = true; - } - else if( S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { - Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S); - gp_Ax3 ax3 = TS->Position(); - Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius()); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C,1.e-7); - tmpSh2 = E; - AddDist2 = TS->MinorRadius(); - IsChange2 = true; - } - } - } - else - tmpSh2 = aSh2; - } - else - tmpSh2 = aSh2; - - if( !IsChange1 && !IsChange2 ) - return -2.0; - - BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2); - if (dst.IsDone()) { - double MinDist = 1.e9; - gp_Pnt PMin1, PMin2, P1, P2; - for (int i = 1; i <= dst.NbSolution(); i++) { - P1 = dst.PointOnShape1(i); - P2 = dst.PointOnShape2(i); - Standard_Real Dist = P1.Distance(P2); - if (MinDist > Dist) { - MinDist = Dist; - PMin1 = P1; - PMin2 = P2; - } - } - if(MinDist<1.e-7) { - Ptmp1 = PMin1; - Ptmp2 = PMin2; - } - else { - gp_Dir aDir(gp_Vec(PMin1,PMin2)); - if( MinDist > (AddDist1+AddDist2) ) { - Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1, - PMin1.Y() + aDir.Y()*AddDist1, - PMin1.Z() + aDir.Z()*AddDist1 ); - Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2, - PMin2.Y() - aDir.Y()*AddDist2, - PMin2.Z() - aDir.Z()*AddDist2 ); - return (MinDist - AddDist1 - AddDist2); - } - else { - if( AddDist1 > 0 ) { - Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1, - PMin1.Y() + aDir.Y()*AddDist1, - PMin1.Z() + aDir.Z()*AddDist1 ); - Ptmp2 = Ptmp1; - } - else { - Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2, - PMin2.Y() - aDir.Y()*AddDist2, - PMin2.Z() - aDir.Z()*AddDist2 ); - Ptmp1 = Ptmp2; - } - } - } - double res = MinDist - AddDist1 - AddDist2; - if(res<0.) res = 0.0; - return res; - } - return -2.0; -} -/* old variant -static bool CheckSingularCase(const TopoDS_Shape& aSh1, - const TopoDS_Shape& aSh2, - gp_Pnt& Ptmp) -{ - TopExp_Explorer anExp; - TopoDS_Shape tmpSh1, tmpSh2; - int nbf = 0; - for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh1 = anExp.Current(); - } - if(nbf==1) { - Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1)); - if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { - nbf = 0; - for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh2 = anExp.Current(); - Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2)); - GeomAPI_IntSS ISS(S1,S2,1.e-7); - if(ISS.IsDone()) { - for(int i=1; i<=ISS.NbLines(); i++) { - Handle(Geom_Curve) C3d = ISS.Line(i); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C3d,1.e-7); - BRepExtrema_DistShapeShape dst(tmpSh2,E); - if (dst.IsDone()) { - gp_Pnt PMin1, PMin2, P1, P2; - double MinDist = 1.e9; - for (int i = 1; i <= dst.NbSolution(); i++) { - P1 = dst.PointOnShape1(i); - P2 = dst.PointOnShape2(i); - Standard_Real Dist = P1.Distance(P2); - if (MinDist > Dist) { - MinDist = Dist; - Ptmp = P1; - } - } - if(MinDist<1.e-7) - return true; - } - } - } - } - } - } - nbf = 0; - for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh1 = anExp.Current(); - } - if(nbf==1) { - Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1)); - if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { - nbf = 0; - for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - tmpSh2 = anExp.Current(); - Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2)); - GeomAPI_IntSS ISS(S1,S2,1.e-7); - if(ISS.IsDone()) { - for(int i=1; i<=ISS.NbLines(); i++) { - Handle(Geom_Curve) C3d = ISS.Line(i); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C3d,1.e-7); - BRepExtrema_DistShapeShape dst(tmpSh2,E); - if (dst.IsDone()) { - gp_Pnt P1,P2; - double MinDist = 1.e9; - for (int i = 1; i <= dst.NbSolution(); i++) { - P1 = dst.PointOnShape1(i); - P2 = dst.PointOnShape2(i); - Standard_Real Dist = P1.Distance(P2); - if (MinDist > Dist) { - MinDist = Dist; - Ptmp = P1; - } - } - if(MinDist<1.e-7) - return true; - } - } - } - } - } - } - return false; -} -*/ - - //============================================================================= /*! * AreCoordsInside */ //============================================================================= -std::vector GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape, - const std::vector& coords, - double tolerance) +std::vector +GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape, + const std::vector& coords, + double tolerance) { - std::vector res; + std::vector isInsideRes; if (!theShape.IsNull()) { Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); if (!aRefShape.IsNull()) { TopoDS_Shape aShape = aRefShape->GetValue(); - if (!aShape.IsNull()) { - BRepClass3d_SolidClassifier SC(aShape); - unsigned int nb_points = coords.size()/3; - for (int i = 0; i < nb_points; i++) { - double x = coords[3*i]; - double y = coords[3*i+1]; - double z = coords[3*i+2]; - gp_Pnt aPnt(x, y, z); - SC.Perform(aPnt, tolerance); - res.push_back( ( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON ) ); + if (!aShape.IsNull()) + { + TopTools_IndexedMapOfShape mapShape; + { + TopExp_Explorer anExp; + for ( anExp.Init( aShape, TopAbs_SOLID ); anExp.More(); anExp.Next() ) + mapShape.Add( anExp.Current() ); + for ( anExp.Init( aShape, TopAbs_FACE, TopAbs_SOLID ); anExp.More(); anExp.Next() ) + mapShape.Add( anExp.Current() ); + for ( anExp.Init( aShape, TopAbs_EDGE, TopAbs_FACE ); anExp.More(); anExp.Next() ) + mapShape.Add( anExp.Current() ); + for ( anExp.Init( aShape, TopAbs_VERTEX, TopAbs_EDGE ); anExp.More(); anExp.Next() ) + mapShape.Add( anExp.Current() ); //// ????????? + } + size_t nb_points = coords.size()/3, nb_points_inside = 0; + isInsideRes.resize( nb_points, false ); + + for ( int iS = 1; iS <= mapShape.Extent(); ++iS ) + { + if ( nb_points_inside == nb_points ) + break; + aShape = mapShape( iS ); + switch ( aShape.ShapeType() ) { + case TopAbs_SOLID: + { + BRepClass3d_SolidClassifier SC( TopoDS::Solid( aShape )); + for ( size_t i = 0; i < nb_points; i++) + { + if ( isInsideRes[ i ]) continue; + gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] ); + SC.Perform( aPnt, tolerance ); + isInsideRes[ i ] = (( SC.State() == TopAbs_IN ) || ( SC.State() == TopAbs_ON )); + nb_points_inside += isInsideRes[ i ]; + } + break; + } + case TopAbs_FACE: + { + Standard_Real u1,u2,v1,v2; + const TopoDS_Face& face = TopoDS::Face( aShape ); + Handle(Geom_Surface) surf = BRep_Tool::Surface( face ); + surf->Bounds( u1,u2,v1,v2 ); + GeomAPI_ProjectPointOnSurf project; + project.Init(surf, u1,u2, v1,v2, tolerance ); + for ( size_t i = 0; i < nb_points; i++) + { + if ( isInsideRes[ i ]) continue; + gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] ); + project.Perform( aPnt ); + if ( project.IsDone() && + project.NbPoints() > 0 && + project.LowerDistance() <= tolerance ) + { + Quantity_Parameter u, v; + project.LowerDistanceParameters(u, v); + gp_Pnt2d uv( u, v ); + BRepClass_FaceClassifier FC ( face, uv, tolerance ); + isInsideRes[ i ] = (( FC.State() == TopAbs_IN ) || ( FC.State() == TopAbs_ON )); + nb_points_inside += isInsideRes[ i ]; + } + } + break; + } + case TopAbs_EDGE: + { + Standard_Real f,l; + const TopoDS_Edge& edge = TopoDS::Edge( aShape ); + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f, l ); + GeomAPI_ProjectPointOnCurve project; + project.Init( curve, f, l ); + for ( size_t i = 0; i < nb_points; i++) + { + if ( isInsideRes[ i ]) continue; + gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] ); + project.Perform( aPnt ); + isInsideRes[ i ] = ( project.NbPoints() > 0 && + project.LowerDistance() <= tolerance ); + nb_points_inside += isInsideRes[ i ]; + } + break; + } + case TopAbs_VERTEX: + { + gp_Pnt aVPnt = BRep_Tool::Pnt( TopoDS::Vertex( aShape )); + for ( size_t i = 0; i < nb_points; i++) + { + if ( isInsideRes[ i ]) continue; + gp_Pnt aPnt( coords[3*i], coords[3*i+1], coords[3*i+2] ); + isInsideRes[ i ] = ( aPnt.SquareDistance( aVPnt ) <= tolerance * tolerance ); + nb_points_inside += isInsideRes[ i ]; + } + break; + } + default:; + } // switch ( aShape.ShapeType() ) } } } } - return res; + return isInsideRes; } //============================================================================= @@ -1890,10 +1842,15 @@ std::vector GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Objec * GetMinDistance */ //============================================================================= -Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance - (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2, - Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1, - Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2) +Standard_Real +GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1, + Handle(GEOM_Object) theShape2, + Standard_Real& X1, + Standard_Real& Y1, + Standard_Real& Z1, + Standard_Real& X2, + Standard_Real& Y2, + Standard_Real& Z2) { SetErrorCode(KO); Standard_Real MinDist = 1.e9; @@ -1913,77 +1870,103 @@ Standard_Real GEOMImpl_IMeasureOperations::GetMinDistance //Compute the parameters try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif - - // Issue 0020231: A min distance bug with torus and vertex. - // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs - - // which of shapes consists of only one vertex? - TopExp_Explorer exp1(aShape1,TopAbs_VERTEX), exp2(aShape2,TopAbs_VERTEX); - TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape(); - TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape(); - exp1.Next(); exp2.Next(); - if ( exp1.More() ) V1.Nullify(); - if ( exp2.More() ) V2.Nullify(); - // vertex and container of solids - TopoDS_Shape V = V1.IsNull() ? V2 : V1; - TopoDS_Shape S = V1.IsNull() ? aShape1 : aShape2; - if ( !V.IsNull() ) { - // classify vertex against solids - gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) ); - for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) { - BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6); - if ( classifier.State() == TopAbs_IN ) { - p.Coord(X1, Y1, Z1); - p.Coord(X2, Y2, Z2); - SetErrorCode(OK); - return 0.0; - } - } + + gp_Pnt aPnt1, aPnt2; + + MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2); + + if (MinDist >= 0.0) { + aPnt1.Coord(X1, Y1, Z1); + aPnt2.Coord(X2, Y2, Z2); + } else { + return MinDist; } - // End Issue 0020231 + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return MinDist; + } + + SetErrorCode(OK); + return MinDist; +} + +//======================================================================= +/*! + * Get coordinates of closest points of two shapes + */ +//======================================================================= +Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) theShape1, + Handle(GEOM_Object) theShape2, + Handle(TColStd_HSequenceOfReal)& theDoubles) +{ + SetErrorCode(KO); + Standard_Integer nbSolutions = 0; + + if (theShape1.IsNull() || theShape2.IsNull()) return nbSolutions; + + Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction(); + Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction(); + if (aRefShape1.IsNull() || aRefShape2.IsNull()) return nbSolutions; + + TopoDS_Shape aShape1 = aRefShape1->GetValue(); + TopoDS_Shape aShape2 = aRefShape2->GetValue(); + if (aShape1.IsNull() || aShape2.IsNull()) { + SetErrorCode("One of Objects has NULL Shape"); + return nbSolutions; + } + + // Compute the extremities + try { + OCC_CATCH_SIGNALS; // skl 30.06.2008 // additional workaround for bugs 19899, 19908 and 19910 from Mantis - gp_Pnt Ptmp1, Ptmp2; - double dist = CheckSingularCase(aShape1, aShape2, Ptmp1, Ptmp2); - if(dist>-1.0) { - Ptmp1.Coord(X1, Y1, Z1); - Ptmp2.Coord(X2, Y2, Z2); + 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 dist; + return nbSolutions; } BRepExtrema_DistShapeShape dst (aShape1, aShape2); if (dst.IsDone()) { - gp_Pnt PMin1, PMin2, P1, P2; + nbSolutions = dst.NbSolution(); + if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal; - for (int i = 1; i <= dst.NbSolution(); i++) { + gp_Pnt P1, P2; + for (int i = 1; i <= nbSolutions; i++) { P1 = dst.PointOnShape1(i); P2 = dst.PointOnShape2(i); - Standard_Real Dist = P1.Distance(P2); - if (MinDist > Dist) { - MinDist = Dist; - PMin1 = P1; - PMin2 = P2; - } + theDoubles->Append(P1.X()); + theDoubles->Append(P1.Y()); + theDoubles->Append(P1.Z()); + theDoubles->Append(P2.X()); + theDoubles->Append(P2.Y()); + theDoubles->Append(P2.Z()); } - - PMin1.Coord(X1, Y1, Z1); - PMin2.Coord(X2, Y2, Z2); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); - return MinDist; + return nbSolutions; } SetErrorCode(OK); - return MinDist; + return nbSolutions; } //======================================================================= @@ -2011,9 +1994,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(); @@ -2063,9 +2044,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); @@ -2141,9 +2120,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); @@ -2203,9 +2180,7 @@ 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()); @@ -2257,9 +2232,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 @@ -2300,9 +2273,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()) { @@ -2482,362 +2453,157 @@ Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false); } - //======================================================================= -//function : StructuralDump -//purpose : Structural (data exchange) style of output. +//function : FillErrorsSub +//purpose : Fill the errors list of subshapes on shape. //======================================================================= -void GEOMImpl_IMeasureOperations::StructuralDump (const BRepCheck_Analyzer& theAna, - const TopoDS_Shape& theShape, - TCollection_AsciiString& theDump) +void GEOMImpl_IMeasureOperations::FillErrorsSub + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + const TopAbs_ShapeEnum theSubType, + TopTools_DataMapOfIntegerListOfShape &theMapErrors) const { - 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; - } - } + TopExp_Explorer anExp(theShape, theSubType); + TopTools_MapOfShape aMapSubShapes; - if (nbv > 0) { - theDump += "VERTEX : "; - if (nbv < 10) theDump += " "; - theDump += TCollection_AsciiString(nbv) + "\n"; - } - if (nbe > 0) { - theDump += "EDGE : "; - if (nbe < 10) theDump += " "; - theDump += TCollection_AsciiString(nbe) + "\n"; - } - if (nbw > 0) { - theDump += "WIRE : "; - if (nbw < 10) theDump += " "; - theDump += TCollection_AsciiString(nbw) + "\n"; - } - if (nbf > 0) { - theDump += "FACE : "; - if (nbf < 10) theDump += " "; - theDump += TCollection_AsciiString(nbf) + "\n"; - } - if (nbs > 0) { - theDump += "SHELL : "; - if (nbs < 10) theDump += " "; - theDump += TCollection_AsciiString(nbs) + "\n"; - } - if (nbo > 0) { - theDump += "SOLID : "; - if (nbo < 10) theDump += " "; - theDump += TCollection_AsciiString(nbo) + "\n"; - } -} + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aSubShape = anExp.Current(); + if (aMapSubShapes.Add(aSubShape)) { + const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape); -//======================================================================= -//function : GetProblemShapes -// purpose : for StructuralDump -//======================================================================= -void GEOMImpl_IMeasureOperations::GetProblemShapes (const BRepCheck_Analyzer& theAna, - const TopoDS_Shape& theShape, - Handle(TopTools_HSequenceOfShape)& sl, - Handle(TColStd_HArray1OfInteger)& NbProblems, - TopTools_DataMapOfShapeListOfShape& theMap) -{ - 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 (itl.Value() != BRepCheck_NoError) { - sl->Append(theShape); - BRepCheck_Status stat = itl.Value(); - NbProblems->SetValue((Standard_Integer)stat, - NbProblems->Value((Standard_Integer)stat) + 1); + 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; } } } - - 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 : Contains +//function : FillErrors +//purpose : Fill the errors list. //======================================================================= -static Standard_Boolean Contains (const TopTools_ListOfShape& L, - const TopoDS_Shape& S) +void GEOMImpl_IMeasureOperations::FillErrors + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + TopTools_DataMapOfIntegerListOfShape &theMapErrors, + TopTools_MapOfShape &theMapShapes) const { - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(L); it.More(); it.Next()) { - if (it.Value().IsSame(S)) { - return Standard_True; + 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) { + // 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; } } - return Standard_False; } //======================================================================= -//function : GetProblemSub -// purpose : for StructuralDump +//function : FillErrors +//purpose : Fill the errors list. //======================================================================= -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) +void GEOMImpl_IMeasureOperations::FillErrors + (const BRepCheck_Analyzer &theAna, + const TopoDS_Shape &theShape, + std::list &theErrors) const { - 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; + // 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); + } } }