0
# Basic Spatial Objects
1
2
Fundamental building blocks including points, vectors, and collections of points. These objects form the foundation of all geometric computations and inherit full NumPy array functionality, making them subclasses of `numpy.ndarray`.
3
4
## Capabilities
5
6
### Point
7
8
Represents a single point in N-dimensional space. Points support distance calculations and visualization while inheriting all NumPy array operations.
9
10
```python { .api }
11
class Point(np.ndarray):
12
"""
13
A point in N-dimensional space.
14
15
Parameters:
16
- array: array-like, coordinates of the point
17
"""
18
def __init__(self, array): ...
19
20
@property
21
def dimension(self) -> int:
22
"""Return the dimension of the point."""
23
24
def distance_point(self, other) -> np.float64:
25
"""
26
Calculate Euclidean distance to another point.
27
28
Parameters:
29
- other: array-like, another point
30
31
Returns:
32
Euclidean distance between points
33
"""
34
35
def set_dimension(self, dim) -> 'Point':
36
"""
37
Set dimension by padding with zeros if needed.
38
39
Parameters:
40
- dim: int, target dimension
41
42
Returns:
43
Point with specified dimension
44
"""
45
46
def plot_2d(self, ax_2d, **kwargs):
47
"""
48
Plot point in 2D.
49
50
Parameters:
51
- ax_2d: matplotlib Axes, 2D plotting axes
52
- **kwargs: additional keywords passed to scatter
53
"""
54
55
def plot_3d(self, ax_3d, **kwargs):
56
"""
57
Plot point in 3D.
58
59
Parameters:
60
- ax_3d: matplotlib Axes3D, 3D plotting axes
61
- **kwargs: additional keywords passed to scatter
62
"""
63
64
def plotter(self, **kwargs):
65
"""Return plotting function for matplotlib integration."""
66
67
def to_array(self) -> np.ndarray:
68
"""Convert to regular numpy array."""
69
70
def is_close(self, other, **kwargs) -> bool:
71
"""Check if arrays are close using numpy.allclose."""
72
73
def is_equal(self, other) -> bool:
74
"""Check if arrays are exactly equal."""
75
76
def round(self, decimals=0):
77
"""Round array values to given precision."""
78
```
79
80
**Usage Example:**
81
```python
82
from skspatial.objects import Point
83
84
# Create points from lists or arrays
85
p1 = Point([1, 2, 3])
86
p2 = Point([4, 5, 6])
87
88
# Use NumPy functionality
89
print(p1.size) # 3
90
print(p1.mean()) # 2.0
91
92
# Use spatial methods
93
distance = p1.distance_point(p2)
94
print(distance) # 5.196152422706632
95
96
# Set dimension
97
p1_2d = p1.set_dimension(2) # Point([1, 2])
98
```
99
100
### Vector
101
102
Represents a vector in N-dimensional space with specialized vector operations including cross products, dot products, angles, and projections.
103
104
```python { .api }
105
class Vector(np.ndarray):
106
"""
107
A vector in N-dimensional space.
108
109
Parameters:
110
- array: array-like, components of the vector
111
"""
112
def __init__(self, array): ...
113
114
@classmethod
115
def from_points(cls, point_a, point_b) -> 'Vector':
116
"""
117
Create vector from two points.
118
119
Parameters:
120
- point_a: array-like, start point
121
- point_b: array-like, end point
122
123
Returns:
124
Vector from point_a to point_b
125
"""
126
127
@property
128
def dimension(self) -> int:
129
"""Return the dimension of the vector."""
130
131
def norm(self, **kwargs) -> np.float64:
132
"""
133
Return the norm (magnitude) of the vector.
134
135
Parameters:
136
- **kwargs: additional keywords passed to numpy.linalg.norm
137
138
Returns:
139
Norm of the vector
140
"""
141
142
def unit(self) -> 'Vector':
143
"""
144
Return the unit vector in the same direction.
145
146
Returns:
147
Unit vector with magnitude 1
148
"""
149
150
def is_zero(self, **kwargs) -> bool:
151
"""
152
Check if vector is zero vector.
153
154
Parameters:
155
- **kwargs: additional keywords passed to math.isclose
156
157
Returns:
158
True if vector is close to zero
159
"""
160
161
def cross(self, other) -> 'Vector':
162
"""
163
Compute cross product with another vector.
164
165
Parameters:
166
- other: array-like, another vector
167
168
Returns:
169
Cross product vector
170
"""
171
172
def cosine_similarity(self, other) -> np.float64:
173
"""
174
Compute cosine similarity with another vector.
175
176
Parameters:
177
- other: array-like, another vector
178
179
Returns:
180
Cosine similarity (-1 to 1)
181
"""
182
183
def angle_between(self, other) -> float:
184
"""
185
Compute angle between vectors in radians.
186
187
Parameters:
188
- other: array-like, another vector
189
190
Returns:
191
Angle in radians (0 to π)
192
"""
193
194
def angle_signed(self, other) -> float:
195
"""
196
Compute signed angle for 2D vectors.
197
198
Parameters:
199
- other: array-like, another 2D vector
200
201
Returns:
202
Signed angle in radians (-π to π)
203
"""
204
205
def is_perpendicular(self, other, **kwargs) -> bool:
206
"""
207
Check if perpendicular to another vector.
208
209
Parameters:
210
- other: array-like, another vector
211
- **kwargs: additional keywords passed to math.isclose
212
213
Returns:
214
True if vectors are perpendicular
215
"""
216
217
def is_parallel(self, other, **kwargs) -> bool:
218
"""
219
Check if parallel to another vector.
220
221
Parameters:
222
- other: array-like, another vector
223
- **kwargs: additional keywords passed to math.isclose
224
225
Returns:
226
True if vectors are parallel
227
"""
228
229
def scalar_projection(self, other) -> np.float64:
230
"""
231
Compute scalar projection onto another vector.
232
233
Parameters:
234
- other: array-like, vector to project onto
235
236
Returns:
237
Scalar projection value
238
"""
239
240
def project_vector(self, other) -> 'Vector':
241
"""
242
Compute vector projection onto another vector.
243
244
Parameters:
245
- other: array-like, vector to project onto
246
247
Returns:
248
Projected vector
249
"""
250
251
def plot_2d(self, ax_2d, point=(0, 0), scalar=1, **kwargs):
252
"""
253
Plot vector in 2D starting from a point.
254
255
Parameters:
256
- ax_2d: matplotlib Axes, 2D plotting axes
257
- point: array-like, starting point (default: origin)
258
- scalar: float, scaling factor (default: 1)
259
- **kwargs: additional keywords passed to plot
260
"""
261
262
def plot_3d(self, ax_3d, point=(0, 0, 0), scalar=1, **kwargs):
263
"""
264
Plot vector in 3D starting from a point.
265
266
Parameters:
267
- ax_3d: matplotlib Axes3D, 3D plotting axes
268
- point: array-like, starting point (default: origin)
269
- scalar: float, scaling factor (default: 1)
270
- **kwargs: additional keywords passed to plot
271
"""
272
273
def side_vector(self, other) -> int:
274
"""
275
Find side of vector where another vector lies (2D only).
276
277
Parameters:
278
- other: array-like, another 2D vector
279
280
Returns:
281
1 if other is to the left, -1 if to the right, 0 if collinear
282
"""
283
284
def angle_signed_3d(self, other, direction_positive) -> float:
285
"""
286
Compute signed angle between 3D vectors using reference direction.
287
288
Parameters:
289
- other: array-like, another 3D vector
290
- direction_positive: array-like, reference direction for positive angles
291
292
Returns:
293
Signed angle in radians (-π to π)
294
"""
295
296
def different_direction(self, **kwargs) -> 'Vector':
297
"""
298
Return a simple vector in different direction.
299
300
Useful for finding perpendicular vectors or generating test vectors.
301
302
Parameters:
303
- **kwargs: additional keywords passed to numpy functions
304
305
Returns:
306
Vector in a different direction from the current vector
307
"""
308
309
def side_vector(self, other) -> int:
310
"""
311
Find which side of this vector another vector is on (2D only).
312
313
Parameters:
314
- other: array-like, another 2D vector
315
316
Returns:
317
-1, 0, or 1 indicating left side, on line, or right side
318
"""
319
320
def angle_signed_3d(self, other, direction_positive) -> float:
321
"""
322
Compute signed angle between 3D vectors using a positive direction.
323
324
Parameters:
325
- other: array-like, another 3D vector
326
- direction_positive: array-like, vector defining positive rotation direction
327
328
Returns:
329
Signed angle in radians
330
"""
331
332
def set_dimension(self, dim) -> 'Vector':
333
"""
334
Set dimension by padding with zeros if needed.
335
336
Parameters:
337
- dim: int, target dimension
338
339
Returns:
340
Vector with specified dimension
341
"""
342
343
def to_array(self) -> np.ndarray:
344
"""Convert to regular numpy array."""
345
346
def is_close(self, other, **kwargs) -> bool:
347
"""Check if arrays are close using numpy.allclose."""
348
349
def is_equal(self, other) -> bool:
350
"""Check if arrays are exactly equal."""
351
352
def round(self, decimals=0):
353
"""Round array values to given precision."""
354
355
def plotter(self, **kwargs):
356
"""Return plotting function for matplotlib integration."""
357
```
358
359
**Usage Example:**
360
```python
361
from skspatial.objects import Vector, Point
362
363
# Create vectors
364
v1 = Vector([1, 0, 0])
365
v2 = Vector([0, 1, 0])
366
367
# Create from points
368
v3 = Vector.from_points([0, 0, 0], [3, 4, 0])
369
370
# Vector operations
371
magnitude = v3.norm() # 5.0
372
unit_v3 = v3.unit() # Vector([0.6, 0.8, 0.0])
373
374
# Cross product
375
cross = v1.cross(v2) # Vector([0, 0, 1])
376
377
# Angle between vectors
378
angle = v1.angle_between(v2) # π/2 radians (90 degrees)
379
380
# Check relationships
381
is_perp = v1.is_perpendicular(v2) # True
382
is_par = v1.is_parallel(v2) # False
383
384
# 2D-specific methods
385
v2d_1 = Vector([1, 0])
386
v2d_2 = Vector([0, 1])
387
side = v2d_1.side_vector(v2d_2) # 1 (left side)
388
389
# 3D signed angle with reference direction
390
v3d_1 = Vector([1, 0, 0])
391
v3d_2 = Vector([0, 1, 0])
392
ref_dir = Vector([0, 0, 1])
393
signed_angle_3d = v3d_1.angle_signed_3d(v3d_2, ref_dir) # π/2 radians
394
395
# Generate different direction vector
396
diff_v = v1.different_direction() # Vector in different direction
397
```
398
399
### Points
400
401
Represents a collection of N points in D-dimensional space as an (N×D) array. Provides methods for analyzing point sets including centroids, collinearity, and coplanarity tests.
402
403
```python { .api }
404
class Points(np.ndarray):
405
"""
406
A collection of points in N-dimensional space.
407
408
Parameters:
409
- points: array-like, (N, D) array of N points with dimension D
410
"""
411
def __init__(self, points): ...
412
413
@property
414
def dimension(self) -> int:
415
"""Return the dimension of the points."""
416
417
def unique(self) -> 'Points':
418
"""
419
Return unique points.
420
421
Returns:
422
Points with duplicates removed
423
"""
424
425
def centroid(self) -> Point:
426
"""
427
Return the centroid of all points.
428
429
Returns:
430
Point representing the centroid
431
"""
432
433
def mean_center(self, return_centroid=False):
434
"""
435
Mean-center points around origin.
436
437
Parameters:
438
- return_centroid: bool, if True return centroid used
439
440
Returns:
441
Mean-centered points, optionally with centroid
442
"""
443
444
def normalize_distance(self) -> 'Points':
445
"""
446
Normalize distances from origin.
447
448
Returns:
449
Points with normalized distances
450
"""
451
452
def affine_rank(self, **kwargs) -> np.int64:
453
"""
454
Return the affine rank of points.
455
456
Parameters:
457
- **kwargs: additional keywords passed to numpy.linalg.matrix_rank
458
459
Returns:
460
Affine rank of the point set
461
"""
462
463
def are_concurrent(self, **kwargs) -> bool:
464
"""
465
Check if all points are the same.
466
467
Parameters:
468
- **kwargs: additional keywords passed to numpy.allclose
469
470
Returns:
471
True if all points are concurrent
472
"""
473
474
def are_collinear(self, **kwargs) -> bool:
475
"""
476
Check if points are collinear.
477
478
Parameters:
479
- **kwargs: additional keywords passed to numpy.linalg.matrix_rank
480
481
Returns:
482
True if points lie on a line
483
"""
484
485
def are_coplanar(self, **kwargs) -> bool:
486
"""
487
Check if points are coplanar.
488
489
Parameters:
490
- **kwargs: additional keywords passed to numpy.linalg.matrix_rank
491
492
Returns:
493
True if points lie on a plane
494
"""
495
496
def set_dimension(self, dim) -> 'Points':
497
"""
498
Set dimension by padding with zeros if needed.
499
500
Parameters:
501
- dim: int, target dimension
502
503
Returns:
504
Points with specified dimension
505
"""
506
507
def plot_2d(self, ax_2d, **kwargs):
508
"""
509
Plot points in 2D.
510
511
Parameters:
512
- ax_2d: matplotlib Axes, 2D plotting axes
513
- **kwargs: additional keywords passed to scatter
514
"""
515
516
def plot_3d(self, ax_3d, **kwargs):
517
"""
518
Plot points in 3D.
519
520
Parameters:
521
- ax_3d: matplotlib Axes3D, 3D plotting axes
522
- **kwargs: additional keywords passed to scatter
523
"""
524
525
def to_array(self) -> np.ndarray:
526
"""Convert to regular numpy array."""
527
528
def is_close(self, other, **kwargs) -> bool:
529
"""Check if arrays are close using numpy.allclose."""
530
531
def is_equal(self, other) -> bool:
532
"""Check if arrays are exactly equal."""
533
534
def round(self, decimals=0):
535
"""Round array values to given precision."""
536
537
def plotter(self, **kwargs):
538
"""Return plotting function for matplotlib integration."""
539
```
540
541
**Usage Example:**
542
```python
543
from skspatial.objects import Points
544
545
# Create collection of points
546
points = Points([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
547
548
# Analyze point set
549
centroid = points.centroid() # Point([4, 5, 6])
550
are_collinear = points.are_collinear() # True
551
552
# Working with 2D points
553
points_2d = Points([[0, 0], [1, 1], [2, 2], [3, 4]])
554
are_collinear_2d = points_2d.are_collinear() # False
555
556
# Check coplanarity for 3D points
557
points_3d = Points([[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]])
558
are_coplanar = points_3d.are_coplanar() # True
559
```