engeom 0.2.15__tar.gz → 0.2.16__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.
- {engeom-0.2.15 → engeom-0.2.16}/Cargo.lock +13 -85
- {engeom-0.2.15 → engeom-0.2.16}/Cargo.toml +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/PKG-INFO +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/Cargo.toml +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil/helpers.rs +12 -12
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/discrete_domain.rs +64 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/domain_window.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/index_mask.rs +7 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/kd_tree.rs +59 -39
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/points.rs +20 -4
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/poisson_disk.rs +3 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/svd_basis.rs +10 -6
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/func1/series1.rs +4 -7
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/circle2.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/curve2.rs +16 -16
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/hull.rs +11 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/polyline2.rs +4 -4
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/mesh.rs +49 -6
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/multi_mesh.rs +47 -19
- engeom-0.2.16/engeom/src/geom3/align3/point_stability.rs +251 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3.rs +10 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/curve3.rs +14 -14
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/collisions.rs +4 -5
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/edges.rs +0 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/filtering.rs +89 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/half_edge/smoothing.rs +4 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/nav_structure.rs +390 -337
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/sampling.rs +3 -3
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/uv_mapping.rs +2 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh.rs +5 -13
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/plane3.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/point_cloud/normal_estimation.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/point_cloud.rs +45 -16
- engeom-0.2.16/engeom/src/io/lptf3/comprehensive.rs +151 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io/lptf3/downsample.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io/lptf3/loader.rs +14 -10
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io/lptf3.rs +39 -1
- engeom-0.2.16/engeom/src/io/point_cloud.rs +148 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io.rs +3 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/lib.rs +1 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology/line_profiles.rs +4 -4
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/kernel.rs +9 -4
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/mapping.rs +1 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/raster_mask.rs +21 -12
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/region_labeling.rs +2 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/roi.rs +3 -3
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/roi_mask.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/scalar_raster.rs +28 -5
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/sensors/laser_profile.rs +20 -3
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/sensors.rs +56 -56
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/stats.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/td/simple_viewer.rs +1 -2
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/utility.rs +2 -2
- {engeom-0.2.15 → engeom-0.2.16/py-engeom}/python/engeom/geom3.pyi +31 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/geom3.rs +6 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/mesh.rs +9 -1
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/point_cloud.rs +8 -2
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/svd_basis.rs +18 -2
- {engeom-0.2.15/py-engeom → engeom-0.2.16}/python/engeom/geom3.pyi +31 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/benches/convolution.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/benches/down_sample.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/benches/index_mask.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/benches/raster_ball_rolling.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/airfoils/camber.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/airfoils/overview.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/common/angles.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/common/core_space.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/common/discrete_domain.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/common/images/surface_point_meas.svg +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/common/svd_basis.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/geom2/alignment.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/geom2/curve.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/geom2/point_collections.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/geom2/shapes.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/index.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/javascripts/mathjax.js +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/docs/python_rust.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/mkdocs.yml +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil/camber.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil/edges.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil/inscribed_circle.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil/orientation.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/airfoil.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/align.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/angles.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/average.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/convert_2d_3d.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/domain_map.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/indices.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/interval.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/surface_point.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/triangulation/parallel_row2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/triangulation.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/vec_f64.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common/voxel_downsample.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/common.rs +1 -1
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/errors.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/func1/common_functions.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/func1/polynomial.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/func1.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/aabb2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/align2/jacobian.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/align2/points_to_curve.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/align2/rc_params2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/align2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/angles2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2/line2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/jacobian.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/mesh_overlap.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/mesh_to_mesh.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/multi_param.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/points_to_cloud.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/points_to_mesh.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/align3/rotations.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/iso3.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/conformal.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/faces.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/half_edge.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/measurement.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/outline.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/mesh/queries.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3/xyzwpr.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/geom3.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io/lptf3/mesh.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/io/lptf3/uncertainty.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology/dimension.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology/surface_deviation.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology/tolerance.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology/tolerance_map.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/metrology.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/area_average.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/ball_rolling.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/index_iter.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/inpaint.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/mask_ops.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/visualize.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2/zhang_suen.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/raster3.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/td/common.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/td/control.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/td/conversion.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/engeom/src/td.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/Cargo.toml +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/airfoils/intro.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/airfoil.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/engeom.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/geom2.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/geom3.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/metrology.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/api/plot.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/bounding_volumes.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/curves.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/images/surface_point_meas.svg +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/index.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/isometries.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/meshes.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/metrology.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/numpy.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/planes_circles_lines.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/points_vectors.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/surf_points.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/docs/svd_basis.md +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/mkdocs.yml +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/_plot/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/_plot/common.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/_plot/matplotlib.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/_plot/pyvista.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/airfoil/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/airfoil.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/align/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/align.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/engeom.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/geom2/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/geom2.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/geom3/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/metrology/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/metrology.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/plot.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/raster3/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/raster3.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/sensors/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/engeom/sensors.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/tests/test_all.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/tests/test_geom2_simple.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/python/tests/test_geom3_simple.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/airfoil.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/alignments.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/bounding.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/common.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/conversions.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/geom2.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/lib.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/metrology.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/raster.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/ray_casting.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/py-engeom/src/sensors.rs +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/pyproject.toml +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/_plot/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/_plot/common.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/_plot/matplotlib.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/_plot/pyvista.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/airfoil/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/airfoil.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/align/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/align.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/engeom.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/geom2/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/geom2.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/geom3/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/metrology/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/metrology.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/plot.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/raster3/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/raster3.pyi +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/sensors/__init__.py +0 -0
- {engeom-0.2.15 → engeom-0.2.16}/python/engeom/sensors.pyi +0 -0
|
@@ -147,12 +147,6 @@ dependencies = [
|
|
|
147
147
|
"syn 2.0.104",
|
|
148
148
|
]
|
|
149
149
|
|
|
150
|
-
[[package]]
|
|
151
|
-
name = "array-init"
|
|
152
|
-
version = "2.1.0"
|
|
153
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
154
|
-
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
|
155
|
-
|
|
156
150
|
[[package]]
|
|
157
151
|
name = "arrayref"
|
|
158
152
|
version = "0.3.9"
|
|
@@ -207,12 +201,6 @@ dependencies = [
|
|
|
207
201
|
"arrayvec",
|
|
208
202
|
]
|
|
209
203
|
|
|
210
|
-
[[package]]
|
|
211
|
-
name = "az"
|
|
212
|
-
version = "1.2.1"
|
|
213
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
214
|
-
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
|
|
215
|
-
|
|
216
204
|
[[package]]
|
|
217
205
|
name = "bit_field"
|
|
218
206
|
version = "0.10.2"
|
|
@@ -449,12 +437,6 @@ version = "0.7.5"
|
|
|
449
437
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
450
438
|
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
|
451
439
|
|
|
452
|
-
[[package]]
|
|
453
|
-
name = "cmov"
|
|
454
|
-
version = "0.3.1"
|
|
455
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
456
|
-
checksum = "1b1dc960ba75d543267db9254da8ec1cb318a037beb3f8d2497520e410096fab"
|
|
457
|
-
|
|
458
440
|
[[package]]
|
|
459
441
|
name = "color_quant"
|
|
460
442
|
version = "1.1.0"
|
|
@@ -664,12 +646,6 @@ version = "0.2.0"
|
|
|
664
646
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
665
647
|
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
|
666
648
|
|
|
667
|
-
[[package]]
|
|
668
|
-
name = "divrem"
|
|
669
|
-
version = "1.0.0"
|
|
670
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
671
|
-
checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82"
|
|
672
|
-
|
|
673
649
|
[[package]]
|
|
674
650
|
name = "dlib"
|
|
675
651
|
version = "0.5.2"
|
|
@@ -679,12 +655,6 @@ dependencies = [
|
|
|
679
655
|
"libloading 0.8.8",
|
|
680
656
|
]
|
|
681
657
|
|
|
682
|
-
[[package]]
|
|
683
|
-
name = "doc-comment"
|
|
684
|
-
version = "0.3.3"
|
|
685
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
686
|
-
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
|
687
|
-
|
|
688
658
|
[[package]]
|
|
689
659
|
name = "downcast-rs"
|
|
690
660
|
version = "1.2.1"
|
|
@@ -723,7 +693,7 @@ dependencies = [
|
|
|
723
693
|
|
|
724
694
|
[[package]]
|
|
725
695
|
name = "engeom"
|
|
726
|
-
version = "0.2.
|
|
696
|
+
version = "0.2.16"
|
|
727
697
|
dependencies = [
|
|
728
698
|
"alum",
|
|
729
699
|
"approx 0.5.1",
|
|
@@ -733,7 +703,7 @@ dependencies = [
|
|
|
733
703
|
"faer",
|
|
734
704
|
"imageproc",
|
|
735
705
|
"itertools 0.14.0",
|
|
736
|
-
"
|
|
706
|
+
"kdtree",
|
|
737
707
|
"levenberg-marquardt",
|
|
738
708
|
"num-traits",
|
|
739
709
|
"parry2d-f64",
|
|
@@ -885,19 +855,6 @@ dependencies = [
|
|
|
885
855
|
"simd-adler32",
|
|
886
856
|
]
|
|
887
857
|
|
|
888
|
-
[[package]]
|
|
889
|
-
name = "fixed"
|
|
890
|
-
version = "1.29.0"
|
|
891
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
892
|
-
checksum = "707070ccf8c4173548210893a0186e29c266901b71ed20cd9e2ca0193dfe95c3"
|
|
893
|
-
dependencies = [
|
|
894
|
-
"az",
|
|
895
|
-
"bytemuck",
|
|
896
|
-
"half",
|
|
897
|
-
"num-traits",
|
|
898
|
-
"typenum",
|
|
899
|
-
]
|
|
900
|
-
|
|
901
858
|
[[package]]
|
|
902
859
|
name = "flate2"
|
|
903
860
|
version = "1.1.2"
|
|
@@ -1441,32 +1398,21 @@ dependencies = [
|
|
|
1441
1398
|
]
|
|
1442
1399
|
|
|
1443
1400
|
[[package]]
|
|
1444
|
-
name = "
|
|
1445
|
-
version = "
|
|
1446
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1447
|
-
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|
1448
|
-
|
|
1449
|
-
[[package]]
|
|
1450
|
-
name = "kiddo"
|
|
1451
|
-
version = "5.2.1"
|
|
1401
|
+
name = "kdtree"
|
|
1402
|
+
version = "0.7.0"
|
|
1452
1403
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1453
|
-
checksum = "
|
|
1404
|
+
checksum = "0f0a0e9f770b65bac9aad00f97a67ab5c5319effed07f6da385da3c2115e47ba"
|
|
1454
1405
|
dependencies = [
|
|
1455
|
-
"aligned-vec",
|
|
1456
|
-
"array-init",
|
|
1457
|
-
"az",
|
|
1458
|
-
"cmov",
|
|
1459
|
-
"divrem",
|
|
1460
|
-
"doc-comment",
|
|
1461
|
-
"fixed",
|
|
1462
|
-
"generator",
|
|
1463
1406
|
"num-traits",
|
|
1464
|
-
"
|
|
1465
|
-
"sorted-vec",
|
|
1466
|
-
"tracing",
|
|
1467
|
-
"tracing-subscriber",
|
|
1407
|
+
"thiserror 1.0.69",
|
|
1468
1408
|
]
|
|
1469
1409
|
|
|
1410
|
+
[[package]]
|
|
1411
|
+
name = "khronos_api"
|
|
1412
|
+
version = "3.1.0"
|
|
1413
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1414
|
+
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
|
1415
|
+
|
|
1470
1416
|
[[package]]
|
|
1471
1417
|
name = "lazy_static"
|
|
1472
1418
|
version = "1.5.0"
|
|
@@ -2417,7 +2363,7 @@ dependencies = [
|
|
|
2417
2363
|
|
|
2418
2364
|
[[package]]
|
|
2419
2365
|
name = "py-engeom"
|
|
2420
|
-
version = "0.2.
|
|
2366
|
+
version = "0.2.16"
|
|
2421
2367
|
dependencies = [
|
|
2422
2368
|
"engeom",
|
|
2423
2369
|
"numpy",
|
|
@@ -3065,12 +3011,6 @@ dependencies = [
|
|
|
3065
3011
|
"wayland-protocols",
|
|
3066
3012
|
]
|
|
3067
3013
|
|
|
3068
|
-
[[package]]
|
|
3069
|
-
name = "sorted-vec"
|
|
3070
|
-
version = "0.8.6"
|
|
3071
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3072
|
-
checksum = "d372029cb5195f9ab4e4b9aef550787dce78b124fcaee8d82519925defcd6f0d"
|
|
3073
|
-
|
|
3074
3014
|
[[package]]
|
|
3075
3015
|
name = "spade"
|
|
3076
3016
|
version = "2.14.0"
|
|
@@ -3408,21 +3348,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
3408
3348
|
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
|
3409
3349
|
dependencies = [
|
|
3410
3350
|
"pin-project-lite",
|
|
3411
|
-
"tracing-attributes",
|
|
3412
3351
|
"tracing-core",
|
|
3413
3352
|
]
|
|
3414
3353
|
|
|
3415
|
-
[[package]]
|
|
3416
|
-
name = "tracing-attributes"
|
|
3417
|
-
version = "0.1.30"
|
|
3418
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3419
|
-
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
|
3420
|
-
dependencies = [
|
|
3421
|
-
"proc-macro2",
|
|
3422
|
-
"quote",
|
|
3423
|
-
"syn 2.0.104",
|
|
3424
|
-
]
|
|
3425
|
-
|
|
3426
3354
|
[[package]]
|
|
3427
3355
|
name = "tracing-core"
|
|
3428
3356
|
version = "0.1.34"
|
|
@@ -22,10 +22,10 @@ bitvec = {version = "1.0.1", features = ["serde"]}
|
|
|
22
22
|
serde_json = "1.0.140"
|
|
23
23
|
itertools = "0.14.0"
|
|
24
24
|
levenberg-marquardt = "0.14.0"
|
|
25
|
-
kiddo = "5.2.1"
|
|
26
25
|
stl_io = { version = "0.8.5", optional = true }
|
|
27
26
|
num-traits = "0.2.19"
|
|
28
27
|
faer = "0.22.6"
|
|
28
|
+
kdtree = "0.7.0"
|
|
29
29
|
|
|
30
30
|
imageproc = "0.25.0"
|
|
31
31
|
colorgrad = "0.7.2"
|
|
@@ -244,16 +244,16 @@ pub fn extract_edge_sub_curve(
|
|
|
244
244
|
|
|
245
245
|
let perimeter = section.length();
|
|
246
246
|
|
|
247
|
-
if let Some(p0) = portion0
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
if let Some(p0) = portion0
|
|
248
|
+
&& p0.length() < perimeter * frac
|
|
249
|
+
{
|
|
250
|
+
return Some(p0);
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
if let Some(p1) = portion1
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
253
|
+
if let Some(p1) = portion1
|
|
254
|
+
&& p1.length() < perimeter * frac
|
|
255
|
+
{
|
|
256
|
+
return Some(p1);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
None
|
|
@@ -357,10 +357,10 @@ impl OrientedCircles {
|
|
|
357
357
|
pub fn push(&mut self, circle: InscribedCircle) {
|
|
358
358
|
let mut c = circle;
|
|
359
359
|
|
|
360
|
-
if let Some(last) = self.last()
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
360
|
+
if let Some(last) = self.last()
|
|
361
|
+
&& last.spanning_ray.dir().dot(&c.spanning_ray.dir()) < 0.0
|
|
362
|
+
{
|
|
363
|
+
c.reverse_in_place();
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
if self.reversed {
|
|
@@ -177,6 +177,35 @@ impl DiscreteDomain {
|
|
|
177
177
|
pub fn bounds_unchecked(&self) -> Interval {
|
|
178
178
|
Interval::new(self.values[0], self.values[self.values.len() - 1])
|
|
179
179
|
}
|
|
180
|
+
|
|
181
|
+
pub fn closest_index(&self, value: f64) -> Option<usize> {
|
|
182
|
+
if self.is_empty() {
|
|
183
|
+
return None;
|
|
184
|
+
}
|
|
185
|
+
if self.len() == 1 {
|
|
186
|
+
return Some(0);
|
|
187
|
+
}
|
|
188
|
+
if value >= self.values[self.len() - 1] {
|
|
189
|
+
return Some(self.len() - 1);
|
|
190
|
+
}
|
|
191
|
+
if value <= self.values[0] {
|
|
192
|
+
return Some(0);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let index = self.index_of(value)?;
|
|
196
|
+
if index == self.len() - 1 {
|
|
197
|
+
return Some(self.len() - 1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let lower_value = self.values[index];
|
|
201
|
+
let upper_value = self.values[index + 1];
|
|
202
|
+
|
|
203
|
+
if (value - lower_value).abs() < (value - upper_value).abs() {
|
|
204
|
+
Some(index)
|
|
205
|
+
} else {
|
|
206
|
+
Some(index + 1)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
180
209
|
}
|
|
181
210
|
|
|
182
211
|
impl Deref for DiscreteDomain {
|
|
@@ -210,6 +239,7 @@ impl TryFrom<Vec<f64>> for DiscreteDomain {
|
|
|
210
239
|
#[cfg(test)]
|
|
211
240
|
mod tests {
|
|
212
241
|
use super::*;
|
|
242
|
+
use rand::Rng;
|
|
213
243
|
use test_case::test_case;
|
|
214
244
|
|
|
215
245
|
#[test]
|
|
@@ -272,4 +302,38 @@ mod tests {
|
|
|
272
302
|
let domain = DiscreteDomain::try_from(vec![1.0, 2.0, 3.0]).unwrap();
|
|
273
303
|
assert_eq!(domain.index_of(x), expected);
|
|
274
304
|
}
|
|
305
|
+
|
|
306
|
+
fn brute_force_closest_index(domain: &DiscreteDomain, value: f64) -> Option<usize> {
|
|
307
|
+
if domain.is_empty() {
|
|
308
|
+
return None;
|
|
309
|
+
}
|
|
310
|
+
let mut closest_index = 0;
|
|
311
|
+
let mut closest_distance = (value - domain.values[0]).abs();
|
|
312
|
+
for (i, &v) in domain.values.iter().enumerate() {
|
|
313
|
+
let distance = (value - v).abs();
|
|
314
|
+
if distance < closest_distance {
|
|
315
|
+
closest_distance = distance;
|
|
316
|
+
closest_index = i;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
Some(closest_index)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
#[test]
|
|
323
|
+
fn stress_test_closest() {
|
|
324
|
+
let n = 1000;
|
|
325
|
+
let mut rng = rand::rng();
|
|
326
|
+
let domain = DiscreteDomain::linear(-10.0, 10.0, 100);
|
|
327
|
+
for _ in 0..n {
|
|
328
|
+
let test_val = rng.random_range(-12.0..12.0);
|
|
329
|
+
let closest_index = domain.closest_index(test_val);
|
|
330
|
+
let expected = brute_force_closest_index(&domain, test_val);
|
|
331
|
+
|
|
332
|
+
assert_eq!(
|
|
333
|
+
closest_index, expected,
|
|
334
|
+
"Failed for test value: {}",
|
|
335
|
+
test_val
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
275
339
|
}
|
|
@@ -64,7 +64,7 @@ impl IndexMask {
|
|
|
64
64
|
self.mask.len()
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
pub fn iter_true(&self) -> MaskTrueIterator {
|
|
67
|
+
pub fn iter_true(&self) -> MaskTrueIterator<'_> {
|
|
68
68
|
MaskTrueIterator {
|
|
69
69
|
mask: self,
|
|
70
70
|
current: 0,
|
|
@@ -279,6 +279,12 @@ impl IndexMask {
|
|
|
279
279
|
}
|
|
280
280
|
Ok(())
|
|
281
281
|
}
|
|
282
|
+
|
|
283
|
+
pub fn fill(&mut self, value: bool) {
|
|
284
|
+
for u in self.mask.as_raw_mut_slice() {
|
|
285
|
+
*u = if value { !0 } else { 0 };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
282
288
|
}
|
|
283
289
|
|
|
284
290
|
pub struct MaskTrueIterator<'a> {
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
use crate::Result;
|
|
1
2
|
use crate::common::{IndexMask, PCoords};
|
|
2
|
-
use
|
|
3
|
-
use
|
|
4
|
-
use std::num::NonZero;
|
|
3
|
+
use kdtree::KdTree as KdTreeInner;
|
|
4
|
+
use kdtree::distance::squared_euclidean;
|
|
5
5
|
use uuid::Uuid;
|
|
6
6
|
|
|
7
|
+
// fn check_tree() {
|
|
8
|
+
// let a: ([f64; 2], usize) = ([0f64, 0f64], 0);
|
|
9
|
+
// let b: ([f64; 2], usize) = ([1f64, 1f64], 1);
|
|
10
|
+
// let c: ([f64; 2], usize) = ([2f64, 2f64], 2);
|
|
11
|
+
// let d: ([f64; 2], usize) = ([3f64, 3f64], 3);
|
|
12
|
+
//
|
|
13
|
+
// let dimensions = 2;
|
|
14
|
+
// let mut kdtree = KdTreeInner::new(dimensions);
|
|
15
|
+
//
|
|
16
|
+
// kdtree.add(&a.0, a.1).unwrap();
|
|
17
|
+
// kdtree.add(&b.0, b.1).unwrap();
|
|
18
|
+
// kdtree.add(&c.0, c.1).unwrap();
|
|
19
|
+
// kdtree.add(&d.0, d.1).unwrap();
|
|
20
|
+
// }
|
|
21
|
+
|
|
7
22
|
/// A KD tree associated with a unique UUID, such that it can be checked to be matched against a
|
|
8
23
|
/// specific entity. The idea is that the UUID of the associated object will change if the object
|
|
9
24
|
/// points are modified, and thus the matched tree can be validated before use.
|
|
@@ -28,7 +43,7 @@ impl<const D: usize> MatchedTree<D> {
|
|
|
28
43
|
|
|
29
44
|
pub trait KdTreeSearch<const D: usize> {
|
|
30
45
|
fn nearest_one(&self, point: &impl PCoords<D>) -> (usize, f64);
|
|
31
|
-
fn nearest(&self, point: &impl PCoords<D>, count:
|
|
46
|
+
fn nearest(&self, point: &impl PCoords<D>, count: usize) -> Vec<(usize, f64)>;
|
|
32
47
|
fn within(&self, point: &impl PCoords<D>, radius: f64) -> Vec<(usize, f64)>;
|
|
33
48
|
|
|
34
49
|
fn len(&self) -> usize;
|
|
@@ -39,7 +54,7 @@ pub trait KdTreeSearch<const D: usize> {
|
|
|
39
54
|
|
|
40
55
|
/// An immutable k-dimensional tree for fast searches on points in D dimensions
|
|
41
56
|
pub struct KdTree<const D: usize> {
|
|
42
|
-
tree:
|
|
57
|
+
tree: KdTreeInner<f64, usize, [f64; D]>,
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
impl<const D: usize> KdTree<D> {
|
|
@@ -50,20 +65,16 @@ impl<const D: usize> KdTree<D> {
|
|
|
50
65
|
/// * `points`: A slice of points.
|
|
51
66
|
///
|
|
52
67
|
/// returns: KdTree<{ D }>
|
|
53
|
-
pub fn new(points: &[impl PCoords<D>]) -> Self {
|
|
68
|
+
pub fn new(points: &[impl PCoords<D>]) -> Result<Self> {
|
|
54
69
|
let mut entries: Vec<[f64; D]> = Vec::with_capacity(points.len());
|
|
55
70
|
for p in points {
|
|
56
71
|
entries.push(p.coords().into());
|
|
57
72
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
pub fn from_slice(s: &[[f64; D]]) -> Self {
|
|
64
|
-
Self {
|
|
65
|
-
tree: kdtree::ImmutableKdTree::new_from_slice(s),
|
|
73
|
+
let mut tree = KdTreeInner::new(D);
|
|
74
|
+
for (i, e) in entries.iter().enumerate() {
|
|
75
|
+
tree.add(*e, i)?;
|
|
66
76
|
}
|
|
77
|
+
Ok(Self { tree })
|
|
67
78
|
}
|
|
68
79
|
}
|
|
69
80
|
|
|
@@ -84,10 +95,15 @@ impl<const D: usize> KdTreeSearch<D> for KdTree<D> {
|
|
|
84
95
|
///
|
|
85
96
|
/// ```
|
|
86
97
|
fn nearest_one(&self, point: &impl PCoords<D>) -> (usize, f64) {
|
|
87
|
-
let
|
|
98
|
+
if let Ok(item) = self
|
|
88
99
|
.tree
|
|
89
|
-
.
|
|
90
|
-
|
|
100
|
+
.nearest(point.coords().as_slice(), 1, &squared_euclidean)
|
|
101
|
+
{
|
|
102
|
+
let (d, u) = &item[0];
|
|
103
|
+
(**u, d.sqrt())
|
|
104
|
+
} else {
|
|
105
|
+
(usize::MAX, f64::INFINITY)
|
|
106
|
+
}
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
/// Find the nearest `count` points in the kd-tree to a given point.
|
|
@@ -104,14 +120,16 @@ impl<const D: usize> KdTreeSearch<D> for KdTree<D> {
|
|
|
104
120
|
/// ```
|
|
105
121
|
///
|
|
106
122
|
/// ```
|
|
107
|
-
fn nearest(&self, point: &impl PCoords<D>, count:
|
|
123
|
+
fn nearest(&self, point: &impl PCoords<D>, count: usize) -> Vec<(usize, f64)> {
|
|
108
124
|
let result = self
|
|
109
125
|
.tree
|
|
110
|
-
.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
.map(|
|
|
114
|
-
|
|
126
|
+
.nearest(point.coords().as_slice(), count, &squared_euclidean);
|
|
127
|
+
|
|
128
|
+
if let Ok(neighbors) = result {
|
|
129
|
+
neighbors.iter().map(|(d, u)| (**u, d.sqrt())).collect()
|
|
130
|
+
} else {
|
|
131
|
+
Vec::new()
|
|
132
|
+
}
|
|
115
133
|
}
|
|
116
134
|
|
|
117
135
|
/// Find all points within a given radius of a point.
|
|
@@ -129,13 +147,15 @@ impl<const D: usize> KdTreeSearch<D> for KdTree<D> {
|
|
|
129
147
|
///
|
|
130
148
|
/// ```
|
|
131
149
|
fn within(&self, point: &impl PCoords<D>, radius: f64) -> Vec<(usize, f64)> {
|
|
132
|
-
let result = self
|
|
133
|
-
.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.map(|
|
|
138
|
-
|
|
150
|
+
if let Ok(result) = self.tree.within(
|
|
151
|
+
point.coords().as_slice(),
|
|
152
|
+
radius * radius,
|
|
153
|
+
&squared_euclidean,
|
|
154
|
+
) {
|
|
155
|
+
result.iter().map(|(d, u)| (**u, d.sqrt())).collect()
|
|
156
|
+
} else {
|
|
157
|
+
Vec::new()
|
|
158
|
+
}
|
|
139
159
|
}
|
|
140
160
|
|
|
141
161
|
/// Get the number of points in the kd-tree.
|
|
@@ -171,7 +191,7 @@ impl<const D: usize> PartialKdTree<D> {
|
|
|
171
191
|
/// ```
|
|
172
192
|
///
|
|
173
193
|
/// ```
|
|
174
|
-
pub fn new(all_points: &[impl PCoords<D>], mask: &IndexMask) -> Self {
|
|
194
|
+
pub fn new(all_points: &[impl PCoords<D>], mask: &IndexMask) -> Result<Self> {
|
|
175
195
|
if mask.len() != all_points.len() {
|
|
176
196
|
panic!("Mask length must match the length of all_points");
|
|
177
197
|
}
|
|
@@ -182,8 +202,8 @@ impl<const D: usize> PartialKdTree<D> {
|
|
|
182
202
|
points.push(all_points[i].coords());
|
|
183
203
|
index_map.push(i);
|
|
184
204
|
}
|
|
185
|
-
let tree = KdTree::new(&points)
|
|
186
|
-
Self { tree, index_map }
|
|
205
|
+
let tree = KdTree::new(&points)?;
|
|
206
|
+
Ok(Self { tree, index_map })
|
|
187
207
|
}
|
|
188
208
|
}
|
|
189
209
|
|
|
@@ -193,7 +213,7 @@ impl<const D: usize> KdTreeSearch<D> for PartialKdTree<D> {
|
|
|
193
213
|
(self.index_map[i], d)
|
|
194
214
|
}
|
|
195
215
|
|
|
196
|
-
fn nearest(&self, point: &impl PCoords<D>, count:
|
|
216
|
+
fn nearest(&self, point: &impl PCoords<D>, count: usize) -> Vec<(usize, f64)> {
|
|
197
217
|
let result = self.tree.nearest(point, count);
|
|
198
218
|
result
|
|
199
219
|
.iter()
|
|
@@ -230,7 +250,7 @@ mod tests {
|
|
|
230
250
|
Point2::new(1.0, 1.0),
|
|
231
251
|
Point2::new(2.0, 2.0),
|
|
232
252
|
];
|
|
233
|
-
let tree = KdTree::new(&points);
|
|
253
|
+
let tree = KdTree::new(&points).expect("KD tree creation failed");
|
|
234
254
|
assert_eq!(tree.len(), 3);
|
|
235
255
|
}
|
|
236
256
|
|
|
@@ -241,7 +261,7 @@ mod tests {
|
|
|
241
261
|
Point2::new(1.0, 1.0),
|
|
242
262
|
Point2::new(2.0, 2.0),
|
|
243
263
|
];
|
|
244
|
-
let tree = KdTree::new(&points);
|
|
264
|
+
let tree = KdTree::new(&points).expect("KD tree creation failed");
|
|
245
265
|
let (i, d) = tree.nearest_one(&Point2::new(1.25, 1.25));
|
|
246
266
|
assert_eq!(i, 1);
|
|
247
267
|
assert_relative_eq!(d, (0.25 * 0.25 * 2.0_f64).sqrt(), epsilon = 1e-6);
|
|
@@ -254,7 +274,7 @@ mod tests {
|
|
|
254
274
|
Point2::new(1.0, 0.0),
|
|
255
275
|
Point2::new(2.0, 0.0),
|
|
256
276
|
];
|
|
257
|
-
let tree = KdTree::new(&points);
|
|
277
|
+
let tree = KdTree::new(&points).expect("KD tree creation failed");
|
|
258
278
|
let within = tree.within(&Point2::new(3.5, 0.0), 2.0);
|
|
259
279
|
assert_eq!(within.len(), 1);
|
|
260
280
|
assert_eq!(within[0].0, 2);
|
|
@@ -267,7 +287,7 @@ mod tests {
|
|
|
267
287
|
.flat_map(|i| (0..20).map(move |j| Point2::new(i as f64, j as f64)))
|
|
268
288
|
.collect::<Vec<_>>();
|
|
269
289
|
|
|
270
|
-
let fixed_tree = KdTree::new(&points);
|
|
290
|
+
let fixed_tree = KdTree::new(&points).expect("KD tree creation failed");
|
|
271
291
|
|
|
272
292
|
for _ in 0..1000 {
|
|
273
293
|
let mut test_select = index_vec(None, points.len());
|
|
@@ -280,7 +300,7 @@ mod tests {
|
|
|
280
300
|
}
|
|
281
301
|
let indices = mask.to_indices();
|
|
282
302
|
|
|
283
|
-
let partial_tree = PartialKdTree::new(&points, &mask);
|
|
303
|
+
let partial_tree = PartialKdTree::new(&points, &mask).expect("KD tree creation failed");
|
|
284
304
|
|
|
285
305
|
for &i in indices.iter() {
|
|
286
306
|
let p = &points[i];
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
//! Common operations on f64 points in D-dimensional space.
|
|
2
2
|
|
|
3
3
|
use crate::common::PCoords;
|
|
4
|
+
use crate::common::kd_tree::{KdTree, KdTreeSearch};
|
|
4
5
|
use crate::common::surface_point::SurfacePoint;
|
|
5
6
|
use parry3d_f64::na::{AbstractRotation, Isometry, Point, SVector};
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
pub fn area<const D: usize>(
|
|
9
|
+
pa: &impl PCoords<D>,
|
|
10
|
+
pb: &impl PCoords<D>,
|
|
11
|
+
pc: &impl PCoords<D>,
|
|
12
|
+
) -> f64 {
|
|
13
|
+
let ab = pb.coords() - pa.coords();
|
|
14
|
+
let ac = pc.coords() - pa.coords();
|
|
15
|
+
|
|
16
|
+
if D == 2 {
|
|
17
|
+
0.5 * (ab[0] * ac[1] - ab[1] * ac[0]).abs()
|
|
18
|
+
} else if D == 3 {
|
|
19
|
+
0.5 * ab.cross(&ac).norm()
|
|
20
|
+
} else {
|
|
21
|
+
panic!("Area calculation is only implemented for 2D and 3D points");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
7
24
|
|
|
8
25
|
/// Calculate the barycentric coordinates of a point `p` with respect to the triangle defined by
|
|
9
26
|
/// points `a`, `b`, and `c` in D-dimensional space. The barycentric coordinates are a way of
|
|
@@ -510,7 +527,6 @@ where
|
|
|
510
527
|
points.iter().map(|p| transform * p).collect()
|
|
511
528
|
}
|
|
512
529
|
|
|
513
|
-
|
|
514
530
|
/// Clusters a set of points by distance tolerance, where all points reachable by a series of hops
|
|
515
531
|
/// less than or equal to the specified tolerance are grouped together into a single cluster.
|
|
516
532
|
///
|
|
@@ -534,7 +550,8 @@ pub fn cluster_points_by_tol<const D: usize>(
|
|
|
534
550
|
while !working.is_empty() {
|
|
535
551
|
let mut group = vec![working.pop().unwrap()];
|
|
536
552
|
loop {
|
|
537
|
-
let tree =
|
|
553
|
+
let tree =
|
|
554
|
+
KdTree::new(&group).expect("KD tree construction failed. Are there enough points?");
|
|
538
555
|
let mut to_add = Vec::new();
|
|
539
556
|
for (i, p) in working.iter().enumerate() {
|
|
540
557
|
// let (d, _) = tree.nearest_one(&to_slice(p), &squared_euclidean);
|
|
@@ -566,7 +583,6 @@ pub fn merge_points_by_tol<const D: usize>(
|
|
|
566
583
|
clusters.iter().map(|c| mean_point(c)).collect()
|
|
567
584
|
}
|
|
568
585
|
|
|
569
|
-
|
|
570
586
|
#[cfg(test)]
|
|
571
587
|
mod tests {
|
|
572
588
|
use super::*;
|
|
@@ -24,7 +24,8 @@ pub fn sample_poisson_disk_all<const D: usize>(
|
|
|
24
24
|
radius: f64,
|
|
25
25
|
) -> IndexMask {
|
|
26
26
|
let pre_mask = voxel_downsample(points, radius * 0.25);
|
|
27
|
-
let partial_tree = PartialKdTree::new(points, &pre_mask)
|
|
27
|
+
let partial_tree = PartialKdTree::new(points, &pre_mask)
|
|
28
|
+
.expect("KD tree construction failed. Are there enough points?");
|
|
28
29
|
|
|
29
30
|
let mut skip_mask = pre_mask.clone();
|
|
30
31
|
let mut final_mask = IndexMask::new(points.len(), false);
|
|
@@ -71,7 +72,7 @@ mod tests {
|
|
|
71
72
|
|
|
72
73
|
// Brute force check that each point only has one point (itself) within the radius
|
|
73
74
|
let kept = keep.clone_indices_of(&points).unwrap();
|
|
74
|
-
let tree = KdTree::new(&kept);
|
|
75
|
+
let tree = KdTree::new(&kept).expect("Tree construction failed");
|
|
75
76
|
for (i, &p) in kept.iter().enumerate() {
|
|
76
77
|
let within = tree.within(&p, r);
|
|
77
78
|
assert_eq!(within.len(), 1);
|