Browse Source

linmath: support round(), floor(), ceil() in vector classes

Closes #821
Leandro (Cerberus1746) Benedet Garcia 6 years ago
parent
commit
12f8363284

+ 58 - 0
panda/src/linmath/lvecBase2_ext_src.I

@@ -218,5 +218,63 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
   return self;
 }
 
+/**
+ *
+ */
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase2)>::
+__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<FLOATNAME(LVecBase2)>::
+__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<FLOATNAME(LVecBase2)>::
+__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

+ 4 - 0
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"

+ 4 - 0
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;
 

+ 60 - 0
panda/src/linmath/lvecBase3_ext_src.I

@@ -221,5 +221,65 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
   return self;
 }
 
+/**
+ *
+ */
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase3)>::
+__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<FLOATNAME(LVecBase3)>::
+__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<FLOATNAME(LVecBase3)>::
+__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

+ 4 - 0
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"

+ 4 - 0
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;
 

+ 63 - 0
panda/src/linmath/lvecBase4_ext_src.I

@@ -229,5 +229,68 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
   return self;
 }
 
+/**
+ *
+ */
+INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase4)>::
+__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<FLOATNAME(LVecBase4)>::
+__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<FLOATNAME(LVecBase4)>::
+__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

+ 4 - 0
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"

+ 4 - 0
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;
 

+ 30 - 0
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.'''
+
[email protected](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
+
[email protected](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
+
[email protected](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

+ 35 - 0
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.'''
+
[email protected](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
+
+
[email protected](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
+
+
[email protected](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

+ 38 - 0
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.'''
+
[email protected](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
+
+
[email protected](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
+
+
[email protected](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