engeom 0.2.5__tar.gz → 0.2.7__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.5 → engeom-0.2.7}/Cargo.lock +1 -1
- {engeom-0.2.5 → engeom-0.2.7}/Cargo.toml +1 -1
- {engeom-0.2.5 → engeom-0.2.7}/PKG-INFO +1 -1
- engeom-0.2.7/docs/api/airfoil.md +3 -0
- engeom-0.2.7/docs/api/engeom.md +5 -0
- engeom-0.2.7/docs/api/geom2.md +3 -0
- engeom-0.2.7/docs/api/geom3.md +4 -0
- engeom-0.2.7/docs/api/metrology.md +9 -0
- engeom-0.2.7/docs/api/plot.md +15 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/metrology.md +0 -1
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil/camber.rs +26 -17
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil.rs +7 -7
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/func1/series1.rs +1 -1
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/measurement.rs +3 -3
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/lib.rs +1 -0
- engeom-0.2.7/engeom/src/metrology/dimension.rs +97 -0
- engeom-0.2.7/engeom/src/metrology.rs +58 -0
- engeom-0.2.7/engeom/src/raster3.rs +60 -0
- {engeom-0.2.5 → engeom-0.2.7}/mkdocs.yml +15 -0
- engeom-0.2.7/python/engeom/_plot/__init__.py +1 -0
- engeom-0.2.7/python/engeom/_plot/common.py +17 -0
- {engeom-0.2.5/python/engeom → engeom-0.2.7/python/engeom/_plot}/matplotlib.py +88 -45
- engeom-0.2.7/python/engeom/_plot/pyvista.py +256 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/airfoil/__init__.py +4 -0
- engeom-0.2.7/python/engeom/airfoil.pyi +485 -0
- engeom-0.2.7/python/engeom/engeom.pyi +46 -0
- engeom-0.2.7/python/engeom/geom2/__init__.py +10 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/geom2.pyi +323 -85
- engeom-0.2.7/python/engeom/geom3/__init__.py +10 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/geom3.pyi +406 -117
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/metrology/__init__.py +4 -0
- engeom-0.2.7/python/engeom/metrology.pyi +137 -0
- engeom-0.2.7/python/engeom/plot.py +26 -0
- engeom-0.2.7/python/engeom/raster3/__init__.py +9 -0
- engeom-0.2.7/python/engeom/raster3.pyi +19 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/airfoil.rs +5 -5
- {engeom-0.2.5 → engeom-0.2.7}/src/geom2.rs +8 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/lib.rs +15 -3
- {engeom-0.2.5 → engeom-0.2.7}/src/mesh.rs +20 -11
- {engeom-0.2.5 → engeom-0.2.7}/src/metrology.rs +25 -17
- engeom-0.2.7/src/raster.rs +40 -0
- engeom-0.2.5/engeom/src/metrology/dimension.rs +0 -45
- engeom-0.2.5/engeom/src/metrology.rs +0 -18
- engeom-0.2.5/python/engeom/airfoil.pyi +0 -334
- engeom-0.2.5/python/engeom/engeom.pyi +0 -13
- engeom-0.2.5/python/engeom/geom2/__init__.py +0 -5
- engeom-0.2.5/python/engeom/geom3/__init__.py +0 -5
- engeom-0.2.5/python/engeom/metrology.pyi +0 -64
- engeom-0.2.5/python/engeom/pyvista.py +0 -178
- {engeom-0.2.5 → engeom-0.2.7}/.github/workflows/CI.yml +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/.gitignore +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/.gitmodules +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/README.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/airfoils/intro.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/bounding_volumes.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/curves.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/images/surface_point_meas.svg +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/index.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/isometries.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/meshes.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/numpy.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/planes_circles_lines.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/points_vectors.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/surf_points.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/docs/svd_basis.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/.gitignore +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/Cargo.lock +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/Cargo.toml +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/README.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/airfoils/camber.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/airfoils/overview.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/common/angles.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/common/core_space.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/common/discrete_domain.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/common/images/surface_point_meas.svg +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/common/svd_basis.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/geom2/alignment.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/geom2/curve.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/geom2/point_collections.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/geom2/shapes.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/index.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/javascripts/mathjax.js +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/docs/python_rust.md +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/mkdocs.yml +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil/edges.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil/helpers.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil/inscribed_circle.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/airfoil/orientation.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/align.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/angles.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/convert_2d_3d.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/discrete_domain.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/indices.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/interval.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/kd_tree.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/points.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/poisson_disk.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/surface_point.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/svd_basis.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common/vec_f64.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/common.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/errors.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/func1/common_functions.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/func1/polynomial.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/func1.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/aabb2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/align2/jacobian.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/align2/points_to_curve.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/align2/rc_params2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/align2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/angles2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/circle2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/curve2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/hull.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/line2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2/polyline2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom2.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/align3/jacobian.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/align3/multi_param.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/align3/points_to_mesh.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/align3/rotations.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/align3.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/curve3.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/conformal.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/edges.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/faces.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/filtering.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/patches.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/queries.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/sampling.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh/uv_mapping.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/mesh.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/plane3.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3/point_cloud.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/geom3.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/io.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/metrology/line_profiles.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/metrology/surface_deviation.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/metrology/tolerance.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/metrology/tolerance_map.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/stats.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/engeom/src/utility.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/pyproject.toml +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/__init__.py +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/align/__init__.py +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/engeom/align.pyi +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/tests/test_all.py +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/tests/test_geom2_simple.py +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/python/tests/test_geom3_simple.py +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/alignments.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/bounding.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/common.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/conversions.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/geom3.rs +0 -0
- {engeom-0.2.5 → engeom-0.2.7}/src/svd_basis.rs +1 -1
@@ -0,0 +1,15 @@
|
|
1
|
+
# Plot Module
|
2
|
+
|
3
|
+
!!! warning
|
4
|
+
This module's API is still under development and will likely change in the future.
|
5
|
+
|
6
|
+
::: engeom.plot
|
7
|
+
options:
|
8
|
+
show_source: false
|
9
|
+
members:
|
10
|
+
- LabelPlace
|
11
|
+
- PyvistaPlotterHelper
|
12
|
+
- GOM_CMAP
|
13
|
+
- GomColorMap
|
14
|
+
- MatplotlibAxesHelper
|
15
|
+
|
@@ -9,4 +9,3 @@
|
|
9
9
|
The metrology features of the `engeom` library are designed to provide a common set of tools for actual measurements,
|
10
10
|
separate from the geometry tools. For example, measurements like scalar distances, areas, GD&T form and position
|
11
11
|
measurements, and more, will be consolidated as entities and operations in the metrology features.
|
12
|
-
|
@@ -5,39 +5,48 @@ use super::helpers::{
|
|
5
5
|
};
|
6
6
|
use crate::airfoil::inscribed_circle::InscribedCircle;
|
7
7
|
use crate::common::points::{dist, mid_point};
|
8
|
-
use crate::common::BestFit;
|
9
8
|
use crate::common::Resample::ByCount;
|
10
9
|
use crate::geom2::hull::farthest_pair_indices;
|
11
10
|
use crate::geom2::polyline2::SpanningRay;
|
12
|
-
use crate::geom2::{rot90, Line2};
|
11
|
+
use crate::geom2::{rot90, Line2, Segment2};
|
13
12
|
use crate::AngleDir::{Ccw, Cw};
|
13
|
+
use crate::{Curve2, UnitVec2};
|
14
14
|
use crate::Result;
|
15
|
-
use crate::{Circle2, Curve2, UnitVec2};
|
16
15
|
use parry2d_f64::query::Ray;
|
17
16
|
use parry2d_f64::shape::ConvexPolygon;
|
18
17
|
|
19
18
|
/// Given a curve representing a camber line, attempt to detect the direction of the upper
|
20
|
-
/// (suction, convex) side of the airfoil section.
|
21
|
-
/// finite number of points and then best-fit a circle to the points. The circle center should be
|
22
|
-
/// on the concave (lower, pressure) side of the camber curve, so the direction from the circle
|
23
|
-
/// center to the center of the camber curve will be the direction of the upper airfoil side.
|
24
|
-
///
|
19
|
+
/// (suction, convex) side of the airfoil section.
|
25
20
|
/// # Arguments
|
26
21
|
///
|
27
22
|
/// * `camber_line`: the curve representing the camber line of the airfoil section
|
28
23
|
///
|
29
24
|
/// returns: Result<Unit<Matrix<f64, Const<2>, Const<1>, ArrayStorage<f64, 2, 1>>>, Box<dyn Error, Global>>
|
30
25
|
pub fn camber_detect_upper_dir(camber_line: &Curve2) -> Result<UnitVec2> {
|
31
|
-
let
|
26
|
+
let check = Segment2::try_new(camber_line.at_front().point(), camber_line.at_back().point())
|
27
|
+
.map_err(|_| "Failed to create segment from camber line while detecting face orientation")?;
|
28
|
+
|
32
29
|
let resampled = camber_line.resample(ByCount(50))?;
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
)
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
|
31
|
+
let mut best = 0.0;
|
32
|
+
let mut best_point = None;
|
33
|
+
|
34
|
+
for p in resampled.points() {
|
35
|
+
let cp = check.projected_point(p);
|
36
|
+
let d = dist(p, &cp);
|
37
|
+
if d > best {
|
38
|
+
best = d;
|
39
|
+
best_point = Some(p);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
if let Some(point) = best_point {
|
44
|
+
let cp = check.projected_point(point);
|
45
|
+
let dir = point - cp;
|
46
|
+
Ok(UnitVec2::new_normalize(dir))
|
47
|
+
} else {
|
48
|
+
Err("Failed to find point on camber line for face orientation detection".into())
|
49
|
+
}
|
41
50
|
}
|
42
51
|
|
43
52
|
/// Attempts to calculate and extract the mean camber line from an airfoil section curve and its
|
@@ -14,7 +14,7 @@ use crate::airfoil::camber::camber_detect_upper_dir;
|
|
14
14
|
use crate::common::points::dist;
|
15
15
|
use crate::common::Intersection;
|
16
16
|
use crate::geom2::hull::convex_hull_2d;
|
17
|
-
use crate::metrology::
|
17
|
+
use crate::metrology::Distance2;
|
18
18
|
use crate::stats::compute_mean;
|
19
19
|
pub use camber::extract_camber_line;
|
20
20
|
pub use edges::{
|
@@ -358,14 +358,14 @@ impl AirfoilGeometry {
|
|
358
358
|
///
|
359
359
|
/// * `gage`:
|
360
360
|
///
|
361
|
-
/// returns: Result<
|
361
|
+
/// returns: Result<Distance2, Box<dyn Error, Global>>
|
362
362
|
///
|
363
363
|
/// # Examples
|
364
364
|
///
|
365
365
|
/// ```
|
366
366
|
///
|
367
367
|
/// ```
|
368
|
-
pub fn get_thickness(&self, gage: AfGage) -> Result<
|
368
|
+
pub fn get_thickness(&self, gage: AfGage) -> Result<Distance2> {
|
369
369
|
let (upper, lower) = match gage {
|
370
370
|
AfGage::OnCamber(x) => {
|
371
371
|
let l = if x < 0.0 { self.camber.length() + x } else { x };
|
@@ -463,13 +463,13 @@ impl AirfoilGeometry {
|
|
463
463
|
}
|
464
464
|
};
|
465
465
|
|
466
|
-
Ok(
|
466
|
+
Ok(Distance2::new(lower, upper, None))
|
467
467
|
}
|
468
468
|
|
469
|
-
pub fn get_thickness_max(&self) -> Result<
|
469
|
+
pub fn get_thickness_max(&self) -> Result<Distance2> {
|
470
470
|
let tmax = self.find_tmax();
|
471
471
|
let (upper, lower) = self.order_points(&tmax.contact_neg, &tmax.contact_pos)?;
|
472
|
-
Ok(
|
472
|
+
Ok(Distance2::new(lower, upper, None))
|
473
473
|
}
|
474
474
|
|
475
475
|
/// Order the points so that the first point returned is on the upper surface and the second
|
@@ -525,7 +525,7 @@ fn order_faces(
|
|
525
525
|
// We should have intersections with both curves. If the outline is clean, we will have exactly
|
526
526
|
// one intersection with each, but if not we might have more than one at a similar distance.
|
527
527
|
if a_t.is_empty() || b_t.is_empty() {
|
528
|
-
Err("Failed to find intersections with the test point".into())
|
528
|
+
Err("Failed to find intersections with the test point while ordering faces".into())
|
529
529
|
} else {
|
530
530
|
let a_m = compute_mean(&a_t)?;
|
531
531
|
let b_m = compute_mean(&b_t)?;
|
@@ -640,7 +640,7 @@ impl Series1 {
|
|
640
640
|
clusters.push(current);
|
641
641
|
}
|
642
642
|
|
643
|
-
// Now go through each cluster and if it is large enough, add all
|
643
|
+
// Now go through each cluster and if it is large enough, add all the indices to the
|
644
644
|
// result vector
|
645
645
|
let mut results = Vec::new();
|
646
646
|
for cluster in clusters {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
//! This module contains features for taking measurements on meshes
|
2
2
|
|
3
3
|
use crate::common::DistMode;
|
4
|
-
use crate::metrology::
|
4
|
+
use crate::metrology::Distance3;
|
5
5
|
use crate::{Mesh, Point3, UnitVec3};
|
6
6
|
|
7
7
|
impl Mesh {
|
@@ -33,7 +33,7 @@ impl Mesh {
|
|
33
33
|
/// ```
|
34
34
|
///
|
35
35
|
/// ```
|
36
|
-
pub fn measure_point_deviation(&self, point: &Point3, dist_mode: DistMode) ->
|
36
|
+
pub fn measure_point_deviation(&self, point: &Point3, dist_mode: DistMode) -> Distance3 {
|
37
37
|
let closest = self.surf_closest_to(point);
|
38
38
|
|
39
39
|
// In both cases, the measurement point `b` will remain the test point and `a` will be the
|
@@ -53,6 +53,6 @@ impl Mesh {
|
|
53
53
|
DistMode::ToPlane => closest.normal,
|
54
54
|
};
|
55
55
|
|
56
|
-
|
56
|
+
Distance3::new(closest.point, *point, Some(d))
|
57
57
|
}
|
58
58
|
}
|
@@ -0,0 +1,97 @@
|
|
1
|
+
//! This module has representations of different types of dimensions
|
2
|
+
|
3
|
+
use crate::common::surface_point::SurfacePoint;
|
4
|
+
use parry3d_f64::na::{Point, SVector, Unit};
|
5
|
+
use crate::common::points::mid_point;
|
6
|
+
|
7
|
+
pub trait Measurement {
|
8
|
+
fn value(&self) -> f64;
|
9
|
+
}
|
10
|
+
|
11
|
+
/// Represents a signed distance between two points in space along a specific direction. The value
|
12
|
+
/// of the measurement will be the vector from `a` to `b` projected onto the direction vector,
|
13
|
+
/// meaning that the value will be positive if `b` is in the direction of the vector and negative
|
14
|
+
/// if `b` is in the opposite direction.
|
15
|
+
pub struct Distance<const D: usize> {
|
16
|
+
/// The starting point of the distance measurement
|
17
|
+
pub a: Point<f64, D>,
|
18
|
+
|
19
|
+
/// The ending point of the distance measurement
|
20
|
+
pub b: Point<f64, D>,
|
21
|
+
|
22
|
+
/// The direction of the distance measurement
|
23
|
+
pub direction: Unit<SVector<f64, D>>,
|
24
|
+
}
|
25
|
+
|
26
|
+
impl<const D: usize> Distance<D> {
|
27
|
+
/// Create a new signed distance measurement between two points in space along a specific
|
28
|
+
/// direction. The value of the measurement will be the vector from `a` to `b` projected onto
|
29
|
+
/// the direction vector, meaning that the value will be positive if `b - a` is in the
|
30
|
+
/// direction of the vector and negative if not.
|
31
|
+
///
|
32
|
+
/// # Arguments
|
33
|
+
///
|
34
|
+
/// * `a`: The start point of the distance measurement
|
35
|
+
/// * `b`: The end point of the distance measurement
|
36
|
+
/// * `direction`: A unit vector representing the direction of the distance measurement. The
|
37
|
+
/// default value is `None`, in which case the direction will be calculated as the normalized
|
38
|
+
/// vector from `a` to `b`, resulting in a positive value with the full magnitude of the
|
39
|
+
/// distance between the two points.
|
40
|
+
///
|
41
|
+
/// returns: Distance<{ D }>
|
42
|
+
///
|
43
|
+
/// # Examples
|
44
|
+
///
|
45
|
+
/// ```
|
46
|
+
/// use engeom::{Point2, UnitVec2, Vector2};
|
47
|
+
/// use engeom::metrology::{Distance2, Measurement};
|
48
|
+
/// use approx::assert_relative_eq;
|
49
|
+
///
|
50
|
+
/// let a = Point2::new(0.0, 0.0);
|
51
|
+
/// let b = Point2::new(1.0, 1.0);
|
52
|
+
///
|
53
|
+
/// let d1 = Distance2::new(a, b, None);
|
54
|
+
/// let d2 = Distance2::new(b, a, None);
|
55
|
+
///
|
56
|
+
/// assert_relative_eq!(d1.value(), 2_f64.sqrt());
|
57
|
+
/// assert_relative_eq!(d2.value(), 2_f64.sqrt());
|
58
|
+
///
|
59
|
+
/// let dir = UnitVec2::new_unchecked(Vector2::x());
|
60
|
+
/// let d3 = Distance2::new(a, b, Some(dir));
|
61
|
+
/// let d4 = Distance2::new(b, a, Some(dir));
|
62
|
+
///
|
63
|
+
/// assert_relative_eq!(d3.value(), 1.0);
|
64
|
+
/// assert_relative_eq!(d4.value(), -1.0);
|
65
|
+
/// ```
|
66
|
+
pub fn new(
|
67
|
+
a: Point<f64, D>,
|
68
|
+
b: Point<f64, D>,
|
69
|
+
direction: Option<Unit<SVector<f64, D>>>,
|
70
|
+
) -> Self {
|
71
|
+
let direction = direction.unwrap_or(Unit::new_normalize(b - a));
|
72
|
+
Self { a, b, direction }
|
73
|
+
}
|
74
|
+
|
75
|
+
/// Reverse the distance measurement by swapping start and end points and flipping the direction
|
76
|
+
/// of measurement. The value and sign of the measurement will be the same after the operation,
|
77
|
+
/// but the points will have been swapped.
|
78
|
+
pub fn reversed(&self) -> Self {
|
79
|
+
Self {
|
80
|
+
a: self.b,
|
81
|
+
b: self.a,
|
82
|
+
direction: -self.direction,
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
/// Compute a SurfacePoint that is located halfway between point `a` and `b` and whose normal
|
87
|
+
/// vector is the direction of the distance measurement.
|
88
|
+
pub fn center(&self) -> SurfacePoint<D> {
|
89
|
+
SurfacePoint::new(mid_point(&self.a, &self.b), self.direction)
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
impl<const D: usize> Measurement for Distance<D> {
|
94
|
+
fn value(&self) -> f64 {
|
95
|
+
self.direction.dot(&(self.b - self.a))
|
96
|
+
}
|
97
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
mod dimension;
|
2
|
+
pub mod line_profiles;
|
3
|
+
mod surface_deviation;
|
4
|
+
mod tolerance;
|
5
|
+
mod tolerance_map;
|
6
|
+
|
7
|
+
pub use tolerance::Tolerance;
|
8
|
+
pub use tolerance_map::{ConstantTolMap, DiscreteDomainTolMap, ToleranceMap};
|
9
|
+
|
10
|
+
pub use dimension::Measurement;
|
11
|
+
use crate::{Iso3, To2D, To3D};
|
12
|
+
|
13
|
+
pub type SurfaceDeviation2 = surface_deviation::SurfaceDeviation<2>;
|
14
|
+
pub type SurfaceDeviationSet2 = surface_deviation::SurfaceDeviationSet<2>;
|
15
|
+
pub type SurfaceDeviation3 = surface_deviation::SurfaceDeviation<3>;
|
16
|
+
pub type SurfaceDeviationSet3 = surface_deviation::SurfaceDeviationSet<3>;
|
17
|
+
|
18
|
+
pub type Distance2 = dimension::Distance<2>;
|
19
|
+
pub type Distance3 = dimension::Distance<3>;
|
20
|
+
|
21
|
+
|
22
|
+
// Conversions between 2D and 3D distances
|
23
|
+
impl Distance2 {
|
24
|
+
/// Convert a 2D distance to a 3D distance using an isometry transformation. The 2D distance
|
25
|
+
/// is converted to 3D by adding a zero z-component, and then it is transformed by the provided
|
26
|
+
/// isometry to move it to some other location in 3D space.
|
27
|
+
///
|
28
|
+
/// # Arguments
|
29
|
+
///
|
30
|
+
/// * `iso`: The isometry transformation to apply to the 2D distance
|
31
|
+
///
|
32
|
+
/// returns: Distance<3>
|
33
|
+
pub fn to_3d(&self, iso: &Iso3) -> Distance3 {
|
34
|
+
let a = iso * self.a.to_3d();
|
35
|
+
let b = iso * self.b.to_3d();
|
36
|
+
let direction = iso * self.direction.to_3d();
|
37
|
+
Distance3::new(a, b, Some(direction))
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
impl Distance3 {
|
42
|
+
/// Convert a 3D distance to a 2D distance using an isometry transformation. The 3D distance
|
43
|
+
/// is first transformed by the provided isometry, and then it is converted to 2D by dropping
|
44
|
+
/// the z-component.
|
45
|
+
///
|
46
|
+
/// # Arguments
|
47
|
+
///
|
48
|
+
/// * `iso`: The isometry transformation to apply to the 3D distance before dropping the
|
49
|
+
/// z-component
|
50
|
+
///
|
51
|
+
/// returns: Distance<2>
|
52
|
+
pub fn to_2d(&self, iso: &Iso3) -> Distance2 {
|
53
|
+
let a = (iso * self.a).to_2d();
|
54
|
+
let b = (iso * self.b).to_2d();
|
55
|
+
let direction = (iso * self.direction).to_2d();
|
56
|
+
Distance2::new(a, b, Some(direction))
|
57
|
+
}
|
58
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
//! This module contains tools for working with 3D voxel grids.
|
2
|
+
|
3
|
+
|
4
|
+
use std::collections::HashSet;
|
5
|
+
|
6
|
+
|
7
|
+
/// This function takes a set of coordinates in a 3D grid and returns a list of clusters of
|
8
|
+
/// connected voxel coordinates.
|
9
|
+
///
|
10
|
+
/// # Arguments
|
11
|
+
///
|
12
|
+
/// * `indices`:
|
13
|
+
///
|
14
|
+
/// returns: Vec<Vec<(u32, u32, u32), Global>, Global>
|
15
|
+
///
|
16
|
+
/// # Examples
|
17
|
+
///
|
18
|
+
/// ```
|
19
|
+
///
|
20
|
+
/// ```
|
21
|
+
pub fn clusters_from_sparse(mut indices: HashSet<(i32, i32, i32)>) -> Vec<Vec<(i32, i32, i32)>> {
|
22
|
+
let mut results = Vec::new();
|
23
|
+
|
24
|
+
while !indices.is_empty() {
|
25
|
+
let mut working = Vec::new();
|
26
|
+
let mut to_visit = Vec::new();
|
27
|
+
|
28
|
+
to_visit.push(pop_index(&mut indices));
|
29
|
+
|
30
|
+
while !to_visit.is_empty() {
|
31
|
+
let current = to_visit.pop().unwrap();
|
32
|
+
working.push(current);
|
33
|
+
|
34
|
+
for x in -1..=1 {
|
35
|
+
for y in -1..=1 {
|
36
|
+
for z in -1..=1 {
|
37
|
+
if x == 0 && y == 0 && z == 0 {
|
38
|
+
continue;
|
39
|
+
}
|
40
|
+
|
41
|
+
let neighbor = (current.0 + x, current.1 + y, current.2 + z);
|
42
|
+
if indices.remove(&neighbor) {
|
43
|
+
to_visit.push(neighbor);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
results.push(working.into_iter().collect());
|
51
|
+
}
|
52
|
+
|
53
|
+
results
|
54
|
+
}
|
55
|
+
|
56
|
+
fn pop_index(indices: &mut HashSet<(i32, i32, i32)>) -> (i32, i32, i32) {
|
57
|
+
let result = indices.iter().next().unwrap().clone();
|
58
|
+
indices.remove(&result);
|
59
|
+
result
|
60
|
+
}
|
@@ -17,6 +17,13 @@ nav:
|
|
17
17
|
- Airfoils:
|
18
18
|
- Introduction: airfoils/intro.md
|
19
19
|
- Metrology: metrology.md
|
20
|
+
- API Reference:
|
21
|
+
- Common: api/engeom.md
|
22
|
+
- Geom2: api/geom2.md
|
23
|
+
- Geom3: api/geom3.md
|
24
|
+
- Metrology: api/metrology.md
|
25
|
+
- Airfoil: api/airfoil.md
|
26
|
+
- Plot: api/plot.md
|
20
27
|
|
21
28
|
markdown_extensions:
|
22
29
|
- pymdownx.arithmatex:
|
@@ -34,6 +41,14 @@ markdown_extensions:
|
|
34
41
|
- pymdownx.superfences
|
35
42
|
- admonition
|
36
43
|
|
44
|
+
plugins:
|
45
|
+
- mkdocstrings:
|
46
|
+
handlers:
|
47
|
+
python:
|
48
|
+
options:
|
49
|
+
docstring_style: sphinx
|
50
|
+
paths: [python]
|
51
|
+
|
37
52
|
extra_javascript:
|
38
53
|
- javascripts/mathjax.js
|
39
54
|
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
|
@@ -0,0 +1 @@
|
|
1
|
+
from .common import LabelPlace
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
class LabelPlace(Enum):
|
4
|
+
"""
|
5
|
+
Represents the different locations where a label can be placed between its anchor points.
|
6
|
+
"""
|
7
|
+
|
8
|
+
Outside = 1
|
9
|
+
""" The label is placed outside the anchor points, on the side of the second point in the measurement. """
|
10
|
+
|
11
|
+
Inside = 2
|
12
|
+
""" The label is placed between the two anchor points. """
|
13
|
+
|
14
|
+
OutsideRev = 3
|
15
|
+
""" The label is placed outside the two anchor points, on the side of the first point in the measurement. """
|
16
|
+
|
17
|
+
|