engeom 0.2.9__cp38-abi3-win_amd64.whl → 0.2.11__cp38-abi3-win_amd64.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.
- engeom/_plot/matplotlib.py +62 -15
- engeom/_plot/pyvista.py +26 -5
- engeom/engeom.pyd +0 -0
- engeom/geom2.pyi +40 -0
- engeom/geom3.pyi +385 -0
- engeom/sensor/__init__.py +6 -0
- engeom/sensor.pyi +58 -0
- {engeom-0.2.9.dist-info → engeom-0.2.11.dist-info}/METADATA +1 -1
- {engeom-0.2.9.dist-info → engeom-0.2.11.dist-info}/RECORD +10 -8
- {engeom-0.2.9.dist-info → engeom-0.2.11.dist-info}/WHEEL +0 -0
engeom/_plot/matplotlib.py
CHANGED
@@ -210,7 +210,7 @@ else:
|
|
210
210
|
|
211
211
|
value = distance.value * scale_value
|
212
212
|
box_style = dict(boxstyle="round,pad=0.3", ec="black", fc="white")
|
213
|
-
self.
|
213
|
+
self.text(template.format(value=value), label_coords, bbox=box_style, **kwargs)
|
214
214
|
|
215
215
|
def _line_if_needed(self, pad: float, actual: Point2, leader_end: Point2):
|
216
216
|
half_pad = pad * 0.5
|
@@ -221,31 +221,78 @@ else:
|
|
221
221
|
t1 = work.scalar_projection(leader_end) + half_pad
|
222
222
|
self.arrow(actual, work.at_distance(t1), arrow="-")
|
223
223
|
|
224
|
-
def
|
224
|
+
def text(self, text: str, pos: PlotCoords, shift: PlotCoords | None = None, ha: str = "center",
|
225
|
+
va: str = "center", **kwargs):
|
225
226
|
"""
|
226
|
-
Annotate a Matplotlib Axes object with text only.
|
227
|
+
Annotate a Matplotlib Axes object with text only, by default in the xy data plane.
|
227
228
|
:param text: the text to annotate
|
228
229
|
:param pos: the position of the annotation
|
230
|
+
:param shift: an optional shift vector to apply to the position
|
231
|
+
:param ha: horizontal alignment
|
232
|
+
:param va: vertical alignment
|
229
233
|
:param kwargs: keyword arguments to pass to the annotate function
|
230
234
|
:return: the annotation object
|
231
235
|
"""
|
232
|
-
|
236
|
+
xy = _tuplefy(pos)
|
237
|
+
if shift is not None:
|
238
|
+
shift = _tuplefy(shift)
|
239
|
+
xy = (xy[0] + shift[0], xy[1] + shift[1])
|
233
240
|
|
234
|
-
|
241
|
+
return self.ax.annotate(text, xy=xy, ha=ha, va=va, **kwargs)
|
242
|
+
|
243
|
+
def points(self, *points: PlotCoords, marker="o", markersize="5", **kwargs):
|
244
|
+
x, y = zip(*[_tuplefy(p) for p in points])
|
245
|
+
return self.ax.plot(x, y, marker, markersize=markersize, **kwargs)
|
246
|
+
|
247
|
+
def labeled_arrow(self, start: PlotCoords, end: PlotCoords, text: str, fraction: float = 0.5,
|
248
|
+
shift: PlotCoords | None = None,
|
249
|
+
arrow="->", color="black", linewidth: float | None = None, linestyle="-",
|
250
|
+
**text_kwargs):
|
235
251
|
"""
|
236
|
-
|
237
|
-
:param start:
|
238
|
-
:param end:
|
239
|
-
:param
|
240
|
-
:
|
252
|
+
|
253
|
+
:param start:
|
254
|
+
:param end:
|
255
|
+
:param text:
|
256
|
+
:param shift:
|
257
|
+
:param fraction:
|
258
|
+
:param arrow:
|
259
|
+
:param color:
|
260
|
+
:param linewidth:
|
261
|
+
:param linestyle:
|
262
|
+
:param text_kwargs: parameters to pass to the text function
|
263
|
+
:return:
|
264
|
+
"""
|
265
|
+
start = Point2(*_tuplefy(start))
|
266
|
+
end = Point2(*_tuplefy(end))
|
267
|
+
|
268
|
+
self.arrow(start, end, arrow=arrow, color=color, linewidth=linewidth, linestyle=linestyle)
|
269
|
+
|
270
|
+
v: Vector2 = end - start
|
271
|
+
position = start + v * fraction
|
272
|
+
self.text(text, position, shift=shift, color=color, **text_kwargs)
|
273
|
+
|
274
|
+
def arrow(self, start: PlotCoords, end: PlotCoords, arrow="->", color="black", linewidth: float | None = None,
|
275
|
+
linestyle="-"):
|
241
276
|
"""
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
277
|
+
Draw an arrow on a Matplotlib Axes object from `start` to `end`.
|
278
|
+
:param start:
|
279
|
+
:param end:
|
280
|
+
:param arrow:
|
281
|
+
:param color:
|
282
|
+
:param linewidth:
|
283
|
+
:param linestyle:
|
284
|
+
:return:
|
285
|
+
"""
|
286
|
+
props = dict(
|
287
|
+
arrowstyle=arrow,
|
288
|
+
fc=color,
|
289
|
+
ec=color,
|
290
|
+
linewidth=linewidth,
|
291
|
+
linestyle=linestyle,
|
247
292
|
)
|
248
293
|
|
294
|
+
return self.ax.annotate("", xy=_tuplefy(end), xytext=_tuplefy(start), arrowprops=props)
|
295
|
+
|
249
296
|
def _font_height(self, font_size: int) -> float:
|
250
297
|
# Get the height of a font in data units
|
251
298
|
fig_dpi = self.ax.figure.dpi
|
engeom/_plot/pyvista.py
CHANGED
@@ -40,6 +40,25 @@ else:
|
|
40
40
|
"""
|
41
41
|
self.plotter = plotter
|
42
42
|
|
43
|
+
def add_points(self, *points, color: pyvista.ColorLike = "b", point_size: float = 5.0,
|
44
|
+
render_points_as_spheres: bool = True, **kwargs) -> pyvista.vtkActor:
|
45
|
+
"""
|
46
|
+
Add one or more points to be plotted.
|
47
|
+
:param points: The points to add.
|
48
|
+
:param color: The color to use for the point(s).
|
49
|
+
:param point_size: The size of the point(s).
|
50
|
+
:param render_points_as_spheres: Whether to render the points as spheres or not.
|
51
|
+
:param kwargs: Additional keyword arguments to pass to the PyVista `Plotter.add_points` method.
|
52
|
+
:return: The PyVista actor that was added to the plotter.
|
53
|
+
"""
|
54
|
+
return self.plotter.add_points(
|
55
|
+
numpy.array([_tuplefy(p) for p in points], dtype=numpy.float64),
|
56
|
+
color=color,
|
57
|
+
point_size=point_size,
|
58
|
+
render_points_as_spheres=render_points_as_spheres,
|
59
|
+
**kwargs
|
60
|
+
)
|
61
|
+
|
43
62
|
def add_curves(
|
44
63
|
self,
|
45
64
|
*curves: Curve3,
|
@@ -204,12 +223,12 @@ else:
|
|
204
223
|
points = numpy.array([[0, 0, 0], [size, 0, 0], [0, size, 0], [0, 0, size]], dtype=numpy.float64)
|
205
224
|
points = iso.transform_points(points)
|
206
225
|
|
207
|
-
self.plotter.add_lines(points[[0, 1]], color="red", width=line_width)
|
208
|
-
|
209
|
-
|
226
|
+
actors = [self.plotter.add_lines(points[[0, 1]], color="red", width=line_width),
|
227
|
+
self.plotter.add_lines(points[[0, 2]], color="green", width=line_width),
|
228
|
+
self.plotter.add_lines(points[[0, 3]], color="blue", width=line_width)]
|
210
229
|
|
211
230
|
if label:
|
212
|
-
self.plotter.add_point_labels(
|
231
|
+
actors.append(self.plotter.add_point_labels(
|
213
232
|
[points[0]],
|
214
233
|
[label],
|
215
234
|
show_points=False,
|
@@ -217,7 +236,9 @@ else:
|
|
217
236
|
font_family="courier",
|
218
237
|
font_size=label_size,
|
219
238
|
bold=False,
|
220
|
-
)
|
239
|
+
))
|
240
|
+
|
241
|
+
return actors
|
221
242
|
|
222
243
|
def label(self, point: PlotCoords, text: str, **kwargs):
|
223
244
|
"""
|
engeom/engeom.pyd
CHANGED
Binary file
|
engeom/geom2.pyi
CHANGED
@@ -236,6 +236,13 @@ class Point2(Iterable[float]):
|
|
236
236
|
"""
|
237
237
|
...
|
238
238
|
|
239
|
+
@staticmethod
|
240
|
+
def mid(a: Point2, b: Point2) -> Point2:
|
241
|
+
"""
|
242
|
+
Return the midpoint between two points. This is the average of the x and y components of the two points.
|
243
|
+
"""
|
244
|
+
...
|
245
|
+
|
239
246
|
|
240
247
|
class SurfacePoint2:
|
241
248
|
"""
|
@@ -377,6 +384,23 @@ class SurfacePoint2:
|
|
377
384
|
"""
|
378
385
|
...
|
379
386
|
|
387
|
+
def offset(self, offset: Vector2) -> SurfacePoint2:
|
388
|
+
"""
|
389
|
+
Offset the surface point by a given vector. The normal vector is not affected.
|
390
|
+
:param offset: the vector to offset the surface point by.
|
391
|
+
:return: a new surface point with the position offset by the given vector.
|
392
|
+
"""
|
393
|
+
...
|
394
|
+
|
395
|
+
def shift(self, distance: float) -> SurfacePoint2:
|
396
|
+
"""
|
397
|
+
Shift the surface point by a given distance along the normal vector. The position of the surface point is
|
398
|
+
affected, but the normal vector is not.
|
399
|
+
:param distance: the distance to shift the surface point.
|
400
|
+
:return: a new surface point with the position shifted by the given distance.
|
401
|
+
"""
|
402
|
+
...
|
403
|
+
|
380
404
|
|
381
405
|
class Iso2:
|
382
406
|
"""
|
@@ -855,6 +879,14 @@ class Curve2:
|
|
855
879
|
"""
|
856
880
|
...
|
857
881
|
|
882
|
+
@property
|
883
|
+
def aabb(self) -> Aabb2:
|
884
|
+
"""
|
885
|
+
Get the axis-aligned bounding box of the curve.
|
886
|
+
:return: the axis-aligned bounding box of the curve.
|
887
|
+
"""
|
888
|
+
...
|
889
|
+
|
858
890
|
|
859
891
|
class Circle2:
|
860
892
|
"""
|
@@ -910,6 +942,14 @@ class Circle2:
|
|
910
942
|
"""
|
911
943
|
...
|
912
944
|
|
945
|
+
def point_at_angle(self, angle: float) -> Point2:
|
946
|
+
"""
|
947
|
+
Get the point on the circle at a given angle.
|
948
|
+
:param angle: the angle in radians.
|
949
|
+
:return: the point on the circle at the given angle.
|
950
|
+
"""
|
951
|
+
...
|
952
|
+
|
913
953
|
|
914
954
|
class Arc2:
|
915
955
|
"""
|
engeom/geom3.pyi
CHANGED
@@ -260,6 +260,13 @@ class Point3(Iterable[float]):
|
|
260
260
|
"""
|
261
261
|
...
|
262
262
|
|
263
|
+
@staticmethod
|
264
|
+
def mid(a: Point3, b: Point3) -> Point3:
|
265
|
+
"""
|
266
|
+
Return the midpoint between two points. This is the average of the x, y, and z coordinates of the two points.
|
267
|
+
"""
|
268
|
+
...
|
269
|
+
|
263
270
|
|
264
271
|
class SurfacePoint3:
|
265
272
|
"""
|
@@ -389,6 +396,15 @@ class SurfacePoint3:
|
|
389
396
|
"""
|
390
397
|
...
|
391
398
|
|
399
|
+
def shift(self, offset: float) -> SurfacePoint3:
|
400
|
+
"""
|
401
|
+
Return a new surface point with the position shifted by the specified distance along the normal vector. The
|
402
|
+
normal vector is unchanged.
|
403
|
+
:param offset: the distance to shift the position by along the normal vector.
|
404
|
+
:return:
|
405
|
+
"""
|
406
|
+
...
|
407
|
+
|
392
408
|
|
393
409
|
class Iso3:
|
394
410
|
"""
|
@@ -445,6 +461,29 @@ class Iso3:
|
|
445
461
|
"""
|
446
462
|
...
|
447
463
|
|
464
|
+
@staticmethod
|
465
|
+
def from_xyzwpr(x: float, y: float, z: float, w: float, p: float, r: float) -> Iso3:
|
466
|
+
"""
|
467
|
+
Create an isometry from the specified translation and rotation angles in yaw, pitch, and roll format, following
|
468
|
+
the convention typically used in robotics. The angles are specified in degrees.
|
469
|
+
:param x:
|
470
|
+
:param y:
|
471
|
+
:param z:
|
472
|
+
:param w:
|
473
|
+
:param p:
|
474
|
+
:param r:
|
475
|
+
:return:
|
476
|
+
"""
|
477
|
+
...
|
478
|
+
|
479
|
+
def to_xyzwpr(self) -> List[float]:
|
480
|
+
"""
|
481
|
+
Convert the isometry to a list of translation and rotation angles in yaw, pitch, and roll format, following the
|
482
|
+
convention typically used in robotics. The angles are returned in degrees.
|
483
|
+
:return: a list of 6 floats representing the translation and rotation angles.
|
484
|
+
"""
|
485
|
+
...
|
486
|
+
|
448
487
|
def __matmul__(self, other: Transformable3) -> Transformable3:
|
449
488
|
"""
|
450
489
|
Multiply another object by the isometry, transforming it and returning a new object of the same type.
|
@@ -521,6 +560,161 @@ class Iso3:
|
|
521
560
|
"""
|
522
561
|
...
|
523
562
|
|
563
|
+
@property
|
564
|
+
def origin(self) -> Point3:
|
565
|
+
"""
|
566
|
+
Get the origin of the isometry as a Point3 object.
|
567
|
+
:return: a Point3 object representing the origin of the isometry.
|
568
|
+
"""
|
569
|
+
...
|
570
|
+
|
571
|
+
def translation(self) -> Iso3:
|
572
|
+
"""
|
573
|
+
Return the translation component of the isometry as a separate isometry.
|
574
|
+
"""
|
575
|
+
...
|
576
|
+
|
577
|
+
def rotation(self) -> Iso3:
|
578
|
+
"""
|
579
|
+
Return the rotation component of the isometry as a separate isometry.
|
580
|
+
"""
|
581
|
+
...
|
582
|
+
|
583
|
+
@staticmethod
|
584
|
+
def from_rx(angle: float) -> Iso3:
|
585
|
+
"""
|
586
|
+
Create an isometry representing a rotation around the x-axis by the specified angle in radians.
|
587
|
+
:param angle: the angle to rotate by in radians.
|
588
|
+
:return: an isometry containing only a rotation component
|
589
|
+
"""
|
590
|
+
...
|
591
|
+
|
592
|
+
@staticmethod
|
593
|
+
def from_ry(angle: float) -> Iso3:
|
594
|
+
"""
|
595
|
+
Create an isometry representing a rotation around the y-axis by the specified angle in radians.
|
596
|
+
:param angle: the angle to rotate by in radians.
|
597
|
+
:return: an isometry containing only a rotation component
|
598
|
+
"""
|
599
|
+
...
|
600
|
+
|
601
|
+
@staticmethod
|
602
|
+
def from_rz(angle: float) -> Iso3:
|
603
|
+
"""
|
604
|
+
Create an isometry representing a rotation around the z-axis by the specified angle in radians.
|
605
|
+
:param angle: the angle to rotate by in radians.
|
606
|
+
:return: an isometry containing only a rotation component
|
607
|
+
"""
|
608
|
+
...
|
609
|
+
|
610
|
+
@staticmethod
|
611
|
+
def from_basis_xy(e0: Vector3, e1: Vector3, origin: Point3 | None = None) -> Iso3:
|
612
|
+
"""
|
613
|
+
Create an isometry from two vectors defining the X and Y axes.
|
614
|
+
|
615
|
+
This method creates an isometry where:
|
616
|
+
- The X axis aligns with e0 (normalized)
|
617
|
+
- The Y axis aligns with e1 (normalized and adjusted to be orthogonal to e0)
|
618
|
+
- The Z axis is calculated as the cross product of X and Y
|
619
|
+
|
620
|
+
:param e0: Vector defining the X axis direction
|
621
|
+
:param e1: Vector defining the approximate Y axis direction (will be orthogonalized)
|
622
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
623
|
+
:return: A new Iso3 representing the coordinate system
|
624
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
625
|
+
"""
|
626
|
+
...
|
627
|
+
|
628
|
+
@staticmethod
|
629
|
+
def from_basis_xz(e0: Vector3, e2: Vector3, origin: Point3 | None = None) -> Iso3:
|
630
|
+
"""
|
631
|
+
Create an isometry from two vectors defining the X and Z axes.
|
632
|
+
|
633
|
+
This method creates an isometry where:
|
634
|
+
- The X axis aligns with e0 (normalized)
|
635
|
+
- The Z axis aligns with e2 (normalized and adjusted to be orthogonal to e0)
|
636
|
+
- The Y axis is calculated as the cross product of Z and X
|
637
|
+
|
638
|
+
:param e0: Vector defining the X axis direction
|
639
|
+
:param e2: Vector defining the approximate Z axis direction (will be orthogonalized)
|
640
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
641
|
+
:return: A new Iso3 representing the coordinate system
|
642
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
643
|
+
"""
|
644
|
+
...
|
645
|
+
|
646
|
+
@staticmethod
|
647
|
+
def from_basis_yz(e1: Vector3, e2: Vector3, origin: Point3 | None = None) -> Iso3:
|
648
|
+
"""
|
649
|
+
Create an isometry from two vectors defining the Y and Z axes.
|
650
|
+
|
651
|
+
This method creates an isometry where:
|
652
|
+
- The Y axis aligns with e1 (normalized)
|
653
|
+
- The Z axis aligns with e2 (normalized and adjusted to be orthogonal to e1)
|
654
|
+
- The X axis is calculated as the cross product of Y and Z
|
655
|
+
|
656
|
+
:param e1: Vector defining the Y axis direction
|
657
|
+
:param e2: Vector defining the approximate Z axis direction (will be orthogonalized)
|
658
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
659
|
+
:return: A new Iso3 representing the coordinate system
|
660
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
661
|
+
"""
|
662
|
+
...
|
663
|
+
|
664
|
+
@staticmethod
|
665
|
+
def from_basis_yx(e1: Vector3, e0: Vector3, origin: Point3 | None = None) -> Iso3:
|
666
|
+
"""
|
667
|
+
Create an isometry from two vectors defining the Y and X axes.
|
668
|
+
|
669
|
+
This method creates an isometry where:
|
670
|
+
- The Y axis aligns with e1 (normalized)
|
671
|
+
- The X axis aligns with e0 (normalized and adjusted to be orthogonal to e1)
|
672
|
+
- The Z axis is calculated as the cross product of X and Y
|
673
|
+
|
674
|
+
:param e1: Vector defining the Y axis direction
|
675
|
+
:param e0: Vector defining the approximate X axis direction (will be orthogonalized)
|
676
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
677
|
+
:return: A new Iso3 representing the coordinate system
|
678
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
679
|
+
"""
|
680
|
+
...
|
681
|
+
|
682
|
+
@staticmethod
|
683
|
+
def from_basis_zx(e2: Vector3, e0: Vector3, origin: Point3 | None = None) -> Iso3:
|
684
|
+
"""
|
685
|
+
Create an isometry from two vectors defining the Z and X axes.
|
686
|
+
|
687
|
+
This method creates an isometry where:
|
688
|
+
- The Z axis aligns with e2 (normalized)
|
689
|
+
- The X axis aligns with e0 (normalized and adjusted to be orthogonal to e2)
|
690
|
+
- The Y axis is calculated as the cross product of Z and X
|
691
|
+
|
692
|
+
:param e2: Vector defining the Z axis direction
|
693
|
+
:param e0: Vector defining the approximate X axis direction (will be orthogonalized)
|
694
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
695
|
+
:return: A new Iso3 representing the coordinate system
|
696
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
697
|
+
"""
|
698
|
+
...
|
699
|
+
|
700
|
+
@staticmethod
|
701
|
+
def from_basis_zy(e2: Vector3, e1: Vector3, origin: Point3 | None = None) -> Iso3:
|
702
|
+
"""
|
703
|
+
Create an isometry from two vectors defining the Z and Y axes.
|
704
|
+
|
705
|
+
This method creates an isometry where:
|
706
|
+
- The Z axis aligns with e2 (normalized)
|
707
|
+
- The Y axis aligns with e1 (normalized and adjusted to be orthogonal to e2)
|
708
|
+
- The X axis is calculated as the cross product of Y and Z
|
709
|
+
|
710
|
+
:param e2: Vector defining the Z axis direction
|
711
|
+
:param e1: Vector defining the approximate Y axis direction (will be orthogonalized)
|
712
|
+
:param origin: Optional point to use as the origin of the isometry (defaults to world origin)
|
713
|
+
:return: A new Iso3 representing the coordinate system
|
714
|
+
:raises: ValueError if the vectors are parallel or too small to create a valid basis
|
715
|
+
"""
|
716
|
+
...
|
717
|
+
|
524
718
|
|
525
719
|
class SvdBasis3:
|
526
720
|
"""
|
@@ -646,6 +840,14 @@ class Plane3:
|
|
646
840
|
"""
|
647
841
|
...
|
648
842
|
|
843
|
+
def intersection_distance(self, sp: SurfacePoint3) -> float | None:
|
844
|
+
"""
|
845
|
+
|
846
|
+
:param sp:
|
847
|
+
:return:
|
848
|
+
"""
|
849
|
+
...
|
850
|
+
|
649
851
|
|
650
852
|
class Mesh:
|
651
853
|
"""
|
@@ -952,6 +1154,143 @@ class Mesh:
|
|
952
1154
|
"""
|
953
1155
|
...
|
954
1156
|
|
1157
|
+
def visual_outline(
|
1158
|
+
self,
|
1159
|
+
facing: Vector3,
|
1160
|
+
max_edge_length: float,
|
1161
|
+
corner_angle: float | None = None
|
1162
|
+
) -> Tuple[NDArray[float], NDArray[numpy.uint8]]:
|
1163
|
+
"""
|
1164
|
+
Capture the edges of a visual outline of the mesh, used to draw a line diagram of the mesh in a 2D space. The
|
1165
|
+
returned results will consist of two numpy arrays. The first will be a floating point array of shape (N, 6)
|
1166
|
+
where N is the number of edges in the outline. The first three columns will be the start point of the edge, and
|
1167
|
+
the last three columns will be the end point of the edge. The second array will be a numpy array of shape (N,)
|
1168
|
+
containing a 0 or 1 for each edge at the associated index. A 0 indicates that the edge is unobstructed in the
|
1169
|
+
view direction, while a 1 indicates that the edge is obstructed by the mesh.
|
1170
|
+
|
1171
|
+
:param facing: A vector with the direction to look at the mesh
|
1172
|
+
:param max_edge_length: The maximum length of an edge to be included in the outline. Edges longer than this
|
1173
|
+
will be broken up into smaller edges.
|
1174
|
+
:param corner_angle: The minimum angle between two adjacent faces for the common edge to be considered a corner
|
1175
|
+
and included in the outline. If None, the default value is 45 degrees.
|
1176
|
+
:return: a tuple of two numpy arrays. The first array is the outline edges, and the second array is a mask
|
1177
|
+
indicating whether the edge is obstructed or not.
|
1178
|
+
"""
|
1179
|
+
...
|
1180
|
+
|
1181
|
+
def convex_hull(self) -> Mesh:
|
1182
|
+
"""
|
1183
|
+
Calculate the convex hull of the mesh. The convex hull is the smallest convex shape that contains all the
|
1184
|
+
vertices of the mesh. This will return a new mesh object containing the vertices and triangles of the convex
|
1185
|
+
hull. This method will not modify the original mesh.
|
1186
|
+
:return: a new mesh object containing the convex hull of the original mesh.
|
1187
|
+
"""
|
1188
|
+
...
|
1189
|
+
|
1190
|
+
@staticmethod
|
1191
|
+
def create_box(length: float, width: float, height: float) -> Mesh:
|
1192
|
+
"""
|
1193
|
+
Creates a box with the center at the origin and the specified length, width, and height
|
1194
|
+
|
1195
|
+
:param length: the size of the box along the X-axis
|
1196
|
+
:param width: the size of the box along the Y-axis
|
1197
|
+
:param height: the size of the box along the Z-axis
|
1198
|
+
:return: a new `Mesh` object representing the box
|
1199
|
+
"""
|
1200
|
+
...
|
1201
|
+
|
1202
|
+
@staticmethod
|
1203
|
+
def create_cylinder(radius: float, height: float, steps: int) -> Mesh:
|
1204
|
+
"""
|
1205
|
+
Creates a cylinder with a radius and height. The cylinder will be centered at the origin and oriented along the
|
1206
|
+
Y-axis.
|
1207
|
+
|
1208
|
+
:param radius: the radius of the cylinder
|
1209
|
+
:param height: the size of the cylinder along the Y-axis
|
1210
|
+
:param steps: the number of subdivisions to create vertices around the cylinder. The more steps the smoother the
|
1211
|
+
cylinder will be.
|
1212
|
+
:return: a new `Mesh` object representing the cylinder
|
1213
|
+
"""
|
1214
|
+
...
|
1215
|
+
|
1216
|
+
@staticmethod
|
1217
|
+
def create_sphere(radius: float, n_theta: int, n_phi: int) -> Mesh:
|
1218
|
+
"""
|
1219
|
+
Creates a sphere with a radius. The sphere will be centered at the origin. The step counts `n_theta` and `n_phi`
|
1220
|
+
will determine the smoothness of the sphere in the radial (n_theta) and polar (n_phi) directions. The poles
|
1221
|
+
will be located at Y=+radius and Y=-radius, and the equator will lie in the XZ plane.
|
1222
|
+
|
1223
|
+
:param radius: the radius of the sphere
|
1224
|
+
:param n_theta: the number of subdivisions to create vertices around the sphere in the theta direction
|
1225
|
+
:param n_phi: the number of subdivisions to create vertices around the sphere in the phi direction
|
1226
|
+
:return: a new `Mesh` object representing the sphere
|
1227
|
+
"""
|
1228
|
+
...
|
1229
|
+
|
1230
|
+
@staticmethod
|
1231
|
+
def create_cone(radius: float, height: float, steps: int) -> Mesh:
|
1232
|
+
"""
|
1233
|
+
Creates a cone with a radius and height. The cone will be centered at the origin and oriented so that the
|
1234
|
+
point of the cone is located at Y=height/2 and the base is located at Y=-height/2.
|
1235
|
+
|
1236
|
+
:param radius: the radius of the base of the cone
|
1237
|
+
:param height: the size of the cone along the Y-axis
|
1238
|
+
:param steps: the number of subdivisions to create vertices around the cone. The more steps the smoother the
|
1239
|
+
cone will be.
|
1240
|
+
:return: a new `Mesh` object representing the cone
|
1241
|
+
"""
|
1242
|
+
...
|
1243
|
+
|
1244
|
+
@staticmethod
|
1245
|
+
def create_capsule(p0: Point3, p1: Point3, radius: float, n_theta: int, n_phi: int) -> Mesh:
|
1246
|
+
"""
|
1247
|
+
Creates a capsule shape between two points with a specified radius. The capsule will be centered between the two
|
1248
|
+
points and oriented along the line connecting them. The step counts `n_theta` and `n_phi` will determine the
|
1249
|
+
smoothness of the sphere in the radial (n_theta) and polar (n_phi) directions.
|
1250
|
+
|
1251
|
+
:param p0: the first point of the capsule
|
1252
|
+
:param p1: the second point of the capsule
|
1253
|
+
:param radius: the radius of the capsule
|
1254
|
+
:param n_theta: the number of subdivisions to create vertices around the sphere in the theta direction
|
1255
|
+
:param n_phi: the number of subdivisions to create vertices around the sphere in the phi direction
|
1256
|
+
:return: a new `Mesh` object representing the capsule
|
1257
|
+
"""
|
1258
|
+
...
|
1259
|
+
|
1260
|
+
@staticmethod
|
1261
|
+
def create_cylinder_between(p0: Point3, p1: Point3, radius: float, steps: int) -> Mesh:
|
1262
|
+
"""
|
1263
|
+
Creates a cylinder between two points with a specified radius. The cylinder will be centered between the two
|
1264
|
+
points and oriented along the line connecting them.
|
1265
|
+
|
1266
|
+
:param p0: the first point of the cylinder
|
1267
|
+
:param p1: the second point of the cylinder
|
1268
|
+
:param radius: the radius of the cylinder
|
1269
|
+
:param steps: the number of subdivisions to create vertices around the cylinder. The more steps the smoother the
|
1270
|
+
cylinder will be.
|
1271
|
+
:return: a new `Mesh` object representing the cylinder
|
1272
|
+
"""
|
1273
|
+
...
|
1274
|
+
|
1275
|
+
@staticmethod
|
1276
|
+
def create_rect_beam_between(p0: Point3, p1: Point3, width: float, height: float, up: Vector3 | None = None) -> Mesh:
|
1277
|
+
"""
|
1278
|
+
Create a rectangular cross-sectioned prism between two points with a specified width and height. The prism will
|
1279
|
+
be centered between the two points and oriented along the line connecting them. The up vector's projection onto
|
1280
|
+
the line connecting the two end points will determine the direction of the height of the prism. If None, the
|
1281
|
+
height will be aligned with the projection of the Z-axis.
|
1282
|
+
|
1283
|
+
If the up vector is parallel to the line connecting the two points, an error will be thrown.
|
1284
|
+
|
1285
|
+
:param p0: the first point of the prism
|
1286
|
+
:param p1: the second point of the prism
|
1287
|
+
:param width: the width of the prism
|
1288
|
+
:param height: the height of the prism
|
1289
|
+
:param up: the up vector to use for the height direction. If None, the Z-axis will be used
|
1290
|
+
:return: a new `Mesh` object representing the prism
|
1291
|
+
"""
|
1292
|
+
...
|
1293
|
+
|
955
1294
|
|
956
1295
|
class FaceFilterHandle:
|
957
1296
|
"""
|
@@ -1028,6 +1367,52 @@ class FaceFilterHandle:
|
|
1028
1367
|
...
|
1029
1368
|
|
1030
1369
|
|
1370
|
+
class MeshCollisionSet:
|
1371
|
+
"""
|
1372
|
+
A class holding a set of meshes for collision detection. This class is used to perform collision detection between
|
1373
|
+
a set of moving and stationary meshes in 3D space.
|
1374
|
+
"""
|
1375
|
+
|
1376
|
+
def __init__(self):
|
1377
|
+
"""
|
1378
|
+
Creates an empty collision set.
|
1379
|
+
"""
|
1380
|
+
...
|
1381
|
+
|
1382
|
+
def add_stationary(self, mesh: Mesh) -> int:
|
1383
|
+
"""
|
1384
|
+
Add a stationary mesh to the collision set. This mesh will be used as a reference for collision detection.
|
1385
|
+
:param mesh: the mesh to add to the collision set.
|
1386
|
+
:return: the ID of the mesh in the collision set.
|
1387
|
+
"""
|
1388
|
+
...
|
1389
|
+
|
1390
|
+
def add_moving(self, mesh: Mesh) -> int:
|
1391
|
+
"""
|
1392
|
+
Add a moving mesh to the collision set. This mesh will be used to check for collisions against the stationary
|
1393
|
+
meshes in the set.
|
1394
|
+
:param mesh: the mesh to add to the collision set.
|
1395
|
+
:return: the ID of the mesh in the collision set.
|
1396
|
+
"""
|
1397
|
+
...
|
1398
|
+
|
1399
|
+
def add_exception(self, id1: int, id2: int):
|
1400
|
+
"""
|
1401
|
+
Add an exception to the collision set. This will prevent the two meshes from being checked for collisions.
|
1402
|
+
:param id1: the ID of the first mesh.
|
1403
|
+
:param id2: the ID of the second mesh.
|
1404
|
+
"""
|
1405
|
+
...
|
1406
|
+
|
1407
|
+
def check_all(self, transforms: List[Tuple[int, Iso3]], stop_at_first: bool) -> List[Tuple[int, int]]:
|
1408
|
+
"""
|
1409
|
+
Check all moving meshes against all stationary meshes for collisions. This will return a list of tuples
|
1410
|
+
containing the IDs of the two meshes that are colliding.
|
1411
|
+
:return: a list of tuples containing the IDs of the colliding meshes.
|
1412
|
+
"""
|
1413
|
+
...
|
1414
|
+
|
1415
|
+
|
1031
1416
|
class CurveStation3:
|
1032
1417
|
"""
|
1033
1418
|
A class representing a station along a curve in 3D space. The station is represented by a point on the curve, a
|
engeom/sensor.pyi
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from .geom3 import Point3, Mesh, Iso3, Vector3
|
3
|
+
from numpy.typing import NDArray
|
4
|
+
|
5
|
+
|
6
|
+
class LaserLine:
|
7
|
+
def __init__(
|
8
|
+
self,
|
9
|
+
ray_origin: Point3,
|
10
|
+
detect_origin: Point3,
|
11
|
+
line_start: Point3,
|
12
|
+
line_end: Point3,
|
13
|
+
min_range: float,
|
14
|
+
max_range: float,
|
15
|
+
rays: int,
|
16
|
+
angle_limit: float | None = None,
|
17
|
+
):
|
18
|
+
"""
|
19
|
+
|
20
|
+
:param ray_origin:
|
21
|
+
:param detect_origin:
|
22
|
+
:param line_start:
|
23
|
+
:param line_end:
|
24
|
+
:param min_range:
|
25
|
+
:param max_range:
|
26
|
+
:param rays:
|
27
|
+
:param angle_limit:
|
28
|
+
"""
|
29
|
+
...
|
30
|
+
|
31
|
+
def get_points(self, target: Mesh, obstruction: Mesh | None, iso: Iso3) -> NDArray[float]:
|
32
|
+
"""
|
33
|
+
|
34
|
+
:param target:
|
35
|
+
:param obstruction:
|
36
|
+
:param iso:
|
37
|
+
:return:
|
38
|
+
"""
|
39
|
+
...
|
40
|
+
|
41
|
+
|
42
|
+
class PanningLaserLine:
|
43
|
+
def __init__(self, laser_line: LaserLine, pan_vector: Vector3, steps: int):
|
44
|
+
"""
|
45
|
+
:param laser_line:
|
46
|
+
:param pan_vector:
|
47
|
+
:param steps:
|
48
|
+
"""
|
49
|
+
...
|
50
|
+
|
51
|
+
def get_points(self, target: Mesh, obstruction: Mesh | None, iso: Iso3) -> NDArray[float]:
|
52
|
+
"""
|
53
|
+
:param target:
|
54
|
+
:param obstruction:
|
55
|
+
:param iso:
|
56
|
+
:return:
|
57
|
+
"""
|
58
|
+
...
|
@@ -1,23 +1,25 @@
|
|
1
|
-
engeom-0.2.
|
2
|
-
engeom-0.2.
|
1
|
+
engeom-0.2.11.dist-info/METADATA,sha256=0wfaJ6d1GSA-0ki0ISulCq8dfNZViDVrj1_ZMTUV31I,498
|
2
|
+
engeom-0.2.11.dist-info/WHEEL,sha256=hKPP3BCTWtTwj6SFaSI--T5aOGqh_llYfbZ_BsqivwA,94
|
3
3
|
engeom/airfoil/__init__.py,sha256=gpS9pVepUu90XJ-ePndNupbUMKI0RGxNXPxD9x0iVHY,274
|
4
4
|
engeom/airfoil.pyi,sha256=VTeJBoS9Iij7p-92R7jCqzPasHmvAUocyzc6BSx7mvM,23557
|
5
5
|
engeom/align/__init__.py,sha256=SEeMqeqLKqJC73Mg8GwPwd9NwWnl-dcCqJ4rPdh8yyc,196
|
6
6
|
engeom/align.pyi,sha256=QCSKrTLkCoaIubcrPU9J-wDZe1lRP0GbPgWZmonXjo0,997
|
7
7
|
engeom/engeom.pyi,sha256=J0L_D-Sc2laJHL36nUAvIP3eN9BDryAxd_6aMQarlZc,1561
|
8
8
|
engeom/geom2/__init__.py,sha256=JFpiLyROUh6vyakG-7JDSlCMCn4QB2MQ8bz3uVCaAIk,373
|
9
|
-
engeom/geom2.pyi,sha256=
|
9
|
+
engeom/geom2.pyi,sha256=uMi4WD6-DtFx8H-RZsKIi-p1fN4p8SzOfBZmEuvNGDU,44357
|
10
10
|
engeom/geom3/__init__.py,sha256=l8B0iDhJ4YiRbslJLN791XWai2DWrpmZptnzIETMS9g,370
|
11
|
-
engeom/geom3.pyi,sha256=
|
11
|
+
engeom/geom3.pyi,sha256=XQKy3lEDybh-81uN7y6DNncj7w6LpR2haF7YTg8TwXg,74421
|
12
12
|
engeom/metrology/__init__.py,sha256=XvEhG8uDm1olWwZHDDrQv9LFP5zXhbsGx27PqRq8WE0,304
|
13
13
|
engeom/metrology.pyi,sha256=9I5un86VB_2gmQBrVYhX8JzILTUADMLB9Em8ttJxrWg,4044
|
14
14
|
engeom/plot.py,sha256=LTqqO-h1EJL6wanM0hB79s9ohWwaCIijMOHVplY3vmc,1079
|
15
15
|
engeom/raster3/__init__.py,sha256=iaayLrvco-ZMZPyeK47ox7rYne_51DNb2T2Q0iNNeKE,289
|
16
16
|
engeom/raster3.pyi,sha256=sBXXYXcDBiDU_OFDQiwa7Q3GcwSiUc4CLy6nJ1MwFqM,790
|
17
|
+
engeom/sensor/__init__.py,sha256=p-1osXrlBX_hXSSlvySszSimMv_4_n273joBcTFx2V0,179
|
18
|
+
engeom/sensor.pyi,sha256=a9y62FqhG-CFFHnJiC03PqBpFtxtfkH0zoDkk9LXWnU,1399
|
17
19
|
engeom/_plot/common.py,sha256=Py78ufN3yi59hPwv21SoGcqyZUJS-_PmK8tlAKgSG7Q,517
|
18
|
-
engeom/_plot/matplotlib.py,sha256=
|
19
|
-
engeom/_plot/pyvista.py,sha256=
|
20
|
+
engeom/_plot/matplotlib.py,sha256=rFL1CPNMUqGO-fwD45V3-shektBMeNq5U15Zxp96hYw,14824
|
21
|
+
engeom/_plot/pyvista.py,sha256=PylGVOa9RtRIYPyHLy969eyW8yIgAk-URVZT0R7WoQ8,12980
|
20
22
|
engeom/_plot/__init__.py,sha256=F_KviZtxzZGwfEjjn8Ep46N4UVl8VpFJWBzbBUE_J7A,30
|
21
23
|
engeom/__init__.py,sha256=kYgFq3jq1quDfV013wEYQMlUBz4QNSpP6u8lFiuTHvc,115
|
22
|
-
engeom/engeom.pyd,sha256=
|
23
|
-
engeom-0.2.
|
24
|
+
engeom/engeom.pyd,sha256=abHGragpjFER8i_46ihIfX-IFW-c0pWjFMHdoOCmR74,2757632
|
25
|
+
engeom-0.2.11.dist-info/RECORD,,
|
File without changes
|