ncca-ngl 0.3.5__py3-none-any.whl → 0.5.1__py3-none-any.whl
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.
- ncca/ngl/PrimData/pack_arrays.py +2 -3
- ncca/ngl/__init__.py +5 -5
- ncca/ngl/base_mesh.py +28 -20
- ncca/ngl/image.py +1 -3
- ncca/ngl/mat2.py +79 -53
- ncca/ngl/mat3.py +104 -185
- ncca/ngl/mat4.py +144 -309
- ncca/ngl/prim_data.py +42 -36
- ncca/ngl/primitives.py +2 -2
- ncca/ngl/pyside_event_handling_mixin.py +0 -108
- ncca/ngl/quaternion.py +69 -36
- ncca/ngl/shader.py +0 -116
- ncca/ngl/shader_program.py +94 -117
- ncca/ngl/texture.py +5 -2
- ncca/ngl/util.py +50 -0
- ncca/ngl/vec2.py +59 -302
- ncca/ngl/vec2_array.py +79 -28
- ncca/ngl/vec3.py +60 -350
- ncca/ngl/vec3_array.py +76 -23
- ncca/ngl/vec4.py +90 -200
- ncca/ngl/vec4_array.py +78 -27
- ncca/ngl/vector_base.py +548 -0
- ncca/ngl/webgpu/__init__.py +20 -0
- ncca/ngl/webgpu/__main__.py +640 -0
- ncca/ngl/webgpu/__main__.py.backup +640 -0
- ncca/ngl/webgpu/base_webgpu_pipeline.py +354 -0
- ncca/ngl/webgpu/custom_shader_pipeline.py +288 -0
- ncca/ngl/webgpu/instanced_geometry_pipeline.py +594 -0
- ncca/ngl/webgpu/line_pipeline.py +405 -0
- ncca/ngl/webgpu/pipeline_factory.py +190 -0
- ncca/ngl/webgpu/pipeline_shaders.py +497 -0
- ncca/ngl/webgpu/point_list_pipeline.py +349 -0
- ncca/ngl/webgpu/point_pipeline.py +336 -0
- ncca/ngl/webgpu/triangle_pipeline.py +419 -0
- ncca/ngl/webgpu/webgpu_constants.py +33 -0
- ncca/ngl/webgpu/webgpu_widget.py +322 -0
- ncca/ngl/webgpu/wip/REFACTORING_SUMMARY.md +82 -0
- ncca/ngl/webgpu/wip/UNIFIED_SYSTEM.md +314 -0
- ncca/ngl/webgpu/wip/buffer_manager.py +396 -0
- ncca/ngl/webgpu/wip/pipeline_config.py +463 -0
- ncca/ngl/webgpu/wip/shader_constants.py +328 -0
- ncca/ngl/webgpu/wip/shader_templates.py +563 -0
- ncca/ngl/webgpu/wip/unified_examples.py +390 -0
- ncca/ngl/webgpu/wip/unified_factory.py +449 -0
- ncca/ngl/webgpu/wip/unified_pipeline.py +469 -0
- ncca/ngl/widgets/__init__.py +18 -2
- ncca/ngl/widgets/__main__.py +2 -1
- ncca/ngl/widgets/lookatwidget.py +2 -1
- ncca/ngl/widgets/mat4widget.py +2 -2
- ncca/ngl/widgets/vec2widget.py +1 -1
- ncca/ngl/widgets/vec3widget.py +1 -0
- {ncca_ngl-0.3.5.dist-info → ncca_ngl-0.5.1.dist-info}/METADATA +3 -2
- ncca_ngl-0.5.1.dist-info/RECORD +105 -0
- ncca/ngl/widgets/transformation_widget.py +0 -299
- ncca_ngl-0.3.5.dist-info/RECORD +0 -82
- {ncca_ngl-0.3.5.dist-info → ncca_ngl-0.5.1.dist-info}/WHEEL +0 -0
ncca/ngl/vec2.py
CHANGED
|
@@ -1,360 +1,117 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Simple float only Vec2 class for 3D graphics, very similar to the pyngl ones
|
|
3
|
+
NumPy-based implementation with VectorBase inheritance for code reuse.
|
|
3
4
|
"""
|
|
4
5
|
|
|
5
|
-
import ctypes
|
|
6
6
|
import math
|
|
7
|
+
from typing import Union
|
|
7
8
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
|
|
10
|
-
from .util import clamp
|
|
11
|
+
from .util import clamp
|
|
12
|
+
from .vector_base import VectorBase, _create_properties
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
class Vec2:
|
|
15
|
+
class Vec2(VectorBase["Vec2"]):
|
|
14
16
|
"""
|
|
15
|
-
A simple
|
|
17
|
+
A simple 2D vector class for graphics, using numpy for efficient operations.
|
|
18
|
+
|
|
16
19
|
Attributes:
|
|
17
20
|
x (float): The x-coordinate of the vector.
|
|
18
21
|
y (float): The y-coordinate of the vector.
|
|
19
22
|
"""
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"""
|
|
25
|
-
Initializes a new instance of the Vec2 class.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
x (float, optional): The x-coordinate of the vector. Defaults to 0.0.
|
|
29
|
-
y (float, optional): The y-coordinate of the vector. Defaults to 0.0.
|
|
30
|
-
"""
|
|
31
|
-
self._x = x # x component of vector : float
|
|
32
|
-
self._y = y # y component of vector : float
|
|
24
|
+
DIMENSION = 2
|
|
25
|
+
COMPONENT_NAMES = ("x", "y")
|
|
26
|
+
DEFAULT_VALUES = (0.0, 0.0)
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
def sizeof(cls):
|
|
36
|
-
return 2 * ctypes.sizeof(ctypes.c_float)
|
|
28
|
+
__slots__ = ["_data"]
|
|
37
29
|
|
|
38
|
-
def
|
|
39
|
-
"""
|
|
40
|
-
Make the Vec2 class iterable.
|
|
41
|
-
Yields:
|
|
42
|
-
float: The x and y components of the vector.
|
|
43
|
-
"""
|
|
44
|
-
yield self.x
|
|
45
|
-
yield self.y
|
|
46
|
-
|
|
47
|
-
def __hash__(self):
|
|
48
|
-
# Use 32-bit float element hashes, then combine
|
|
49
|
-
seed = 0
|
|
50
|
-
for v in (self.x, self.y):
|
|
51
|
-
# ensure 32-bit float semantics
|
|
52
|
-
h = hash(float(np.float32(v)))
|
|
53
|
-
seed = hash_combine(seed, h)
|
|
54
|
-
return seed
|
|
55
|
-
|
|
56
|
-
def copy(self) -> "Vec2":
|
|
57
|
-
"""
|
|
58
|
-
Create a copy of the vector.
|
|
59
|
-
Returns:
|
|
60
|
-
Vec2: A new instance of Vec2 with the same x and y values.
|
|
61
|
-
"""
|
|
62
|
-
return Vec2(self.x, self.y)
|
|
63
|
-
|
|
64
|
-
def __getitem__(self, index):
|
|
65
|
-
"""
|
|
66
|
-
Get the component of the vector at the given index.
|
|
67
|
-
Args:
|
|
68
|
-
index (int): The index of the component (0 for x, 1 for y, 2 for z).
|
|
69
|
-
Returns:
|
|
70
|
-
float: The value of the component at the given index.
|
|
71
|
-
Raises:
|
|
72
|
-
IndexError: If the index is out of range.
|
|
30
|
+
def cross(self, rhs: "Vec2") -> float:
|
|
73
31
|
"""
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
return components[index]
|
|
77
|
-
except IndexError:
|
|
78
|
-
raise IndexError("Index out of range. Valid indices are 0, 1,")
|
|
32
|
+
Cross product of two vectors a x b (2D version returns scalar).
|
|
79
33
|
|
|
80
|
-
def _validate_and_set(self, v, name):
|
|
81
|
-
"""
|
|
82
|
-
check if v is a float or int
|
|
83
34
|
Args:
|
|
84
|
-
|
|
85
|
-
Raises:
|
|
86
|
-
ValueError: If v is not a float or int.
|
|
87
|
-
"""
|
|
88
|
-
if not isinstance(v, (int, float, np.float32)):
|
|
89
|
-
raise ValueError("need float or int")
|
|
90
|
-
else:
|
|
91
|
-
setattr(self, name, v)
|
|
92
|
-
|
|
93
|
-
def __add__(self, rhs):
|
|
94
|
-
"""
|
|
95
|
-
vector addition a+b
|
|
35
|
+
rhs (Vec2): The right-hand side vector to cross product with.
|
|
96
36
|
|
|
97
|
-
Args:
|
|
98
|
-
rhs (Vec2): The right-hand side vector to add.
|
|
99
37
|
Returns:
|
|
100
|
-
|
|
38
|
+
float: 2D cross product (perpendicular dot product).
|
|
101
39
|
"""
|
|
102
|
-
|
|
103
|
-
r.x = self.x + rhs.x
|
|
104
|
-
r.y = self.y + rhs.y
|
|
105
|
-
return r
|
|
40
|
+
return self._data[0] * rhs._data[1] - self._data[1] * rhs._data[0]
|
|
106
41
|
|
|
107
|
-
def
|
|
42
|
+
def reflect(self, n: "Vec2") -> "Vec2":
|
|
108
43
|
"""
|
|
109
|
-
vector
|
|
44
|
+
Reflect a vector about a normal.
|
|
110
45
|
|
|
111
46
|
Args:
|
|
112
|
-
|
|
113
|
-
Returns:
|
|
114
|
-
Vec2: returns this vector after adding the rhs vector.
|
|
115
|
-
"""
|
|
116
|
-
self.x += rhs.x
|
|
117
|
-
self.y += rhs.y
|
|
118
|
-
return self
|
|
119
|
-
|
|
120
|
-
def __sub__(self, rhs):
|
|
121
|
-
"""
|
|
122
|
-
vector subtraction a-b
|
|
47
|
+
n (Vec2): The normal to reflect about.
|
|
123
48
|
|
|
124
|
-
Args:
|
|
125
|
-
rhs (Vec2): The right-hand side vector to add.
|
|
126
49
|
Returns:
|
|
127
|
-
Vec2: A new vector that is the result of
|
|
50
|
+
Vec2: A new vector that is the result of reflecting this vector about the normal.
|
|
128
51
|
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
52
|
+
d = self.dot(n)
|
|
53
|
+
# I - 2.0 * dot(N, I) * N
|
|
54
|
+
return Vec2(
|
|
55
|
+
self._data[0] - 2.0 * d * n._data[0], self._data[1] - 2.0 * d * n._data[1]
|
|
56
|
+
)
|
|
133
57
|
|
|
134
|
-
def
|
|
58
|
+
def outer(self, rhs: "Vec2"):
|
|
135
59
|
"""
|
|
136
|
-
|
|
60
|
+
Outer product of two vectors a x b.
|
|
137
61
|
|
|
138
62
|
Args:
|
|
139
|
-
rhs (Vec2): The right-hand side vector to
|
|
140
|
-
Returns:
|
|
141
|
-
Vec2: returns this vector after subtracting the rhs vector.
|
|
142
|
-
"""
|
|
143
|
-
self.x -= rhs.x
|
|
144
|
-
self.y -= rhs.y
|
|
145
|
-
return self
|
|
63
|
+
rhs (Vec2): The right-hand side vector to outer product with.
|
|
146
64
|
|
|
147
|
-
def __eq__(self, rhs):
|
|
148
|
-
"""
|
|
149
|
-
vector comparison a==b using math.isclose not we only compare to 6 decimal places
|
|
150
|
-
Args:
|
|
151
|
-
rhs (Vec2): The right-hand side vector to compare.
|
|
152
65
|
Returns:
|
|
153
|
-
|
|
154
|
-
NotImplemented: If the right-hand side is not a Vec2.
|
|
66
|
+
Mat2: A new 2x2 matrix that is the result of the outer product.
|
|
155
67
|
"""
|
|
68
|
+
from .mat2 import Mat2
|
|
156
69
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
def __neq__(self, rhs):
|
|
162
|
-
"""
|
|
163
|
-
vector comparison a!=b using math.isclose not we only compare to 6 decimal places
|
|
164
|
-
Args:
|
|
165
|
-
rhs (Vec2): The right-hand side vector to compare.
|
|
166
|
-
Returns:
|
|
167
|
-
bool: True if the vectors are not close, False otherwise.
|
|
168
|
-
NotImplemented: If the right-hand side is not a Vec2.
|
|
169
|
-
"""
|
|
70
|
+
result = Mat2()
|
|
71
|
+
result.m = np.outer(self._data, rhs._data).astype(np.float64)
|
|
72
|
+
return result
|
|
170
73
|
|
|
171
|
-
|
|
172
|
-
return NotImplemented
|
|
173
|
-
return not (math.isclose(self.x, rhs.x) and math.isclose(self.y, rhs.y))
|
|
174
|
-
|
|
175
|
-
def __neg__(self):
|
|
176
|
-
"""
|
|
177
|
-
negate a vector -a
|
|
178
|
-
"""
|
|
179
|
-
self.x = -self.x
|
|
180
|
-
self.y = -self.y
|
|
181
|
-
return self
|
|
182
|
-
|
|
183
|
-
def set(self, x, y):
|
|
184
|
-
"""
|
|
185
|
-
set the x,y,z values of the vector
|
|
186
|
-
Args:
|
|
187
|
-
x (float): The x-coordinate of the vector.
|
|
188
|
-
y (float): The y-coordinate of the vector.
|
|
189
|
-
Raises :
|
|
190
|
-
ValueError: if x,y are not float
|
|
74
|
+
def __matmul__(self, rhs):
|
|
191
75
|
"""
|
|
192
|
-
|
|
193
|
-
self.x = float(x)
|
|
194
|
-
self.y = float(y)
|
|
195
|
-
except ValueError:
|
|
196
|
-
raise ValueError(f"Vec2.set {x=} {y=} all need to be float")
|
|
76
|
+
Vec2 @ Mat2 matrix multiplication.
|
|
197
77
|
|
|
198
|
-
def dot(self, rhs):
|
|
199
|
-
"""
|
|
200
|
-
dot product of two vectors a.b
|
|
201
78
|
Args:
|
|
202
|
-
rhs (
|
|
203
|
-
"""
|
|
204
|
-
return self.x * rhs.x + self.y * rhs.y
|
|
205
|
-
|
|
206
|
-
def length(self):
|
|
207
|
-
"""
|
|
208
|
-
length of vector
|
|
209
|
-
Returns:
|
|
210
|
-
float: The length of the vector.
|
|
211
|
-
"""
|
|
212
|
-
return math.sqrt(self.x**2 + self.y**2)
|
|
213
|
-
|
|
214
|
-
def length_squared(self):
|
|
215
|
-
"""
|
|
216
|
-
length of vector squared sometimes used to avoid the sqrt for performance
|
|
217
|
-
Returns:
|
|
218
|
-
float: The length of the vector squared
|
|
219
|
-
"""
|
|
220
|
-
return self.x**2 + self.y**2
|
|
79
|
+
rhs (Mat2): The matrix to multiply by.
|
|
221
80
|
|
|
222
|
-
def inner(self, rhs):
|
|
223
|
-
"""
|
|
224
|
-
inner product of two vectors a.b
|
|
225
|
-
Args:
|
|
226
|
-
rhs (Vec2): The right-hand side vector to inner product with.
|
|
227
81
|
Returns:
|
|
228
|
-
|
|
82
|
+
Vec2: A new vector that is the result of multiplying this vector by the matrix.
|
|
229
83
|
"""
|
|
230
|
-
return (
|
|
84
|
+
return Vec2(
|
|
85
|
+
self._data[0] * rhs.m[0, 0] + self._data[1] * rhs.m[1, 0],
|
|
86
|
+
self._data[0] * rhs.m[0, 1] + self._data[1] * rhs.m[1, 1],
|
|
87
|
+
)
|
|
231
88
|
|
|
232
|
-
def
|
|
233
|
-
"""
|
|
234
|
-
set the vector to zero
|
|
89
|
+
def set(self, *args: float) -> None:
|
|
235
90
|
"""
|
|
236
|
-
|
|
237
|
-
self.y = 0.0
|
|
91
|
+
Set the x,y values of the vector.
|
|
238
92
|
|
|
239
|
-
def cross(self, rhs):
|
|
240
|
-
"""
|
|
241
|
-
cross product of two vectors a x b
|
|
242
93
|
Args:
|
|
243
|
-
|
|
244
|
-
Returns:
|
|
245
|
-
float : 2D cross product or perpendicular dot product.
|
|
246
|
-
"""
|
|
247
|
-
return self.x * rhs.y - self.y * rhs.x
|
|
94
|
+
*args: Component values (x, y).
|
|
248
95
|
|
|
249
|
-
def normalize(self):
|
|
250
|
-
"""
|
|
251
|
-
normalize the vector to unit length
|
|
252
|
-
Returns:
|
|
253
|
-
Vec2: A new vector that is the result of normalizing this vector.
|
|
254
96
|
Raises:
|
|
255
|
-
|
|
97
|
+
ValueError: If wrong number of arguments or they are not floats.
|
|
256
98
|
"""
|
|
257
|
-
|
|
99
|
+
if len(args) != 2:
|
|
100
|
+
raise ValueError(f"Vec2.set requires 2 arguments, got {len(args)}")
|
|
258
101
|
try:
|
|
259
|
-
self.
|
|
260
|
-
self.
|
|
261
|
-
except
|
|
262
|
-
raise
|
|
263
|
-
f"Vec2.normalize {vector_length} length is zero most likely calling normalize on a zero vector"
|
|
264
|
-
)
|
|
265
|
-
return self
|
|
266
|
-
|
|
267
|
-
def reflect(self, n):
|
|
268
|
-
"""
|
|
269
|
-
reflect a vector about a normal
|
|
270
|
-
Args:
|
|
271
|
-
n (Vec2): The normal to reflect about.
|
|
272
|
-
Returns:
|
|
273
|
-
Vec2: A new vector that is the result of reflecting this vector about the normal.
|
|
274
|
-
"""
|
|
275
|
-
d = self.dot(n)
|
|
276
|
-
# I - 2.0 * dot(N, I) * N
|
|
277
|
-
return Vec2(self.x - 2.0 * d * n.x, self.y - 2.0 * d * n.y)
|
|
278
|
-
|
|
279
|
-
def clamp(self, low, high):
|
|
280
|
-
"""
|
|
281
|
-
clamp the vector to a range
|
|
282
|
-
Args:
|
|
283
|
-
low (float): The low end of the range.
|
|
284
|
-
high (float): The high end of the range.
|
|
285
|
-
|
|
286
|
-
"""
|
|
287
|
-
self.x = clamp(self.x, low, high)
|
|
288
|
-
self.y = clamp(self.y, low, high)
|
|
289
|
-
|
|
290
|
-
def __repr__(self):
|
|
291
|
-
"object representation for debugging"
|
|
292
|
-
return f"Vec2 [{self.x},{self.y}]"
|
|
293
|
-
|
|
294
|
-
def __truediv__(self, rhs):
|
|
295
|
-
if isinstance(rhs, (float, int)):
|
|
296
|
-
return Vec2(self.x / rhs, self.y / rhs)
|
|
297
|
-
elif isinstance(rhs, Vec2):
|
|
298
|
-
return Vec2(self.x / rhs.x, self.y / rhs.y)
|
|
299
|
-
else:
|
|
300
|
-
raise ValueError(f"can only do piecewise division with a scalar {rhs=}")
|
|
301
|
-
|
|
302
|
-
def __str__(self):
|
|
303
|
-
"object representation for debugging"
|
|
304
|
-
return f"[{self.x},{self.y}]"
|
|
305
|
-
|
|
306
|
-
def __mul__(self, rhs):
|
|
307
|
-
"""
|
|
308
|
-
piecewise scalar multiplication
|
|
309
|
-
Args:
|
|
310
|
-
rhs (float): The scalar to multiply by.
|
|
311
|
-
Returns:
|
|
312
|
-
Vec2: A new vector that is the result of multiplying this vector by the scalar.
|
|
313
|
-
Raises:
|
|
314
|
-
ValueError: If the right-hand side is not a float.
|
|
315
|
-
"""
|
|
316
|
-
if isinstance(rhs, (float, int)):
|
|
317
|
-
return Vec2(self.x * rhs, self.y * rhs)
|
|
318
|
-
else:
|
|
319
|
-
raise ValueError(f"can only do piecewise multiplication with a scalar {rhs=}")
|
|
320
|
-
|
|
321
|
-
def __rmul__(self, rhs):
|
|
322
|
-
"""
|
|
323
|
-
piecewise scalar multiplication
|
|
324
|
-
Args:
|
|
325
|
-
rhs (float): The scalar to multiply by.
|
|
326
|
-
Returns:
|
|
327
|
-
Vec2: A new vector that is the result of multiplying this vector by the scalar.
|
|
328
|
-
Raises:
|
|
329
|
-
ValueError: If the right-hand side is not a float.
|
|
330
|
-
"""
|
|
331
|
-
return self * rhs
|
|
332
|
-
|
|
333
|
-
def __matmul__(self, rhs):
|
|
334
|
-
"""
|
|
335
|
-
"Vec2 @ Mat2 matrix multiplication"
|
|
336
|
-
Args:
|
|
337
|
-
rhs (Mat2): The matrix to multiply by.
|
|
338
|
-
Returns:
|
|
339
|
-
Vec2: A new vector that is the result of multiplying this vector by the matrix.
|
|
340
|
-
"""
|
|
341
|
-
return Vec2(
|
|
342
|
-
self.x * rhs.m[0][0] + self.y * rhs.m[1][0],
|
|
343
|
-
self.x * rhs.m[0][1] + self.y * rhs.m[1][1],
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
# Helper function to create properties
|
|
348
|
-
def _create_property(attr_name):
|
|
349
|
-
def getter(self):
|
|
350
|
-
return getattr(self, f"_{attr_name}")
|
|
102
|
+
self._data[0] = float(args[0])
|
|
103
|
+
self._data[1] = float(args[1])
|
|
104
|
+
except ValueError:
|
|
105
|
+
raise ValueError(f"Vec2.set {args=} all need to be float")
|
|
351
106
|
|
|
352
|
-
def
|
|
353
|
-
|
|
107
|
+
def __repr__(self) -> str:
|
|
108
|
+
"""Object representation for debugging."""
|
|
109
|
+
return f"Vec2 [{self._data[0]},{self._data[1]}]"
|
|
354
110
|
|
|
355
|
-
|
|
111
|
+
def __str__(self) -> str:
|
|
112
|
+
"""String representation of the vector."""
|
|
113
|
+
return f"[{self._data[0]},{self._data[1]}]"
|
|
356
114
|
|
|
357
115
|
|
|
358
|
-
#
|
|
359
|
-
|
|
360
|
-
setattr(Vec2, attr, _create_property(attr))
|
|
116
|
+
# Add properties for x, y components
|
|
117
|
+
_create_properties(Vec2)
|
ncca/ngl/vec2_array.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
A container for ngl.Vec2 objects that mimics some of the behavior of a std::vector
|
|
3
|
+
Optimized for graphics APIs with contiguous numpy storage
|
|
3
4
|
"""
|
|
4
5
|
|
|
5
6
|
import numpy as np
|
|
@@ -9,40 +10,55 @@ from .vec2 import Vec2
|
|
|
9
10
|
|
|
10
11
|
class Vec2Array:
|
|
11
12
|
"""
|
|
12
|
-
A class to hold
|
|
13
|
+
A class to hold Vec2 data in contiguous memory for efficient GPU transfer.
|
|
14
|
+
Internally uses a numpy array of shape (N, 2) for optimal performance.
|
|
13
15
|
"""
|
|
14
16
|
|
|
15
17
|
def __init__(self, values=None):
|
|
16
18
|
"""
|
|
17
|
-
Initializes the
|
|
19
|
+
Initializes the Vec2Array.
|
|
18
20
|
|
|
19
21
|
Args:
|
|
20
|
-
values (iterable | int, optional): An iterable of
|
|
21
|
-
If an integer, the array is initialized with that many default
|
|
22
|
-
If an iterable, it's initialized with the
|
|
22
|
+
values (iterable | int, optional): An iterable of Vec2 objects or an integer.
|
|
23
|
+
If an integer, the array is initialized with that many default Vec2s.
|
|
24
|
+
If an iterable, it's initialized with the Vec2s from the iterable.
|
|
23
25
|
Defaults to None (an empty array).
|
|
24
26
|
"""
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
if values is None:
|
|
28
|
+
# Empty array - start with shape (0, 2)
|
|
29
|
+
self._data = np.zeros((0, 2), dtype=np.float64)
|
|
30
|
+
elif isinstance(values, int):
|
|
31
|
+
# Initialize N default Vec2s (0, 0)
|
|
32
|
+
self._data = np.zeros((values, 2), dtype=np.float64)
|
|
33
|
+
else:
|
|
34
|
+
# Initialize from iterable of Vec2 objects
|
|
35
|
+
vec_list = []
|
|
36
|
+
for v in values:
|
|
37
|
+
if not isinstance(v, Vec2):
|
|
38
|
+
raise TypeError("All elements must be of type Vec2")
|
|
39
|
+
vec_list.append([v.x, v.y])
|
|
40
|
+
self._data = np.array(vec_list, dtype=np.float64)
|
|
34
41
|
|
|
35
42
|
def __getitem__(self, index):
|
|
36
43
|
"""
|
|
37
44
|
Get the Vec2 at the specified index.
|
|
38
45
|
|
|
39
46
|
Args:
|
|
40
|
-
index (int): The index of the element.
|
|
47
|
+
index (int | slice): The index or slice of the element(s).
|
|
41
48
|
|
|
42
49
|
Returns:
|
|
43
50
|
Vec2: The Vec2 object at the given index.
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
Vec2Array: A new Vec2Array if slicing.
|
|
52
|
+
"""
|
|
53
|
+
if isinstance(index, slice):
|
|
54
|
+
# Return a new Vec2Array with sliced data
|
|
55
|
+
result = Vec2Array()
|
|
56
|
+
result._data = self._data[index].copy()
|
|
57
|
+
return result
|
|
58
|
+
else:
|
|
59
|
+
# Return a single Vec2
|
|
60
|
+
row = self._data[index]
|
|
61
|
+
return Vec2(row[0], row[1])
|
|
46
62
|
|
|
47
63
|
def __setitem__(self, index, value):
|
|
48
64
|
"""
|
|
@@ -50,11 +66,11 @@ class Vec2Array:
|
|
|
50
66
|
|
|
51
67
|
Args:
|
|
52
68
|
index (int): The index of the element to set.
|
|
53
|
-
value (
|
|
69
|
+
value (Vec2): The new Vec2 object.
|
|
54
70
|
"""
|
|
55
71
|
if not isinstance(value, Vec2):
|
|
56
72
|
raise TypeError("Only Vec2 objects can be assigned")
|
|
57
|
-
self._data[index] = value
|
|
73
|
+
self._data[index] = [value.x, value.y]
|
|
58
74
|
|
|
59
75
|
def __len__(self):
|
|
60
76
|
"""
|
|
@@ -64,9 +80,25 @@ class Vec2Array:
|
|
|
64
80
|
|
|
65
81
|
def __iter__(self):
|
|
66
82
|
"""
|
|
67
|
-
Return an iterator
|
|
83
|
+
Return an iterator that yields Vec2 objects.
|
|
84
|
+
"""
|
|
85
|
+
for i in range(len(self._data)):
|
|
86
|
+
row = self._data[i]
|
|
87
|
+
yield Vec2(row[0], row[1])
|
|
88
|
+
|
|
89
|
+
def __eq__(self, other):
|
|
90
|
+
"""
|
|
91
|
+
Compare two Vec2Array instances for equality.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
other: Another Vec2Array instance to compare with.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
bool: True if the arrays contain the same data, False otherwise.
|
|
68
98
|
"""
|
|
69
|
-
|
|
99
|
+
if not isinstance(other, Vec2Array):
|
|
100
|
+
return NotImplemented
|
|
101
|
+
return np.array_equal(self._data, other._data)
|
|
70
102
|
|
|
71
103
|
def append(self, value):
|
|
72
104
|
"""
|
|
@@ -77,7 +109,8 @@ class Vec2Array:
|
|
|
77
109
|
"""
|
|
78
110
|
if not isinstance(value, Vec2):
|
|
79
111
|
raise TypeError("Only Vec2 objects can be appended")
|
|
80
|
-
|
|
112
|
+
new_row = np.array([[value.x, value.y]], dtype=np.float64)
|
|
113
|
+
self._data = np.vstack([self._data, new_row])
|
|
81
114
|
|
|
82
115
|
def extend(self, values):
|
|
83
116
|
"""
|
|
@@ -88,7 +121,12 @@ class Vec2Array:
|
|
|
88
121
|
"""
|
|
89
122
|
if not all(isinstance(v, Vec2) for v in values):
|
|
90
123
|
raise TypeError("All elements must be of type Vec2")
|
|
91
|
-
|
|
124
|
+
|
|
125
|
+
new_rows = np.array([[v.x, v.y] for v in values], dtype=np.float64)
|
|
126
|
+
if len(self._data) == 0:
|
|
127
|
+
self._data = new_rows
|
|
128
|
+
else:
|
|
129
|
+
self._data = np.vstack([self._data, new_rows])
|
|
92
130
|
|
|
93
131
|
def to_list(self):
|
|
94
132
|
"""
|
|
@@ -97,22 +135,35 @@ class Vec2Array:
|
|
|
97
135
|
Returns:
|
|
98
136
|
list: A list of x, y components concatenated.
|
|
99
137
|
"""
|
|
100
|
-
return
|
|
138
|
+
return self._data.flatten().tolist()
|
|
101
139
|
|
|
102
140
|
def to_numpy(self):
|
|
103
141
|
"""
|
|
104
142
|
Convert the array of Vec2 objects to a numpy array.
|
|
143
|
+
This is the primary method for GPU data transfer.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
numpy.ndarray: A float32 numpy array of shape (N*2,) for GPU transfer.
|
|
147
|
+
"""
|
|
148
|
+
return self._data.astype(np.float32).flatten()
|
|
149
|
+
|
|
150
|
+
def get_array(self):
|
|
151
|
+
"""
|
|
152
|
+
Get the underlying numpy array in shape (N, 2).
|
|
153
|
+
Useful for vectorized operations.
|
|
105
154
|
|
|
106
155
|
Returns:
|
|
107
|
-
numpy.ndarray:
|
|
156
|
+
numpy.ndarray: The internal float64 array of shape (N, 2).
|
|
108
157
|
"""
|
|
109
|
-
return
|
|
158
|
+
return self._data
|
|
110
159
|
|
|
111
160
|
def __repr__(self):
|
|
112
|
-
|
|
161
|
+
vec_list = [Vec2(row[0], row[1]) for row in self._data]
|
|
162
|
+
return f"Vec2Array({vec_list!r})"
|
|
113
163
|
|
|
114
164
|
def __str__(self):
|
|
115
|
-
|
|
165
|
+
vec_list = [Vec2(row[0], row[1]) for row in self._data]
|
|
166
|
+
return str(vec_list)
|
|
116
167
|
|
|
117
168
|
def sizeof(self):
|
|
118
169
|
"""
|