diff --git a/src/Base/PlacementPy.xml b/src/Base/PlacementPy.xml index 97ce441e8d..f2dc26dbcb 100644 --- a/src/Base/PlacementPy.xml +++ b/src/Base/PlacementPy.xml @@ -85,7 +85,7 @@ Placement(Base, Axis, Angle) -- define position and rotation - + inverse() -> Placement @@ -93,6 +93,27 @@ Placement(Base, Axis, Angle) -- define position and rotation + + + + pow(t, shorten = true): raise this placement to real power using ScLERP interpolation. + If 'shorten' is true, ensures rotation quaternion is net positive, to make the path shorter. + Also available as ** operator. + + + + + + + sclerp(t, placement2, shorten = True): interpolate between self and placement2. + Interpolation is a continuous motion along a helical path, made of equal transforms if discretized. + t = 0.0 - return self. t = 1.0 - return placement2. t can also be outside of 0..1 range, for extrapolation. + If quaternions of rotations of the two placements differ in sign, the interpolation will + take a long path. If 'shorten' is true, the signs are harmonized before interpolation, and the + interpolation takes the shorter path. + + + diff --git a/src/Base/PlacementPyImp.cpp b/src/Base/PlacementPyImp.cpp index c1f6884925..0ff7ebe2da 100644 --- a/src/Base/PlacementPyImp.cpp +++ b/src/Base/PlacementPyImp.cpp @@ -229,6 +229,29 @@ PyObject* PlacementPy::inverse(PyObject * args) return new PlacementPy(new Placement(p)); } +PyObject* PlacementPy::pow(PyObject* args) +{ + double t; + PyObject* shorten = Py_True; + if (!PyArg_ParseTuple(args, "d|O!", &t, &(PyBool_Type), &shorten)) + return nullptr; + Base::Placement ret = getPlacementPtr()->pow(t, PyObject_IsTrue(shorten)); + return new PlacementPy(new Placement(ret)); +} + + +PyObject* PlacementPy::sclerp(PyObject* args) +{ + PyObject* pyplm2; + double t; + PyObject* shorten = Py_True; + if (!PyArg_ParseTuple(args, "dO!|O!", &t, &(PlacementPy::Type), &pyplm2, &(PyBool_Type), &shorten)) + return nullptr; + Base::Placement plm2 = static_cast(pyplm2)->value(); + Base::Placement ret = Base::Placement::sclerp(*getPlacementPtr(), plm2, t, PyObject_IsTrue(shorten)); + return new PlacementPy(new Placement(ret)); +} + PyObject* PlacementPy::isIdentity(PyObject *args) { if (!PyArg_ParseTuple(args, "")) @@ -342,34 +365,24 @@ PyObject* PlacementPy::number_multiply_handler(PyObject *self, PyObject *other) PyObject * PlacementPy::number_power_handler (PyObject* self, PyObject* other, PyObject* arg) { - if (!PyObject_TypeCheck(self, &(PlacementPy::Type)) || + Py::Object pw(other); + Py::Tuple tup(1); + tup[0] = pw; -#if PY_MAJOR_VERSION < 3 - !PyInt_Check(other) -#else - !PyLong_Check(other) -#endif - || arg != Py_None - ) + double pw_v; + if (!PyArg_ParseTuple(tup.ptr(), "d", &pw_v)){ + //PyErr_SetString(PyExc_NotImplementedError, "Wrong exponent type (expect float)."); + return nullptr; + } + if (!PyObject_TypeCheck(self, &(PlacementPy::Type)) + || arg != Py_None) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return 0; } - auto a = static_cast(self)->value(); - - long b = Py::Int(other); - if(!b) - return new PlacementPy(Placement()); - - if(b < 0) { - b = -b; - a.invert(); - } - auto res = a; - for(--b;b;--b) - res *= a; - return new PlacementPy(res); + Placement a = static_cast(self)->value(); + return new PlacementPy(a.pow(pw_v)); } PyObject* PlacementPy::number_add_handler(PyObject * /*self*/, PyObject * /*other*/)