math3d-py 1.3.0__tar.gz → 1.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of math3d-py might be problematic. Click here for more details.

Files changed (87) hide show
  1. {math3d_py-1.3.0 → math3d_py-1.4.1}/PKG-INFO +1 -1
  2. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/SupportingTypes.h +78 -2
  3. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/CMakeLists.txt +1 -1
  4. math3d_py-1.4.1/py/math3d/math3d.pyi +327 -0
  5. math3d_py-1.4.1/py/math3d/py.typed +0 -0
  6. math3d_py-1.4.1/py/math3d/types.hpp +108 -0
  7. math3d_py-1.4.1/py/math3d/vector.hpp +102 -0
  8. {math3d_py-1.3.0 → math3d_py-1.4.1}/pyproject.toml +1 -1
  9. {math3d_py-1.3.0 → math3d_py-1.4.1}/pypublish +2 -2
  10. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Types.cpp +32 -0
  11. math3d_py-1.4.1/tmp/math3d/__init__.py +1 -0
  12. math3d_py-1.4.1/tmp/math3d/__init__.pyi +20 -0
  13. math3d_py-1.4.1/tmp/math3d/linear_system.hpp +15 -0
  14. math3d_py-1.4.1/tmp/math3d/math3d.cpp +116 -0
  15. math3d_py-1.4.1/tmp/math3d/math3d.cpython-313-darwin.so +0 -0
  16. math3d_py-1.4.1/tmp/math3d/matrix.hpp +57 -0
  17. math3d_py-1.4.1/tmp/math3d/py.typed +0 -0
  18. {math3d_py-1.3.0/py → math3d_py-1.4.1/tmp}/math3d/types.hpp +26 -0
  19. math3d_py-1.4.1/tmp/math3d/util.h +13 -0
  20. {math3d_py-1.3.0 → math3d_py-1.4.1}/.DS_Store +0 -0
  21. {math3d_py-1.3.0 → math3d_py-1.4.1}/.github/workflows/cmake-single-platform.yml +0 -0
  22. {math3d_py-1.3.0 → math3d_py-1.4.1}/.github/workflows/jekyll-gh-pages.yml +0 -0
  23. {math3d_py-1.3.0 → math3d_py-1.4.1}/.gitignore +0 -0
  24. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/.gitignore +0 -0
  25. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/3dmath.iml +0 -0
  26. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/editor.xml +0 -0
  27. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/misc.xml +0 -0
  28. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/modules.xml +0 -0
  29. {math3d_py-1.3.0 → math3d_py-1.4.1}/.idea/vcs.xml +0 -0
  30. {math3d_py-1.3.0 → math3d_py-1.4.1}/CMakeLists.txt +0 -0
  31. {math3d_py-1.3.0 → math3d_py-1.4.1}/LICENSE.txt +0 -0
  32. {math3d_py-1.3.0 → math3d_py-1.4.1}/README.md +0 -0
  33. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/.DS_Store +0 -0
  34. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/Constants.h +0 -0
  35. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/IdentityMatrix.h +0 -0
  36. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/LinearSystem.h +0 -0
  37. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/Matrix.h +0 -0
  38. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/MatrixOperations.h +0 -0
  39. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/MatrixUtil.h +0 -0
  40. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/OrthographicProjectionMatrix.h +0 -0
  41. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/PolarCoordinates.h +0 -0
  42. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/ProjectionMatrix.h +0 -0
  43. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/Quaternion.h +0 -0
  44. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/RotationMatrix.h +0 -0
  45. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/ScalingMatrix.h +0 -0
  46. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/TranslationMatrix.h +0 -0
  47. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/TypeAliases.h +0 -0
  48. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/Utilities.h +0 -0
  49. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/Vector.h +0 -0
  50. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/primitives/ConvexPrimitive.h +0 -0
  51. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/primitives/Plane.h +0 -0
  52. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/primitives/Primitive.h +0 -0
  53. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/primitives/Ray.h +0 -0
  54. {math3d_py-1.3.0 → math3d_py-1.4.1}/include/3dmath/primitives/Sphere.h +0 -0
  55. {math3d_py-1.3.0 → math3d_py-1.4.1}/poetry.lock +0 -0
  56. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/__init__.py +0 -0
  57. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/__init__.pyi +0 -0
  58. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/linear_system.hpp +0 -0
  59. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/math3d.cpp +0 -0
  60. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/matrix.hpp +0 -0
  61. {math3d_py-1.3.0 → math3d_py-1.4.1}/py/math3d/util.h +0 -0
  62. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/CMakeLists.txt +0 -0
  63. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/ConvexPrimitive.cpp +0 -0
  64. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/LinearSystem.cpp +0 -0
  65. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Matrix.cpp +0 -0
  66. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/MatrixOperations.cpp +0 -0
  67. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/OrthographicProjectionMatrix.cpp +0 -0
  68. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Plane.cpp +0 -0
  69. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/PolarCoordinates.cpp +0 -0
  70. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Quaternion.cpp +0 -0
  71. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Ray.cpp +0 -0
  72. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/RotationMatrix.cpp +0 -0
  73. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/ScalingMatrix.cpp +0 -0
  74. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Sphere.cpp +0 -0
  75. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/TestSupport.h +0 -0
  76. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/TranslationMatrix.cpp +0 -0
  77. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/Vector.cpp +0 -0
  78. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/VectorConvenienceMembers.cpp +0 -0
  79. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Ray.obj +0 -0
  80. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Sphere.obj +0 -0
  81. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Sphere.stl +0 -0
  82. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Xy.stl +0 -0
  83. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Xz.stl +0 -0
  84. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/baseline/Yz.stl +0 -0
  85. {math3d_py-1.3.0 → math3d_py-1.4.1}/tests/support/PrimitivesTestSupport.h +0 -0
  86. {math3d_py-1.3.0/py → math3d_py-1.4.1/tmp}/math3d/math3d.pyi +0 -0
  87. {math3d_py-1.3.0/py → math3d_py-1.4.1/tmp}/math3d/vector.hpp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: math3d_py
3
- Version: 1.3.0
3
+ Version: 1.4.1
4
4
  Summary: Python bindings for 3dmath
5
5
  Author-Email: Murali Dhanakoti <dhanakoti.murali@gmail.com>
6
6
  Requires-Python: <3.14,>=3.13
@@ -21,9 +21,13 @@ namespace math3d {
21
21
  T length() const { return max - min; }
22
22
  T center() const { return static_cast<T>(0.5*(max + min)); }
23
23
  void scale(T const scale) { min *= scale; max *= scale; }
24
- std::string asString() const {
24
+ [[nodiscard]] std::string asString() const {
25
25
  return std::format("[{},{}]", min, max);
26
26
  }
27
+ void merge(Extent const& another) {
28
+ min = std::min(min, another.min);
29
+ max = std::max(max, another.max);
30
+ }
27
31
  };
28
32
 
29
33
  template<typename T>
@@ -130,9 +134,81 @@ namespace math3d {
130
134
  return ss.str();
131
135
  }
132
136
 
133
- bool isValid() const {
137
+ [[nodiscard]] bool isValid() const {
134
138
  return x.min < x.max && y.min < y.max && z.min < z.max;
135
139
  }
140
+
141
+ void merge(Bounds3D const& another) {
142
+ x.merge(another.x);
143
+ y.merge(another.y);
144
+ z.merge(another.z);
145
+ }
146
+
147
+ [[nodiscard]]
148
+ Vector3<T> min() const {
149
+ return {x.min, y.min, z.min};
150
+ }
151
+
152
+ [[nodiscard]]
153
+ Vector3<T> max() const {
154
+ return {x.max, y.max, z.max};
155
+ }
156
+
157
+ /// @brief Gets the corner vertices of this bounding box
158
+ ///
159
+ /// The corners are returned lower back to front with the bottom corners appearing before the top ones
160
+ [[nodiscard]]
161
+ std::array<Vector3<T>, 8> corners() const {
162
+ using Vec3 = Vector3<T>;
163
+
164
+ auto lower_left_back = min();
165
+ auto lower_right_back = lower_left_back + Vec3{x.length(), 0, 0};
166
+ auto upper_right_back= lower_right_back + Vec3{0, y.length(), 0};
167
+ auto upper_left_back = upper_right_back - Vec3{x.length(), 0, 0};
168
+
169
+ auto upper_right_front = max();
170
+ auto upper_left_front = upper_right_front - Vec3{x.length(), 0, 0};
171
+ auto lower_left_front = upper_left_front - Vec3{0, y.length(), 0};
172
+ auto lower_right_front = lower_left_front + Vec3{x.length(), 0, 0};
173
+
174
+ return {lower_left_back, lower_right_back, upper_right_back, upper_left_back,
175
+ lower_left_front, lower_right_front, upper_right_front, upper_left_front};
176
+ }
177
+
178
+ /// @brief Gets vertex indices of the quadrilateral faces of this bounding box
179
+ ///
180
+ /// Edges are returned in the following face order: front, right, back, left, bottom, and top
181
+ [[nodiscard]]
182
+ static constexpr std::array<std::array<uint8_t , 4>, 6> edges() {
183
+
184
+ using Face = std::array<uint8_t, 4>;
185
+
186
+ return {
187
+ Face{4, 5, 6, 7},
188
+ Face{5, 1, 2, 6},
189
+ Face{0, 1, 2, 3},
190
+ Face{0, 4, 7, 3},
191
+ Face{0, 1, 5, 4},
192
+ Face{6, 2, 3, 7}
193
+ };
194
+ }
195
+
196
+ [[nodiscard]]
197
+ Extent<T> extent(Direction dir) const {
198
+ if (dir == Direction::x) {
199
+ return x;
200
+ }
201
+ if (dir == Direction::y) {
202
+ return y;
203
+ }
204
+ if (dir == Direction::z) {
205
+ return z;
206
+ }
207
+ throw std::runtime_error(
208
+ std::format("Direction {} is not supported in the extent accessor",
209
+ std::underlying_type_t<Direction>(dir))
210
+ );
211
+ }
136
212
  };
137
213
 
138
214
  template<typename T>
@@ -1,6 +1,6 @@
1
1
  cmake_minimum_required(VERSION 3.24.2)
2
2
 
3
- project(3dmath_python VERSION 1.1.0)
3
+ project(3dmath_python VERSION 1.3.0)
4
4
 
5
5
  set(CMAKE_CXX_STANDARD 23)
6
6
  set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -0,0 +1,327 @@
1
+ from __future__ import annotations
2
+ import pybind11_stubgen.typing_ext
3
+ import typing
4
+ __all__: list[str] = ['AABB', 'Extent', 'Identity2', 'Identity3', 'Identity4', 'LinearSystem2', 'LinearSystem3', 'LinearSystem4', 'Matrix2', 'Matrix3', 'Matrix4', 'Vector2', 'Vector3', 'Vector4', 'col_major', 'order', 'row_major']
5
+ class AABB:
6
+ @typing.overload
7
+ def __init__(self) -> None:
8
+ ...
9
+ @typing.overload
10
+ def __init__(self, arg0: Extent, arg1: Extent, arg2: Extent) -> None:
11
+ ...
12
+ @typing.overload
13
+ def __init__(self, arg0: Vector3, arg1: Vector3) -> None:
14
+ ...
15
+ def __repr__(self) -> str:
16
+ ...
17
+ def __str__(self) -> str:
18
+ ...
19
+ def corners(self) -> typing.Annotated[list[Vector3], pybind11_stubgen.typing_ext.FixedSize(8)]:
20
+ ...
21
+ def edges(self) -> typing.Annotated[list[typing.Annotated[list[int], pybind11_stubgen.typing_ext.FixedSize(4)]], pybind11_stubgen.typing_ext.FixedSize(6)]:
22
+ ...
23
+ def max(self) -> Vector3:
24
+ ...
25
+ def merge(self, arg0: AABB) -> None:
26
+ ...
27
+ def min(self) -> Vector3:
28
+ ...
29
+ def x_extent(self) -> Extent:
30
+ ...
31
+ def y_extent(self) -> Extent:
32
+ ...
33
+ def z_extent(self) -> Extent:
34
+ ...
35
+ class Extent:
36
+ max: float
37
+ min: float
38
+ @typing.overload
39
+ def __init__(self) -> None:
40
+ ...
41
+ @typing.overload
42
+ def __init__(self, arg0: float, arg1: float) -> None:
43
+ ...
44
+ def __repr__(self) -> str:
45
+ ...
46
+ def __str__(self) -> str:
47
+ ...
48
+ def center(self) -> float:
49
+ ...
50
+ def length(self) -> float:
51
+ ...
52
+ def update(self, arg0: float) -> None:
53
+ ...
54
+ class Identity2(Matrix2):
55
+ def __init__(self) -> None:
56
+ ...
57
+ class Identity3(Matrix3):
58
+ def __init__(self) -> None:
59
+ ...
60
+ class Identity4(Matrix4):
61
+ def __init__(self) -> None:
62
+ ...
63
+ class LinearSystem2:
64
+ @staticmethod
65
+ def solve(arg0: Matrix2, arg1: Vector2) -> Vector2:
66
+ ...
67
+ class LinearSystem3:
68
+ @staticmethod
69
+ def solve(arg0: Matrix3, arg1: Vector3) -> Vector3:
70
+ ...
71
+ class LinearSystem4:
72
+ @staticmethod
73
+ def solve(arg0: Matrix4, arg1: Vector4) -> Vector4:
74
+ ...
75
+ class Matrix2:
76
+ @typing.overload
77
+ def __getitem__(self, arg0: int) -> Vector2:
78
+ ...
79
+ @typing.overload
80
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
81
+ ...
82
+ @typing.overload
83
+ def __init__(self) -> None:
84
+ ...
85
+ @typing.overload
86
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
87
+ ...
88
+ @typing.overload
89
+ def __mul__(self, arg0: Matrix2) -> Matrix2:
90
+ ...
91
+ @typing.overload
92
+ def __mul__(self, arg0: Vector2) -> Vector2:
93
+ ...
94
+ def __repr__(self) -> str:
95
+ ...
96
+ def __str__(self) -> str:
97
+ ...
98
+ def determinant(self) -> float:
99
+ ...
100
+ def inverse(self) -> Matrix2:
101
+ ...
102
+ def row(self, arg0: int) -> Vector2:
103
+ ...
104
+ def transpose(self) -> Matrix2:
105
+ ...
106
+ def upper_triangular(self) -> Matrix2:
107
+ ...
108
+ class Matrix3:
109
+ @typing.overload
110
+ def __getitem__(self, arg0: int) -> Vector3:
111
+ ...
112
+ @typing.overload
113
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
114
+ ...
115
+ @typing.overload
116
+ def __init__(self) -> None:
117
+ ...
118
+ @typing.overload
119
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
120
+ ...
121
+ @typing.overload
122
+ def __mul__(self, arg0: Matrix3) -> Matrix3:
123
+ ...
124
+ @typing.overload
125
+ def __mul__(self, arg0: Vector3) -> Vector3:
126
+ ...
127
+ def __repr__(self) -> str:
128
+ ...
129
+ def __str__(self) -> str:
130
+ ...
131
+ def determinant(self) -> float:
132
+ ...
133
+ def inverse(self) -> Matrix3:
134
+ ...
135
+ def row(self, arg0: int) -> Vector3:
136
+ ...
137
+ def transpose(self) -> Matrix3:
138
+ ...
139
+ def upper_triangular(self) -> Matrix3:
140
+ ...
141
+ class Matrix4:
142
+ @typing.overload
143
+ def __getitem__(self, arg0: int) -> Vector4:
144
+ ...
145
+ @typing.overload
146
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
147
+ ...
148
+ @typing.overload
149
+ def __init__(self) -> None:
150
+ ...
151
+ @typing.overload
152
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
153
+ ...
154
+ @typing.overload
155
+ def __mul__(self, arg0: Matrix4) -> Matrix4:
156
+ ...
157
+ @typing.overload
158
+ def __mul__(self, arg0: Vector4) -> Vector4:
159
+ ...
160
+ def __repr__(self) -> str:
161
+ ...
162
+ def __str__(self) -> str:
163
+ ...
164
+ def determinant(self) -> float:
165
+ ...
166
+ def inverse(self) -> Matrix4:
167
+ ...
168
+ def row(self, arg0: int) -> Vector4:
169
+ ...
170
+ def transpose(self) -> Matrix4:
171
+ ...
172
+ def upper_triangular(self) -> Matrix4:
173
+ ...
174
+ class Vector2:
175
+ x: float
176
+ y: float
177
+ def __add__(self, arg0: Vector2) -> Vector2:
178
+ ...
179
+ @typing.overload
180
+ def __init__(self) -> None:
181
+ ...
182
+ @typing.overload
183
+ def __init__(self, arg0: typing.Iterable) -> None:
184
+ ...
185
+ def __mul__(self, arg0: float) -> Vector2:
186
+ ...
187
+ def __repr__(self) -> str:
188
+ ...
189
+ def __rmul__(self, arg0: float) -> Vector2:
190
+ ...
191
+ def __str__(self) -> str:
192
+ ...
193
+ def __sub__(self, arg0: Vector2) -> Vector2:
194
+ ...
195
+ def __truediv__(self, arg0: float) -> Vector2:
196
+ ...
197
+ def dot(self, arg0: Vector2) -> float:
198
+ ...
199
+ def length(self) -> float:
200
+ ...
201
+ def length_sqr(self) -> float:
202
+ ...
203
+ def normalize(self) -> Vector2:
204
+ ...
205
+ def projection(self, arg0: Vector2) -> tuple[Vector2, Vector2]:
206
+ ...
207
+ class Vector3:
208
+ x: float
209
+ y: float
210
+ z: float
211
+ def __add__(self, arg0: Vector3) -> Vector3:
212
+ ...
213
+ @typing.overload
214
+ def __init__(self) -> None:
215
+ ...
216
+ @typing.overload
217
+ def __init__(self, arg0: typing.Iterable) -> None:
218
+ ...
219
+ @typing.overload
220
+ def __init__(self, arg0: float, arg1: float, arg2: float) -> None:
221
+ ...
222
+ @typing.overload
223
+ def __mul__(self, arg0: float) -> Vector3:
224
+ ...
225
+ @typing.overload
226
+ def __mul__(self, arg0: Vector3) -> Vector3:
227
+ ...
228
+ def __repr__(self) -> str:
229
+ ...
230
+ def __rmul__(self, arg0: float) -> Vector3:
231
+ ...
232
+ def __str__(self) -> str:
233
+ ...
234
+ def __sub__(self, arg0: Vector3) -> Vector3:
235
+ ...
236
+ def __truediv__(self, arg0: float) -> Vector3:
237
+ ...
238
+ def dot(self, arg0: Vector3) -> float:
239
+ ...
240
+ def length(self) -> float:
241
+ ...
242
+ def length_sqr(self) -> float:
243
+ ...
244
+ def normalize(self) -> Vector3:
245
+ ...
246
+ def projection(self, arg0: Vector3) -> tuple[Vector3, Vector3]:
247
+ ...
248
+ class Vector4:
249
+ w: float
250
+ x: float
251
+ y: float
252
+ z: float
253
+ def __add__(self, arg0: Vector4) -> Vector4:
254
+ ...
255
+ @typing.overload
256
+ def __init__(self) -> None:
257
+ ...
258
+ @typing.overload
259
+ def __init__(self, arg0: typing.Iterable) -> None:
260
+ ...
261
+ @typing.overload
262
+ def __init__(self, arg0: float, arg1: float, arg2: float, arg3: float) -> None:
263
+ ...
264
+ @typing.overload
265
+ def __init__(self, arg0: Vector3) -> None:
266
+ ...
267
+ def __mul__(self, arg0: float) -> Vector4:
268
+ ...
269
+ def __repr__(self) -> str:
270
+ ...
271
+ def __rmul__(self, arg0: float) -> Vector4:
272
+ ...
273
+ def __str__(self) -> str:
274
+ ...
275
+ def __sub__(self, arg0: Vector4) -> Vector4:
276
+ ...
277
+ def __truediv__(self, arg0: float) -> Vector4:
278
+ ...
279
+ def dot(self, arg0: Vector4) -> float:
280
+ ...
281
+ def length(self) -> float:
282
+ ...
283
+ def length_sqr(self) -> float:
284
+ ...
285
+ def normalize(self) -> Vector4:
286
+ ...
287
+ def projection(self, arg0: Vector4) -> tuple[Vector4, Vector4]:
288
+ ...
289
+ class order:
290
+ """
291
+ Members:
292
+
293
+ row_major
294
+
295
+ col_major
296
+ """
297
+ __members__: typing.ClassVar[dict[str, order]] # value = {'row_major': <order.row_major: 1>, 'col_major': <order.col_major: 0>}
298
+ col_major: typing.ClassVar[order] # value = <order.col_major: 0>
299
+ row_major: typing.ClassVar[order] # value = <order.row_major: 1>
300
+ def __eq__(self, other: typing.Any) -> bool:
301
+ ...
302
+ def __getstate__(self) -> int:
303
+ ...
304
+ def __hash__(self) -> int:
305
+ ...
306
+ def __index__(self) -> int:
307
+ ...
308
+ def __init__(self, value: int) -> None:
309
+ ...
310
+ def __int__(self) -> int:
311
+ ...
312
+ def __ne__(self, other: typing.Any) -> bool:
313
+ ...
314
+ def __repr__(self) -> str:
315
+ ...
316
+ def __setstate__(self, state: int) -> None:
317
+ ...
318
+ def __str__(self) -> str:
319
+ ...
320
+ @property
321
+ def name(self) -> str:
322
+ ...
323
+ @property
324
+ def value(self) -> int:
325
+ ...
326
+ col_major: order # value = <order.col_major: 0>
327
+ row_major: order # value = <order.row_major: 1>
File without changes
@@ -0,0 +1,108 @@
1
+ #pragma once
2
+
3
+ #include "pybind11/pybind11.h"
4
+
5
+ #include "SupportingTypes.h"
6
+
7
+ namespace py = pybind11;
8
+ namespace m3d = math3d;
9
+
10
+ template<typename T>
11
+ void bind_Extent(py::module_ const& module, std::string_view className) {
12
+ using Extent = m3d::Extent<T>;
13
+ py::class_<Extent>(module, className.data())
14
+ .def(py::init([] {
15
+ Extent extent;
16
+ extent.min = std::numeric_limits<T>::max();
17
+ extent.max = -std::numeric_limits<T>::max();
18
+ return extent;
19
+ }))
20
+ .def(py::init([](T min, T max) {
21
+ Extent extent {};
22
+ extent.min = min;
23
+ extent.max = max;
24
+ return extent;
25
+ }))
26
+ .def_property("min",
27
+ [](Extent const& extent) {
28
+ return extent.min;
29
+ },
30
+ [](Extent& extent, T min) {
31
+ extent.min = min;
32
+ }
33
+ )
34
+ .def_property("max",
35
+ [](Extent const& extent) {
36
+ return extent.max;
37
+ },
38
+ [](Extent& extent, T max) {
39
+ extent.max = max;
40
+ }
41
+ )
42
+ .def("length", [](Extent const& extent) {
43
+ return extent.length();
44
+ })
45
+ .def("center", [](Extent const& extent) {
46
+ return extent.center();
47
+ })
48
+ .def("update", [](Extent& extent, T val) {
49
+ extent.min = std::min(extent.min, val);
50
+ extent.max = std::max(extent.max, val);
51
+ })
52
+ .def("__str__", [](Extent const& extent) {
53
+ return extent.asString();
54
+ })
55
+ .def("__repr__", [](Extent const& extent) {
56
+ return std::format("Extent = {} Valid = {}", extent.asString(), extent.min < extent.max);
57
+ });
58
+ }
59
+
60
+ template<typename T>
61
+ void bind_Bounds(py::module_ const& module, std::string_view className) {
62
+ using Bounds = m3d::Bounds3D<T>;
63
+ py::class_<Bounds>(module, className.data())
64
+ .def(py::init())
65
+ .def(py::init([](m3d::Extent<T> const& x, m3d::Extent<T> const& y, m3d::Extent<T> const& z) {
66
+ return Bounds {x, y, z};
67
+ }))
68
+ .def(py::init([](m3d::Vector3<T> const& min, m3d::Vector3<T> const& max) {
69
+ return Bounds(m3d::Extent<T>{min.x, max.x}, m3d::Extent<T>{min.y, max.y}, m3d::Extent<T>{min.z, max.z});
70
+ }))
71
+ .def("min", [](Bounds const& self) {
72
+ return self.min();
73
+ })
74
+ .def("max", [](Bounds const& self) {
75
+ return self.max();
76
+ })
77
+ .def("corners", [](Bounds const& self) {
78
+ return self.corners();
79
+ })
80
+ .def("edges", [](Bounds const& self) {
81
+ return self.edges();
82
+ })
83
+ .def("merge", [](Bounds& self, Bounds const& another) {
84
+ self.merge(another);
85
+ })
86
+ .def("x_extent", [](Bounds const& self) {
87
+ return self.extent(Bounds::Direction::x);
88
+ })
89
+ .def("y_extent", [](Bounds const& self) {
90
+ return self.extent(Bounds::Direction::y);
91
+ })
92
+ .def("z_extent", [](Bounds const& self) {
93
+ return self.extent(Bounds::Direction::z);
94
+ })
95
+ .def("__str__", [](Bounds const& bounds) {
96
+ return bounds.asString();
97
+ })
98
+ .def("__repr__", [](Bounds const& bounds) {
99
+ return std::format(
100
+ "{} Valid = {}\n"
101
+ "Center = {}\n"
102
+ "X Length = {}\n"
103
+ "Y Length = {}\n"
104
+ "Z Length = {}\n"
105
+ "Diagonal Length {}", bounds.asString(), bounds.isValid(), bounds.center().asString(),
106
+ bounds.x.length(), bounds.y.length(), bounds.z.length(), bounds.length());
107
+ });
108
+ }
@@ -0,0 +1,102 @@
1
+ #pragma once
2
+ #include "pybind11/pybind11.h"
3
+ #include "pybind11/operators.h"
4
+ #include "pybind11/stl.h"
5
+ #include "util.h"
6
+ #include "Vector.h"
7
+
8
+ namespace py = pybind11;
9
+
10
+ template<typename T, uint32_t Size>
11
+ void bind_Vector(py::module_ const& module, char const* className) {
12
+ using vector = math3d::Vector<T, Size>;
13
+ auto pyVecClass =
14
+ py::class_<vector>(module, className)
15
+ // Construction
16
+ .def(py::init())
17
+ .def(py::init([](py::iterable const& list) {
18
+ auto const input = list.cast<std::vector<T>>();
19
+ return vector{input};
20
+ }))
21
+ // Formatted output
22
+ .def("__str__", [](vector const& v) {
23
+ return util::convertSpaceToNewLine(v.asString());
24
+ })
25
+ .def("__repr__", [](vector const& v) {
26
+ return util::convertSpaceToNewLine(v.asString());
27
+ })
28
+ // Operations
29
+ .def(py::self + py::self)
30
+ .def(py::self - py::self)
31
+ .def(py::self * T{})
32
+ .def(T{} * py::self)
33
+ .def(py::self / T{})
34
+ .def("dot", &vector::dot)
35
+ .def("normalize", [](vector& v) { v.normalize(); return v; })
36
+ .def("length", [](vector const& v) { return v.length(); })
37
+ .def("length_sqr", [](vector const& v) { return v.lengthSquared(); })
38
+ .def("projection", [](vector const& self, vector const& u) {
39
+ auto vectorProjection = self.getVectorProjection(u);
40
+ return std::pair{vectorProjection.parallel, vectorProjection.perpendicular};
41
+ });
42
+ if constexpr (Size == 3) {
43
+ pyVecClass
44
+ .def(py::init([](T x, T y, T z) {
45
+ return vector({x, y, z});
46
+ }))
47
+ .def(py::self * py::self);
48
+ }
49
+ if constexpr (Size == 4) {
50
+ pyVecClass
51
+ .def(py::init([](T x, T y, T z, T w) {
52
+ return vector({x, y, z, w});
53
+ }))
54
+ .def(py::init([](math3d::Vector3<T> const& vec3) {
55
+ std::vector<T> input {vec3.x, vec3.y, vec3.z, 1.F};
56
+ return vector{input};
57
+ }));
58
+ }
59
+
60
+ // Convenience member access (x, y, z, w)
61
+ // .x, .y, .z, .w are Vector<T, N>::Proxy and its conversion operator has to be invoked to get the raw value
62
+ // hence the static cast
63
+ if constexpr (Size >= 2 && Size <= 4) {
64
+ pyVecClass.def_property("x",
65
+ [](vector const& self) {
66
+ return static_cast<T>(self.x);
67
+ },
68
+ [](vector& self, T value) {
69
+ self.x = value;
70
+ }
71
+ )
72
+ .def_property("y",
73
+ [](vector const& self) {
74
+ return static_cast<T>(self.y);
75
+ },
76
+ [](vector& self, T value) {
77
+ self.y = value;
78
+ }
79
+ );
80
+ }
81
+ if constexpr (Size == 3 || Size == 4 ) {
82
+ pyVecClass.def_property("z",
83
+ [](vector const& self) {
84
+ return static_cast<T>(self.z);
85
+ },
86
+ [](vector& self, T value) {
87
+ self.z = value;
88
+ }
89
+ );
90
+ }
91
+ if constexpr (Size == 4) {
92
+ pyVecClass.def_property("w",
93
+ [](vector const& self) {
94
+ return static_cast<T>(self.w);
95
+ },
96
+ [](vector& self, T value) {
97
+ self.w = value;
98
+ }
99
+ );
100
+ }
101
+
102
+ }
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "math3d_py"
7
- version = "1.3.0"
7
+ version = "1.4.1"
8
8
  description = "Python bindings for 3dmath"
9
9
  authors = [{ name = "Murali Dhanakoti", email = "dhanakoti.murali@gmail.com" }]
10
10
  requires-python = ">=3.13,<3.14"
@@ -27,8 +27,8 @@ if [[ $# -eq 1 && "$1" == "major_ver" ]]; then
27
27
  fi
28
28
 
29
29
  rm -rf dist/*
30
- CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu) \
31
- CMAKE_ARGS="-DenableTesting=OFF" poetry run python -m build
32
30
  touch py/math3d/py.typed
33
31
  poetry run pybind11-stubgen math3d -o py
32
+ CMAKE_BUILD_PARALLEL_LEVEL="$(sysctl -n hw.ncpu)" \
33
+ CMAKE_ARGS="-DenableTesting=OFF" poetry run python -m build
34
34
  poetry run twine upload dist/*
@@ -122,3 +122,35 @@ TEST(Bounds3D, Validity) {
122
122
  {+0.5, +0.5, +0.5}};
123
123
  ASSERT_TRUE(bounds.isValid()) << "Bounds initialized with a unit cube must have been classified as valid";
124
124
  }
125
+
126
+ TEST(Extent, Merging) {
127
+ Extent e1 {-10.F, 0.F};
128
+ Extent constexpr e2 {5.F, 10.F};
129
+ e1.merge(e2);
130
+ ASSERT_EQ(e1.min, -10.F);
131
+ ASSERT_EQ(e1.max, 10.F);
132
+ }
133
+
134
+ TEST(Bounds, Merging) {
135
+ Bounds3D smallerBounds {{-10, -10, -10}, {10, 10, 10}};
136
+ Bounds3D const biggerBounds {{-100, -100, -100}, {100, 100, 100}};
137
+ ASSERT_FALSE(smallerBounds.contains({-100, -100, -100}));
138
+ smallerBounds.merge(biggerBounds);
139
+ ASSERT_TRUE(smallerBounds.contains({-100, -100, -100}));
140
+ ASSERT_TRUE(smallerBounds.contains({100, 100, 100}));
141
+
142
+ Bounds3D boundsA {{-10, -10, -10}, { 10, 10, 10}};
143
+ Bounds3D const boundsB {{-100, -1, -2}, { 5, 200, 3}};
144
+ boundsA.merge(boundsB);
145
+ ASSERT_NEAR((boundsA.min() - Vector3{-100, -10, -10}).lengthSquared(), 0, 1e-6);
146
+ ASSERT_NEAR((boundsA.max() - Vector3{10, 200, 10}).lengthSquared(), 0, 1e-6);
147
+ }
148
+
149
+ TEST(Bounds, Corners) {
150
+ Bounds3D const bounds {{-10, -10, -10}, { 10, 10, 10}};
151
+ auto const corners = bounds.corners();
152
+ ASSERT_EQ((bounds.min() - corners.at(0)).lengthSquared(), 0);
153
+ ASSERT_EQ(((bounds.min() + Vector3{bounds.x.length(), bounds.y.length(), 0}) - corners.at(2)).lengthSquared(), 0);
154
+ ASSERT_EQ((bounds.max() - corners.at(6)).lengthSquared(), 0);
155
+ ASSERT_EQ(((bounds.max() - Vector3{bounds.x.length(), bounds.y.length(), 0}) - corners.at(4)).lengthSquared(), 0);
156
+ }
@@ -0,0 +1 @@
1
+ from .math3d import *
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+ from math3d.math3d import AABB
3
+ from math3d.math3d import Extent
4
+ from math3d.math3d import Identity2
5
+ from math3d.math3d import Identity3
6
+ from math3d.math3d import Identity4
7
+ from math3d.math3d import LinearSystem2
8
+ from math3d.math3d import LinearSystem3
9
+ from math3d.math3d import LinearSystem4
10
+ from math3d.math3d import Matrix2
11
+ from math3d.math3d import Matrix3
12
+ from math3d.math3d import Matrix4
13
+ from math3d.math3d import Vector2
14
+ from math3d.math3d import Vector3
15
+ from math3d.math3d import Vector4
16
+ from math3d.math3d import order
17
+ from . import math3d
18
+ __all__: list[str] = ['AABB', 'Extent', 'Identity2', 'Identity3', 'Identity4', 'LinearSystem2', 'LinearSystem3', 'LinearSystem4', 'Matrix2', 'Matrix3', 'Matrix4', 'Vector2', 'Vector3', 'Vector4', 'col_major', 'math3d', 'order', 'row_major']
19
+ col_major: order # value = <order.col_major: 0>
20
+ row_major: order # value = <order.row_major: 1>
@@ -0,0 +1,15 @@
1
+ #pragma once
2
+ #include "pybind11/pybind11.h"
3
+ #include "LinearSystem.h"
4
+
5
+ namespace py = pybind11;
6
+
7
+ template<typename T, uint32_t Size>
8
+ void bind_linearSystem(py::module_ const& module, char const* className) {
9
+
10
+ using linear_system = math3d::LinearSystem<T, Size>;
11
+
12
+ py::class_<linear_system>(module, className)
13
+ .def_static("solve", &linear_system::solveLinearSystem);
14
+
15
+ }
@@ -0,0 +1,116 @@
1
+ #include "pybind11/pybind11.h"
2
+ #include "vector.hpp"
3
+ #include "matrix.hpp"
4
+ #include "linear_system.hpp"
5
+ #include "types.hpp"
6
+
7
+ #include <unordered_map>
8
+ #include <format>
9
+
10
+ namespace {
11
+
12
+ #ifdef MAX_DIMENSIONS
13
+ auto constexpr MaxDimension {MAX_DIMENSIONS};
14
+ #else
15
+ auto constexpr MaxDimension {4};
16
+ #endif
17
+
18
+ enum class Type : uint8_t {
19
+ Vector,
20
+ Matrix,
21
+ LinearSystem,
22
+ IdentityMatrix,
23
+ Extent,
24
+ Bounds
25
+ };
26
+ std::unordered_map<Type, char const*> TypePrefixMap {
27
+ {Type::Vector, "Vector"},
28
+ {Type::Matrix, "Matrix"},
29
+ {Type::LinearSystem, "LinearSystem"},
30
+ {Type::IdentityMatrix, "Identity"},
31
+ {Type::Bounds, "AABB"},
32
+ {Type::Extent, "Extent"}
33
+ };
34
+
35
+ template<typename Type, Type Start, Type End>
36
+ class TypeIterator {
37
+ public:
38
+ TypeIterator() = default;
39
+
40
+ TypeIterator begin() {
41
+ return *this;
42
+ }
43
+
44
+ TypeIterator end() {
45
+ return TypeIterator{End + 1};
46
+ }
47
+
48
+ bool operator==(TypeIterator const& another) {
49
+ return value == another.value;
50
+ }
51
+
52
+ private:
53
+ std::underlying_type_t<Type> value {Start};
54
+ };
55
+
56
+ auto pyCompositeTypeCreator = [](Type const type, pybind11::module_ const& pythonModule, auto const integerConstant) {
57
+ constexpr uint8_t dimension = integerConstant + 2;
58
+ auto const typeName = TypePrefixMap[type] + std::to_string(dimension);
59
+ if (typeName.empty()) {
60
+ throw std::runtime_error{std::format("Unknown type {}", std::to_underlying(type))};
61
+ }
62
+ switch (type) {
63
+ case Type::Vector:
64
+ bind_Vector<double, dimension>(pythonModule, typeName.c_str());
65
+ break;
66
+ case Type::Matrix:
67
+ bind_Matrix<double, dimension, dimension>(pythonModule, typeName.c_str());
68
+ break;
69
+ case Type::LinearSystem:
70
+ bind_linearSystem<double, dimension>(pythonModule, typeName.c_str());
71
+ break;
72
+ case Type::IdentityMatrix:
73
+ bind_identityMatrix<double, dimension, dimension>(pythonModule, typeName.c_str());
74
+ break;
75
+ default:
76
+ break;
77
+ }
78
+ };
79
+
80
+ void createSimpleType(Type const type, pybind11::module_ const& module) {
81
+ auto const typeName = TypePrefixMap.at(type);
82
+ switch (type) {
83
+ case Type::Extent:
84
+ bind_Extent<double>(module, typeName);
85
+ break;
86
+ case Type::Bounds:
87
+ bind_Bounds<double>(module, typeName);
88
+ break;
89
+ default:
90
+ throw std::runtime_error(std::format("Unknown simple type {}", std::to_underlying(type)));
91
+ }
92
+
93
+ }
94
+
95
+ template <uint8_t... integers>
96
+ void createCompositeType(Type const type, pybind11::module_& module, std::integer_sequence<uint8_t, integers...>) {
97
+ (pyCompositeTypeCreator(type, module, std::integral_constant<uint8_t, integers>{}), ...);
98
+ }
99
+ }
100
+
101
+ PYBIND11_MODULE(math3d, module) {
102
+ // NOTE: std::make_integer_sequence returns integer_sequence<unsigned, 0, 1, ... , N-1>
103
+ // Therefore, when MaxDimension is 4, the integer sequence is 0, 1, 2 (range [0, 3)), which gets is translated to
104
+ // types with suffix 2, 3, 4 e.g. vec2, vec3, and vec4
105
+ auto constexpr intSeq = std::make_integer_sequence<uint8_t, MaxDimension-1>{};
106
+ createCompositeType(Type::Vector, module, intSeq);
107
+ py::enum_<math3d::Order>(module, "order")
108
+ .value("row_major", math3d::Order::RowMajor)
109
+ .value("col_major", math3d::Order::ColumnMajor)
110
+ .export_values();
111
+ createCompositeType(Type::Matrix, module, intSeq);
112
+ createCompositeType(Type::LinearSystem, module, intSeq);
113
+ createCompositeType(Type::IdentityMatrix, module, intSeq);
114
+ createSimpleType(Type::Extent, module);
115
+ createSimpleType(Type::Bounds, module);
116
+ }
@@ -0,0 +1,57 @@
1
+ #pragma once
2
+ #include "pybind11/pybind11.h"
3
+ #include "pybind11/operators.h"
4
+
5
+ #include "MatrixOperations.h"
6
+
7
+ namespace py = pybind11;
8
+
9
+ template<typename T, uint32_t Rows, uint32_t Cols>
10
+ void bind_Matrix(py::module_ const& module, char const* className) {
11
+
12
+ using matrix = math3d::Matrix<T, Rows, Cols>;
13
+ using vector = math3d::Vector<T, Cols>;
14
+
15
+ py::class_<matrix>(module, className)
16
+ .def(py::init())
17
+ .def(py::init([](py::iterable const& data, math3d::Order const order) {
18
+ std::vector<std::vector<T>> dataAsVec;
19
+ for (auto outer : data) {
20
+ std::vector<T> inner = outer.cast<std::vector<T>>();
21
+ dataAsVec.push_back(std::move(inner));
22
+ }
23
+ return matrix{dataAsVec, order};
24
+ }))
25
+ .def("__getitem__", [](matrix const& matrix, uint32_t const index) {
26
+ return matrix.operator[](index);
27
+ })
28
+ .def("__getitem__", [](matrix const& matrix, std::pair<uint32_t, uint32_t> const& index_pair) {
29
+ return matrix.operator()(index_pair.first, index_pair.second);
30
+ })
31
+ .def("row", [](matrix const& matrix, uint32_t row) {
32
+ return matrix.operator()(row);
33
+ })
34
+ .def(py::self * py::self)
35
+ .def(py::self * vector{})
36
+ .def("__str__", &matrix::asString)
37
+ .def("__repr__", &matrix::asString)
38
+
39
+ // Operations
40
+ .def("transpose", &matrix::transpose)
41
+ .def("upper_triangular", [](matrix const& input) {
42
+ matrix output;
43
+ input.convertToUpperTriangular(output);
44
+ return output;
45
+ })
46
+ .def("determinant", &matrix::determinant)
47
+ .def("inverse", &matrix::inverse)
48
+ ;
49
+ }
50
+
51
+ template<typename T, uint32_t Rows, uint32_t Cols>
52
+ void bind_identityMatrix(py::module_ const& module, char const* className) {
53
+ using identityMatrix = math3d::IdentityMatrix<T, Rows, Cols>;
54
+ using matrix = math3d::Matrix<T, Rows, Cols>;
55
+ py::class_<identityMatrix, matrix>(module, className)
56
+ .def(py::init());
57
+ }
File without changes
@@ -11,18 +11,44 @@ template<typename T>
11
11
  void bind_Extent(py::module_ const& module, std::string_view className) {
12
12
  using Extent = m3d::Extent<T>;
13
13
  py::class_<Extent>(module, className.data())
14
+ .def(py::init([] {
15
+ Extent extent;
16
+ extent.min = std::numeric_limits<T>::max();
17
+ extent.max = -std::numeric_limits<T>::max();
18
+ return extent;
19
+ }))
14
20
  .def(py::init([](T min, T max) {
15
21
  Extent extent {};
16
22
  extent.min = min;
17
23
  extent.max = max;
18
24
  return extent;
19
25
  }))
26
+ .def_property("min",
27
+ [](Extent const& extent) {
28
+ return extent.min;
29
+ },
30
+ [](Extent& extent, T min) {
31
+ extent.min = min;
32
+ }
33
+ )
34
+ .def_property("max",
35
+ [](Extent const& extent) {
36
+ return extent.max;
37
+ },
38
+ [](Extent& extent, T max) {
39
+ extent.max = max;
40
+ }
41
+ )
20
42
  .def("length", [](Extent const& extent) {
21
43
  return extent.length();
22
44
  })
23
45
  .def("center", [](Extent const& extent) {
24
46
  return extent.center();
25
47
  })
48
+ .def("update", [](Extent& extent, T val) {
49
+ extent.min = std::min(extent.min, val);
50
+ extent.max = std::max(extent.max, val);
51
+ })
26
52
  .def("__str__", [](Extent const& extent) {
27
53
  return extent.asString();
28
54
  })
@@ -0,0 +1,13 @@
1
+ #pragma once
2
+ #include <ranges>
3
+ #include <string>
4
+ #include <algorithm>
5
+
6
+ namespace util {
7
+ inline auto convertSpaceToNewLine = [](std::string&& str) {
8
+ std::string result{std::move(str)};
9
+ std::ranges::replace(result.begin(), result.end(), ' ', '\n');
10
+ result = result.substr(1, result.size()-2);
11
+ return result;
12
+ };
13
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes