engeom 0.2.10__tar.gz → 0.2.11__tar.gz

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.
Files changed (156) hide show
  1. {engeom-0.2.10 → engeom-0.2.11}/Cargo.lock +1 -1
  2. {engeom-0.2.10 → engeom-0.2.11}/Cargo.toml +1 -1
  3. {engeom-0.2.10 → engeom-0.2.11}/PKG-INFO +1 -1
  4. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh.rs +68 -21
  5. engeom-0.2.11/engeom/src/geom3/xyzwpr.rs +141 -0
  6. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3.rs +2 -0
  7. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/lib.rs +4 -0
  8. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/geom3.pyi +123 -14
  9. {engeom-0.2.10 → engeom-0.2.11}/src/geom3.rs +91 -2
  10. {engeom-0.2.10 → engeom-0.2.11}/src/mesh.rs +72 -12
  11. {engeom-0.2.10 → engeom-0.2.11}/.github/workflows/CI.yml +0 -0
  12. {engeom-0.2.10 → engeom-0.2.11}/.gitignore +0 -0
  13. {engeom-0.2.10 → engeom-0.2.11}/.gitmodules +0 -0
  14. {engeom-0.2.10 → engeom-0.2.11}/README.md +0 -0
  15. {engeom-0.2.10 → engeom-0.2.11}/docs/airfoils/intro.md +0 -0
  16. {engeom-0.2.10 → engeom-0.2.11}/docs/api/airfoil.md +0 -0
  17. {engeom-0.2.10 → engeom-0.2.11}/docs/api/engeom.md +0 -0
  18. {engeom-0.2.10 → engeom-0.2.11}/docs/api/geom2.md +0 -0
  19. {engeom-0.2.10 → engeom-0.2.11}/docs/api/geom3.md +0 -0
  20. {engeom-0.2.10 → engeom-0.2.11}/docs/api/metrology.md +0 -0
  21. {engeom-0.2.10 → engeom-0.2.11}/docs/api/plot.md +0 -0
  22. {engeom-0.2.10 → engeom-0.2.11}/docs/bounding_volumes.md +0 -0
  23. {engeom-0.2.10 → engeom-0.2.11}/docs/curves.md +0 -0
  24. {engeom-0.2.10 → engeom-0.2.11}/docs/images/surface_point_meas.svg +0 -0
  25. {engeom-0.2.10 → engeom-0.2.11}/docs/index.md +0 -0
  26. {engeom-0.2.10 → engeom-0.2.11}/docs/isometries.md +0 -0
  27. {engeom-0.2.10 → engeom-0.2.11}/docs/meshes.md +0 -0
  28. {engeom-0.2.10 → engeom-0.2.11}/docs/metrology.md +0 -0
  29. {engeom-0.2.10 → engeom-0.2.11}/docs/numpy.md +0 -0
  30. {engeom-0.2.10 → engeom-0.2.11}/docs/planes_circles_lines.md +0 -0
  31. {engeom-0.2.10 → engeom-0.2.11}/docs/points_vectors.md +0 -0
  32. {engeom-0.2.10 → engeom-0.2.11}/docs/surf_points.md +0 -0
  33. {engeom-0.2.10 → engeom-0.2.11}/docs/svd_basis.md +0 -0
  34. {engeom-0.2.10 → engeom-0.2.11}/engeom/.gitignore +0 -0
  35. {engeom-0.2.10 → engeom-0.2.11}/engeom/Cargo.lock +0 -0
  36. {engeom-0.2.10 → engeom-0.2.11}/engeom/Cargo.toml +0 -0
  37. {engeom-0.2.10 → engeom-0.2.11}/engeom/README.md +0 -0
  38. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/airfoils/camber.md +0 -0
  39. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/airfoils/overview.md +0 -0
  40. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/common/angles.md +0 -0
  41. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/common/core_space.md +0 -0
  42. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/common/discrete_domain.md +0 -0
  43. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/common/images/surface_point_meas.svg +0 -0
  44. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/common/svd_basis.md +0 -0
  45. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/geom2/alignment.md +0 -0
  46. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/geom2/curve.md +0 -0
  47. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/geom2/point_collections.md +0 -0
  48. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/geom2/shapes.md +0 -0
  49. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/index.md +0 -0
  50. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/javascripts/mathjax.js +0 -0
  51. {engeom-0.2.10 → engeom-0.2.11}/engeom/docs/python_rust.md +0 -0
  52. {engeom-0.2.10 → engeom-0.2.11}/engeom/mkdocs.yml +0 -0
  53. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil/camber.rs +0 -0
  54. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil/edges.rs +0 -0
  55. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil/helpers.rs +0 -0
  56. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil/inscribed_circle.rs +0 -0
  57. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil/orientation.rs +0 -0
  58. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/airfoil.rs +0 -0
  59. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/align.rs +0 -0
  60. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/angles.rs +0 -0
  61. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/convert_2d_3d.rs +0 -0
  62. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/discrete_domain.rs +0 -0
  63. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/indices.rs +0 -0
  64. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/interval.rs +0 -0
  65. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/kd_tree.rs +0 -0
  66. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/points.rs +0 -0
  67. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/poisson_disk.rs +0 -0
  68. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/surface_point.rs +0 -0
  69. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/svd_basis.rs +0 -0
  70. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common/vec_f64.rs +0 -0
  71. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/common.rs +0 -0
  72. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/errors.rs +0 -0
  73. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/func1/common_functions.rs +0 -0
  74. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/func1/polynomial.rs +0 -0
  75. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/func1/series1.rs +0 -0
  76. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/func1.rs +0 -0
  77. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/aabb2.rs +0 -0
  78. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/align2/jacobian.rs +0 -0
  79. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/align2/points_to_curve.rs +0 -0
  80. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/align2/rc_params2.rs +0 -0
  81. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/align2.rs +0 -0
  82. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/angles2.rs +0 -0
  83. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/circle2.rs +0 -0
  84. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/curve2.rs +0 -0
  85. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/hull.rs +0 -0
  86. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/line2.rs +0 -0
  87. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2/polyline2.rs +0 -0
  88. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom2.rs +0 -0
  89. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/align3/jacobian.rs +0 -0
  90. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/align3/multi_param.rs +0 -0
  91. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/align3/points_to_mesh.rs +0 -0
  92. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/align3/rotations.rs +0 -0
  93. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/align3.rs +0 -0
  94. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/curve3.rs +0 -0
  95. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/iso3.rs +0 -0
  96. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/collisions.rs +0 -0
  97. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/conformal.rs +0 -0
  98. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/edges.rs +0 -0
  99. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/faces.rs +0 -0
  100. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/filtering.rs +0 -0
  101. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/measurement.rs +0 -0
  102. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/outline.rs +0 -0
  103. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/patches.rs +0 -0
  104. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/queries.rs +0 -0
  105. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/sampling.rs +0 -0
  106. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/mesh/uv_mapping.rs +0 -0
  107. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/plane3.rs +0 -0
  108. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/geom3/point_cloud.rs +0 -0
  109. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/io.rs +0 -0
  110. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology/dimension.rs +0 -0
  111. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology/line_profiles.rs +0 -0
  112. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology/surface_deviation.rs +0 -0
  113. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology/tolerance.rs +0 -0
  114. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology/tolerance_map.rs +0 -0
  115. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/metrology.rs +0 -0
  116. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/raster3.rs +0 -0
  117. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/sensor.rs +0 -0
  118. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/stats.rs +0 -0
  119. {engeom-0.2.10 → engeom-0.2.11}/engeom/src/utility.rs +0 -0
  120. {engeom-0.2.10 → engeom-0.2.11}/mkdocs.yml +0 -0
  121. {engeom-0.2.10 → engeom-0.2.11}/pyproject.toml +0 -0
  122. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/__init__.py +0 -0
  123. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/_plot/__init__.py +0 -0
  124. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/_plot/common.py +0 -0
  125. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/_plot/matplotlib.py +0 -0
  126. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/_plot/pyvista.py +0 -0
  127. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/airfoil/__init__.py +0 -0
  128. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/airfoil.pyi +0 -0
  129. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/align/__init__.py +0 -0
  130. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/align.pyi +0 -0
  131. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/engeom.pyi +0 -0
  132. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/geom2/__init__.py +0 -0
  133. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/geom2.pyi +0 -0
  134. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/geom3/__init__.py +0 -0
  135. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/metrology/__init__.py +0 -0
  136. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/metrology.pyi +0 -0
  137. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/plot.py +0 -0
  138. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/raster3/__init__.py +0 -0
  139. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/raster3.pyi +0 -0
  140. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/sensor/__init__.py +0 -0
  141. {engeom-0.2.10 → engeom-0.2.11}/python/engeom/sensor.pyi +0 -0
  142. {engeom-0.2.10 → engeom-0.2.11}/python/tests/test_all.py +0 -0
  143. {engeom-0.2.10 → engeom-0.2.11}/python/tests/test_geom2_simple.py +0 -0
  144. {engeom-0.2.10 → engeom-0.2.11}/python/tests/test_geom3_simple.py +0 -0
  145. {engeom-0.2.10 → engeom-0.2.11}/src/airfoil.rs +0 -0
  146. {engeom-0.2.10 → engeom-0.2.11}/src/alignments.rs +0 -0
  147. {engeom-0.2.10 → engeom-0.2.11}/src/bounding.rs +0 -0
  148. {engeom-0.2.10 → engeom-0.2.11}/src/common.rs +0 -0
  149. {engeom-0.2.10 → engeom-0.2.11}/src/conversions.rs +0 -0
  150. {engeom-0.2.10 → engeom-0.2.11}/src/geom2.rs +0 -0
  151. {engeom-0.2.10 → engeom-0.2.11}/src/lib.rs +0 -0
  152. {engeom-0.2.10 → engeom-0.2.11}/src/metrology.rs +0 -0
  153. {engeom-0.2.10 → engeom-0.2.11}/src/raster.rs +0 -0
  154. {engeom-0.2.10 → engeom-0.2.11}/src/ray_casting.rs +0 -0
  155. {engeom-0.2.10 → engeom-0.2.11}/src/sensor.rs +0 -0
  156. {engeom-0.2.10 → engeom-0.2.11}/src/svd_basis.rs +0 -0
@@ -1025,7 +1025,7 @@ dependencies = [
1025
1025
 
1026
1026
  [[package]]
1027
1027
  name = "py-engeom"
1028
- version = "0.2.10"
1028
+ version = "0.2.11"
1029
1029
  dependencies = [
1030
1030
  "engeom",
1031
1031
  "numpy",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "py-engeom"
3
- version = "0.2.10"
3
+ version = "0.2.11"
4
4
  edition = "2021"
5
5
 
6
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engeom
3
- Version: 0.2.10
3
+ Version: 0.2.11
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -2,6 +2,7 @@
2
2
  //! indices into the vertex list. This abstraction is built around the `TriMesh` type from the
3
3
  //! `parry3d` crate.
4
4
 
5
+ mod collisions;
5
6
  mod conformal;
6
7
  mod edges;
7
8
  mod faces;
@@ -12,15 +13,14 @@ mod patches;
12
13
  mod queries;
13
14
  mod sampling;
14
15
  mod uv_mapping;
15
- mod collisions;
16
16
 
17
- pub use self::uv_mapping::UvMapping;
18
17
  pub use self::collisions::MeshCollisionSet;
19
- use crate::geom3::Aabb3;
18
+ pub use self::uv_mapping::UvMapping;
19
+ use crate::geom3::{Aabb3, IsoExtensions3};
20
20
  use crate::{Iso3, Point2, Point3, Result, SurfacePoint3, UnitVec3, Vector3};
21
21
  pub use edges::MeshEdges;
22
22
  use parry3d_f64::shape::{TriMesh, TriMeshFlags};
23
- use parry3d_f64::transformation;
23
+ use parry3d_f64::{shape, transformation};
24
24
 
25
25
  #[derive(Clone)]
26
26
  pub struct Mesh {
@@ -204,32 +204,79 @@ impl Mesh {
204
204
  }
205
205
  }
206
206
 
207
- pub fn create_box(width: f64, height: f64, depth: f64, is_solid: bool) -> Self {
208
- let (vertices, triangles) = box_geom(width, height, depth);
207
+ pub fn create_cone(half_height: f64, radius: f64, steps: usize) -> Self {
208
+ let cone = shape::Cone::new(half_height, radius);
209
+ let (vertices, faces) = cone.to_trimesh(steps as u32);
210
+
211
+ Self::new(vertices, faces, true)
212
+ }
213
+
214
+ pub fn create_capsule(
215
+ p0: &Point3,
216
+ p1: &Point3,
217
+ radius: f64,
218
+ n_theta: usize,
219
+ n_phi: usize,
220
+ ) -> Self {
221
+ let capsule = shape::Capsule::new(*p0, *p1, radius);
222
+ let (vertices, faces) = capsule.to_trimesh(n_theta as u32, n_phi as u32);
223
+
224
+ Self::new(vertices, faces, true)
225
+ }
226
+
227
+ pub fn create_sphere(radius: f64, n_theta: usize, n_phi: usize) -> Self {
228
+ let sphere = shape::Ball::new(radius);
229
+ let (vertices, faces) = sphere.to_trimesh(n_theta as u32, n_phi as u32);
230
+
231
+ Self::new(vertices, faces, true)
232
+ }
233
+
234
+ pub fn create_box(length: f64, width: f64, height: f64, is_solid: bool) -> Self {
235
+ let bx = shape::Cuboid::new(Vector3::new(length / 2.0, width / 2.0, height / 2.0));
236
+ let (vertices, triangles) = bx.to_trimesh();
209
237
  Self::new(vertices, triangles, is_solid)
210
238
  }
211
239
 
212
240
  pub fn create_cylinder(radius: f64, height: f64, steps: usize) -> Self {
213
- let mut vertices = Vec::new();
214
- let mut faces: Vec<[u32; 3]> = Vec::new();
241
+ let cyl = shape::Cylinder::new(height / 2.0, radius);
242
+ let (vertices, faces) = cyl.to_trimesh(steps as u32);
243
+
244
+ Self::new(vertices, faces, true)
245
+ }
246
+
247
+ pub fn create_rect_beam_between(
248
+ p0: &Point3,
249
+ p1: &Point3,
250
+ width: f64,
251
+ height: f64,
252
+ up: &Vector3,
253
+ ) -> Result<Self> {
254
+ let v = *p1 - *p0;
255
+ let pc = *p0 + v / 2.0;
256
+ let box_geom = shape::Cuboid::new(Vector3::new(width / 2.0, height / 2.0, v.norm() / 2.0));
215
257
 
216
- for i in 0..steps {
217
- let angle = i as f64 * 2.0 * std::f64::consts::PI / (steps as f64);
218
- let x = radius * angle.cos();
219
- let y = radius * angle.sin();
258
+ // I think this is OK?
259
+ let transform = Iso3::try_from_basis_zy(&v, up, Some(pc))?;
220
260
 
221
- // First vertex is i * 2
222
- vertices.push(Point3::new(x, y, 0.0));
223
- // Second vertex is i * 2 + 1
224
- vertices.push(Point3::new(x, y, height));
261
+ let (vertices, faces) = box_geom.to_trimesh();
262
+ let mut mesh = Self::new(vertices, faces, true);
263
+ mesh.transform(&transform);
264
+ Ok(mesh)
265
+ }
225
266
 
226
- let k = (i + 1) % steps;
267
+ pub fn create_cylinder_between(p0: &Point3, p1: &Point3, radius: f64, steps: usize) -> Self {
268
+ let v = *p1 - *p0;
269
+ let pc = *p0 + v / 2.0;
270
+ let cyl = shape::Cylinder::new(v.norm() / 2.0, radius);
227
271
 
228
- faces.push([(i * 2) as u32, (i * 2 + 1) as u32, (k * 2 + 1) as u32]);
229
- faces.push([(i * 2) as u32, (k * 2) as u32, (k * 2 + 1) as u32]);
230
- }
272
+ // I think this is OK?
273
+ let transform = Iso3::try_from_basis_yz(&v, &Vector3::z(), Some(pc))
274
+ .unwrap_or(Iso3::try_from_basis_yx(&v, &Vector3::x(), Some(pc)).unwrap());
231
275
 
232
- Mesh::new(vertices, faces, false)
276
+ let (vertices, faces) = cyl.to_trimesh(steps as u32);
277
+ let mut mesh = Self::new(vertices, faces, true);
278
+ mesh.transform(&transform);
279
+ mesh
233
280
  }
234
281
 
235
282
  pub fn get_patches(&self) -> Vec<Vec<usize>> {
@@ -0,0 +1,141 @@
1
+ use serde::{Deserialize, Serialize};
2
+ use crate::{Iso3, Vector3};
3
+ use crate::na::{Translation3, UnitQuaternion};
4
+
5
+ /// A struct representing a 6D pose in XYZ and WPR (Yaw, Pitch, Roll) format, commonly used by
6
+ /// FANUC robots. Angles are represented in degrees.
7
+ #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
8
+ pub struct XyzWpr {
9
+ pub x: f64,
10
+ pub y: f64,
11
+ pub z: f64,
12
+ pub w: f64,
13
+ pub p: f64,
14
+ pub r: f64,
15
+ }
16
+
17
+ impl XyzWpr {
18
+ pub fn new(x: f64, y: f64, z: f64, w: f64, p: f64, r: f64) -> Self {
19
+ XyzWpr { x, y, z, w, p, r }
20
+ }
21
+
22
+ pub fn from_isometry(isometry: &Iso3) -> Self {
23
+ let translation = isometry.translation.vector;
24
+ let rotation = isometry.rotation;
25
+ let (r, p, w) = rotation.euler_angles();
26
+ XyzWpr::new(
27
+ translation.x,
28
+ translation.y,
29
+ translation.z,
30
+ w.to_degrees(),
31
+ p.to_degrees(),
32
+ r.to_degrees(),
33
+ )
34
+ }
35
+
36
+ pub fn to_isometry(&self) -> Iso3 {
37
+ let translation = Vector3::new(self.x, self.y, self.z);
38
+ let rotation = UnitQuaternion::from_euler_angles(
39
+ self.r.to_radians(),
40
+ self.p.to_radians(),
41
+ self.w.to_radians(),
42
+ );
43
+ Iso3::from_parts(Translation3::from(translation), rotation)
44
+ }
45
+
46
+ pub fn approx_eq(&self, other: &XyzWpr, epsilon: f64) -> bool {
47
+ let m0 = self.to_isometry().to_matrix();
48
+ let m1 = other.to_isometry().to_matrix();
49
+ let diff = m0 - m1;
50
+ diff.amax() < epsilon
51
+ }
52
+ }
53
+
54
+ impl std::fmt::Display for XyzWpr {
55
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56
+ write!(
57
+ f,
58
+ "XyzWpr {{ x: {}, y: {}, z: {}, w: {}, p: {}, r: {} }}",
59
+ self.x, self.y, self.z, self.w, self.p, self.r
60
+ )
61
+ }
62
+ }
63
+
64
+ #[cfg(test)]
65
+ mod tests {
66
+ use super::*;
67
+ use crate::na::{try_convert, Matrix4};
68
+ use approx::assert_relative_eq;
69
+ use test_case::test_case;
70
+
71
+ #[test_case((-0.8156824504, -0.5743236360, -0.0693866068, -413.8635232282, 0.0004524620, 0.1193088953, -0.9928570807, 263.1863811434, 0.5784997281, -0.8098874913, -0.0970583124, 291.9820746748, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-413.8635232282, 263.1863811434, 291.9820746748, -96.8338333769, -35.3450905433, 179.9682178248))]
72
+ #[test_case((-0.1500516217, 0.5455385155, -0.8245436550, -149.1668440821, 0.9459952737, -0.1631791693, -0.2801169415, 59.3543506644, -0.2873629291, -0.8220464019, -0.4915915582, 543.2838251943, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-149.1668440821, 59.3543506644, 543.2838251943, -120.8798246395, 16.7001441168, 99.0130388728))]
73
+ #[test_case((0.5009445358, 0.6825401810, 0.5321592557, 31.0642288750, -0.8639774486, 0.3581642754, 0.3539227601, -26.7743169615, 0.0509660705, -0.6370692687, 0.7691197609, 37.9006405971, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (31.0642288750, -26.7743169615, 37.9006405971, -39.6352782596, -2.9214064154, -59.8943255222))]
74
+ #[test_case((0.9089103503, -0.4069146210, 0.0911178708, 33.5138781088, -0.0854907806, 0.0320310501, 0.9958239494, 96.1164814542, -0.4081339260, -0.9129044326, -0.0056740956, -300.9032245106, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (33.5138781088, 96.1164814542, -300.9032245106, -90.3561134473, 24.0876647389, -5.3733485621))]
75
+ #[test_case((-0.1653518888, 0.9687851465, -0.1847000075, 77.8658952620, 0.9532759246, 0.2050088803, 0.2218927005, 100.2923343848, 0.2528314941, -0.1393796933, -0.9574181619, -127.6541936118, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (77.8658952620, 100.2923343848, -127.6541936118, -171.7171410357, -14.6451288996, 99.8404139441))]
76
+ #[test_case((-0.4118951499, 0.3279601759, -0.8501673415, -70.6389144769, -0.3403719856, -0.9208299694, -0.1903131075, 22.3217390074, -0.8452746873, 0.2109841002, 0.4909138545, 18.1798498130, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-70.6389144769, 22.3217390074, 18.1798498130, 23.2569815201, 57.7013782986, -140.4311743532))]
77
+ #[test_case((-0.7479917678, -0.6191725989, -0.2390263753, 604.2872268462, -0.4057545090, 0.1415967662, 0.9029471935, -20.9333741686, -0.5252347986, 0.7723830970, -0.3571452893, 30.4479677368, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (604.2872268462, -20.9333741686, 30.4479677368, 114.8155367373, 31.6840511268, -151.5220050073))]
78
+ #[test_case((0.4873440333, 0.6172398073, 0.6176656163, 77.4016768659, 0.3323406191, 0.5230063131, -0.7848656633, -28.4720503689, -0.8074933474, 0.5877749712, 0.0497501464, -19.7908480100, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (77.4016768659, -28.4720503689, -19.7908480100, 85.1619317507, 53.8517426985, 34.2917400153))]
79
+ #[test_case((0.0833272687, 0.6836449300, 0.7250421891, 471.9320306822, -0.8519144952, -0.3286045615, 0.4077508246, -102.6726730677, 0.5170089546, -0.6516507130, 0.5550253049, 588.5120154719, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (471.9320306822, -102.6726730677, 588.5120154719, -49.5782300627, -31.1318310910, -84.4135682965))]
80
+ #[test_case((-0.2510504585, 0.9157805028, -0.3135597837, -577.6445766741, -0.0345374583, -0.3322023607, -0.9425755967, -216.2517731052, -0.9673576543, -0.2258044778, 0.1150282859, 240.9460890915, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-577.6445766741, -216.2517731052, 240.9460890915, -63.0050045001, 75.3203125033, -172.1668871906))]
81
+ #[test_case((0.1791056335, -0.5890186234, -0.7880217213, 411.6803610302, 0.6839325663, -0.5012295385, 0.5300992308, 331.0434986878, -0.7072180829, -0.6338974767, 0.3130759848, -361.9951518329, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (411.6803610302, 331.0434986878, -361.9951518329, -63.7156683382, 45.0090193165, 75.3251405039))]
82
+ #[test_case((-0.7389487926, -0.6540675080, 0.1617107816, 5.4890201453, -0.6393453686, 0.7564348576, 0.1379992968, -26.5744088848, -0.2125845282, -0.0014146255, -0.9771416567, -99.6628429743, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (5.4890201453, -26.5744088848, -99.6628429743, -179.9170519309, 12.2738553488, -139.1333357015))]
83
+ #[test_case((-0.2037395422, 0.6790363200, -0.7052658187, -1.7434467919, -0.8508250650, -0.4791894336, -0.2155787453, -14.7633944063, -0.4843417261, 0.5561359212, 0.6753709570, -79.9344894886, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-1.7434467919, -14.7633944063, -79.9344894886, 39.4698348110, 28.9693530939, -103.4665369616))]
84
+ #[test_case((0.7230637290, 0.1432361537, -0.6757678952, -49.7118498703, 0.5101470443, 0.5488670300, 0.6621895322, 20.3765636776, 0.4657561992, -0.8235462268, 0.3237943410, 8.4422995188, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (-49.7118498703, 20.3765636776, 8.4422995188, -68.5366961539, -27.7591729450, 35.2043221840))]
85
+ #[test_case((0.9572590453, -0.2498925755, 0.1456324858, 59.5794643289, -0.2886479285, -0.7934076632, 0.5358979878, 6.7548483372, -0.0183709982, -0.5550297115, -0.8316276365, -88.8341095469, 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000), (59.5794643289, 6.7548483372, -88.8341095469, -146.2807856754, 1.0526398756, -16.7799423973))]
86
+ fn xyzwpr_to_isometry(
87
+ mf: (
88
+ f64,
89
+ f64,
90
+ f64,
91
+ f64,
92
+ f64,
93
+ f64,
94
+ f64,
95
+ f64,
96
+ f64,
97
+ f64,
98
+ f64,
99
+ f64,
100
+ f64,
101
+ f64,
102
+ f64,
103
+ f64,
104
+ ),
105
+ pf: (f64, f64, f64, f64, f64, f64),
106
+ ) {
107
+ let m = Matrix4::new(
108
+ mf.0, mf.1, mf.2, mf.3, mf.4, mf.5, mf.6, mf.7, mf.8, mf.9, mf.10, mf.11, mf.12, mf.13,
109
+ mf.14, mf.15,
110
+ );
111
+ let p = XyzWpr::new(pf.0, pf.1, pf.2, pf.5, pf.4, pf.3);
112
+ let t = p.to_isometry();
113
+ let m_ = t.to_matrix();
114
+ assert_relative_eq!(m, m_, epsilon = 1e-5);
115
+ }
116
+
117
+ #[test_case((213.3455874397, -541.8828362001, -95.1324602951, -164.2348619634, 24.0489557219, -170.7519141710))]
118
+ #[test_case((70.6318465112, 113.6560228546, 346.7855689786, -26.3445451403, -30.6825741682, -92.3381779921))]
119
+ #[test_case((-18.5208462508, 554.3972482202, 531.8505273397, 24.9359848528, -20.6580074641, -118.2163130322))]
120
+ #[test_case((-279.4908707038, 107.0379921066, 347.6153730196, 141.6846980303, 42.9511504078, 21.8352677126))]
121
+ #[test_case((61.7823486174, 39.0960520469, 7.1731831514, 63.6707920489, 28.5547935126, 65.2651276746))]
122
+ #[test_case((17.8583707934, -103.5277608846, -41.9211021563, -129.0763419754, -64.3075695674, -119.6216242866))]
123
+ #[test_case((381.5649351646, -118.4073378481, 86.8318954547, -69.6420826640, 50.3520931676, -113.9445091815))]
124
+ #[test_case((-46.1766927642, -55.8019771470, -84.1930750980, -148.4720043329, 11.1136514360, 139.1677460882))]
125
+ #[test_case((222.2302724845, -372.5432843996, 266.9542861389, 88.4476440066, 35.3943355124, -166.3788546777))]
126
+ #[test_case((459.8055541953, 401.5061123248, 180.9052529976, 121.5295678361, -30.3457576176, 66.0945383908))]
127
+ #[test_case((-68.9503102461, -79.4547936268, -62.0503091459, 121.1860503955, 5.5438249089, -33.3572843285))]
128
+ fn xyzwpr_from_isometry(pf: (f64, f64, f64, f64, f64, f64)) {
129
+ let p = XyzWpr::new(pf.0, pf.1, pf.2, pf.5, pf.4, pf.3);
130
+ let i = p.to_isometry();
131
+
132
+ let p_ = XyzWpr::from_isometry(&i);
133
+
134
+ assert_relative_eq!(p.x, p_.x, epsilon = 1e-5);
135
+ assert_relative_eq!(p.y, p_.y, epsilon = 1e-5);
136
+ assert_relative_eq!(p.z, p_.z, epsilon = 1e-5);
137
+ assert_relative_eq!(p.w, p_.w, epsilon = 1e-5);
138
+ assert_relative_eq!(p.p, p_.p, epsilon = 1e-5);
139
+ assert_relative_eq!(p.r, p_.r, epsilon = 1e-5);
140
+ }
141
+ }
@@ -4,6 +4,7 @@ pub mod mesh;
4
4
  mod plane3;
5
5
  mod point_cloud;
6
6
  mod iso3;
7
+ mod xyzwpr;
7
8
 
8
9
  use parry3d_f64::na::UnitQuaternion;
9
10
 
@@ -17,6 +18,7 @@ pub use mesh::{Mesh, UvMapping, MeshCollisionSet};
17
18
  pub use plane3::Plane3;
18
19
  pub use point_cloud::{PointCloud, PointCloudFeatures, PointCloudKdTree};
19
20
  pub use iso3::IsoExtensions3;
21
+ pub use xyzwpr::XyzWpr;
20
22
 
21
23
  pub type Point3 = parry3d_f64::na::Point3<f64>;
22
24
  pub type Vector3 = parry3d_f64::na::Vector3<f64>;
@@ -15,6 +15,10 @@ pub mod sensor;
15
15
 
16
16
  pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
17
17
 
18
+ // Re-export parry and nalgebra
19
+ pub use parry3d_f64::na as na;
20
+ pub use parry3d_f64 as parry3d;
21
+
18
22
  // Common one dimensional functions
19
23
  pub use func1::{Func1, Gaussian1, Line1, Polynomial, Series1};
20
24
 
@@ -461,6 +461,29 @@ class Iso3:
461
461
  """
462
462
  ...
463
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
+
464
487
  def __matmul__(self, other: Transformable3) -> Transformable3:
465
488
  """
466
489
  Multiply another object by the isometry, transforming it and returning a new object of the same type.
@@ -537,6 +560,14 @@ class Iso3:
537
560
  """
538
561
  ...
539
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
+
540
571
  def translation(self) -> Iso3:
541
572
  """
542
573
  Return the translation component of the isometry as a separate isometry.
@@ -1157,14 +1188,14 @@ class Mesh:
1157
1188
  ...
1158
1189
 
1159
1190
  @staticmethod
1160
- def create_box(width: float, height: float, depth: float) -> Mesh:
1191
+ def create_box(length: float, width: float, height: float) -> Mesh:
1161
1192
  """
1162
- Creates a box with the corner at the origin and the specified width, height, and depth all positive.
1193
+ Creates a box with the center at the origin and the specified length, width, and height
1163
1194
 
1164
- :param width:
1165
- :param height:
1166
- :param depth:
1167
- :return:
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
1168
1199
  """
1169
1200
  ...
1170
1201
 
@@ -1172,14 +1203,91 @@ class Mesh:
1172
1203
  def create_cylinder(radius: float, height: float, steps: int) -> Mesh:
1173
1204
  """
1174
1205
  Creates a cylinder with a radius and height. The cylinder will be centered at the origin and oriented along the
1175
- Z-axis. The bottom of the cylinder will be at Z = 0 and the top will be at Z = height. The cylinder will be
1176
- created with a number of steps around the circumference, which will determine the number of vertices used to
1177
- create the cylinder. The number of steps should be at least 3. The first set of vertices will be at X = radius,
1178
- Y = 0.
1179
- :param radius:
1180
- :param height:
1181
- :param steps:
1182
- :return:
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
1183
1291
  """
1184
1292
  ...
1185
1293
 
@@ -1304,6 +1412,7 @@ class MeshCollisionSet:
1304
1412
  """
1305
1413
  ...
1306
1414
 
1415
+
1307
1416
  class CurveStation3:
1308
1417
  """
1309
1418
  A class representing a station along a curve in 3D space. The station is represented by a point on the curve, a
@@ -614,6 +614,74 @@ impl From<engeom::CurveStation3<'_>> for CurveStation3 {
614
614
  // Transformations
615
615
  // ================================================================================================
616
616
 
617
+ #[pyclass]
618
+ #[derive(Clone, Debug)]
619
+ pub struct XyzWpr {
620
+ inner: engeom::geom3::XyzWpr,
621
+ }
622
+
623
+ impl XyzWpr {
624
+ pub fn get_inner(&self) -> &engeom::geom3::XyzWpr {
625
+ &self.inner
626
+ }
627
+
628
+ pub fn from_inner(inner: engeom::geom3::XyzWpr) -> Self {
629
+ Self { inner }
630
+ }
631
+ }
632
+
633
+ // #[pymethods]
634
+ // impl XyzWpr {
635
+ // #[new]
636
+ // fn new(x: f64, y: f64, z: f64, w: f64, p: f64, r: f64) -> Self {
637
+ // Self {
638
+ // inner: engeom::geom3::XyzWpr::new(x, y, z, w, p, r),
639
+ // }
640
+ // }
641
+ //
642
+ // #[getter]
643
+ // fn values(&self) -> Vec<f64> {
644
+ // vec![
645
+ // self.inner.x,
646
+ // self.inner.y,
647
+ // self.inner.z,
648
+ // self.inner.w,
649
+ // self.inner.p,
650
+ // self.inner.r,
651
+ // ]
652
+ // }
653
+ //
654
+ // #[getter]
655
+ // fn x(&self) -> f64 {
656
+ // self.inner.x
657
+ // }
658
+ //
659
+ // #[getter]
660
+ // fn y(&self) -> f64 {
661
+ // self.inner.y
662
+ // }
663
+ //
664
+ // #[getter]
665
+ // fn z(&self) -> f64 {
666
+ // self.inner.z
667
+ // }
668
+ //
669
+ // #[getter]
670
+ // fn w(&self) -> f64 {
671
+ // self.inner.w
672
+ // }
673
+ //
674
+ // #[getter]
675
+ // fn p(&self) -> f64 {
676
+ // self.inner.p
677
+ // }
678
+ //
679
+ // #[getter]
680
+ // fn r(&self) -> f64 {
681
+ // self.inner.r
682
+ // }
683
+ // }
684
+
617
685
  #[derive(FromPyObject)]
618
686
  enum Transformable3 {
619
687
  Iso(Iso3),
@@ -654,6 +722,27 @@ impl Iso3 {
654
722
  )
655
723
  }
656
724
 
725
+ #[getter]
726
+ fn origin(&self) -> Point3 {
727
+ Point3::from_inner(engeom::Point3::new(
728
+ self.inner.translation.x,
729
+ self.inner.translation.y,
730
+ self.inner.translation.z,
731
+ ))
732
+ }
733
+
734
+ #[staticmethod]
735
+ fn from_xyzwpr(x: f64, y: f64, z: f64, w: f64, p: f64, r: f64) -> Self {
736
+ Self {
737
+ inner: engeom::geom3::XyzWpr::new(x, y, z, w, p, r).to_isometry(),
738
+ }
739
+ }
740
+
741
+ fn to_xyzwpr(&self) -> Vec<f64> {
742
+ let v = engeom::geom3::XyzWpr::from_isometry(&self.inner);
743
+ vec![v.x, v.y, v.z, v.w, v.p, v.r]
744
+ }
745
+
657
746
  #[new]
658
747
  fn new(matrix: PyReadonlyArrayDyn<'_, f64>) -> PyResult<Self> {
659
748
  if matrix.shape().len() != 2 || matrix.shape()[0] != 4 || matrix.shape()[1] != 4 {
@@ -769,13 +858,13 @@ impl Iso3 {
769
858
 
770
859
  fn translation(&self) -> Iso3 {
771
860
  Self {
772
- inner: engeom::Iso3::from_parts(self.inner.translation, UnitQuaternion::identity())
861
+ inner: engeom::Iso3::from_parts(self.inner.translation, UnitQuaternion::identity()),
773
862
  }
774
863
  }
775
864
 
776
865
  fn rotation(&self) -> Iso3 {
777
866
  Self {
778
- inner: engeom::Iso3::from_parts(Translation3::identity(), self.inner.rotation)
867
+ inner: engeom::Iso3::from_parts(Translation3::identity(), self.inner.rotation),
779
868
  }
780
869
  }
781
870