+ if (theShape.IsNull()) return;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull()) return;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The Objects has NULL Shape");
+ return;
+ }
+
+ //Compute the parameters
+ 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);
+ } else if (aShape.ShapeType() == TopAbs_FACE ||
+ aShape.ShapeType() == TopAbs_SHELL) {
+ BRepGProp::SurfaceProperties(aShape, System);
+ } else {
+ BRepGProp::VolumeProperties(aShape, System);
+ }
+ gp_Mat I = System.MatrixOfInertia();
+
+ I11 = I(1,1);
+ I12 = I(1,2);
+ I13 = I(1,3);
+
+ I21 = I(2,1);
+ I22 = I(2,2);
+ I23 = I(2,3);
+
+ I31 = I(3,1);
+ I32 = I(3,2);
+ I33 = I(3,3);
+
+ GProp_PrincipalProps Pr = System.PrincipalProperties();
+ Pr.Moments(Ix,Iy,Iz);
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return;
+ }
+
+ SetErrorCode(OK);
+}
+
+//=============================================================================
+/*!
+ * GetBoundingBox
+ */
+//=============================================================================
+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)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull()) return;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull()) return;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The Objects has NULL Shape");
+ return;
+ }
+
+ //Compute the parameters
+ 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");
+ return;
+ }
+
+ aShape = aCopyTool.Shape();
+
+ // remove triangulation to obtain more exact boundaries
+ 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) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return;
+ }
+
+ 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 {
+#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());
+ 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
+ */
+//=============================================================================
+void GEOMImpl_IMeasureOperations::GetTolerance
+ (Handle(GEOM_Object) theShape,
+ Standard_Real& FaceMin, Standard_Real& FaceMax,
+ Standard_Real& EdgeMin, Standard_Real& EdgeMax,
+ Standard_Real& VertMin, Standard_Real& VertMax)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull()) return;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull()) return;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The Objects has NULL Shape");
+ return;
+ }
+
+ //Compute the parameters
+ Standard_Real T;
+ FaceMin = EdgeMin = VertMin = RealLast();
+ 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);
+ if (T > FaceMax)
+ FaceMax = T;
+ if (T < FaceMin)
+ FaceMin = T;
+ }
+ for (TopExp_Explorer ExE (aShape, TopAbs_EDGE); ExE.More(); ExE.Next()) {
+ TopoDS_Edge Edge = TopoDS::Edge(ExE.Current());
+ T = BRep_Tool::Tolerance(Edge);
+ if (T > EdgeMax)
+ EdgeMax = T;
+ if (T < EdgeMin)
+ EdgeMin = T;
+ }
+ for (TopExp_Explorer ExV (aShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
+ TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current());
+ T = BRep_Tool::Tolerance(Vertex);
+ if (T > VertMax)
+ VertMax = T;
+ if (T < VertMin)
+ VertMin = T;
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return;
+ }
+
+ SetErrorCode(OK);
+}
+
+//=============================================================================
+/*!
+ * CheckShape
+ */
+//=============================================================================
+bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
+ const Standard_Boolean theIsCheckGeom,
+ TCollection_AsciiString& theDump)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull()) return false;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull()) return false;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The Objects has NULL Shape");
+ return false;
+ }
+
+ //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);
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return false;
+ }
+
+ SetErrorCode(OK);
+ return isValid;
+}
+
+//=============================================================================
+/*!
+ * CheckSelfIntersections
+ */
+//=============================================================================
+bool GEOMImpl_IMeasureOperations::CheckSelfIntersections
+ (Handle(GEOM_Object) theShape,
+ Handle(TColStd_HSequenceOfInteger)& theIntersections)
+{
+ SetErrorCode(KO);
+ bool isGood = false;
+
+ if (theIntersections.IsNull())
+ theIntersections = new TColStd_HSequenceOfInteger;
+ else
+ theIntersections->Clear();
+
+ if (theShape.IsNull())
+ return isGood;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull()) return isGood;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) return isGood;
+
+ // 0. Prepare data
+ BRep_Builder aBB;
+ TopoDS_Compound aCS;
+ TopoDS_Shape 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);
+
+ BOPCol_ListOfShape aLCS;
+ aLCS.Append(aScopy);
+ //
+ BOPAlgo_CheckerSI aCSI; // checker of self-interferences
+ aCSI.SetArguments(aLCS);
+
+ // 1. Launch the checker
+ aCSI.Perform();
+ Standard_Integer iErr = aCSI.ErrorStatus();
+ if (iErr) {
+ return false; // Error
+ }
+
+ isGood = true;
+ //
+ Standard_Integer aNbS, n1, n2;
+ BOPDS_MapIteratorMapOfPassKey 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();
+ 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);
+
+ theIntersections->Append(anIndices.FindIndex(aS1));
+ theIntersections->Append(anIndices.FindIndex(aS2));
+ isGood = false;
+ }
+
+ 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)
+ nbTypes[iType] = 0;
+ nbTypes[aShape.ShapeType()]++;
+
+ TopTools_MapOfShape aMapOfShape;
+ aMapOfShape.Add(aShape);
+ TopTools_ListOfShape aListOfShape;
+ aListOfShape.Append(aShape);
+
+ TopTools_ListIteratorOfListOfShape itL (aListOfShape);
+ for (; itL.More(); itL.Next()) {
+ TopoDS_Iterator it (itL.Value());
+ for (; it.More(); it.Next()) {
+ TopoDS_Shape s = it.Value();
+ if (aMapOfShape.Add(s)) {
+ aListOfShape.Append(s);
+ nbTypes[s.ShapeType()]++;
+ }
+ }
+ }
+
+ Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbTypes[TopAbs_VERTEX]) + "\n";
+ Astr = Astr + " EDGE : " + TCollection_AsciiString(nbTypes[TopAbs_EDGE]) + "\n";
+ Astr = Astr + " WIRE : " + TCollection_AsciiString(nbTypes[TopAbs_WIRE]) + "\n";
+ Astr = Astr + " FACE : " + TCollection_AsciiString(nbTypes[TopAbs_FACE]) + "\n";
+ Astr = Astr + " SHELL : " + TCollection_AsciiString(nbTypes[TopAbs_SHELL]) + "\n";
+ 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());
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return Astr;
+ }
+
+ SetErrorCode(OK);
+ return Astr;
+}
+
+//=============================================================================
+/*!
+ * AreCoordsInside
+ */
+//=============================================================================
+std::vector<bool>
+GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape,
+ const std::vector<double>& coords,
+ double tolerance)
+{
+ std::vector<bool> isInsideRes;
+ if (!theShape.IsNull()) {
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (!aRefShape.IsNull()) {
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ 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 isInsideRes;
+}
+
+//=============================================================================
+/*!
+ * 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)
+{
+ SetErrorCode(KO);
+ Standard_Real MinDist = 1.e9;
+
+ if (theShape1.IsNull() || theShape2.IsNull()) return MinDist;
+
+ Handle(GEOM_Function) aRefShape1 = theShape1->GetLastFunction();
+ Handle(GEOM_Function) aRefShape2 = theShape2->GetLastFunction();
+ if (aRefShape1.IsNull() || aRefShape2.IsNull()) return MinDist;
+
+ TopoDS_Shape aShape1 = aRefShape1->GetValue();
+ TopoDS_Shape aShape2 = aRefShape2->GetValue();
+ if (aShape1.IsNull() || aShape2.IsNull()) {
+ SetErrorCode("One of Objects has NULL Shape");
+ return MinDist;
+ }
+
+ //Compute the parameters
+ try {
+#if OCC_VERSION_LARGE > 0x06010000
+ OCC_CATCH_SIGNALS;
+#endif
+
+ 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;
+ }
+ }
+ 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 {
+#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;
+ }
+
+ BRepExtrema_DistShapeShape dst (aShape1, aShape2);
+ if (dst.IsDone()) {
+ nbSolutions = dst.NbSolution();
+ if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal;
+
+ gp_Pnt P1, P2;
+ 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());
+ }
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return nbSolutions;
+ }
+
+ SetErrorCode(OK);
+ return nbSolutions;
+}
+
+//=======================================================================
+/*!
+ * Get coordinates of point
+ */
+//=======================================================================
+void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape,
+ Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull())
+ return;
+
+ Handle(GEOM_Function) aRefShape = theShape->GetLastFunction();
+ if (aRefShape.IsNull())
+ return;
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull() || aShape.ShapeType() != TopAbs_VERTEX)
+ {
+ SetErrorCode( "Shape must be a vertex" );
+ return;
+ }
+
+ 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();
+ theZ = aPnt.Z();
+
+ SetErrorCode(OK);
+ }
+ catch (Standard_Failure)
+ {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode( aFail->GetMessageString() );
+ }
+}
+
+//=======================================================================
+/*!
+ * Compute angle (in degrees) between two lines
+ */
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine1,
+ Handle(GEOM_Object) theLine2)
+{
+ if (theLine1->GetType() == GEOM_VECTOR &&
+ theLine2->GetType() == GEOM_VECTOR)
+ return GetAngleBtwVectors(theLine1, theLine2);
+
+ SetErrorCode(KO);
+
+ Standard_Real anAngle = -1.0;
+
+ if (theLine1.IsNull() || theLine2.IsNull())
+ return anAngle;
+
+ Handle(GEOM_Function) aRefLine1 = theLine1->GetLastFunction();
+ Handle(GEOM_Function) aRefLine2 = theLine2->GetLastFunction();
+ if (aRefLine1.IsNull() || aRefLine2.IsNull())
+ return anAngle;
+
+ TopoDS_Shape aLine1 = aRefLine1->GetValue();
+ TopoDS_Shape aLine2 = aRefLine2->GetValue();
+ if (aLine1.IsNull() || aLine2.IsNull() ||
+ aLine1.ShapeType() != TopAbs_EDGE ||
+ aLine2.ShapeType() != TopAbs_EDGE)
+ {
+ SetErrorCode("Two edges must be given");
+ return anAngle;
+ }
+
+ try {
+#if OCC_VERSION_LARGE > 0x06010000
+ OCC_CATCH_SIGNALS;
+#endif
+ TopoDS_Edge E1 = TopoDS::Edge(aLine1);
+ TopoDS_Edge E2 = TopoDS::Edge(aLine2);
+
+ double fp,lp;
+ Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
+ Handle(Geom_Curve) C2 = BRep_Tool::Curve(E2,fp,lp);
+
+ if ( C1.IsNull() || C2.IsNull() ||
+ !C1->IsKind(STANDARD_TYPE(Geom_Line)) ||
+ !C2->IsKind(STANDARD_TYPE(Geom_Line)))
+ {
+ SetErrorCode("The edges must be linear");
+ return anAngle;
+ }
+
+ Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(C1);
+ Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(C2);
+
+ gp_Lin aLin1 = L1->Lin();
+ gp_Lin aLin2 = L2->Lin();
+
+ anAngle = aLin1.Angle(aLin2);
+ anAngle *= 180. / M_PI; // convert radians into degrees
+
+ if (anAngle > 90.0) {
+ anAngle = 180.0 - anAngle;
+ }
+
+ SetErrorCode(OK);
+ }
+ catch (Standard_Failure)
+ {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ }
+
+ return anAngle;
+}
+
+//=======================================================================
+/*!
+ * Compute angle (in degrees) between two vectors
+ */
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Object) theVec1,
+ Handle(GEOM_Object) theVec2)
+{
+ SetErrorCode(KO);
+
+ Standard_Real anAngle = -1.0;