engeom 0.2.10__tar.gz → 0.2.12__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.12}/Cargo.lock +1 -1
  2. {engeom-0.2.10 → engeom-0.2.12}/Cargo.toml +1 -1
  3. {engeom-0.2.10 → engeom-0.2.12}/PKG-INFO +1 -1
  4. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh.rs +68 -21
  5. engeom-0.2.12/engeom/src/geom3/xyzwpr.rs +141 -0
  6. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3.rs +2 -0
  7. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/lib.rs +4 -0
  8. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/geom2.pyi +77 -0
  9. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/geom3.pyi +187 -14
  10. {engeom-0.2.10 → engeom-0.2.12}/src/bounding.rs +12 -0
  11. {engeom-0.2.10 → engeom-0.2.12}/src/conversions.rs +14 -1
  12. {engeom-0.2.10 → engeom-0.2.12}/src/geom2.rs +76 -3
  13. {engeom-0.2.10 → engeom-0.2.12}/src/geom3.rs +75 -2
  14. {engeom-0.2.10 → engeom-0.2.12}/src/mesh.rs +72 -12
  15. {engeom-0.2.10 → engeom-0.2.12}/.github/workflows/CI.yml +0 -0
  16. {engeom-0.2.10 → engeom-0.2.12}/.gitignore +0 -0
  17. {engeom-0.2.10 → engeom-0.2.12}/.gitmodules +0 -0
  18. {engeom-0.2.10 → engeom-0.2.12}/README.md +0 -0
  19. {engeom-0.2.10 → engeom-0.2.12}/docs/airfoils/intro.md +0 -0
  20. {engeom-0.2.10 → engeom-0.2.12}/docs/api/airfoil.md +0 -0
  21. {engeom-0.2.10 → engeom-0.2.12}/docs/api/engeom.md +0 -0
  22. {engeom-0.2.10 → engeom-0.2.12}/docs/api/geom2.md +0 -0
  23. {engeom-0.2.10 → engeom-0.2.12}/docs/api/geom3.md +0 -0
  24. {engeom-0.2.10 → engeom-0.2.12}/docs/api/metrology.md +0 -0
  25. {engeom-0.2.10 → engeom-0.2.12}/docs/api/plot.md +0 -0
  26. {engeom-0.2.10 → engeom-0.2.12}/docs/bounding_volumes.md +0 -0
  27. {engeom-0.2.10 → engeom-0.2.12}/docs/curves.md +0 -0
  28. {engeom-0.2.10 → engeom-0.2.12}/docs/images/surface_point_meas.svg +0 -0
  29. {engeom-0.2.10 → engeom-0.2.12}/docs/index.md +0 -0
  30. {engeom-0.2.10 → engeom-0.2.12}/docs/isometries.md +0 -0
  31. {engeom-0.2.10 → engeom-0.2.12}/docs/meshes.md +0 -0
  32. {engeom-0.2.10 → engeom-0.2.12}/docs/metrology.md +0 -0
  33. {engeom-0.2.10 → engeom-0.2.12}/docs/numpy.md +0 -0
  34. {engeom-0.2.10 → engeom-0.2.12}/docs/planes_circles_lines.md +0 -0
  35. {engeom-0.2.10 → engeom-0.2.12}/docs/points_vectors.md +0 -0
  36. {engeom-0.2.10 → engeom-0.2.12}/docs/surf_points.md +0 -0
  37. {engeom-0.2.10 → engeom-0.2.12}/docs/svd_basis.md +0 -0
  38. {engeom-0.2.10 → engeom-0.2.12}/engeom/.gitignore +0 -0
  39. {engeom-0.2.10 → engeom-0.2.12}/engeom/Cargo.lock +0 -0
  40. {engeom-0.2.10 → engeom-0.2.12}/engeom/Cargo.toml +0 -0
  41. {engeom-0.2.10 → engeom-0.2.12}/engeom/README.md +0 -0
  42. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/airfoils/camber.md +0 -0
  43. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/airfoils/overview.md +0 -0
  44. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/common/angles.md +0 -0
  45. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/common/core_space.md +0 -0
  46. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/common/discrete_domain.md +0 -0
  47. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/common/images/surface_point_meas.svg +0 -0
  48. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/common/svd_basis.md +0 -0
  49. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/geom2/alignment.md +0 -0
  50. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/geom2/curve.md +0 -0
  51. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/geom2/point_collections.md +0 -0
  52. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/geom2/shapes.md +0 -0
  53. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/index.md +0 -0
  54. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/javascripts/mathjax.js +0 -0
  55. {engeom-0.2.10 → engeom-0.2.12}/engeom/docs/python_rust.md +0 -0
  56. {engeom-0.2.10 → engeom-0.2.12}/engeom/mkdocs.yml +0 -0
  57. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil/camber.rs +0 -0
  58. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil/edges.rs +0 -0
  59. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil/helpers.rs +0 -0
  60. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil/inscribed_circle.rs +0 -0
  61. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil/orientation.rs +0 -0
  62. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/airfoil.rs +0 -0
  63. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/align.rs +0 -0
  64. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/angles.rs +0 -0
  65. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/convert_2d_3d.rs +0 -0
  66. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/discrete_domain.rs +0 -0
  67. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/indices.rs +0 -0
  68. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/interval.rs +0 -0
  69. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/kd_tree.rs +0 -0
  70. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/points.rs +0 -0
  71. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/poisson_disk.rs +0 -0
  72. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/surface_point.rs +0 -0
  73. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/svd_basis.rs +0 -0
  74. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common/vec_f64.rs +0 -0
  75. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/common.rs +0 -0
  76. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/errors.rs +0 -0
  77. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/func1/common_functions.rs +0 -0
  78. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/func1/polynomial.rs +0 -0
  79. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/func1/series1.rs +0 -0
  80. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/func1.rs +0 -0
  81. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/aabb2.rs +0 -0
  82. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/align2/jacobian.rs +0 -0
  83. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/align2/points_to_curve.rs +0 -0
  84. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/align2/rc_params2.rs +0 -0
  85. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/align2.rs +0 -0
  86. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/angles2.rs +0 -0
  87. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/circle2.rs +0 -0
  88. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/curve2.rs +0 -0
  89. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/hull.rs +0 -0
  90. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/line2.rs +0 -0
  91. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2/polyline2.rs +0 -0
  92. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom2.rs +0 -0
  93. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/align3/jacobian.rs +0 -0
  94. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/align3/multi_param.rs +0 -0
  95. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/align3/points_to_mesh.rs +0 -0
  96. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/align3/rotations.rs +0 -0
  97. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/align3.rs +0 -0
  98. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/curve3.rs +0 -0
  99. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/iso3.rs +0 -0
  100. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/collisions.rs +0 -0
  101. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/conformal.rs +0 -0
  102. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/edges.rs +0 -0
  103. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/faces.rs +0 -0
  104. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/filtering.rs +0 -0
  105. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/measurement.rs +0 -0
  106. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/outline.rs +0 -0
  107. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/patches.rs +0 -0
  108. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/queries.rs +0 -0
  109. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/sampling.rs +0 -0
  110. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/mesh/uv_mapping.rs +0 -0
  111. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/plane3.rs +0 -0
  112. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/geom3/point_cloud.rs +0 -0
  113. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/io.rs +0 -0
  114. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology/dimension.rs +0 -0
  115. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology/line_profiles.rs +0 -0
  116. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology/surface_deviation.rs +0 -0
  117. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology/tolerance.rs +0 -0
  118. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology/tolerance_map.rs +0 -0
  119. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/metrology.rs +0 -0
  120. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/raster3.rs +0 -0
  121. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/sensor.rs +0 -0
  122. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/stats.rs +0 -0
  123. {engeom-0.2.10 → engeom-0.2.12}/engeom/src/utility.rs +0 -0
  124. {engeom-0.2.10 → engeom-0.2.12}/mkdocs.yml +0 -0
  125. {engeom-0.2.10 → engeom-0.2.12}/pyproject.toml +0 -0
  126. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/__init__.py +0 -0
  127. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/_plot/__init__.py +0 -0
  128. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/_plot/common.py +0 -0
  129. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/_plot/matplotlib.py +0 -0
  130. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/_plot/pyvista.py +0 -0
  131. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/airfoil/__init__.py +0 -0
  132. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/airfoil.pyi +0 -0
  133. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/align/__init__.py +0 -0
  134. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/align.pyi +0 -0
  135. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/engeom.pyi +0 -0
  136. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/geom2/__init__.py +0 -0
  137. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/geom3/__init__.py +0 -0
  138. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/metrology/__init__.py +0 -0
  139. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/metrology.pyi +0 -0
  140. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/plot.py +0 -0
  141. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/raster3/__init__.py +0 -0
  142. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/raster3.pyi +0 -0
  143. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/sensor/__init__.py +0 -0
  144. {engeom-0.2.10 → engeom-0.2.12}/python/engeom/sensor.pyi +0 -0
  145. {engeom-0.2.10 → engeom-0.2.12}/python/tests/test_all.py +0 -0
  146. {engeom-0.2.10 → engeom-0.2.12}/python/tests/test_geom2_simple.py +0 -0
  147. {engeom-0.2.10 → engeom-0.2.12}/python/tests/test_geom3_simple.py +0 -0
  148. {engeom-0.2.10 → engeom-0.2.12}/src/airfoil.rs +0 -0
  149. {engeom-0.2.10 → engeom-0.2.12}/src/alignments.rs +0 -0
  150. {engeom-0.2.10 → engeom-0.2.12}/src/common.rs +0 -0
  151. {engeom-0.2.10 → engeom-0.2.12}/src/lib.rs +0 -0
  152. {engeom-0.2.10 → engeom-0.2.12}/src/metrology.rs +0 -0
  153. {engeom-0.2.10 → engeom-0.2.12}/src/raster.rs +0 -0
  154. {engeom-0.2.10 → engeom-0.2.12}/src/ray_casting.rs +0 -0
  155. {engeom-0.2.10 → engeom-0.2.12}/src/sensor.rs +0 -0
  156. {engeom-0.2.10 → engeom-0.2.12}/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.12"
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.12"
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.12
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
 
@@ -138,6 +138,22 @@ class Vector2(Iterable[float]):
138
138
  """
139
139
  ...
140
140
 
141
+ def with_x(self, x: float) -> Vector2:
142
+ """
143
+ Return a new vector with the same y component as this vector, but with the x component set to the given value.
144
+ :param x: the new x component of the vector.
145
+ :return: a new vector with the same y component as this vector, but with the x component set to the given value.
146
+ """
147
+ ...
148
+
149
+ def with_y(self, y: float) -> Vector2:
150
+ """
151
+ Return a new vector with the same x component as this vector, but with the y component set to the given value.
152
+ :param y: the new y component of the vector.
153
+ :return: a new vector with the same x component as this vector, but with the y component set to the given value.
154
+ """
155
+ ...
156
+
141
157
 
142
158
  class Point2(Iterable[float]):
143
159
  """
@@ -243,6 +259,22 @@ class Point2(Iterable[float]):
243
259
  """
244
260
  ...
245
261
 
262
+ def with_x(self, x: float) -> Point2:
263
+ """
264
+ Return a new point with the same y component as this point, but with the x component set to the given value.
265
+ :param x: the new x component of the point.
266
+ :return: a new point with the same y component as this point, but with the x component set to the given value.
267
+ """
268
+ ...
269
+
270
+ def with_y(self, y: float) -> Point2:
271
+ """
272
+ Return a new point with the same x component as this point, but with the y component set to the given value.
273
+ :param y: the new y component of the point.
274
+ :return: a new point with the same x component as this point, but with the y component set to the given value.
275
+ """
276
+ ...
277
+
246
278
 
247
279
  class SurfacePoint2:
248
280
  """
@@ -950,6 +982,43 @@ class Circle2:
950
982
  """
951
983
  ...
952
984
 
985
+ @staticmethod
986
+ def fitting(points: NDArray[float], guess: Circle2 | None = None, sigma: float | None = None) -> Circle2:
987
+ """
988
+ Fit a circle to a set of points using an unconstrained Levenberg-Marquardt minimization of the sum of
989
+ squared errors between the points and the boundary of the circle.
990
+
991
+ The initial guess is used to provide a starting point for the optimization. If no guess is provided, the
992
+ unit circle will be used.
993
+
994
+ The sigma parameter is used to weight the points in the optimization. If no sigma is provided, all points
995
+ will be weighted equally, otherwise points beyond `sigma` standard deviations from the mean will be
996
+ assigned a weight of 0.0.
997
+ :param points: the points to fit the circle to.
998
+ :param guess: an optional initial guess for the circle. If None, the unit circle will be used.
999
+ :param sigma: an optional standard deviation to use for weighting the points. If None, all points will be
1000
+ weighted equally.
1001
+ :return: a new `Circle2` object representing the fitted circle.
1002
+ """
1003
+ ...
1004
+
1005
+ @staticmethod
1006
+ def ransac(points: NDArray[float], tol: float, iterations: int | None = None, min_r: float | None = None,
1007
+ max_r: float | None = None) -> Circle2:
1008
+ """
1009
+ Fit a circle to a set of points using the RANSAC algorithm. The algorithm will randomly sample points from the
1010
+ input set and fit a circle to them, then check how many points are within the given tolerance of the fitted
1011
+ circle. The best fitting circle will be returned.
1012
+
1013
+ :param points: the points to fit the circle to.
1014
+ :param tol: the tolerance for the RANSAC algorithm.
1015
+ :param iterations: the number of iterations to run. If None, a default value of 500 will be used.
1016
+ :param min_r: the minimum radius of the circle. If None, no minimum will be enforced.
1017
+ :param max_r: the maximum radius of the circle. If None, no maximum will be enforced.
1018
+ :return: a new `Circle2` object representing the fitted circle.
1019
+ """
1020
+ ...
1021
+
953
1022
 
954
1023
  class Arc2:
955
1024
  """
@@ -1148,3 +1217,11 @@ class Aabb2:
1148
1217
  :return: a new AABB object with the shrunk bounds.
1149
1218
  """
1150
1219
  ...
1220
+
1221
+ def merged(self, other: Aabb2) -> Aabb2:
1222
+ """
1223
+ Merge this AABB with another AABB and return a new AABB.
1224
+ :param other: the other AABB to merge with.
1225
+ :return: a new AABB object that is the result of merging this AABB with the other AABB.
1226
+ """
1227
+ ...