math3d-py 1.3.0__tar.gz → 1.3.4__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.3.4}/PKG-INFO +1 -1
  2. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/SupportingTypes.h +22 -2
  3. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/CMakeLists.txt +1 -1
  4. math3d_py-1.3.4/py/math3d/math3d.pyi +303 -0
  5. math3d_py-1.3.4/py/math3d/py.typed +0 -0
  6. math3d_py-1.3.4/py/math3d/types.hpp +84 -0
  7. {math3d_py-1.3.0 → math3d_py-1.3.4}/pyproject.toml +1 -1
  8. {math3d_py-1.3.0 → math3d_py-1.3.4}/pypublish +2 -2
  9. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Types.cpp +24 -0
  10. math3d_py-1.3.4/tmp/math3d/__init__.py +1 -0
  11. math3d_py-1.3.4/tmp/math3d/__init__.pyi +20 -0
  12. math3d_py-1.3.4/tmp/math3d/linear_system.hpp +15 -0
  13. math3d_py-1.3.4/tmp/math3d/math3d.cpp +116 -0
  14. math3d_py-1.3.4/tmp/math3d/math3d.cpython-313-darwin.so +0 -0
  15. math3d_py-1.3.4/tmp/math3d/matrix.hpp +57 -0
  16. math3d_py-1.3.4/tmp/math3d/py.typed +0 -0
  17. {math3d_py-1.3.0/py → math3d_py-1.3.4/tmp}/math3d/types.hpp +26 -0
  18. math3d_py-1.3.4/tmp/math3d/util.h +13 -0
  19. math3d_py-1.3.4/tmp/math3d/vector.hpp +101 -0
  20. {math3d_py-1.3.0 → math3d_py-1.3.4}/.DS_Store +0 -0
  21. {math3d_py-1.3.0 → math3d_py-1.3.4}/.github/workflows/cmake-single-platform.yml +0 -0
  22. {math3d_py-1.3.0 → math3d_py-1.3.4}/.github/workflows/jekyll-gh-pages.yml +0 -0
  23. {math3d_py-1.3.0 → math3d_py-1.3.4}/.gitignore +0 -0
  24. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/.gitignore +0 -0
  25. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/3dmath.iml +0 -0
  26. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/editor.xml +0 -0
  27. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/misc.xml +0 -0
  28. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/modules.xml +0 -0
  29. {math3d_py-1.3.0 → math3d_py-1.3.4}/.idea/vcs.xml +0 -0
  30. {math3d_py-1.3.0 → math3d_py-1.3.4}/CMakeLists.txt +0 -0
  31. {math3d_py-1.3.0 → math3d_py-1.3.4}/LICENSE.txt +0 -0
  32. {math3d_py-1.3.0 → math3d_py-1.3.4}/README.md +0 -0
  33. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/.DS_Store +0 -0
  34. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/Constants.h +0 -0
  35. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/IdentityMatrix.h +0 -0
  36. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/LinearSystem.h +0 -0
  37. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/Matrix.h +0 -0
  38. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/MatrixOperations.h +0 -0
  39. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/MatrixUtil.h +0 -0
  40. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/OrthographicProjectionMatrix.h +0 -0
  41. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/PolarCoordinates.h +0 -0
  42. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/ProjectionMatrix.h +0 -0
  43. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/Quaternion.h +0 -0
  44. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/RotationMatrix.h +0 -0
  45. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/ScalingMatrix.h +0 -0
  46. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/TranslationMatrix.h +0 -0
  47. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/TypeAliases.h +0 -0
  48. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/Utilities.h +0 -0
  49. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/Vector.h +0 -0
  50. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/primitives/ConvexPrimitive.h +0 -0
  51. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/primitives/Plane.h +0 -0
  52. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/primitives/Primitive.h +0 -0
  53. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/primitives/Ray.h +0 -0
  54. {math3d_py-1.3.0 → math3d_py-1.3.4}/include/3dmath/primitives/Sphere.h +0 -0
  55. {math3d_py-1.3.0 → math3d_py-1.3.4}/poetry.lock +0 -0
  56. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/__init__.py +0 -0
  57. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/__init__.pyi +0 -0
  58. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/linear_system.hpp +0 -0
  59. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/math3d.cpp +0 -0
  60. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/matrix.hpp +0 -0
  61. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/util.h +0 -0
  62. {math3d_py-1.3.0 → math3d_py-1.3.4}/py/math3d/vector.hpp +0 -0
  63. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/CMakeLists.txt +0 -0
  64. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/ConvexPrimitive.cpp +0 -0
  65. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/LinearSystem.cpp +0 -0
  66. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Matrix.cpp +0 -0
  67. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/MatrixOperations.cpp +0 -0
  68. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/OrthographicProjectionMatrix.cpp +0 -0
  69. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Plane.cpp +0 -0
  70. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/PolarCoordinates.cpp +0 -0
  71. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Quaternion.cpp +0 -0
  72. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Ray.cpp +0 -0
  73. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/RotationMatrix.cpp +0 -0
  74. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/ScalingMatrix.cpp +0 -0
  75. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Sphere.cpp +0 -0
  76. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/TestSupport.h +0 -0
  77. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/TranslationMatrix.cpp +0 -0
  78. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/Vector.cpp +0 -0
  79. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/VectorConvenienceMembers.cpp +0 -0
  80. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Ray.obj +0 -0
  81. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Sphere.obj +0 -0
  82. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Sphere.stl +0 -0
  83. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Xy.stl +0 -0
  84. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Xz.stl +0 -0
  85. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/baseline/Yz.stl +0 -0
  86. {math3d_py-1.3.0 → math3d_py-1.3.4}/tests/support/PrimitivesTestSupport.h +0 -0
  87. {math3d_py-1.3.0/py → math3d_py-1.3.4/tmp}/math3d/math3d.pyi +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.3.4
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,25 @@ 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
+ }
136
156
  };
137
157
 
138
158
  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,303 @@
1
+ from __future__ import annotations
2
+ import typing
3
+ __all__: list[str] = ['AABB', 'Extent', 'Identity2', 'Identity3', 'Identity4', 'LinearSystem2', 'LinearSystem3', 'LinearSystem4', 'Matrix2', 'Matrix3', 'Matrix4', 'Vector2', 'Vector3', 'Vector4', 'col_major', 'order', 'row_major']
4
+ class AABB:
5
+ @typing.overload
6
+ def __init__(self) -> None:
7
+ ...
8
+ @typing.overload
9
+ def __init__(self, arg0: Extent, arg1: Extent, arg2: Extent) -> None:
10
+ ...
11
+ def __repr__(self) -> str:
12
+ ...
13
+ def __str__(self) -> str:
14
+ ...
15
+ def merge(self, arg0: AABB) -> None:
16
+ ...
17
+ class Extent:
18
+ max: float
19
+ min: float
20
+ @typing.overload
21
+ def __init__(self) -> None:
22
+ ...
23
+ @typing.overload
24
+ def __init__(self, arg0: float, arg1: float) -> None:
25
+ ...
26
+ def __repr__(self) -> str:
27
+ ...
28
+ def __str__(self) -> str:
29
+ ...
30
+ def center(self) -> float:
31
+ ...
32
+ def length(self) -> float:
33
+ ...
34
+ def update(self, arg0: float) -> None:
35
+ ...
36
+ class Identity2(Matrix2):
37
+ def __init__(self) -> None:
38
+ ...
39
+ class Identity3(Matrix3):
40
+ def __init__(self) -> None:
41
+ ...
42
+ class Identity4(Matrix4):
43
+ def __init__(self) -> None:
44
+ ...
45
+ class LinearSystem2:
46
+ @staticmethod
47
+ def solve(arg0: Matrix2, arg1: Vector2) -> Vector2:
48
+ ...
49
+ class LinearSystem3:
50
+ @staticmethod
51
+ def solve(arg0: Matrix3, arg1: Vector3) -> Vector3:
52
+ ...
53
+ class LinearSystem4:
54
+ @staticmethod
55
+ def solve(arg0: Matrix4, arg1: Vector4) -> Vector4:
56
+ ...
57
+ class Matrix2:
58
+ @typing.overload
59
+ def __getitem__(self, arg0: int) -> Vector2:
60
+ ...
61
+ @typing.overload
62
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
63
+ ...
64
+ @typing.overload
65
+ def __init__(self) -> None:
66
+ ...
67
+ @typing.overload
68
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
69
+ ...
70
+ @typing.overload
71
+ def __mul__(self, arg0: Matrix2) -> Matrix2:
72
+ ...
73
+ @typing.overload
74
+ def __mul__(self, arg0: Vector2) -> Vector2:
75
+ ...
76
+ def __repr__(self) -> str:
77
+ ...
78
+ def __str__(self) -> str:
79
+ ...
80
+ def determinant(self) -> float:
81
+ ...
82
+ def inverse(self) -> Matrix2:
83
+ ...
84
+ def row(self, arg0: int) -> Vector2:
85
+ ...
86
+ def transpose(self) -> Matrix2:
87
+ ...
88
+ def upper_triangular(self) -> Matrix2:
89
+ ...
90
+ class Matrix3:
91
+ @typing.overload
92
+ def __getitem__(self, arg0: int) -> Vector3:
93
+ ...
94
+ @typing.overload
95
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
96
+ ...
97
+ @typing.overload
98
+ def __init__(self) -> None:
99
+ ...
100
+ @typing.overload
101
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
102
+ ...
103
+ @typing.overload
104
+ def __mul__(self, arg0: Matrix3) -> Matrix3:
105
+ ...
106
+ @typing.overload
107
+ def __mul__(self, arg0: Vector3) -> Vector3:
108
+ ...
109
+ def __repr__(self) -> str:
110
+ ...
111
+ def __str__(self) -> str:
112
+ ...
113
+ def determinant(self) -> float:
114
+ ...
115
+ def inverse(self) -> Matrix3:
116
+ ...
117
+ def row(self, arg0: int) -> Vector3:
118
+ ...
119
+ def transpose(self) -> Matrix3:
120
+ ...
121
+ def upper_triangular(self) -> Matrix3:
122
+ ...
123
+ class Matrix4:
124
+ @typing.overload
125
+ def __getitem__(self, arg0: int) -> Vector4:
126
+ ...
127
+ @typing.overload
128
+ def __getitem__(self, arg0: tuple[int, int]) -> float:
129
+ ...
130
+ @typing.overload
131
+ def __init__(self) -> None:
132
+ ...
133
+ @typing.overload
134
+ def __init__(self, arg0: typing.Iterable, arg1: order) -> None:
135
+ ...
136
+ @typing.overload
137
+ def __mul__(self, arg0: Matrix4) -> Matrix4:
138
+ ...
139
+ @typing.overload
140
+ def __mul__(self, arg0: Vector4) -> Vector4:
141
+ ...
142
+ def __repr__(self) -> str:
143
+ ...
144
+ def __str__(self) -> str:
145
+ ...
146
+ def determinant(self) -> float:
147
+ ...
148
+ def inverse(self) -> Matrix4:
149
+ ...
150
+ def row(self, arg0: int) -> Vector4:
151
+ ...
152
+ def transpose(self) -> Matrix4:
153
+ ...
154
+ def upper_triangular(self) -> Matrix4:
155
+ ...
156
+ class Vector2:
157
+ x: float
158
+ y: float
159
+ def __add__(self, arg0: Vector2) -> Vector2:
160
+ ...
161
+ @typing.overload
162
+ def __init__(self) -> None:
163
+ ...
164
+ @typing.overload
165
+ def __init__(self, arg0: typing.Iterable) -> None:
166
+ ...
167
+ def __mul__(self, arg0: float) -> Vector2:
168
+ ...
169
+ def __repr__(self) -> str:
170
+ ...
171
+ def __str__(self) -> str:
172
+ ...
173
+ def __sub__(self, arg0: Vector2) -> Vector2:
174
+ ...
175
+ def __truediv__(self, arg0: float) -> Vector2:
176
+ ...
177
+ def dot(self, arg0: Vector2) -> float:
178
+ ...
179
+ def length(self) -> float:
180
+ ...
181
+ def length_sqr(self) -> float:
182
+ ...
183
+ def normalize(self) -> Vector2:
184
+ ...
185
+ def projection(self, arg0: Vector2) -> tuple[Vector2, Vector2]:
186
+ ...
187
+ class Vector3:
188
+ x: float
189
+ y: float
190
+ z: float
191
+ def __add__(self, arg0: Vector3) -> Vector3:
192
+ ...
193
+ @typing.overload
194
+ def __init__(self) -> None:
195
+ ...
196
+ @typing.overload
197
+ def __init__(self, arg0: typing.Iterable) -> None:
198
+ ...
199
+ @typing.overload
200
+ def __init__(self, arg0: float, arg1: float, arg2: float) -> None:
201
+ ...
202
+ @typing.overload
203
+ def __mul__(self, arg0: float) -> Vector3:
204
+ ...
205
+ @typing.overload
206
+ def __mul__(self, arg0: Vector3) -> Vector3:
207
+ ...
208
+ def __repr__(self) -> str:
209
+ ...
210
+ def __str__(self) -> str:
211
+ ...
212
+ def __sub__(self, arg0: Vector3) -> Vector3:
213
+ ...
214
+ def __truediv__(self, arg0: float) -> Vector3:
215
+ ...
216
+ def dot(self, arg0: Vector3) -> float:
217
+ ...
218
+ def length(self) -> float:
219
+ ...
220
+ def length_sqr(self) -> float:
221
+ ...
222
+ def normalize(self) -> Vector3:
223
+ ...
224
+ def projection(self, arg0: Vector3) -> tuple[Vector3, Vector3]:
225
+ ...
226
+ class Vector4:
227
+ w: float
228
+ x: float
229
+ y: float
230
+ z: float
231
+ def __add__(self, arg0: Vector4) -> Vector4:
232
+ ...
233
+ @typing.overload
234
+ def __init__(self) -> None:
235
+ ...
236
+ @typing.overload
237
+ def __init__(self, arg0: typing.Iterable) -> None:
238
+ ...
239
+ @typing.overload
240
+ def __init__(self, arg0: float, arg1: float, arg2: float, arg3: float) -> None:
241
+ ...
242
+ @typing.overload
243
+ def __init__(self, arg0: Vector3) -> None:
244
+ ...
245
+ def __mul__(self, arg0: float) -> Vector4:
246
+ ...
247
+ def __repr__(self) -> str:
248
+ ...
249
+ def __str__(self) -> str:
250
+ ...
251
+ def __sub__(self, arg0: Vector4) -> Vector4:
252
+ ...
253
+ def __truediv__(self, arg0: float) -> Vector4:
254
+ ...
255
+ def dot(self, arg0: Vector4) -> float:
256
+ ...
257
+ def length(self) -> float:
258
+ ...
259
+ def length_sqr(self) -> float:
260
+ ...
261
+ def normalize(self) -> Vector4:
262
+ ...
263
+ def projection(self, arg0: Vector4) -> tuple[Vector4, Vector4]:
264
+ ...
265
+ class order:
266
+ """
267
+ Members:
268
+
269
+ row_major
270
+
271
+ col_major
272
+ """
273
+ __members__: typing.ClassVar[dict[str, order]] # value = {'row_major': <order.row_major: 1>, 'col_major': <order.col_major: 0>}
274
+ col_major: typing.ClassVar[order] # value = <order.col_major: 0>
275
+ row_major: typing.ClassVar[order] # value = <order.row_major: 1>
276
+ def __eq__(self, other: typing.Any) -> bool:
277
+ ...
278
+ def __getstate__(self) -> int:
279
+ ...
280
+ def __hash__(self) -> int:
281
+ ...
282
+ def __index__(self) -> int:
283
+ ...
284
+ def __init__(self, value: int) -> None:
285
+ ...
286
+ def __int__(self) -> int:
287
+ ...
288
+ def __ne__(self, other: typing.Any) -> bool:
289
+ ...
290
+ def __repr__(self) -> str:
291
+ ...
292
+ def __setstate__(self, state: int) -> None:
293
+ ...
294
+ def __str__(self) -> str:
295
+ ...
296
+ @property
297
+ def name(self) -> str:
298
+ ...
299
+ @property
300
+ def value(self) -> int:
301
+ ...
302
+ col_major: order # value = <order.col_major: 0>
303
+ row_major: order # value = <order.row_major: 1>
File without changes
@@ -0,0 +1,84 @@
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("merge", [](Bounds& self, Bounds const& another) {
69
+ self.merge(another);
70
+ })
71
+ .def("__str__", [](Bounds const& bounds) {
72
+ return bounds.asString();
73
+ })
74
+ .def("__repr__", [](Bounds const& bounds) {
75
+ return std::format(
76
+ "{} Valid = {}\n"
77
+ "Center = {}\n"
78
+ "X Length = {}\n"
79
+ "Y Length = {}\n"
80
+ "Z Length = {}\n"
81
+ "Diagonal Length {}", bounds.asString(), bounds.isValid(), bounds.center().asString(),
82
+ bounds.x.length(), bounds.y.length(), bounds.z.length(), bounds.length());
83
+ });
84
+ }
@@ -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.3.4"
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,27 @@ 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
+ }
@@ -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
+ }
@@ -0,0 +1,101 @@
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(py::self / T{})
33
+ .def("dot", &vector::dot)
34
+ .def("normalize", [](vector& v) { v.normalize(); return v; })
35
+ .def("length", [](vector const& v) { return v.length(); })
36
+ .def("length_sqr", [](vector const& v) { return v.lengthSquared(); })
37
+ .def("projection", [](vector const& self, vector const& u) {
38
+ auto vectorProjection = self.getVectorProjection(u);
39
+ return std::pair{vectorProjection.parallel, vectorProjection.perpendicular};
40
+ });
41
+ if constexpr (Size == 3) {
42
+ pyVecClass
43
+ .def(py::init([](T x, T y, T z) {
44
+ return vector({x, y, z});
45
+ }))
46
+ .def(py::self * py::self);
47
+ }
48
+ if constexpr (Size == 4) {
49
+ pyVecClass
50
+ .def(py::init([](T x, T y, T z, T w) {
51
+ return vector({x, y, z, w});
52
+ }))
53
+ .def(py::init([](math3d::Vector3<T> const& vec3) {
54
+ std::vector<T> input {vec3.x, vec3.y, vec3.z, 1.F};
55
+ return vector{input};
56
+ }));
57
+ }
58
+
59
+ // Convenience member access (x, y, z, w)
60
+ // .x, .y, .z, .w are Vector<T, N>::Proxy and its conversion operator has to be invoked to get the raw value
61
+ // hence the static cast
62
+ if constexpr (Size >= 2 && Size <= 4) {
63
+ pyVecClass.def_property("x",
64
+ [](vector const& self) {
65
+ return static_cast<T>(self.x);
66
+ },
67
+ [](vector& self, T value) {
68
+ self.x = value;
69
+ }
70
+ )
71
+ .def_property("y",
72
+ [](vector const& self) {
73
+ return static_cast<T>(self.y);
74
+ },
75
+ [](vector& self, T value) {
76
+ self.y = value;
77
+ }
78
+ );
79
+ }
80
+ if constexpr (Size == 3 || Size == 4 ) {
81
+ pyVecClass.def_property("z",
82
+ [](vector const& self) {
83
+ return static_cast<T>(self.z);
84
+ },
85
+ [](vector& self, T value) {
86
+ self.z = value;
87
+ }
88
+ );
89
+ }
90
+ if constexpr (Size == 4) {
91
+ pyVecClass.def_property("w",
92
+ [](vector const& self) {
93
+ return static_cast<T>(self.w);
94
+ },
95
+ [](vector& self, T value) {
96
+ self.w = value;
97
+ }
98
+ );
99
+ }
100
+
101
+ }
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