#include <GEOMImpl_MeasureDriver.hxx>
#include <GEOMImpl_IPatchFace.hxx>
+#include <GEOMImpl_IProximity.hxx>
#include <GEOMImpl_PatchFaceDriver.hxx>
+#include <GEOMImpl_ShapeProximityDriver.hxx>
#include <GEOMImpl_Types.hxx>
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
}
}
}
+
+//=======================================================================
+//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;
+}