File size: 9,440 Bytes
985c397 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | // SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PY_GEOMETRYPY_H
#define PY_GEOMETRYPY_H
#include <CXX/Extensions.hxx>
#include <FCGlobal.h>
#include <Base/BoundBoxPy.h>
#include <Base/MatrixPy.h>
#include <Base/RotationPy.h>
#include <Base/PlacementPy.h>
namespace Base
{
class Matrix4D;
class Rotation;
class Placement;
template<typename T>
class Vector3;
using Vector3d = Vector3<double>;
using Vector3f = Vector3<float>;
template<typename T>
inline Vector3<T> getVectorFromTuple(PyObject* py)
{
Py::Sequence tuple(py);
if (tuple.size() != 3) {
throw Py::ValueError("Expected sequence of size 3");
}
T vx = static_cast<T>(Py::Float(tuple[0]));
T vy = static_cast<T>(Py::Float(tuple[1]));
T vz = static_cast<T>(Py::Float(tuple[2]));
return Vector3<T>(vx, vy, vz);
}
class BaseExport Vector2dPy: public Py::PythonClass<Vector2dPy> // NOLINT
{
public:
static Py::PythonType& behaviors();
static PyTypeObject* type_object();
static bool check(PyObject* py);
static Py::PythonClassObject<Vector2dPy> create(const Vector2d&);
static Py::PythonClassObject<Vector2dPy> create(double vx, double vy);
Vector2dPy(Py::PythonClassInstance* self, Py::Tuple& args, Py::Dict& kwds);
~Vector2dPy() override;
static void init_type();
Py::Object getattro(const Py::String& name_) override;
int setattro(const Py::String& name_, const Py::Object& value) override;
Py::Object repr() override;
inline const Vector2d& value() const
{
return v;
}
inline void setValue(const Vector2d& n)
{
v = n;
}
inline void setValue(double vx, double vy)
{
v.x = vx;
v.y = vy;
}
/** @name methods for group handling */
//@{
Py::Object number_negative() override;
Py::Object number_positive() override;
Py::Object number_absolute() override;
Py::Object number_invert() override;
Py::Object number_int() override;
Py::Object number_float() override;
Py::Object number_add(const Py::Object&) override;
Py::Object number_subtract(const Py::Object&) override;
Py::Object number_multiply(const Py::Object&) override;
Py::Object number_remainder(const Py::Object&) override;
Py::Object number_divmod(const Py::Object&) override;
Py::Object number_lshift(const Py::Object&) override;
Py::Object number_rshift(const Py::Object&) override;
Py::Object number_and(const Py::Object&) override;
Py::Object number_xor(const Py::Object&) override;
Py::Object number_or(const Py::Object&) override;
Py::Object number_power(const Py::Object&, const Py::Object&) override;
//@}
Py::Object isNull(const Py::Tuple&);
Py::Object length(const Py::Tuple&);
Py::Object atan2(const Py::Tuple&);
Py::Object square(const Py::Tuple&);
Py::Object scale(const Py::Tuple&);
Py::Object rotate(const Py::Tuple&);
Py::Object normalize(const Py::Tuple&);
Py::Object perpendicular(const Py::Tuple&);
Py::Object distance(const Py::Tuple&);
Py::Object isEqual(const Py::Tuple&);
Py::Object getAngle(const Py::Tuple&);
Py::Object projectToLine(const Py::Tuple&);
private:
Vector2d v;
};
} // namespace Base
namespace Py
{
using Vector2d = PythonClassObject<Base::Vector2dPy>;
inline Base::Vector2d toVector2d(PyObject* py)
{
Base::Vector2dPy* py2d = Py::Vector2d(py).getCxxObject();
return py2d ? py2d->value() : Base::Vector2d();
}
inline Base::Vector2d toVector2d(const Object& py)
{
Base::Vector2dPy* py2d = Py::Vector2d(py).getCxxObject();
return py2d ? py2d->value() : Base::Vector2d();
}
// Implementing the vector class in the fashion of the PyCXX library.
class BaseExport Vector: public Object // NOLINT
{
public:
explicit Vector(PyObject* pyob, bool owned)
: Object(pyob, owned)
{
validate();
}
Vector(const Vector& ob)
: Object(ob)
{
validate();
}
explicit Vector(const Base::Vector3d&);
explicit Vector(const Base::Vector3f&);
bool accepts(PyObject* obj) const override;
Vector(const Object& other)
: Object(other.ptr())
{
validate();
}
Vector& operator=(const Object& rhs)
{
return (*this = *rhs);
}
Vector& operator=(const Vector& rhs)
{
return (*this = *rhs);
}
Vector& operator=(PyObject* rhsp);
Vector& operator=(const Base::Vector3d&);
Vector& operator=(const Base::Vector3f&);
operator Base::Vector3d() const
{
return toVector();
}
Base::Vector3d toVector() const;
private:
static int Vector_TypeCheck(PyObject*);
};
/**
* This is a template class to provide wrapper classes for geometric classes like
* Base::Matrix4D, Base::Rotation and their Python binding classes.
* Since the class inherits from Py::Object it can be used in the same fashion as
* Py::String, Py::List, etc. to simplify the usage with them.
* @author Werner Mayer
*/
// The first template parameter represents the basic geometric class e.g. Rotation,
// the second parameter is reserved for its Python binding class, i.e. RotationPy.
// The third template parameter is the definition of a pointer to the method
// of the Python binding class to return the managed geometric instance. In our
// example this is the method RotationPy::getRotationPtr.
template<class T, class PyT, T* (PyT::*valuePtr)() const>
class GeometryT: public Object // NOLINT
{
public:
explicit GeometryT(PyObject* pyob, bool owned)
: Object(pyob, owned)
{
validate();
}
GeometryT(const GeometryT& ob)
: Object(*ob)
{
validate();
}
explicit GeometryT()
{
set(new PyT(new T()), true);
validate();
}
explicit GeometryT(const T& val)
{
set(new PyT(new T(val)), true);
validate();
}
GeometryT(const Object& other)
: Object(other.ptr())
{
validate();
}
bool accepts(PyObject* pyob) const override
{
return pyob && Geometry_TypeCheck(pyob);
}
GeometryT& operator=(const Object& rhs)
{
*this = *rhs;
return *this;
}
GeometryT& operator=(PyObject* rhsp)
{
if (ptr() == rhsp) {
return *this;
}
set(rhsp, false);
return *this;
}
GeometryT& operator=(const T& val)
{
set(new PyT(val), true);
return *this;
}
const T& getValue() const
{
// cast the PyObject pointer to the matching sub-class
// and call then the defined member function
PyT* py = static_cast<PyT*>(ptr());
T* val = (py->*valuePtr)();
return *val;
}
operator T() const
{
return getValue();
}
PyT* getPy() const
{
PyT* py = static_cast<PyT*>(ptr());
return py;
}
private:
static int Geometry_TypeCheck(PyObject* obj)
{
return PyObject_TypeCheck(obj, &(PyT::Type));
}
};
// PyCXX wrapper classes Py::Matrix, Py::Rotation, Py::Placement, ...
using BoundingBox = GeometryT<Base::BoundBox3d, Base::BoundBoxPy, &Base::BoundBoxPy::getBoundBoxPtr>;
using Matrix = GeometryT<Base::Matrix4D, Base::MatrixPy, &Base::MatrixPy::getMatrixPtr>;
using Rotation = GeometryT<Base::Rotation, Base::RotationPy, &Base::RotationPy::getRotationPtr>;
using Placement = GeometryT<Base::Placement, Base::PlacementPy, &Base::PlacementPy::getPlacementPtr>;
} // namespace Py
#endif // PY_GEOMETRYPY_H
|