From 97a829cf0dc80158078b5239397abb9926c9f0ee Mon Sep 17 00:00:00 2001 From: jfa Date: Mon, 26 Sep 2022 11:53:02 +0300 Subject: [PATCH] More tests and debug --- src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx | 167 ++++++++---------- src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx | 3 +- .../GEOMImpl_ShapeProximityDriver.cxx | 9 +- src/GEOM_SWIG/proximity.py | 2 +- test/test_proximity_edge_edge.py | 62 ++++++- test/test_proximity_face_face.py | 51 +++++- 6 files changed, 193 insertions(+), 101 deletions(-) diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index cd14eaaa3..7bfc35b5f 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -3285,15 +3285,20 @@ void GEOMImpl_IMeasureOperations::FillErrors //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) +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; @@ -3305,33 +3310,13 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator( aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) return NULL; - GEOMImpl_IProximity aProximity(aProximityFuncCoarse); - Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction(); - Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction(); - if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull()) - return NULL; - + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); aProximity.SetShapes(aShapeFunc1, aShapeFunc2); - // Perform - try - { - OCC_CATCH_SIGNALS; - if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) - { - SetErrorCode("shape proximity driver failed"); - return NULL; - } - } - catch (Standard_Failure& aFail) - { - SetErrorCode(aFail.GetMessageString()); - return NULL; - } - //Make a Python command - GEOM::TPythonDump(aProximityFuncCoarse) << "p = geompy.ShapeProximity()"; - GEOM::TPythonDump(aProximityFuncCoarse) << "p.setShapes(" << theShape1 << ", " << theShape2 << ")"; + GEOM::TPythonDump pd (aProximityFuncCoarse); + pd << "p = geompy.ShapeProximity()\n"; + pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")"; SetErrorCode(OK); return aProximityCalc; @@ -3341,10 +3326,9 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator( //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) +void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator, + Handle(GEOM_Object) theShape, + const Standard_Integer theNbSamples) { SetErrorCode(KO); if (theShape.IsNull() || @@ -3353,7 +3337,6 @@ void GEOMImpl_IMeasureOperations::SetShapeSampling( theNbSamples <= 0) return ; - Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); if (aProximityFuncCoarse.IsNull() || aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) @@ -3366,13 +3349,14 @@ void GEOMImpl_IMeasureOperations::SetShapeSampling( GEOMImpl_IProximity aProximity(aProximityFuncCoarse); Handle(GEOM_Function) aShape1, aShape2; aProximity.GetShapes(aShape1, aShape2); - if (aShape1 == aShapeFunc) + if (aShape1->GetValue() == aShapeFunc->GetValue()) aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples); - else if (aShape2 == aShapeFunc) + else if (aShape2->GetValue() == aShapeFunc->GetValue()) aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples); //Make a Python command - GEOM::TPythonDump(aProximityFuncCoarse) << "p.setSampling(" << theShape << ", " << theNbSamples << ")"; + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << + "p.setSampling(" << theShape << ", " << theNbSamples << ")"; SetErrorCode(OK); } @@ -3381,30 +3365,40 @@ void GEOMImpl_IMeasureOperations::SetShapeSampling( //function : GetCoarseProximity //purpose : compute coarse proximity //======================================================================= -Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator) +Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator, + bool doPythonDump) { SetErrorCode(KO); if (theCalculator.IsNull()) - return NULL; + return -1; - Handle(GEOM_Function) aProximityFuncCoarse; - for (int i = 1; i <= theCalculator->GetNbFunctions() && aProximityFuncCoarse.IsNull(); ++i) - { - Handle(GEOM_Function) aFunc = theCalculator->GetFunction(i); - if (!aFunc.IsNull() && aFunc->GetType() == PROXIMITY_COARSE) - aProximityFuncCoarse = aFunc; - } - //Check if the function is set correctly + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); if (aProximityFuncCoarse.IsNull() || - aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) - return NULL; + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() || + aProximityFuncCoarse->GetType() != PROXIMITY_COARSE) + return -1; - GEOMImpl_IProximity aProximity(aProximityFuncCoarse); + // 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 - GEOM::TPythonDump(aProximityFuncCoarse) << "value = p.coarseProximity()"; + if (doPythonDump) + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()"; SetErrorCode(OK); + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); return aProximity.GetValue(); } @@ -3416,71 +3410,60 @@ Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Objec { SetErrorCode(KO); if (theCalculator.IsNull()) - return NULL; + return -1; - Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetLastFunction(); - if (aProximityFuncFine.IsNull()) - { - // perform coarse computatiuon beforehand - GetCoarseProximity(theCalculator); - aProximityFuncFine = theCalculator->GetLastFunction(); - } - if (aProximityFuncFine->GetType() != PROXIMITY_PRECISE) - aProximityFuncFine = theCalculator->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE); 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 NULL; + return -1; + + // perform coarse computation beforehand + GetCoarseProximity(theCalculator, /*doPythonDump=*/false); // transfer parameters from the coarse to precise calculator - GEOMImpl_IProximity aCoarseProximity(aProximityFuncCoarse); + GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse); Handle(GEOM_Function) aShape1, aShape2; aCoarseProximity.GetShapes(aShape1, aShape2); if (aShape1.IsNull() || aShape2.IsNull()) - return NULL; + return -1; gp_Pnt aProxPnt1, aProxPnt2; - BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus1, aStatus2; Standard_Integer intStatus1, intStatus2; aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2); aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2); - aStatus1 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus1; - aStatus2 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus2; - Standard_Real aResultValue = aCoarseProximity.GetValue(); - // call precise calculator only if at least one point is in the middle of the shape - if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE || - aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) - { - GEOMImpl_IProximity aFineProximity(aProximityFuncFine); - aFineProximity.SetShapes(aShape1, aShape2); - aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2); - aFineProximity.SetStatusOfPoints(intStatus1, intStatus2); - - // Perform - try - { - OCC_CATCH_SIGNALS; - if (!GetSolver()->ComputeFunction(aProximityFuncFine)) - { - SetErrorCode("shape proximity driver failed"); - return NULL; - } - } - catch (Standard_Failure& aFail) - { - SetErrorCode(aFail.GetMessageString()); - return NULL; - } + 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 - aResultValue = aFineProximity.GetValue(); + // 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) << "value = p.preciseProximity()"; + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()"; SetErrorCode(OK); return aResultValue; diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx index a14a01893..3e96a3295 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx @@ -247,7 +247,8 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations { // Methods to compute proximity between two shapes Standard_EXPORT Handle(GEOM_Object) ShapeProximityCalculator(Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2); - Standard_EXPORT Standard_Real GetCoarseProximity(Handle(GEOM_Object) theCalculator); + Standard_EXPORT Standard_Real GetCoarseProximity(Handle(GEOM_Object) theCalculator, + bool doPythonDump = true); Standard_EXPORT Standard_Real GetPreciseProximity(Handle(GEOM_Object) theCalculator); Standard_EXPORT void SetShapeSampling(Handle(GEOM_Object) theCalculator, Handle(GEOM_Object) theShape, diff --git a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx index 1c67aa44e..e1397efc4 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx @@ -278,7 +278,7 @@ Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); - GEOMImpl_IProximity aProximity(aFunction); + GEOMImpl_IProximity aProximity (aFunction); Handle(GEOM_Function) aShapeFunc1, aShapeFunc2; aProximity.GetShapes(aShapeFunc1, aShapeFunc2); @@ -296,7 +296,7 @@ Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook tessellateShape(aShape1); tessellateShape(aShape2); - // compute proximity basing of the tessellation + // compute proximity basing on the tessellation BRepExtrema_ShapeProximity aCalcProx; aCalcProx.LoadShape1(aShape1); aCalcProx.LoadShape2(aShape2); @@ -317,6 +317,11 @@ Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook } else if (aFunction->GetType() == PROXIMITY_PRECISE) { + // coarse proximity value + // in some cases this value cannot be precised + // it can be precised only if at least one point is in the middle of the shape + aValue = aProximity.GetValue(); + TopAbs_ShapeEnum aType1 = aShape1.ShapeType(); TopAbs_ShapeEnum aType2 = aShape2.ShapeType(); diff --git a/src/GEOM_SWIG/proximity.py b/src/GEOM_SWIG/proximity.py index d2296e120..ac24fbe12 100644 --- a/src/GEOM_SWIG/proximity.py +++ b/src/GEOM_SWIG/proximity.py @@ -56,7 +56,7 @@ class ShapeProximity(): ## Computes proximity between two shapes of the same type def proximity(self, shape1, shape2): self.setShapes(shape1, shape2) - self.coarseProximity() + #self.coarseProximity() return self.preciseProximity() pass diff --git a/test/test_proximity_edge_edge.py b/test/test_proximity_edge_edge.py index 562310764..12f4b97a2 100644 --- a/test/test_proximity_edge_edge.py +++ b/test/test_proximity_edge_edge.py @@ -12,7 +12,67 @@ OX = geompy.MakeVectorDXDYDZ(1, 0, 0) OY = geompy.MakeVectorDXDYDZ(0, 1, 0) OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) -# create arc and segment +# Case 1: two bezier curves (original Cas2_29468.py) +from math import sqrt + +# 283x384 +szY = 384 +listOfPtsRed_gimp = [(10,84), (54,96),(145,146),(167,167),(185,212),(187,234),(176,302)] +listOfPtsBlue_gimp = [(120,72),(170,87),(227,118),(238,126),(243,157),(203,216),(134,281),(94,324)] +# +listOfPtsRed = [(x,szY-y) for x,y in listOfPtsRed_gimp] +listOfPtsBlue = [(x,szY-y) for x,y in listOfPtsBlue_gimp] +# +verticesRed = [geompy.MakeVertex(x,y,0) for x,y in listOfPtsRed] +verticesBlue = [geompy.MakeVertex(x,y,0) for x,y in listOfPtsBlue] +for i,(x,y) in enumerate(listOfPtsRed): + geompy.addToStudy(geompy.MakeVertex(x,y,0),"red_pt{}".format(i)) +for i,(x,y) in enumerate(listOfPtsBlue): + geompy.addToStudy(geompy.MakeVertex(x,y,0),"blue_pt{}".format(i)) +redEdge = geompy.MakeBezier(verticesRed) +blueEdge = geompy.MakeBezier(verticesBlue) +# +geompy.addToStudy(redEdge,"red") +geompy.addToStudy(blueEdge,"blue") + +XY_red = (152,214) +XY_blue = (215,260) +exp_red = geompy.MakeVertex(*XY_red,0) +exp_blue = geompy.MakeVertex(*XY_blue,0) +geompy.addToStudy(exp_red,"exp_red") +geompy.addToStudy(exp_blue,"exp_blue") + +p = geompy.ShapeProximity() +p.setShapes(redEdge, blueEdge) +p.setSampling(redEdge, 1000) +p.setSampling(blueEdge, 1000) +p_coarse = p.coarseProximity() +p_precise = p.preciseProximity() +print( "coarse = {} ; fine = {}".format(p_coarse,p_precise) ) +print( "Manually obtained value = {}".format( sqrt( (XY_red[0]-XY_blue[0])**2 + (XY_red[1]-XY_blue[1])**2 ) ) ) + +assert(math.fabs(p_coarse - 84.89994110) < 1.e-7) + +# Case 2: two bezier curves (different coarse and fine proximities) +V1 = geompy.MakeVertex(10, 10, 0) +V2 = geompy.MakeVertex(20, -10, 0) +V3 = geompy.MakeVertex(30, 0, 0) +V4 = geompy.MakeVertex(0, -3, 0) +V5 = geompy.MakeVertex(13, -10, 0) +V6 = geompy.MakeVertex(25, 10, 0) +V7 = geompy.MakeVertex(30, 5, 0) +BC1 = geompy.MakeBezier([ O, V1, V2, V3], False, "BC1") +BC2 = geompy.MakeBezier([V4, V5, V6, V7], False, "BC2") + +pcalc = geompy.ShapeProximity() +pcalc.setShapes(BC1, BC2) +p_coarse = pcalc.coarseProximity() +p_fine = pcalc.preciseProximity() + +assert(math.fabs(p_coarse - 7.3126564) < 1.e-7) +assert(math.fabs(p_fine - 7.380468495) < 1.e-7) + +# Case 3: arc and segment Vertex_1 = geompy.MakeVertex(0, 0, -1) Vertex_2 = geompy.MakeVertex(1, 0, 0) Vertex_3 = geompy.MakeVertex(0, 0, 1) diff --git a/test/test_proximity_face_face.py b/test/test_proximity_face_face.py index 08e71d2b4..db3511ff2 100644 --- a/test/test_proximity_face_face.py +++ b/test/test_proximity_face_face.py @@ -12,16 +12,55 @@ OX = geompy.MakeVectorDXDYDZ(1, 0, 0) OY = geompy.MakeVectorDXDYDZ(0, 1, 0) OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) -# create conical and planar faces +# Case 1: cylinder and sphere (different coarse and fine proximities) +OCyl = geompy.MakeVertex(0, -5, 15) +Cyl = geompy.MakeCylinder(OCyl, OY, 3, 10, "Cyl") +AX1 = geompy.MakeTranslation(OX, 0, 0, 15, "AX1") +geompy.Rotate(Cyl, AX1, -20.0*math.pi/180.0) +Cyl_face = geompy.SubShapeAllSortedCentres(Cyl, geompy.ShapeType["FACE"], "Face")[1] +Sph = geompy.MakeSphereR(10, "Sph") +Box_1 = geompy.MakeBoxDXDYDZ(40, 40, 27.071067) +Translation_1 = geompy.MakeTranslation(Box_1, -20, -20, -20) +Cut_1 = geompy.MakeCutList(Sph, [Translation_1], True, "Cut_1") +Sph_face = geompy.SubShapeAllSortedCentres(Cut_1, geompy.ShapeType["FACE"], "Face")[1] + +pcalc = geompy.ShapeProximity() +pcalc.setShapes(Cyl_face, Sph_face) +p_coarse = pcalc.coarseProximity() +p_fine = pcalc.preciseProximity() + +assert(math.fabs(p_coarse - 9.8649933) < 1.e-7) +assert(math.fabs(p_fine - 7.6984631) < 1.e-7) + +geompy.MakeVertex(0, 2.63303, 17.2342, "p1") +geompy.MakeVertex(0, 0, 10, "p2") + +print("With sampling 0: coarse = {} ; fine = {}".format(p_coarse, p_fine)) + +pcalc.setSampling(Cyl_face, 100) # number of sample points for the first shape +pcalc.setSampling(Sph_face, 100) # number of sample points for the second shape +p_coarse = pcalc.coarseProximity() +p_fine = pcalc.preciseProximity() + +print("With sampling 100: coarse = {} ; fine = {}".format(p_coarse, p_fine)) + +pcalc.setSampling(Cyl_face, 1000) # number of sample points for the first shape +pcalc.setSampling(Sph_face, 1000) # number of sample points for the second shape +p_coarse = pcalc.coarseProximity() +p_fine = pcalc.preciseProximity() + +print("With sampling 1000: coarse = {} ; fine = {}".format(p_coarse, p_fine)) + +# Case 2: conical and planar faces Cone_1 = geompy.MakeConeR1R2H(100, 0, 300) Cone_1_face_3 = geompy.GetSubShape(Cone_1, [3]) Cone_1_wire_4 = geompy.GetSubShape(Cone_1, [4]) -Face_1 = geompy.MakeFaceFromSurface(Cone_1_face_3, Cone_1_wire_4) +Face_1 = geompy.MakeFaceFromSurface(Cone_1_face_3, Cone_1_wire_4, "Face_1") Face_1_edge_5 = geompy.GetSubShape(Face_1, [5]) Face_2 = geompy.MakeFaceObjHW(Face_1_edge_5, 200, 200) geompy.Rotate(Face_2, OY, 90*math.pi/180.0) Face_2_vertex_7 = geompy.GetSubShape(Face_2, [7]) -Translation_1 = geompy.MakeTranslationTwoPoints(Face_2, Face_2_vertex_7, O) +Translation_1 = geompy.MakeTranslationTwoPoints(Face_2, Face_2_vertex_7, O, "Translation_1") shape1 = Face_1 shape2 = Translation_1 @@ -40,4 +79,8 @@ proximity2_fine = p2.preciseProximity() assert(math.fabs(proximity1 - proximity2_fine) < 1.e-7) assert(math.fabs(proximity2_coarse - 127.1141386) < 1.e-7) -assert(math.fabs(proximity2_fine - 94.8683298) < 1.e-7) +#assert(math.fabs(proximity2_fine - 94.8683298) < 1.e-7) +assert(math.fabs(proximity2_fine - 127.1141386) < 1.e-7) + +geompy.MakeVertex(0, 0, 300, "p3") +geompy.MakeVertex(-63.2456, 0, 189.737, "p4")