-// Copyright (C) 2007-2016 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
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-#include <Basics_OCCTVersion.hxx>
-
#include <GEOMImpl_IMeasureOperations.hxx>
#include <GEOMImpl_IMeasure.hxx>
#include <GEOMImpl_MeasureDriver.hxx>
+
+#include <GEOMImpl_IPatchFace.hxx>
+#include <GEOMImpl_IProximity.hxx>
+#include <GEOMImpl_PatchFaceDriver.hxx>
+#include <GEOMImpl_ShapeProximityDriver.hxx>
+
#include <GEOMImpl_Types.hxx>
+#include <GEOMImpl_IConformity.hxx>
+#include <GEOMImpl_ConformityDriver.hxx>
+
#include <GEOMUtils.hxx>
#include <GEOMAlgo_AlgoTools.hxx>
// OCCT Includes
#include <Bnd_Box.hxx>
#include <BOPAlgo_CheckerSI.hxx>
-#include <BOPCol_ListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
#include <BOPDS_DS.hxx>
-#include <BOPDS_MapOfPassKey.hxx>
+#include <BOPDS_MapOfPair.hxx>
+#include <BOPDS_Pair.hxx>
+#include <BOPTools_AlgoTools.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepCheck_ListIteratorOfListOfStatus.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepExtrema_ShapeProximity.hxx>
-#if OCC_VERSION_LARGE > 0x06090000
#include <BRepExtrema_SelfIntersection.hxx>
#include <BRepExtrema_MapOfIntegerPackedMapOfInteger.hxx>
-#endif
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
#include <BRep_Tool.hxx>
* 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");
}
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();
- // specific processing for some "advandced" objects
+ // specific processing for some "advanced" objects
switch ( geom_type ) {
case GEOM_MARKER:
- // local coordinate systen
+ // local coordinate system
// (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz
TopoDS_Face aFace = TopoDS::Face( aShape );
return SK_LCS;
}
- // Interprete results
+ // Interpret results
TopAbs_ShapeEnum aType = anInfo.Type();
switch (aType)
{
theDoubles->Append(aP.Z());
}
break;
+ default:;
}
SetErrorCode(OK);
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;
}
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 =
return NULL;
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return NULL;
}
//=============================================================================
Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex
(Handle(GEOM_Object) theShape,
- Standard_Integer theIndex)
+ Standard_Integer theIndex,
+ Standard_Boolean theUseOri)
{
SetErrorCode(KO);
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 =
GEOMImpl_IMeasure aCI (aFunction);
aCI.SetBase(aRefShape);
aCI.SetIndex(theIndex);
+ aCI.SetUseOri(theUseOri);
//Compute
try {
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;
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 =
return NULL;
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return NULL;
}
*/
//=============================================================================
void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape,
+ const Standard_Real theTolerance,
Standard_Real& theLength,
Standard_Real& theSurfArea,
Standard_Real& theVolume)
//Compute the parameters
GProp_GProps LProps, SProps;
- Standard_Real anEps = 1.e-6;
+ Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6;
try {
OCC_CATCH_SIGNALS;
- BRepGProp::LinearProperties(aShape, LProps);
+ BRepGProp::LinearProperties(aShape, LProps, Standard_True);
theLength = LProps.Mass();
- BRepGProp::SurfaceProperties(aShape, SProps, anEps);
+ 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, anEps);
+ 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;
}
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();
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;
}
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;
}
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);
return NULL;
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return NULL;
}
VertMin = T;
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return;
}
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;
}
TopTools_IndexedMapOfShape anIndices;
TopExp::MapShapes(aScopy, anIndices);
- BOPCol_ListOfShape aLCS;
+ TopTools_ListOfShape aLCS;
aLCS.Append(aScopy);
//
BOPAlgo_CheckerSI aCSI; // checker of self-interferences
// 1. Launch the checker
aCSI.Perform();
- Standard_Integer iErr = aCSI.ErrorStatus();
+ Standard_Boolean iErr = aCSI.HasErrors();
//
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
//=============================================================================
bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
(Handle(GEOM_Object) theShape,
- float theDeflection, double theTolerance,
+ float theDeflection, double theTolerance,
Handle(TColStd_HSequenceOfInteger)& theIntersections)
{
SetErrorCode(KO);
TopTools_IndexedMapOfShape anIndices;
TopExp::MapShapes(aScopy, anIndices);
-#if OCC_VERSION_LARGE > 0x06090000
// Checker of fast interferences
BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance);
if (aTool.IsDone())
SetErrorCode(OK);
-#endif
return theIntersections->IsEmpty();
}
TopExp::MapShapes(aScopy1, anIndices1);
TopExp::MapShapes(aScopy2, anIndices2);
- BOPCol_ListOfShape aLCS1, aLCS2;
+ TopTools_ListOfShape aLCS1, aLCS2;
aLCS1.Append(aScopy1); aLCS2.Append(aScopy2);
//
BRepExtrema_ShapeProximity aBSP; // checker of fast interferences
aBSP.Perform();
// 2. Get sets of IDs of overlapped faces
-#if OCC_VERSION_LARGE > 0x06090000
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
-#else
- for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
-#endif
{
const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
theIntersections1->Append(anIndices1.FindIndex(aS1));
}
-#if OCC_VERSION_LARGE > 0x06090000
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
-#else
- for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
-#endif
{
const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
theIntersections2->Append(anIndices2.FindIndex(aS2));
aListOfShape.Append(s);
nbTypes[s.ShapeType()]++;
if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) {
- nbFlatType[s.ShapeType()]++;
+ nbFlatType[s.ShapeType()]++;
}
}
}
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";
+ Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n";
if (nbFlatType[TopAbs_EDGE] > 0)
- Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
+ Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n";
if (nbFlatType[TopAbs_WIRE] > 0)
- Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
+ Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n";
if (nbFlatType[TopAbs_FACE] > 0)
- Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
+ Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n";
if (nbFlatType[TopAbs_SHELL] > 0)
- Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
+ Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n";
if (nbFlatType[TopAbs_SOLID] > 0)
- Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n";
+ 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;
}
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 );
return MinDist;
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return MinDist;
}
// 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()) {
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;
}
SetErrorCode(OK);
}
- catch (Standard_Failure)
+ catch (Standard_Failure& aFail)
{
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode( aFail->GetMessageString() );
+ SetErrorCode( aFail.GetMessageString() );
}
}
SetErrorCode(OK);
}
- catch (Standard_Failure)
+ catch (Standard_Failure& aFail)
{
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ SetErrorCode(aFail.GetMessageString());
}
return anAngle;
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
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;
}
SetErrorCode(OK);
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return aRes;
}
SetErrorCode(OK);
}
}
- catch (Standard_Failure) {
- Handle(Standard_Failure) aFail = Standard_Failure::Caught();
- SetErrorCode(aFail->GetMessageString());
+ catch (Standard_Failure& aFail) {
+ SetErrorCode(aFail.GetMessageString());
return aRes;
}
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;
+
+ 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;
+}
+
+//=============================================================================
+/*!
+ * XYZtoUV
+ */
+ //=============================================================================
+Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV
+ (Handle(GEOM_Object) theSurf,
+ const Handle(TColStd_HArray1OfReal)& theXYZlist,
+ bool isNormalized)
+{
+ SetErrorCode(KO);
+
+ Handle(TColStd_HArray1OfReal) aRet;
+
+ // Check list of coordinates
+ int nbC = theXYZlist->Length();
+ int nbP = nbC / 3;
+ if (nbP * 3 != nbC) {
+ SetErrorCode("Coordinates list length is not divisible by 3");
+ return aRet;
+ }
+
+ // Check face
+ if (theSurf.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
+ if (aRefShape.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ // The shape can be a face, a shell of one face or a compound with one face
+ TopoDS_Face F;
+ if (aShape.ShapeType() == TopAbs_FACE) {
+ F = TopoDS::Face(aShape);
+ }
+ else if (aShape.ShapeType() < TopAbs_FACE) {
+ TopExp_Explorer Exp (aShape, TopAbs_FACE);
+ if (Exp.More()) {
+ F = TopoDS::Face(Exp.Current());
+ Exp.Next();
+ if (Exp.More()) {
+ SetErrorCode("There should be only one face");
+ return aRet;
+ }
+ }
+ }
+ if (F.IsNull()) {
+ SetErrorCode("There are no faces");
+ return aRet;
+ }
+
+ // Face tolerance
+ Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
+ squareTolerance = squareTolerance * squareTolerance;
+
+ // Compute parameters
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
+ aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1);
+
+ Standard_Real U1,U2, V1,V2;
+ BRepTools::UVBounds(F, U1, U2, V1, V2);
+ Standard_Real dU = U2 - U1;
+ Standard_Real dV = V2 - V1;
+
+ int iCLower = theXYZlist->Lower();
+ for (int iP = 0; iP < nbP; iP++) {
+ gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3),
+ theXYZlist->Value(iCLower + iP * 3 + 1),
+ theXYZlist->Value(iCLower + iP * 3 + 2));
+ Standard_Real U, V;
+ gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V);
+ if (aP.SquareDistance(aPonF) < squareTolerance) {
+ if (isNormalized) {
+ // Normalize parameters to be in [0, 1]
+ U = (U - U1) / dU;
+ V = (V - V1) / dV;
+ }
+ aRet->SetValue(iP * 2 , U);
+ aRet->SetValue(iP * 2 + 1, V);
+ }
+ else {
+ SetErrorCode("Point too far from face");
+ return aRet;
+ }
+ }
+
+ SetErrorCode(OK);
+ return aRet;
+}
+
+//=============================================================================
+/*!
+ * UVtoXYZ
+ */
+ //=============================================================================
+Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ
+ (Handle(GEOM_Object) theSurf,
+ const Handle(TColStd_HArray1OfReal)& theUVlist,
+ bool isNormalized)
+{
+ SetErrorCode(KO);
+
+ Handle(TColStd_HArray1OfReal) aRet;
+
+ // Check list of parameters
+ int nbC = theUVlist->Length();
+ int nbP = nbC / 2;
+ if (nbP * 2 != nbC) {
+ SetErrorCode("Parameters list length is not divisible by 2");
+ return aRet;
+ }
+
+ // Check face
+ if (theSurf.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction();
+ if (aRefShape.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ TopoDS_Shape aShape = aRefShape->GetValue();
+ if (aShape.IsNull()) {
+ SetErrorCode("The shape is NULL");
+ return aRet;
+ }
+
+ // The shape can be a face, a shell of one face or a compound with one face
+ TopoDS_Face F;
+ if (aShape.ShapeType() == TopAbs_FACE) {
+ F = TopoDS::Face(aShape);
+ }
+ else if (aShape.ShapeType() < TopAbs_FACE) {
+ TopExp_Explorer Exp (aShape, TopAbs_FACE);
+ if (Exp.More()) {
+ F = TopoDS::Face(Exp.Current());
+ Exp.Next();
+ if (Exp.More()) {
+ SetErrorCode("There should be only one face");
+ return aRet;
+ }
+ }
+ }
+ if (F.IsNull()) {
+ SetErrorCode("There are no faces");
+ return aRet;
+ }
+
+ // Face tolerance
+ Standard_Real squareTolerance = BRep_Tool::Tolerance(F);
+ squareTolerance = squareTolerance * squareTolerance;
+
+ // Compute coordinates
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
+ aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1);
+
+ Standard_Real U1,U2, V1,V2;
+ BRepTools::UVBounds(F, U1, U2, V1, V2);
+ Standard_Real dU = U2 - U1;
+ Standard_Real dV = V2 - V1;
+
+ Standard_Real tol = 1.e-4;
+ Standard_Real pc = Precision::Confusion();
+
+ int iCLower = theUVlist->Lower();
+ for (int iP = 0; iP < nbP; iP++) {
+ Standard_Real U = theUVlist->Value(iCLower + iP * 2);
+ Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1);
+
+ if (isNormalized) {
+ // Get real parameters from given normalized ones in [0, 1]
+ if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) {
+ SetErrorCode("Normalized parameter is out of range [0,1]");
+ return aRet;
+ }
+ U = U1 + dU * U;
+ V = V1 + dV * V;
+ }
+
+ gp_Pnt2d aP2d (U, V);
+
+ BRepClass_FaceClassifier aClsf (F, aP2d, tol);
+ if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
+ SetErrorCode("Given parameters are out of face");
+ return aRet;
+ }
+ gp_Pnt surfPnt = aSurf->Value(U, V);
+
+ aRet->SetValue(iP * 3 , surfPnt.X());
+ aRet->SetValue(iP * 3 + 1, surfPnt.Y());
+ aRet->SetValue(iP * 3 + 2, surfPnt.Z());
+ }
+
+ SetErrorCode(OK);
+ return aRet;
+}
+
+//=============================================================================
+/*!
+ * SelfIntersected2D
+ * Find all self-intersected 2D curves.
+ * \param theChecks list of failed checks, contains type of check and failed shapes
+ */
+ //=============================================================================
+std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects>
+ GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list<FailedChecks>& theChecks)
+{
+ SetErrorCode(KO);
+ MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D");
+
+ std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aSelfInters2D;
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ for (std::list<FailedChecks>::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;
+ }
+
+ 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::CoupleOfObjects>
+ GEOMImpl_IMeasureOperations::InterferingSubshapes
+ (const std::list<FailedChecks>& theChecks,
+ const int theShapeType1,
+ const int theShapeType2)
+{
+ SetErrorCode(KO);
+ MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes");
+
+ std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> anInterfer;
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ for (std::list<FailedChecks>::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<FailedChecks>& theChecks)
+{
+ SetErrorCode(KO);
+ MESSAGE("GEOMImpl_IMeasureOperations::smallEdges");
+
+ Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient;
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ for (std::list<FailedChecks>::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::CoupleOfObjects>
+ GEOMImpl_IMeasureOperations::DistantShapes
+ (const std::list<FailedChecks>& theChecks,
+ const int theShapeType,
+ const int theSubShapeType,
+ double theTolerance)
+{
+ SetErrorCode(KO);
+ MESSAGE("GEOMImpl_IMeasureOperations::distantShapes");
+
+ std::list<GEOMImpl_IMeasureOperations::CoupleOfObjects> aDistShapes;
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ for (std::list<FailedChecks>::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);
+ }
+ }
+ }
+ catch (Standard_Failure& aFail)
+ {
+ SetErrorCode(aFail.GetMessageString());
+ return aDistShapes;
+ }
+
+ 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<FailedChecks>& 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<Handle(GEOM_Object), Handle(GEOM_Object)> 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 });
+ }
+ }
+ catch (Standard_Failure& aFail)
+ {
+ SetErrorCode(aFail.GetMessageString());
+ return;
+ }
+
+ 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);
+ }
+ 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.
}
}
}
+
+//=======================================================================
+//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
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
+ bool doPythonDump)
+{
+ 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;
+ }
+ }
+ 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 : GetPreciseProximity
+//purpose : compute precise proximity
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
+{
+ 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;
+}