Expressions: Add Vector API expression functions (#10237)

This commit is contained in:
Daniel-Khodabakhsh
2023-08-15 21:00:16 -07:00
committed by GitHub
parent a49e104993
commit 8003606222
3 changed files with 220 additions and 0 deletions

View File

@@ -1757,6 +1757,7 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
case TAN:
case TANH:
case TRUNC:
case VNORMALIZE:
if (args.size() != 1)
ARGUMENT_THROW("exactly one required.");
break;
@@ -1774,6 +1775,12 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
case MROTATEY:
case MROTATEZ:
case POW:
case VANGLE:
case VCROSS:
case VDOT:
case VSCALEX:
case VSCALEY:
case VSCALEZ:
if (args.size() != 2)
ARGUMENT_THROW("exactly two required.");
break;
@@ -1793,9 +1800,18 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
ARGUMENT_THROW("exactly two, three, or four required.");
break;
case VECTOR:
case VLINEDIST:
case VLINESEGDIST:
case VLINEPROJ:
case VPLANEDIST:
case VPLANEPROJ:
if (args.size() != 3)
ARGUMENT_THROW("exactly three required.");
break;
case VSCALE:
if (args.size() != 4)
ARGUMENT_THROW("exactly four required.");
break;
case MATRIX:
if (args.size() > 16)
ARGUMENT_THROW("exactly 16 or less required.");
@@ -2101,6 +2117,36 @@ Py::Object FunctionExpression::translationMatrix(double x, double y, double z)
return Py::asObject(new Base::MatrixPy(matrix));
}
double FunctionExpression::extractLengthValueArgument(
const Expression *expression,
const std::vector<Expression*> &arguments,
int argumentIndex
)
{
Quantity argumentQuantity = pyToQuantity(arguments[argumentIndex]->getPyValue(), expression);
if (!(argumentQuantity.isDimensionlessOrUnit(Unit::Length))) {
_EXPR_THROW("Unit must be either empty or a length.", expression);
}
return argumentQuantity.getValue();
}
Base::Vector3d FunctionExpression::extractVectorArgument(
const Expression *expression,
const std::vector<Expression*> &arguments,
int argumentIndex
)
{
Py::Object argument = arguments[argumentIndex]->getPyValue();
if (!PyObject_TypeCheck(argument.ptr(), &Base::VectorPy::Type)) {
_EXPR_THROW("Argument must be a vector.", expression);
}
return static_cast<Base::VectorPy*>(argument.ptr())->value();
}
Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std::vector<Expression*> &args)
{
if(!expr || !expr->getOwner())
@@ -2268,6 +2314,76 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std
case HIDDENREF:
case HREF:
return args[0]->getPyValue();
case VANGLE:
case VCROSS:
case VDOT:
case VLINEDIST:
case VLINESEGDIST:
case VLINEPROJ:
case VNORMALIZE:
case VPLANEDIST:
case VPLANEPROJ:
case VSCALE:
case VSCALEX:
case VSCALEY:
case VSCALEZ: {
Base::Vector3d vector1 = extractVectorArgument(expr, args, 0);
switch (f) {
case VNORMALIZE:
return Py::asObject(new Base::VectorPy(vector1.Normalize()));
case VSCALE: {
double scaleX = extractLengthValueArgument(expr, args, 1);
double scaleY = extractLengthValueArgument(expr, args, 2);
double scaleZ = extractLengthValueArgument(expr, args, 3);
vector1.Scale(scaleX, scaleY, scaleZ);
return Py::asObject(new Base::VectorPy(vector1));
}
case VSCALEX: {
double scaleX = extractLengthValueArgument(expr, args, 1);
vector1.ScaleX(scaleX);
return Py::asObject(new Base::VectorPy(vector1));
}
case VSCALEY: {
double scaleY = extractLengthValueArgument(expr, args, 1);
vector1.ScaleY(scaleY);
return Py::asObject(new Base::VectorPy(vector1));
}
case VSCALEZ: {
double scaleZ = extractLengthValueArgument(expr, args, 1);
vector1.ScaleZ(scaleZ);
return Py::asObject(new Base::VectorPy(vector1));
}
}
Base::Vector3d vector2 = extractVectorArgument(expr, args, 1);
switch (f) {
case VANGLE:
return Py::asObject(new QuantityPy(new Quantity(vector1.GetAngle(vector2) * 180 / M_PI, Unit::Angle)));
case VCROSS:
return Py::asObject(new Base::VectorPy(vector1.Cross(vector2)));
case VDOT:
return Py::Float(vector1.Dot(vector2));
}
Base::Vector3d vector3 = extractVectorArgument(expr, args, 2);
switch (f) {
case VLINEDIST:
return Py::asObject(new QuantityPy(new Quantity(vector1.DistanceToLine(vector2, vector3), Unit::Length)));
case VLINESEGDIST:
return Py::asObject(new Base::VectorPy(vector1.DistanceToLineSegment(vector2, vector3)));
case VLINEPROJ:
vector1.ProjectToLine(vector2, vector3);
return Py::asObject(new Base::VectorPy(vector1));
case VPLANEDIST:
return Py::asObject(new QuantityPy(new Quantity(vector1.DistanceToPlane(vector2, vector3), Unit::Length)));
case VPLANEPROJ:
vector1.ProjectToPlane(vector2, vector3);
return Py::asObject(new Base::VectorPy(vector1));
}
}
}
Py::Object e1 = args[0]->getPyValue();
@@ -2623,6 +2739,32 @@ void FunctionExpression::_toString(std::ostream &ss, bool persistent,int) const
ss << "tanh("; break;;
case TRUNC:
ss << "trunc("; break;;
case VANGLE:
ss << "vangle("; break;;
case VCROSS:
ss << "vcross("; break;;
case VDOT:
ss << "vdot("; break;;
case VLINEDIST:
ss << "vlinedist("; break;;
case VLINESEGDIST:
ss << "vlinesegdist("; break;;
case VLINEPROJ:
ss << "vlineproj("; break;;
case VNORMALIZE:
ss << "vnormalize("; break;;
case VPLANEDIST:
ss << "vplanedist("; break;;
case VPLANEPROJ:
ss << "vplaneproj("; break;;
case VSCALE:
ss << "vscale("; break;;
case VSCALEX:
ss << "vscalex("; break;;
case VSCALEY:
ss << "vscaley("; break;;
case VSCALEZ:
ss << "vscalez("; break;;
case MINVERT:
ss << "minvert("; break;;
case MROTATE:
@@ -3495,6 +3637,19 @@ static void initParser(const App::DocumentObject *owner)
registered_functions["tan"] = FunctionExpression::TAN;
registered_functions["tanh"] = FunctionExpression::TANH;
registered_functions["trunc"] = FunctionExpression::TRUNC;
registered_functions["vangle"] = FunctionExpression::VANGLE;
registered_functions["vcross"] = FunctionExpression::VCROSS;
registered_functions["vdot"] = FunctionExpression::VDOT;
registered_functions["vlinedist"] = FunctionExpression::VLINEDIST;
registered_functions["vlinesegdist"] = FunctionExpression::VLINESEGDIST;
registered_functions["vlineproj"] = FunctionExpression::VLINEPROJ;
registered_functions["vnormalize"] = FunctionExpression::VNORMALIZE;
registered_functions["vplanedist"] = FunctionExpression::VPLANEDIST;
registered_functions["vplaneproj"] = FunctionExpression::VPLANEPROJ;
registered_functions["vscale"] = FunctionExpression::VSCALE;
registered_functions["vscalex"] = FunctionExpression::VSCALEX;
registered_functions["vscaley"] = FunctionExpression::VSCALEY;
registered_functions["vscalez"] = FunctionExpression::VSCALEZ;
registered_functions["minvert"] = FunctionExpression::MINVERT;
registered_functions["mrotate"] = FunctionExpression::MROTATE;