use super::*;
pub(super) fn projected_reference_paths(
ctx: &FeatureContext,
frame: &Frame,
unresolved: &mut Vec<String>,
) -> Result<Vec<(String, Vec<NurbsCurve>)>, String> {
let names = common::reference_names(ctx.param("projectedEdges"));
if names.is_empty() {
return Ok(Vec::new());
}
let normal = frame.z_axis.normalized()?;
let mut paths = Vec::with_capacity(names.len());
for name in names {
let Some(edge) = ctx.scene.resolve_edge(&name) else {
unresolved.push(name);
continue;
};
let curve = common::edge_curve(edge)
.map_err(|error| format!("sketch: projected {error}"))?;
let projected = project_curve(&curve, frame.origin, normal)?;
paths.push((format!("{}:REF:{name}", ctx.id), vec![projected]));
}
Ok(paths)
}
fn project_curve(curve: &NurbsCurve, origin: Vec3, normal: Vec3) -> Result<NurbsCurve, String> {
let mut control_points = Vec::with_capacity(curve.control_points.len());
for cp in &curve.control_points {
let point = cp.point()?;
let signed = point.sub(origin).dot(normal);
control_points.push(Vec4::from_point(point.sub(normal.scale(signed)), cp.w));
}
NurbsCurve::new(curve.degree, curve.knots.clone(), control_points)
}