0
# Linear Geometry
1
2
Lines, line segments, and planes with comprehensive geometric operations including projections, intersections, and distance calculations. Supports both infinite geometric objects and bounded segments with best-fit operations for data analysis.
3
4
## Capabilities
5
6
### Line
7
8
Represents an infinite line in N-dimensional space defined by a point and direction vector. Provides comprehensive geometric operations including projections, intersections, and transformations.
9
10
```python { .api }
11
class Line:
12
"""
13
An infinite line in N-dimensional space.
14
15
Parameters:
16
- point: array-like, a point on the line
17
- direction: array-like, direction vector of the line
18
"""
19
def __init__(self, point, direction): ...
20
21
@classmethod
22
def from_points(cls, point_a, point_b) -> 'Line':
23
"""
24
Create line from two points.
25
26
Parameters:
27
- point_a: array-like, first point
28
- point_b: array-like, second point
29
30
Returns:
31
Line passing through both points
32
"""
33
34
@classmethod
35
def from_slope(cls, slope, y_intercept) -> 'Line':
36
"""
37
Create 2D line from slope and y-intercept.
38
39
Parameters:
40
- slope: float, slope of the line
41
- y_intercept: float, y-intercept value
42
43
Returns:
44
2D line with specified slope and intercept
45
"""
46
47
@classmethod
48
def best_fit(cls, points, tol=None, return_error=False, **kwargs) -> 'Line':
49
"""
50
Find line of best fit for points.
51
52
Parameters:
53
- points: array-like, points to fit line to
54
- tol: float, optional tolerance for singular value decomposition
55
- return_error: bool, if True return fit error
56
- **kwargs: additional keywords passed to numpy functions
57
58
Returns:
59
Best fit line, optionally with error value
60
"""
61
62
@property
63
def point(self) -> Point:
64
"""Point on the line."""
65
66
@property
67
def direction(self) -> Vector:
68
"""Direction vector of the line (same as vector)."""
69
70
@property
71
def vector(self) -> Vector:
72
"""Direction vector of the line (same as direction)."""
73
74
@property
75
def dimension(self) -> int:
76
"""Dimension of the line."""
77
78
def is_coplanar(self, other, **kwargs) -> bool:
79
"""
80
Check if coplanar with another line.
81
82
Parameters:
83
- other: Line, another line
84
- **kwargs: additional keywords passed to numpy functions
85
86
Returns:
87
True if lines are coplanar
88
"""
89
90
def to_point(self, t=1) -> Point:
91
"""
92
Get point along line using parameter t.
93
94
Parameters:
95
- t: float, parameter value (default: 1)
96
97
Returns:
98
Point at position: point + t * direction
99
"""
100
101
def project_point(self, point) -> Point:
102
"""
103
Project point onto line.
104
105
Parameters:
106
- point: array-like, point to project
107
108
Returns:
109
Projected point on the line
110
"""
111
112
def project_points(self, points) -> Points:
113
"""
114
Project multiple points onto line.
115
116
Parameters:
117
- points: array-like, points to project
118
119
Returns:
120
Projected points on the line
121
"""
122
123
def project_vector(self, vector) -> Vector:
124
"""
125
Project vector onto line.
126
127
Parameters:
128
- vector: array-like, vector to project
129
130
Returns:
131
Projected vector along line direction
132
"""
133
134
def side_point(self, point) -> int:
135
"""
136
Find side of line where point lies (2D only).
137
138
Parameters:
139
- point: array-like, 2D point
140
141
Returns:
142
1 if left side, -1 if right side, 0 if on line
143
"""
144
145
def distance_point(self, point) -> np.float64:
146
"""
147
Calculate distance from point to line.
148
149
Parameters:
150
- point: array-like, point
151
152
Returns:
153
Perpendicular distance to line
154
"""
155
156
def distance_points(self, points) -> np.ndarray:
157
"""
158
Calculate distances from points to line.
159
160
Parameters:
161
- points: array-like, multiple points
162
163
Returns:
164
Array of distances to line
165
"""
166
167
def distance_line(self, other) -> np.float64:
168
"""
169
Calculate distance between lines.
170
171
Parameters:
172
- other: Line, another line
173
174
Returns:
175
Minimum distance between lines
176
"""
177
178
def intersect_line(self, other, check_coplanar=True, **kwargs) -> Point:
179
"""
180
Find intersection with another line.
181
182
Parameters:
183
- other: Line, another line
184
- check_coplanar: bool, check if lines are coplanar (default: True)
185
- **kwargs: additional keywords passed to numpy functions
186
187
Returns:
188
Intersection point
189
190
Raises:
191
ValueError if lines are parallel or skew
192
"""
193
194
def transform_points(self, points) -> np.ndarray:
195
"""
196
Transform points to 1D coordinates along line.
197
198
Parameters:
199
- points: array-like, points to transform
200
201
Returns:
202
1D coordinate array along line
203
"""
204
205
def contains_point(self, point, **kwargs) -> bool:
206
"""
207
Check if line contains point.
208
209
Parameters:
210
- point: array-like, point to check
211
- **kwargs: additional keywords passed to math.isclose
212
213
Returns:
214
True if point lies on line
215
"""
216
217
def is_close(self, other, **kwargs) -> bool:
218
"""
219
Check if close to another line.
220
221
Parameters:
222
- other: Line, another line
223
- **kwargs: additional keywords passed to numpy.allclose
224
225
Returns:
226
True if lines are close
227
"""
228
229
def sum_squares(self, points) -> np.float64:
230
"""
231
Calculate sum of squared distances from points.
232
233
Parameters:
234
- points: array-like, points
235
236
Returns:
237
Sum of squared distances
238
"""
239
240
def plot_2d(self, ax_2d, t_1=0, t_2=1, **kwargs):
241
"""
242
Plot 2D line segment.
243
244
Parameters:
245
- ax_2d: matplotlib Axes, 2D plotting axes
246
- t_1: float, start parameter (default: 0)
247
- t_2: float, end parameter (default: 1)
248
- **kwargs: additional keywords passed to plot
249
"""
250
251
def plot_3d(self, ax_3d, t_1=0, t_2=1, **kwargs):
252
"""
253
Plot 3D line segment.
254
255
Parameters:
256
- ax_3d: matplotlib Axes3D, 3D plotting axes
257
- t_1: float, start parameter (default: 0)
258
- t_2: float, end parameter (default: 1)
259
- **kwargs: additional keywords passed to plot
260
"""
261
```
262
263
**Usage Example:**
264
```python
265
from skspatial.objects import Line, Point
266
267
# Create line from point and direction
268
line = Line(point=[0, 0, 0], direction=[1, 1, 0])
269
270
# Create line from two points
271
line2 = Line.from_points([1, 2, 3], [4, 5, 6])
272
273
# Create 2D line from slope
274
line_2d = Line.from_slope(slope=2, y_intercept=1)
275
276
# Project point onto line
277
point = Point([5, 6, 7])
278
projected = line.project_point(point)
279
280
# Find intersection
281
intersection = line.intersect_line(line2)
282
283
# Line of best fit
284
import numpy as np
285
points = np.random.randn(20, 3)
286
best_fit_line = Line.best_fit(points)
287
```
288
289
### Plane
290
291
Represents an infinite plane in N-dimensional space defined by a point and normal vector. Provides comprehensive operations for projections, intersections, and geometric analysis.
292
293
```python { .api }
294
class Plane:
295
"""
296
An infinite plane in N-dimensional space.
297
298
Parameters:
299
- point: array-like, a point on the plane
300
- normal: array-like, normal vector to the plane
301
"""
302
def __init__(self, point, normal): ...
303
304
@classmethod
305
def from_vectors(cls, point, vector_a, vector_b, **kwargs) -> 'Plane':
306
"""
307
Create plane from point and two vectors.
308
309
Parameters:
310
- point: array-like, point on the plane
311
- vector_a: array-like, first vector in plane
312
- vector_b: array-like, second vector in plane
313
- **kwargs: additional keywords passed to numpy functions
314
315
Returns:
316
Plane defined by point and span of vectors
317
"""
318
319
@classmethod
320
def from_points(cls, point_a, point_b, point_c, **kwargs) -> 'Plane':
321
"""
322
Create plane from three points.
323
324
Parameters:
325
- point_a: array-like, first point
326
- point_b: array-like, second point
327
- point_c: array-like, third point
328
- **kwargs: additional keywords passed to numpy functions
329
330
Returns:
331
Plane passing through all three points
332
"""
333
334
@classmethod
335
def best_fit(cls, points, tol=None, return_error=False, **kwargs) -> 'Plane':
336
"""
337
Find plane of best fit for points.
338
339
Parameters:
340
- points: array-like, points to fit plane to
341
- tol: float, optional tolerance for singular value decomposition
342
- return_error: bool, if True return fit error
343
- **kwargs: additional keywords passed to numpy functions
344
345
Returns:
346
Best fit plane, optionally with error value
347
"""
348
349
@property
350
def point(self) -> Point:
351
"""Point on the plane."""
352
353
@property
354
def normal(self) -> Vector:
355
"""Normal vector to the plane (same as vector)."""
356
357
@property
358
def vector(self) -> Vector:
359
"""Normal vector to the plane (same as normal)."""
360
361
@property
362
def dimension(self) -> int:
363
"""Dimension of the plane."""
364
365
def cartesian(self) -> Tuple[np.float64, np.float64, np.float64, np.float64]:
366
"""
367
Return Cartesian equation coefficients.
368
369
Returns:
370
Tuple (a, b, c, d) for equation ax + by + cz = d
371
"""
372
373
def project_point(self, point) -> Point:
374
"""
375
Project point onto plane.
376
377
Parameters:
378
- point: array-like, point to project
379
380
Returns:
381
Projected point on the plane
382
"""
383
384
def project_points(self, points) -> Points:
385
"""
386
Project multiple points onto plane.
387
388
Parameters:
389
- points: array-like, points to project
390
391
Returns:
392
Projected points on the plane
393
"""
394
395
def project_vector(self, vector) -> Vector:
396
"""
397
Project vector onto plane.
398
399
Parameters:
400
- vector: array-like, vector to project
401
402
Returns:
403
Projected vector in the plane
404
"""
405
406
def project_line(self, line, **kwargs) -> Line:
407
"""
408
Project line onto plane.
409
410
Parameters:
411
- line: Line, line to project
412
- **kwargs: additional keywords passed to numpy functions
413
414
Returns:
415
Projected line in the plane
416
"""
417
418
def distance_point_signed(self, point) -> np.float64:
419
"""
420
Calculate signed distance from point to plane.
421
422
Parameters:
423
- point: array-like, point
424
425
Returns:
426
Signed distance (positive on normal side)
427
"""
428
429
def distance_points_signed(self, points) -> np.ndarray:
430
"""
431
Calculate signed distances from points to plane.
432
433
Parameters:
434
- points: array-like, multiple points
435
436
Returns:
437
Array of signed distances
438
"""
439
440
def distance_point(self, point) -> np.float64:
441
"""
442
Calculate absolute distance from point to plane.
443
444
Parameters:
445
- point: array-like, point
446
447
Returns:
448
Absolute distance to plane
449
"""
450
451
def distance_points(self, points) -> np.ndarray:
452
"""
453
Calculate absolute distances from points to plane.
454
455
Parameters:
456
- points: array-like, multiple points
457
458
Returns:
459
Array of absolute distances
460
"""
461
462
def side_point(self, point) -> int:
463
"""
464
Find side of plane where point lies.
465
466
Parameters:
467
- point: array-like, point
468
469
Returns:
470
1 if on normal side, -1 if opposite, 0 if on plane
471
"""
472
473
def intersect_line(self, line, **kwargs) -> Point:
474
"""
475
Find intersection with line.
476
477
Parameters:
478
- line: Line, line to intersect
479
- **kwargs: additional keywords passed to numpy functions
480
481
Returns:
482
Intersection point
483
484
Raises:
485
ValueError if line is parallel to plane
486
"""
487
488
def intersect_plane(self, other, **kwargs) -> Line:
489
"""
490
Find intersection with another plane.
491
492
Parameters:
493
- other: Plane, another plane
494
- **kwargs: additional keywords passed to numpy functions
495
496
Returns:
497
Intersection line
498
499
Raises:
500
ValueError if planes are parallel
501
"""
502
503
def to_mesh(self, lims_x=(-1, 1), lims_y=(-1, 1)):
504
"""
505
Generate mesh coordinates for plotting.
506
507
Parameters:
508
- lims_x: tuple, x-axis limits (default: (-1, 1))
509
- lims_y: tuple, y-axis limits (default: (-1, 1))
510
511
Returns:
512
X, Y, Z mesh arrays for plotting
513
"""
514
515
def to_points(self, **kwargs) -> Points:
516
"""
517
Return points on the plane surface.
518
519
Parameters:
520
- **kwargs: additional keywords for mesh generation
521
522
Returns:
523
Points sampled on plane surface
524
"""
525
526
def contains_point(self, point, **kwargs) -> bool:
527
"""
528
Check if plane contains point.
529
530
Parameters:
531
- point: array-like, point to check
532
- **kwargs: additional keywords passed to math.isclose
533
534
Returns:
535
True if point lies on plane
536
"""
537
538
def plot_3d(self, ax_3d, lims_x=(-1, 1), lims_y=(-1, 1), **kwargs):
539
"""
540
Plot 3D plane surface.
541
542
Parameters:
543
- ax_3d: matplotlib Axes3D, 3D plotting axes
544
- lims_x: tuple, x-axis limits (default: (-1, 1))
545
- lims_y: tuple, y-axis limits (default: (-1, 1))
546
- **kwargs: additional keywords passed to plot_surface
547
"""
548
```
549
550
**Usage Example:**
551
```python
552
from skspatial.objects import Plane, Line, Point
553
554
# Create plane from point and normal
555
plane = Plane(point=[0, 0, 0], normal=[0, 0, 1])
556
557
# Create plane from three points
558
plane2 = Plane.from_points([0, 0, 0], [1, 0, 0], [0, 1, 0])
559
560
# Create plane from vectors
561
plane3 = Plane.from_vectors([0, 0, 0], [1, 0, 0], [0, 1, 0])
562
563
# Project point onto plane
564
point = Point([5, 6, 7])
565
projected = plane.project_point(point) # Point([5, 6, 0])
566
567
# Find intersection with line
568
line = Line([0, 0, -5], [0, 0, 1])
569
intersection = plane.intersect_line(line) # Point([0, 0, 0])
570
571
# Plane of best fit
572
import numpy as np
573
points = np.random.randn(50, 3)
574
best_fit_plane = Plane.best_fit(points)
575
```
576
577
### LineSegment
578
579
Represents a finite line segment between two endpoints. Provides intersection testing and visualization for bounded linear geometry.
580
581
```python { .api }
582
class LineSegment:
583
"""
584
A finite line segment between two points.
585
586
Parameters:
587
- point_a: array-like, first endpoint
588
- point_b: array-like, second endpoint
589
"""
590
def __init__(self, point_a, point_b): ...
591
592
@property
593
def point_a(self) -> Point:
594
"""First endpoint of the segment."""
595
596
@property
597
def point_b(self) -> Point:
598
"""Second endpoint of the segment."""
599
600
def contains_point(self, point, **kwargs) -> bool:
601
"""
602
Check if point lies on the line segment.
603
604
Parameters:
605
- point: array-like, point to check
606
- **kwargs: additional keywords passed to math.isclose
607
608
Returns:
609
True if point is on the segment between endpoints
610
"""
611
612
def intersect_line_segment(self, other, **kwargs) -> Point:
613
"""
614
Find intersection with another line segment.
615
616
Parameters:
617
- other: LineSegment, another line segment
618
- **kwargs: additional keywords passed to numpy functions
619
620
Returns:
621
Intersection point
622
623
Raises:
624
ValueError if segments don't intersect
625
"""
626
627
def plot_2d(self, ax_2d, **kwargs):
628
"""
629
Plot 2D line segment.
630
631
Parameters:
632
- ax_2d: matplotlib Axes, 2D plotting axes
633
- **kwargs: additional keywords passed to plot
634
"""
635
636
def plot_3d(self, ax_3d, **kwargs):
637
"""
638
Plot 3D line segment.
639
640
Parameters:
641
- ax_3d: matplotlib Axes3D, 3D plotting axes
642
- **kwargs: additional keywords passed to plot
643
"""
644
```
645
646
**Usage Example:**
647
```python
648
from skspatial.objects import LineSegment, Point
649
650
# Create line segment
651
segment = LineSegment([0, 0], [3, 4])
652
653
# Check if point is on segment
654
point = Point([1.5, 2])
655
on_segment = segment.contains_point(point) # True
656
657
# Find intersection with another segment
658
segment2 = LineSegment([0, 3], [3, 0])
659
intersection = segment.intersect_line_segment(segment2)
660
```