From 4b538a38ab39ef69a5c31439d302a3ee06ff1fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Fri, 29 Jul 2022 17:07:33 +0200 Subject: [PATCH] Fix Placement.rotate() to match documentation Documentation for Placement.rotate() claims this function would be compatible to TopoShape.rotate() which isn't exactly correct as the generated placements differ because of backwards multiplication. This commit adds a "comp" (as in "compatible") keyword argument that - when "True" (default is False) - produces a Placement that is interchangable with the one that is generated from TopoShape.rotate(). --- src/Base/PlacementPy.xml | 13 ++++++++---- src/Base/PlacementPyImp.cpp | 40 +++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/Base/PlacementPy.xml b/src/Base/PlacementPy.xml index 658bd6f26a..79ebff89ed 100644 --- a/src/Base/PlacementPy.xml +++ b/src/Base/PlacementPy.xml @@ -63,14 +63,19 @@ Alias to move(), to be compatible with TopoShape.translate().\n vector : Base.Vector\n Vector by which to move the placement. - + - rotate(center, axis, angle) -> None\n + rotate(center, axis, angle, comp) -> None\n Rotate the current placement around center and axis with the given angle. -This method is compatible with TopoShape.rotate().\n +This method is compatible with TopoShape.rotate() if the (optional) keyword +argument comp is True (default=False). + center : Base.Vector, sequence of float\n Rotation center. axis : Base.Vector, sequence of float\n Rotation axis. -angle : float\n Rotation angle in degrees. +angle : float\n Rotation angle in degrees. +comp : bool\n optional keyword only argument, if True (default=False), +behave like TopoShape.rotate() (i.e. the resulting placements are interchangeable). + diff --git a/src/Base/PlacementPyImp.cpp b/src/Base/PlacementPyImp.cpp index f7d9761492..8b62c7ed49 100644 --- a/src/Base/PlacementPyImp.cpp +++ b/src/Base/PlacementPyImp.cpp @@ -163,22 +163,36 @@ PyObject* PlacementPy::translate(PyObject * args) return move(args); } -PyObject* PlacementPy::rotate(PyObject *args) { - PyObject *obj1, *obj2; +PyObject* PlacementPy::rotate(PyObject *args, PyObject *kw) { double angle; - if (!PyArg_ParseTuple(args, "OOd", &obj1, &obj2, &angle)) + char *keywords[] = { "center", "axis", "angle", "comp", nullptr }; + Vector3d center; + Vector3d axis; + PyObject* pyComp = Py_False; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "(ddd)(ddd)d|$O!", keywords, ¢er.x, ¢er.y, ¢er.z, + &axis.x, &axis.y, &axis.z, &angle, &PyBool_Type, &pyComp)) return nullptr; - + try { - Py::Sequence p1(obj1), p2(obj2); - Vector3d center((double)Py::Float(p1[0]), - (double)Py::Float(p1[1]), - (double)Py::Float(p1[2])); - Vector3d axis((double)Py::Float(p2[0]), - (double)Py::Float(p2[1]), - (double)Py::Float(p2[2])); - (*getPlacementPtr()) *= Placement( - Vector3d(),Rotation(axis,toRadians(angle)),center); + /* + * if comp is False, we retain the original behaviour that - contrary to the documentation - generates + * Placements different from TopoShape.rotate() to ensure compatibility for existing code + */ + bool comp = Base::asBoolean(pyComp); + + if (!comp) { + (*getPlacementPtr()) *= Placement( + Vector3d(),Rotation(axis,toRadians(angle)),center); + } else + { + // multiply new Placement the same way TopoShape.rotate() does + + Placement p = *getPlacementPtr(); + *getPlacementPtr() = Placement( + Vector3d(),Rotation(axis,toRadians(angle)),center) * p; + } + Py_Return; } catch (const Py::Exception&) {