use super::super::*;
use cadmpeg_ir::document::CadIr;
use cadmpeg_ir::draft::{CommitSession, ModelDraft};
use cadmpeg_ir::geometry::{NurbsSurface, Pcurve, PcurveGeometry, Surface, SurfaceGeometry};
use cadmpeg_ir::ids::{BodyId, CoedgeId, PcurveId, RegionId, SurfaceId};
use cadmpeg_ir::index::ModelIndex;
use cadmpeg_ir::math::{Point2, Point3, Vector3};
use cadmpeg_ir::topology::{Body, BodyKind, Region, Vertex};
use cadmpeg_ir::units::Units;
use std::collections::HashSet;
fn surface_draft(id: &str) -> ModelDraft {
let mut draft = ModelDraft::new();
draft
.insert(Surface {
id: SurfaceId(id.into()),
geometry: SurfaceGeometry::Plane {
origin: Point3::new(0.0, 0.0, 0.0),
normal: Vector3::new(0.0, 0.0, 1.0),
u_axis: Vector3::new(1.0, 0.0, 0.0),
},
source_object: None,
})
.expect("insert surface into draft");
draft
}
#[test]
fn cross_root_surface_filter_tracks_successful_commits_only() {
let committed_id = "step:data:surface#implicit-face-1";
let rejected_id = "step:data:surface#implicit-face-2";
let mut ir = CadIr::empty(Units::default());
let mut session = CommitSession::new(&ir);
session
.commit_model(surface_draft(committed_id), &mut ir)
.expect("first root commit");
let mut second_root = surface_draft(committed_id);
drop_committed_surfaces(&mut second_root, &session, &ir);
assert!(second_root.model().surfaces.is_empty());
let mut rejected_root = surface_draft(rejected_id);
rejected_root
.insert(Vertex {
id: "step:data:vertex#rejected".into(),
point: "step:data:point#missing".into(),
tolerance: None,
})
.expect("insert invalid root reference");
assert!(session.commit_model(rejected_root, &mut ir).is_err());
let mut later_root = surface_draft(rejected_id);
drop_committed_surfaces(&mut later_root, &session, &ir);
assert_eq!(later_root.model().surfaces.len(), 1);
}
#[test]
fn pcurve_fit_keeps_exact_points_at_a_degenerate_surface_boundary() {
let surface_id = SurfaceId("step:data:surface#boundary".into());
let surface_geometry = SurfaceGeometry::Nurbs(NurbsSurface {
u_degree: 1,
v_degree: 1,
u_knots: vec![0.0, 0.0, 1.0, 1.0],
v_knots: vec![0.0, 0.0, 1.0, 1.0],
u_count: 2,
v_count: 2,
control_points: vec![
Point3::new(0.0, 0.0, 0.0),
Point3::new(0.0, 0.0, 0.0),
Point3::new(1.0, 0.0, 0.0),
Point3::new(1.0, 1.0, 0.0),
],
weights: None,
u_periodic: false,
v_periodic: false,
});
let mut ir = CadIr::empty(Units::default());
ir.model.surfaces.push(Surface {
id: surface_id.clone(),
geometry: surface_geometry.clone(),
source_object: None,
});
let index = ModelIndex::new(&ir);
let pcurve = PcurveGeometry::Line {
origin: cadmpeg_ir::math::Point2::new(0.0, 0.0),
direction: cadmpeg_ir::math::Point2::new(1.0, 0.0),
};
let fit = pcurve_endpoint_fit(
&index,
&surface_id,
&pcurve,
&surface_geometry,
Point3::new(0.0, 0.0, 0.0),
Point3::new(1.0, 0.0, 0.0),
)
.expect("surface points should be evaluable at the boundary");
assert_eq!(fit.start_parameter, 0.0);
assert_eq!(fit.end_parameter, 1.0);
assert!(fit.score <= f64::EPSILON);
}
#[test]
fn synthesized_pcurve_chart_rejects_a_collapsed_bowed_axis() {
let bowed = PcurveGeometry::Nurbs {
degree: 2,
knots: vec![0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
control_points: vec![
Point2::new(0.0, 0.0),
Point2::new(1.0, 1.0),
Point2::new(0.0, 2.0),
],
weights: None,
periodic: false,
};
assert!(endpoint_parameter_transform(
&bowed,
[Point2::new(0.0, 0.0), Point2::new(0.0, 2.0)],
[[1.0, 0.0], [1.0, 2.0]],
[false, false],
)
.is_none());
let isoparametric = PcurveGeometry::Trimmed {
basis: Box::new(PcurveGeometry::Line {
origin: Point2::new(0.0, 0.0),
direction: Point2::new(0.0, 1.0),
}),
parameter_range: [0.0, 1.0],
same_sense: true,
};
assert!(endpoint_parameter_transform(
&isoparametric,
[Point2::new(0.0, 0.0), Point2::new(0.0, 1.0)],
[[3.0, 4.0], [3.0, 5.0]],
[false, false],
)
.is_some());
}
#[test]
fn selected_pcurve_variants_are_use_scoped() {
let source_id = PcurveId("step:data:pcurve#shared".into());
let source_geometry = PcurveGeometry::Line {
origin: Point2::new(0.0, 0.0),
direction: Point2::new(1.0, 0.0),
};
let selected_geometry = PcurveGeometry::Line {
origin: Point2::new(4.0, 0.0),
direction: Point2::new(1.0, 0.0),
};
let mut ir = CadIr::empty(Units::default());
ir.model.pcurves.push(Pcurve {
id: source_id.clone(),
geometry: source_geometry.clone(),
wrapper_reversed: None,
native_tail_flags: None,
parameter_range: None,
fit_tolerance: None,
});
let selected = SelectedPcurve {
id: source_id.clone(),
geometry: selected_geometry.clone(),
parameter_range: Some([0.0, 1.0]),
};
let (first, first_variant) =
materialize_pcurve_variant(&ir, &selected, &CoedgeId("step:data:coedge#first".into()));
let (second, second_variant) =
materialize_pcurve_variant(&ir, &selected, &CoedgeId("step:data:coedge#second".into()));
assert_ne!(first, source_id);
assert_ne!(second, source_id);
assert_ne!(first, second);
assert_eq!(ir.model.pcurves[0].geometry, source_geometry);
assert_eq!(
first_variant.expect("first pcurve variant").geometry,
selected_geometry
);
assert_eq!(
second_variant.expect("second pcurve variant").geometry,
selected_geometry
);
}
#[test]
fn periodic_surface_line_seeds_cover_both_parameter_axes() {
let surface_id = SurfaceId("step:data:surface#periodic-seeds".into());
let surface_geometry = SurfaceGeometry::Torus {
center: Point3::new(0.0, 0.0, 0.0),
axis: Vector3::new(0.0, 0.0, 1.0),
ref_direction: Vector3::new(1.0, 0.0, 0.0),
major_radius: 2.0,
minor_radius: 1.0,
};
let mut ir = CadIr::empty(Units::default());
ir.model.surfaces.push(Surface {
id: surface_id.clone(),
geometry: surface_geometry.clone(),
source_object: None,
});
let index = ModelIndex::new(&ir);
for direction in [Point2::new(1.0, 0.0), Point2::new(0.0, 1.0)] {
let geometry = PcurveGeometry::Line {
origin: Point2::new(0.0, 0.0),
direction,
};
let seeds = pcurve_selection_seeds(&index, &surface_id, &geometry, &surface_geometry);
assert!(seeds
.iter()
.any(|seed| { (*seed - std::f64::consts::PI).abs() <= 1.0e-12 }));
}
}
#[test]
fn shared_surface_carrier_is_staged_once() {
let surface = Surface {
id: SurfaceId("step:data:surface#shared".into()),
geometry: SurfaceGeometry::Plane {
origin: Point3::new(0.0, 0.0, 0.0),
normal: Vector3::new(0.0, 0.0, 1.0),
u_axis: Vector3::new(1.0, 0.0, 0.0),
},
source_object: None,
};
let body_id = BodyId("step:data:body#shared-surface".into());
let region_id = RegionId("step:data:region#shared-surface".into());
let built = super::super::staged_topology(
HashSet::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
vec![surface.clone(), surface],
Vec::new(),
Region {
id: region_id.clone(),
body: body_id.clone(),
shells: Vec::new(),
},
Body {
id: body_id,
kind: BodyKind::Sheet,
regions: vec![region_id],
transform: None,
name: None,
color: None,
visible: None,
},
)
.expect("duplicate references to one source surface must stage");
assert_eq!(built.draft.model().surfaces.len(), 1);
}