1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use fj_math::{Point, Scalar};
use crate::objects::{GlobalVertex, SurfaceVertex};
use super::{Validate, ValidationConfig, ValidationError};
impl Validate for SurfaceVertex {
fn validate_with_config(
&self,
config: &ValidationConfig,
errors: &mut Vec<ValidationError>,
) {
SurfaceVertexValidationError::check_position(self, config, errors);
}
}
impl Validate for GlobalVertex {
fn validate_with_config(
&self,
_: &ValidationConfig,
_: &mut Vec<ValidationError>,
) {
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum SurfaceVertexValidationError {
#[error(
"`SurfaceVertex` position doesn't match position of its global form\n\
- Surface position: {surface_position:?}\n\
- Surface position converted to global position: \
{surface_position_as_global:?}\n\
- Global position: {global_position:?}\n\
- Distance between the positions: {distance}\n\
- `SurfaceVertex`: {surface_vertex:#?}"
)]
PositionMismatch {
surface_position: Point<2>,
surface_position_as_global: Point<3>,
global_position: Point<3>,
distance: Scalar,
surface_vertex: SurfaceVertex,
},
}
impl SurfaceVertexValidationError {
fn check_position(
surface_vertex: &SurfaceVertex,
config: &ValidationConfig,
errors: &mut Vec<ValidationError>,
) {
let surface_position_as_global = surface_vertex
.surface()
.geometry()
.point_from_surface_coords(surface_vertex.position());
let global_position = surface_vertex.global_form().position();
let distance = surface_position_as_global.distance_to(&global_position);
if distance > config.identical_max_distance {
errors.push(
Box::new(Self::PositionMismatch {
surface_position: surface_vertex.position(),
surface_position_as_global,
global_position,
distance,
surface_vertex: surface_vertex.clone(),
})
.into(),
);
}
}
}
#[cfg(test)]
mod tests {
use fj_math::Point;
use crate::{
insert::Insert,
objects::{GlobalVertex, SurfaceVertex},
partial::{
Partial, PartialGlobalVertex, PartialObject, PartialSurfaceVertex,
},
services::Services,
validate::Validate,
};
#[test]
fn surface_vertex_position_mismatch() -> anyhow::Result<()> {
let mut services = Services::new();
let valid = PartialSurfaceVertex {
position: Some([0., 0.].into()),
surface: Partial::from(services.objects.surfaces.xy_plane()),
global_form: Partial::from_partial(PartialGlobalVertex {
position: Some(Point::from([0., 0., 0.])),
}),
}
.build(&mut services.objects);
let invalid = SurfaceVertex::new(
valid.position(),
valid.surface().clone(),
GlobalVertex::new([1., 0., 0.]).insert(&mut services.objects),
);
valid.validate_and_return_first_error()?;
assert!(invalid.validate_and_return_first_error().is_err());
Ok(())
}
}