0
# Curved Geometry
1
2
Circles, spheres, and cylinders with specialized methods for curved surface computations, intersections, volume calculations, and fitting operations for point clouds.
3
4
## Capabilities
5
6
### Circle
7
8
Represents a circle in 2D space with center point and radius. Provides area calculations, intersections, and fitting capabilities.
9
10
```python { .api }
11
class Circle:
12
"""
13
A circle in 2D space.
14
15
Parameters:
16
- point: array-like, center point (2D)
17
- radius: float, radius of the circle
18
"""
19
def __init__(self, point, radius): ...
20
21
@classmethod
22
def from_points(cls, point_a, point_b, point_c, **kwargs) -> 'Circle':
23
"""
24
Create circle from three points.
25
26
Parameters:
27
- point_a: array-like, first point (2D)
28
- point_b: array-like, second point (2D)
29
- point_c: array-like, third point (2D)
30
- **kwargs: additional keywords passed to numpy functions
31
32
Returns:
33
Circle passing through all three points
34
"""
35
36
@classmethod
37
def best_fit(cls, points) -> 'Circle':
38
"""
39
Find circle of best fit for 2D points.
40
41
Parameters:
42
- points: array-like, 2D points to fit circle to
43
44
Returns:
45
Best fit circle
46
"""
47
48
@property
49
def point(self) -> Point:
50
"""Center point of the circle (2D)."""
51
52
@property
53
def radius(self) -> float:
54
"""Radius of the circle."""
55
56
@property
57
def dimension(self) -> int:
58
"""Dimension of the circle (always 2)."""
59
60
def circumference(self) -> float:
61
"""
62
Calculate circumference of the circle.
63
64
Returns:
65
Circumference (2πr)
66
"""
67
68
def area(self) -> float:
69
"""
70
Calculate area of the circle.
71
72
Returns:
73
Area (πr²)
74
"""
75
76
def intersect_circle(self, other) -> Tuple[Point, Point]:
77
"""
78
Find intersection points with another circle.
79
80
Parameters:
81
- other: Circle, another circle
82
83
Returns:
84
Tuple of two intersection points
85
86
Raises:
87
ValueError if circles don't intersect
88
"""
89
90
def intersect_line(self, line) -> Tuple[Point, Point]:
91
"""
92
Find intersection points with a line.
93
94
Parameters:
95
- line: Line, line to intersect
96
97
Returns:
98
Tuple of intersection points
99
100
Raises:
101
ValueError if line doesn't intersect circle
102
"""
103
104
def distance_point(self, point) -> np.float64:
105
"""
106
Calculate distance from point to circle edge.
107
108
Parameters:
109
- point: array-like, point
110
111
Returns:
112
Distance to closest point on circle circumference
113
"""
114
115
def contains_point(self, point, **kwargs) -> bool:
116
"""
117
Check if circle contains point.
118
119
Parameters:
120
- point: array-like, point to check
121
- **kwargs: additional keywords passed to math.isclose
122
123
Returns:
124
True if point is on circle circumference
125
"""
126
127
def project_point(self, point) -> Point:
128
"""
129
Project point onto circle circumference.
130
131
Parameters:
132
- point: array-like, point to project
133
134
Returns:
135
Closest point on circle circumference
136
"""
137
138
def plot_2d(self, ax_2d, **kwargs):
139
"""
140
Plot 2D circle.
141
142
Parameters:
143
- ax_2d: matplotlib Axes, 2D plotting axes
144
- **kwargs: additional keywords passed to plotting functions
145
"""
146
```
147
148
**Usage Example:**
149
```python
150
from skspatial.objects import Circle, Line, Point
151
152
# Create circle from center and radius
153
circle = Circle([0, 0], radius=5)
154
155
# Create circle from three points
156
circle2 = Circle.from_points([0, 0], [1, 0], [0, 1])
157
158
# Calculate properties
159
area = circle.area() # 25π
160
circumference = circle.circumference() # 10π
161
162
# Find intersections
163
line = Line([0, -10], [0, 1])
164
intersections = circle.intersect_line(line) # Two points where line crosses circle
165
166
# Circle of best fit
167
import numpy as np
168
points_2d = np.random.randn(20, 2) * 3 + [2, 3] # Noisy circle data
169
best_fit_circle = Circle.best_fit(points_2d)
170
```
171
172
### Sphere
173
174
Represents a sphere in 3D space with center point and radius. Provides volume calculations, surface area, intersections, and mesh generation.
175
176
```python { .api }
177
class Sphere:
178
"""
179
A sphere in 3D space.
180
181
Parameters:
182
- point: array-like, center point (3D)
183
- radius: float, radius of the sphere
184
"""
185
def __init__(self, point, radius): ...
186
187
@classmethod
188
def best_fit(cls, points) -> 'Sphere':
189
"""
190
Find sphere of best fit for 3D points.
191
192
Parameters:
193
- points: array-like, 3D points to fit sphere to
194
195
Returns:
196
Best fit sphere
197
"""
198
199
@property
200
def point(self) -> Point:
201
"""Center point of the sphere (3D)."""
202
203
@property
204
def radius(self) -> float:
205
"""Radius of the sphere."""
206
207
@property
208
def dimension(self) -> int:
209
"""Dimension of the sphere (always 3)."""
210
211
def surface_area(self) -> float:
212
"""
213
Calculate surface area of the sphere.
214
215
Returns:
216
Surface area (4πr²)
217
"""
218
219
def volume(self) -> float:
220
"""
221
Calculate volume of the sphere.
222
223
Returns:
224
Volume (4/3 πr³)
225
"""
226
227
def intersect_line(self, line) -> Tuple[Point, Point]:
228
"""
229
Find intersection points with a line.
230
231
Parameters:
232
- line: Line, line to intersect
233
234
Returns:
235
Tuple of intersection points
236
237
Raises:
238
ValueError if line doesn't intersect sphere
239
"""
240
241
def to_mesh(self, n_angles=30):
242
"""
243
Generate mesh coordinates for plotting.
244
245
Parameters:
246
- n_angles: int, number of angles for discretization (default: 30)
247
248
Returns:
249
X, Y, Z mesh arrays for plotting
250
"""
251
252
def to_points(self, **kwargs) -> Points:
253
"""
254
Return points on the sphere surface.
255
256
Parameters:
257
- **kwargs: additional keywords for mesh generation
258
259
Returns:
260
Points sampled on sphere surface
261
"""
262
263
def distance_point(self, point) -> np.float64:
264
"""
265
Calculate distance from point to sphere surface.
266
267
Parameters:
268
- point: array-like, point
269
270
Returns:
271
Distance to closest point on sphere surface
272
"""
273
274
def contains_point(self, point, **kwargs) -> bool:
275
"""
276
Check if sphere contains point.
277
278
Parameters:
279
- point: array-like, point to check
280
- **kwargs: additional keywords passed to math.isclose
281
282
Returns:
283
True if point is on sphere surface
284
"""
285
286
def project_point(self, point) -> Point:
287
"""
288
Project point onto sphere surface.
289
290
Parameters:
291
- point: array-like, point to project
292
293
Returns:
294
Closest point on sphere surface
295
"""
296
297
def plot_3d(self, ax_3d, n_angles=30, **kwargs):
298
"""
299
Plot 3D sphere surface.
300
301
Parameters:
302
- ax_3d: matplotlib Axes3D, 3D plotting axes
303
- n_angles: int, number of angles for discretization (default: 30)
304
- **kwargs: additional keywords passed to plot_surface
305
"""
306
```
307
308
**Usage Example:**
309
```python
310
from skspatial.objects import Sphere, Line, Point
311
312
# Create sphere from center and radius
313
sphere = Sphere([0, 0, 0], radius=3)
314
315
# Calculate properties
316
volume = sphere.volume() # 36π
317
surface_area = sphere.surface_area() # 36π
318
319
# Find intersections with line
320
line = Line([0, 0, -5], [0, 0, 1])
321
intersections = sphere.intersect_line(line) # Entry and exit points
322
323
# Sphere of best fit
324
import numpy as np
325
# Generate noisy sphere data
326
theta = np.random.uniform(0, 2*np.pi, 100)
327
phi = np.random.uniform(0, np.pi, 100)
328
points_3d = np.column_stack([
329
3 * np.sin(phi) * np.cos(theta),
330
3 * np.sin(phi) * np.sin(theta),
331
3 * np.cos(phi)
332
]) + np.random.normal(0, 0.1, (100, 3))
333
best_fit_sphere = Sphere.best_fit(points_3d)
334
```
335
336
### Cylinder
337
338
Represents a cylinder in 3D space defined by base center, axis vector, and radius. Provides volume calculations, surface areas, and intersection operations.
339
340
```python { .api }
341
class Cylinder:
342
"""
343
A cylinder in 3D space.
344
345
Parameters:
346
- point: array-like, center of cylinder base (3D)
347
- vector: array-like, axis vector (3D)
348
- radius: float, radius of the cylinder
349
"""
350
def __init__(self, point, vector, radius): ...
351
352
@classmethod
353
def from_points(cls, point_a, point_b, radius) -> 'Cylinder':
354
"""
355
Create cylinder from two points and radius.
356
357
Parameters:
358
- point_a: array-like, first point on axis (3D)
359
- point_b: array-like, second point on axis (3D)
360
- radius: float, radius of the cylinder
361
362
Returns:
363
Cylinder with axis from point_a to point_b
364
"""
365
366
@classmethod
367
def best_fit(cls, points) -> 'Cylinder':
368
"""
369
Find cylinder of best fit for 3D points.
370
371
Parameters:
372
- points: array-like, 3D points to fit cylinder to
373
374
Returns:
375
Best fit cylinder
376
"""
377
378
@property
379
def point(self) -> Point:
380
"""Center of cylinder base (3D)."""
381
382
@property
383
def vector(self) -> Vector:
384
"""Axis vector of the cylinder (3D)."""
385
386
@property
387
def radius(self) -> float:
388
"""Radius of the cylinder."""
389
390
@property
391
def dimension(self) -> int:
392
"""Dimension of the cylinder (always 3)."""
393
394
def length(self) -> np.float64:
395
"""
396
Calculate length of the cylinder.
397
398
Returns:
399
Length along axis vector
400
"""
401
402
def lateral_surface_area(self) -> np.float64:
403
"""
404
Calculate lateral surface area of the cylinder.
405
406
Returns:
407
Lateral surface area (2πrh)
408
"""
409
410
def surface_area(self) -> np.float64:
411
"""
412
Calculate total surface area of the cylinder.
413
414
Returns:
415
Total surface area (2πr² + 2πrh)
416
"""
417
418
def volume(self) -> np.float64:
419
"""
420
Calculate volume of the cylinder.
421
422
Returns:
423
Volume (πr²h)
424
"""
425
426
def is_point_within(self, point) -> bool:
427
"""
428
Check if point is inside the cylinder.
429
430
Parameters:
431
- point: array-like, point to check (3D)
432
433
Returns:
434
True if point is within cylinder volume
435
"""
436
437
def intersect_line(self, line, n_digits=None, infinite=True):
438
"""
439
Find intersection points with a line.
440
441
Parameters:
442
- line: Line, line to intersect
443
- n_digits: int, optional precision for calculations
444
- infinite: bool, treat cylinder as infinite (default: True)
445
446
Returns:
447
Intersection points with cylinder surface
448
449
Raises:
450
ValueError if line doesn't intersect cylinder
451
"""
452
453
def to_mesh(self, n_along_axis=100, n_angles=30):
454
"""
455
Generate mesh coordinates for plotting.
456
457
Parameters:
458
- n_along_axis: int, points along axis (default: 100)
459
- n_angles: int, angular discretization (default: 30)
460
461
Returns:
462
X, Y, Z mesh arrays for plotting
463
"""
464
465
def to_points(self, **kwargs) -> Points:
466
"""
467
Return points on the cylinder surface.
468
469
Parameters:
470
- **kwargs: additional keywords for mesh generation
471
472
Returns:
473
Points sampled on cylinder surface
474
"""
475
476
def plot_3d(self, ax_3d, n_along_axis=100, n_angles=30, **kwargs):
477
"""
478
Plot 3D cylinder surface.
479
480
Parameters:
481
- ax_3d: matplotlib Axes3D, 3D plotting axes
482
- n_along_axis: int, points along axis (default: 100)
483
- n_angles: int, angular discretization (default: 30)
484
- **kwargs: additional keywords passed to plot_surface
485
"""
486
```
487
488
**Usage Example:**
489
```python
490
from skspatial.objects import Cylinder, Line, Point
491
492
# Create cylinder from base center, axis, and radius
493
cylinder = Cylinder([0, 0, 0], [0, 0, 5], radius=2)
494
495
# Create cylinder from two points
496
cylinder2 = Cylinder.from_points([0, 0, 0], [0, 0, 10], radius=1.5)
497
498
# Calculate properties
499
volume = cylinder.volume() # 20π
500
surface_area = cylinder.surface_area() # 28π
501
length = cylinder.length() # 5
502
503
# Check if point is inside
504
point = Point([1, 1, 2.5])
505
is_inside = cylinder.is_point_within(point) # True (within radius and height)
506
507
# Find intersections with line
508
line = Line([-3, 0, 2.5], [1, 0, 0]) # Horizontal line through cylinder
509
intersections = cylinder.intersect_line(line) # Entry and exit points
510
511
# Cylinder of best fit
512
import numpy as np
513
# Generate cylindrical point cloud
514
theta = np.random.uniform(0, 2*np.pi, 200)
515
z = np.random.uniform(0, 5, 200)
516
points_3d = np.column_stack([
517
2 * np.cos(theta) + np.random.normal(0, 0.1, 200),
518
2 * np.sin(theta) + np.random.normal(0, 0.1, 200),
519
z + np.random.normal(0, 0.1, 200)
520
])
521
best_fit_cylinder = Cylinder.best_fit(points_3d)
522
```