1
/***************************************************************************
2
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
24
#include "PreCompiled.h"
26
#include "GeometryPyCXX.h"
27
#include <Base/PyWrapParseTupleAndKeywords.h>
29
// inclusion of the generated files (generated out of PlacementPy.xml)
30
#include "PlacementPy.h"
31
#include "PlacementPy.cpp"
34
#include "RotationPy.h"
40
// returns a string which represents the object e.g. when printed in python
41
std::string PlacementPy::representation() const
46
PlacementPy::PointerType ptr = getPlacementPtr();
47
std::stringstream str;
48
ptr->getRotation().getYawPitchRoll(yaw, pitch, roll);
50
str << "Placement [Pos=(";
51
str << ptr->getPosition().x << "," << ptr->getPosition().y << "," << ptr->getPosition().z;
52
str << "), Yaw-Pitch-Roll=(" << yaw << "," << pitch << "," << roll << ")]";
57
PyObject* PlacementPy::PyMake(PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/)
59
// create a new instance of PlacementPy and the Twin object
60
return new PlacementPy(new Placement);
65
int PlacementPy::PyInit(PyObject* args, PyObject* /*kwd*/)
68
if (PyArg_ParseTuple(args, "")) {
73
if (PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type), &o)) {
75
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(o)->value();
76
getPlacementPtr()->fromMatrix(mat);
79
catch (const Base::Exception& e) {
80
PyErr_SetString(e.getPyExceptionType(), e.what());
86
if (PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &o)) {
87
Base::Placement* plm = static_cast<Base::PlacementPy*>(o)->getPlacementPtr();
88
*(getPlacementPtr()) = *plm;
95
if (PyArg_ParseTuple(args,
97
&(Base::VectorPy::Type), &o,
98
&(Base::VectorPy::Type), &d,
100
// NOTE: The first parameter defines the translation, the second the rotation axis
101
// and the last parameter defines the rotation angle in degree.
102
Base::Rotation rot(static_cast<Base::VectorPy*>(d)->value(), angle / 180.0 * D_PI);
103
*getPlacementPtr() = Base::Placement(static_cast<Base::VectorPy*>(o)->value(), rot);
108
if (PyArg_ParseTuple(args,
110
&(Base::VectorPy::Type), &o,
111
&(Base::RotationPy::Type), &d)) {
112
Base::Vector3d* pos = static_cast<Base::VectorPy*>(o)->getVectorPtr();
113
getPlacementPtr()->setPosition(*pos);
114
Base::Rotation* rot = static_cast<Base::RotationPy*>(d)->getRotationPtr();
115
getPlacementPtr()->setRotation(*rot);
121
if (PyArg_ParseTuple(args,
123
&(Base::VectorPy::Type), &o,
124
&(Base::RotationPy::Type), &d,
125
&(Base::VectorPy::Type), &c)) {
126
Base::Vector3d* pos = static_cast<Base::VectorPy*>(o)->getVectorPtr();
127
Base::Rotation* rot = static_cast<Base::RotationPy*>(d)->getRotationPtr();
128
Base::Vector3d* cnt = static_cast<Base::VectorPy*>(c)->getVectorPtr();
129
Base::Placement p(*pos, *rot, *cnt);
130
getPlacementPtr()->operator=(p);
134
PyErr_SetString(PyExc_TypeError, "empty parameter list, matrix or placement expected");
139
PyObject* PlacementPy::richCompare(PyObject* v, PyObject* w, int op)
141
if (PyObject_TypeCheck(v, &(PlacementPy::Type))
142
&& PyObject_TypeCheck(w, &(PlacementPy::Type))) {
143
Base::Placement p1 = *static_cast<PlacementPy*>(v)->getPlacementPtr();
144
Base::Placement p2 = *static_cast<PlacementPy*>(w)->getPlacementPtr();
146
PyObject* res = nullptr;
147
if (op != Py_EQ && op != Py_NE) {
148
PyErr_SetString(PyExc_TypeError, "no ordering relation is defined for Placement");
152
res = (p1 == p2) ? Py_True : Py_False;
156
res = (p1 != p2) ? Py_True : Py_False;
160
// This always returns False
161
Py_INCREF(Py_NotImplemented);
162
return Py_NotImplemented;
165
PyObject* PlacementPy::move(PyObject* args)
168
if (!PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &vec)) {
171
getPlacementPtr()->move(static_cast<VectorPy*>(vec)->value());
175
PyObject* PlacementPy::translate(PyObject* args)
181
PyObject* PlacementPy::rotate(PyObject* args, PyObject* kwds)
184
static const std::array<const char*, 6> kwlist {"center", "axis", "angle", "comp", nullptr};
187
PyObject* pyComp = Py_False; // NOLINT
189
if (!Base::Wrapped_ParseTupleAndKeywords(args,
193
¢er.x, ¢er.y, ¢er.z,
194
&axis.x, &axis.y, &axis.z,
195
&angle, &PyBool_Type, &pyComp)) {
201
* if comp is False, we retain the original behaviour that - contrary to the (old)
202
* documentation - generates Placements different from TopoShape.rotate() to ensure
203
* compatibility for existing code
205
bool comp = Base::asBoolean(pyComp);
208
getPlacementPtr()->multRight(
209
Placement(Vector3d(), Rotation(axis, toRadians<double>(angle)), center));
212
// multiply new Placement the same way TopoShape.rotate() does
213
getPlacementPtr()->multLeft(
214
Placement(Vector3d(), Rotation(axis, toRadians<double>(angle)), center));
219
catch (const Py::Exception&) {
225
PyObject* PlacementPy::multiply(PyObject* args)
228
if (!PyArg_ParseTuple(args, "O!", &(PlacementPy::Type), &plm)) {
231
Placement mult = (*getPlacementPtr()) * (*static_cast<PlacementPy*>(plm)->getPlacementPtr());
232
return new PlacementPy(new Placement(mult));
235
PyObject* PlacementPy::multVec(PyObject* args)
238
if (!PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &vec)) {
241
Base::Vector3d pnt(static_cast<VectorPy*>(vec)->value());
242
getPlacementPtr()->multVec(pnt, pnt);
243
return new VectorPy(new Vector3d(pnt));
246
PyObject* PlacementPy::copy(PyObject* args)
248
if (!PyArg_ParseTuple(args, "")) {
251
return new PlacementPy(new Placement(*getPlacementPtr()));
254
PyObject* PlacementPy::toMatrix(PyObject* args)
256
if (!PyArg_ParseTuple(args, "")) {
259
Base::Matrix4D mat = getPlacementPtr()->toMatrix();
260
return new MatrixPy(new Matrix4D(mat));
263
PyObject* PlacementPy::inverse(PyObject* args)
265
if (!PyArg_ParseTuple(args, "")) {
268
Base::Placement p = getPlacementPtr()->inverse();
269
return new PlacementPy(new Placement(p));
272
PyObject* PlacementPy::pow(PyObject* args)
275
PyObject* shorten = Py_True;
276
if (!PyArg_ParseTuple(args, "d|O!", &t, &(PyBool_Type), &shorten)) {
279
Base::Placement ret = getPlacementPtr()->pow(t, Base::asBoolean(shorten));
280
return new PlacementPy(new Placement(ret));
284
PyObject* PlacementPy::sclerp(PyObject* args)
288
PyObject* shorten = Py_True;
289
if (!PyArg_ParseTuple(args,
291
&(PlacementPy::Type),
298
Base::Placement plm2 = static_cast<Base::PlacementPy*>(pyplm2)->value();
299
Base::Placement ret =
300
Base::Placement::sclerp(*getPlacementPtr(), plm2, t, Base::asBoolean(shorten));
301
return new PlacementPy(new Placement(ret));
304
PyObject* PlacementPy::slerp(PyObject* args)
308
if (!PyArg_ParseTuple(args, "O!d", &(PlacementPy::Type), &pyplm2, &t)) {
311
Base::Placement plm2 = static_cast<Base::PlacementPy*>(pyplm2)->value();
312
Base::Placement ret = Base::Placement::slerp(*getPlacementPtr(), plm2, t);
313
return new PlacementPy(new Placement(ret));
316
PyObject* PlacementPy::isIdentity(PyObject* args)
319
if (!PyArg_ParseTuple(args, "|d", &tol)) {
322
bool none = tol > 0 ? getPlacementPtr()->isIdentity(tol) : getPlacementPtr()->isIdentity();
323
return Py_BuildValue("O", (none ? Py_True : Py_False));
326
PyObject* PlacementPy::isSame(PyObject* args)
330
if (!PyArg_ParseTuple(args, "O!|d", &PlacementPy::Type, &plm, &tol)) {
334
Base::Placement plm1 = *getPlacementPtr();
335
Base::Placement plm2 = *static_cast<PlacementPy*>(plm)->getPlacementPtr();
336
bool same = tol > 0.0 ? plm1.isSame(plm2, tol) : plm1.isSame(plm2);
337
return Py_BuildValue("O", (same ? Py_True : Py_False));
340
Py::Object PlacementPy::getBase() const
342
return Py::Vector(getPlacementPtr()->getPosition()); // NOLINT
345
void PlacementPy::setBase(Py::Object arg)
347
getPlacementPtr()->setPosition(Py::Vector(arg).toVector());
350
Py::Object PlacementPy::getRotation() const
352
return Py::Rotation(getPlacementPtr()->getRotation());
355
void PlacementPy::setRotation(Py::Object arg)
358
if (rot.accepts(arg.ptr())) {
359
getPlacementPtr()->setRotation(static_cast<Base::Rotation>(Py::Rotation(arg)));
363
if (tuple.accepts(arg.ptr())) {
365
getPlacementPtr()->setRotation(Base::Rotation(static_cast<double>(Py::Float(tuple[0])),
366
static_cast<double>(Py::Float(tuple[1])),
367
static_cast<double>(Py::Float(tuple[2])),
368
static_cast<double>(Py::Float(tuple[3]))));
372
throw Py::TypeError("either Rotation or tuple of four floats expected");
375
Py::Object PlacementPy::getMatrix() const
377
return Py::Matrix(getPlacementPtr()->toMatrix());
380
void PlacementPy::setMatrix(Py::Object arg)
383
if (!mat.accepts(arg.ptr())) {
384
throw Py::TypeError("Expect type Matrix");
388
getPlacementPtr()->fromMatrix(mat);
390
catch (const Base::ValueError& e) {
391
throw Py::ValueError(e.what());
395
PyObject* PlacementPy::getCustomAttributes(const char* attr) const
397
// for backward compatibility
398
if (strcmp(attr, "isNull") == 0) {
401
w = PyUnicode_InternFromString("isIdentity");
402
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
403
res = PyObject_GenericGetAttr(const_cast<PlacementPy*>(this), w);
410
int PlacementPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
415
PyObject* PlacementPy::number_multiply_handler(PyObject* self, PyObject* other)
417
if (PyObject_TypeCheck(self, &(PlacementPy::Type))) {
418
Base::Placement a = static_cast<PlacementPy*>(self)->value();
420
if (PyObject_TypeCheck(other, &(VectorPy::Type))) {
422
a.multVec(static_cast<VectorPy*>(other)->value(), res);
423
return new VectorPy(res);
426
if (PyObject_TypeCheck(other, &(RotationPy::Type))) {
427
Placement b(Vector3d(), static_cast<RotationPy*>(other)->value());
428
return new PlacementPy(a * b);
431
if (PyObject_TypeCheck(other, &(PlacementPy::Type))) {
432
const auto& b = static_cast<PlacementPy*>(other)->value();
433
return new PlacementPy(a * b);
436
if (PyObject_TypeCheck(other, &(MatrixPy::Type))) {
437
const auto& b = static_cast<MatrixPy*>(other)->value();
438
return new MatrixPy(a.toMatrix() * b);
442
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
446
PyObject* PlacementPy::number_power_handler(PyObject* self, PyObject* other, PyObject* arg)
448
Py::Object pw(other);
453
if (!PyArg_ParseTuple(tup.ptr(), "d", &pw_v)) {
456
if (!PyObject_TypeCheck(self, &(PlacementPy::Type)) || arg != Py_None) {
457
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
461
Placement a = static_cast<PlacementPy*>(self)->value();
462
return new PlacementPy(a.pow(pw_v));
465
PyObject* PlacementPy::number_add_handler(PyObject* /*self*/, PyObject* /*other*/)
467
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
471
PyObject* PlacementPy::number_subtract_handler(PyObject* /*self*/, PyObject* /*other*/)
473
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
477
PyObject* PlacementPy::number_divide_handler(PyObject* /*self*/, PyObject* /*other*/)
479
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
483
PyObject* PlacementPy::number_remainder_handler(PyObject* /*self*/, PyObject* /*other*/)
485
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
489
PyObject* PlacementPy::number_divmod_handler(PyObject* /*self*/, PyObject* /*other*/)
491
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
495
PyObject* PlacementPy::number_negative_handler(PyObject* /*self*/)
497
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
501
PyObject* PlacementPy::number_positive_handler(PyObject* /*self*/)
503
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
507
PyObject* PlacementPy::number_absolute_handler(PyObject* /*self*/)
509
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
513
int PlacementPy::number_nonzero_handler(PyObject* /*self*/)
518
PyObject* PlacementPy::number_invert_handler(PyObject* /*self*/)
520
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
524
PyObject* PlacementPy::number_lshift_handler(PyObject* /*self*/, PyObject* /*other*/)
526
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
530
PyObject* PlacementPy::number_rshift_handler(PyObject* /*self*/, PyObject* /*other*/)
532
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
536
PyObject* PlacementPy::number_and_handler(PyObject* /*self*/, PyObject* /*other*/)
538
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
542
PyObject* PlacementPy::number_xor_handler(PyObject* /*self*/, PyObject* /*other*/)
544
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
548
PyObject* PlacementPy::number_or_handler(PyObject* /*self*/, PyObject* /*other*/)
550
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
554
PyObject* PlacementPy::number_int_handler(PyObject* /*self*/)
556
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");
560
PyObject* PlacementPy::number_float_handler(PyObject* /*self*/)
562
PyErr_SetString(PyExc_NotImplementedError, "Not implemented");