From 12f8363284f4e4eee39587ba67b3b1de001d934a Mon Sep 17 00:00:00 2001 From: "Leandro (Cerberus1746) Benedet Garcia" Date: Mon, 30 Dec 2019 03:04:44 +0100 Subject: [PATCH] linmath: support round(), floor(), ceil() in vector classes Closes #821 --- panda/src/linmath/lvecBase2_ext_src.I | 58 ++++++++++++++++++++++++ panda/src/linmath/lvecBase2_ext_src.h | 4 ++ panda/src/linmath/lvecBase2_src.h | 4 ++ panda/src/linmath/lvecBase3_ext_src.I | 60 +++++++++++++++++++++++++ panda/src/linmath/lvecBase3_ext_src.h | 4 ++ panda/src/linmath/lvecBase3_src.h | 4 ++ panda/src/linmath/lvecBase4_ext_src.I | 63 +++++++++++++++++++++++++++ panda/src/linmath/lvecBase4_ext_src.h | 4 ++ panda/src/linmath/lvecBase4_src.h | 4 ++ tests/linmath/test_lvector2.py | 30 +++++++++++++ tests/linmath/test_lvector3.py | 35 +++++++++++++++ tests/linmath/test_lvector4.py | 38 ++++++++++++++++ 12 files changed, 308 insertions(+) create mode 100644 tests/linmath/test_lvector2.py create mode 100644 tests/linmath/test_lvector3.py create mode 100644 tests/linmath/test_lvector4.py diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index c76cb6649f..886ade8d18 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -218,5 +218,63 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { return self; } +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__round__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::round(_this->_v(0)); + vec->_v(1) = std::round(_this->_v(1)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__floor__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); +#endif + + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::floor(_this->_v(0)); + vec->_v(1) = std::floor(_this->_v(1)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ceil__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::ceil(_this->_v(0)); + vec->_v(1) = std::ceil(_this->_v(1)); + } + return py_vec; +} + #undef PYNUMBER_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h index 9abffe5859..59349980f1 100644 --- a/panda/src/linmath/lvecBase2_ext_src.h +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -25,6 +25,10 @@ public: INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); + + INLINE_LINMATH PyObject *__round__(PyObject *self) const; + INLINE_LINMATH PyObject *__floor__(PyObject *self) const; + INLINE_LINMATH PyObject *__ceil__(PyObject *self) const; }; #include "lvecBase2_ext_src.I" diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index c868f90d60..b58a22bd42 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -136,6 +136,10 @@ PUBLISHED: EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self)); + INLINE_LINMATH FLOATNAME(LVecBase2) fmax(const FLOATNAME(LVecBase2) &other) const; INLINE_LINMATH FLOATNAME(LVecBase2) fmin(const FLOATNAME(LVecBase2) &other) const; diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index ba163ec637..0715f84235 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -221,5 +221,65 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { return self; } +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__round__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::round(_this->_v(0)); + vec->_v(1) = std::round(_this->_v(1)); + vec->_v(2) = std::round(_this->_v(2)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__floor__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::floor(_this->_v(0)); + vec->_v(1) = std::floor(_this->_v(1)); + vec->_v(2) = std::floor(_this->_v(2)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ceil__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::ceil(_this->_v(0)); + vec->_v(1) = std::ceil(_this->_v(1)); + vec->_v(2) = std::ceil(_this->_v(2)); + } + return py_vec; +} + #undef PYNUMBER_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h index 4f91322f23..a80733c6a7 100644 --- a/panda/src/linmath/lvecBase3_ext_src.h +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -25,6 +25,10 @@ public: INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); + + INLINE_LINMATH PyObject *__round__(PyObject *self) const; + INLINE_LINMATH PyObject *__floor__(PyObject *self) const; + INLINE_LINMATH PyObject *__ceil__(PyObject *self) const; }; #include "lvecBase3_ext_src.I" diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index 3536615aeb..00575a71a7 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -155,6 +155,10 @@ PUBLISHED: EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self)); + INLINE_LINMATH FLOATNAME(LVecBase3) fmax(const FLOATNAME(LVecBase3) &other) const; INLINE_LINMATH FLOATNAME(LVecBase3) fmin(const FLOATNAME(LVecBase3) &other) const; diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 78d359c315..0866e184ac 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -229,5 +229,68 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { return self; } +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__round__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::round(_this->_v(0)); + vec->_v(1) = std::round(_this->_v(1)); + vec->_v(2) = std::round(_this->_v(2)); + vec->_v(3) = std::round(_this->_v(3)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__floor__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::floor(_this->_v(0)); + vec->_v(1) = std::floor(_this->_v(1)); + vec->_v(2) = std::floor(_this->_v(2)); + vec->_v(3) = std::floor(_this->_v(3)); + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ceil__(PyObject *self) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); +#endif + PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = std::ceil(_this->_v(0)); + vec->_v(1) = std::ceil(_this->_v(1)); + vec->_v(2) = std::ceil(_this->_v(2)); + vec->_v(3) = std::ceil(_this->_v(3)); + } + return py_vec; +} + #undef PYNUMBER_FLOATTYPE #undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h index 9d7d837c89..e5115fb2df 100644 --- a/panda/src/linmath/lvecBase4_ext_src.h +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -25,6 +25,10 @@ public: INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); + + INLINE_LINMATH PyObject *__round__(PyObject *self) const; + INLINE_LINMATH PyObject *__floor__(PyObject *self) const; + INLINE_LINMATH PyObject *__ceil__(PyObject *self) const; }; #include "lvecBase4_ext_src.I" diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index b634791d91..ab98ba88dc 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -163,6 +163,10 @@ PUBLISHED: EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self)); + EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self)); + INLINE_LINMATH FLOATNAME(LVecBase4) fmax(const FLOATNAME(LVecBase4) &other) const; INLINE_LINMATH FLOATNAME(LVecBase4) fmin(const FLOATNAME(LVecBase4) &other) const; diff --git a/tests/linmath/test_lvector2.py b/tests/linmath/test_lvector2.py new file mode 100644 index 0000000000..d5aab7f96f --- /dev/null +++ b/tests/linmath/test_lvector2.py @@ -0,0 +1,30 @@ +from math import floor, ceil +import sys + +import pytest + +from panda3d.core import Vec2 + + +original_vector = Vec2(2.3, -2.6) + +reason = '''Rounding in Python 2.7 expects to return a float value, since it returns a Vector it +does not work. When Python 2.7 gets deprecated, remove this check.''' + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_round(): + rounded_vector = round(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_floor(): + rounded_vector = floor(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_ceil(): + rounded_vector = ceil(original_vector) + assert rounded_vector.x == 3 + assert rounded_vector.y == -2 diff --git a/tests/linmath/test_lvector3.py b/tests/linmath/test_lvector3.py new file mode 100644 index 0000000000..7ddefa728c --- /dev/null +++ b/tests/linmath/test_lvector3.py @@ -0,0 +1,35 @@ +from math import floor, ceil +import sys + +import pytest + +from panda3d.core import Vec3 + + +original_vector = Vec3(2.3, -2.6, 3.5) + +reason = '''Rounding in Python 2.7 expects to return a float value, since it returns a Vector it +does not work. When Python 2.7 gets deprecated, remove this check.''' + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_round(): + rounded_vector = round(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + assert rounded_vector.z == 4 + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_floor(): + rounded_vector = floor(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + assert rounded_vector.z == 3 + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_ceil(): + rounded_vector = ceil(original_vector) + assert rounded_vector.x == 3 + assert rounded_vector.y == -2 + assert rounded_vector.z == 4 diff --git a/tests/linmath/test_lvector4.py b/tests/linmath/test_lvector4.py new file mode 100644 index 0000000000..61768f1434 --- /dev/null +++ b/tests/linmath/test_lvector4.py @@ -0,0 +1,38 @@ +from math import floor, ceil +import sys + +import pytest + +from panda3d.core import Vec4 + + +original_vector = Vec4(2.3, -2.6, 3.5, 1) + +reason = '''Rounding in Python 2.7 expects to return a float value, since it returns a Vector it +does not work. When Python 2.7 gets deprecated, remove this check.''' + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_round(): + rounded_vector = round(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + assert rounded_vector.z == 4 + assert rounded_vector.w == 1 + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_floor(): + rounded_vector = floor(original_vector) + assert rounded_vector.x == 2 + assert rounded_vector.y == -3 + assert rounded_vector.z == 3 + assert rounded_vector.w == 1 + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason=reason) +def test_ceil(): + rounded_vector = ceil(original_vector) + assert rounded_vector.x == 3 + assert rounded_vector.y == -2 + assert rounded_vector.z == 4 + assert rounded_vector.w == 1