use axiolid_model::PointOnSurface as KernelPointOnSurface;
use axiolid_model::{GeometryNode, NodeId, PointOnCurve as KernelPointOnCurve};
use ifc_model::EntityId;
use crate::error::GeometryResult;
use crate::lower::curve::{lower_curve_node, scale_parameter};
use crate::lower::session::LoweringSession;
use crate::lower::surface::lower_surface_node;
use crate::resource::point::{PointOnCurve, PointOnSurface};
use crate::transform::Transform;
const KIND: &str = "point";
pub fn lower_point_on_curve_node(
session: &mut LoweringSession<'_>,
id: EntityId,
frame: Transform,
) -> GeometryResult<NodeId> {
if let Some(node) = session.memoized(id, KIND, frame) {
return Ok(node);
}
session.enter(id, KIND)?;
let result = build_point_on_curve(session, id, frame);
session.exit(id);
let node = result?;
session.memoize(id, KIND, frame, node);
Ok(node)
}
fn build_point_on_curve(
session: &mut LoweringSession<'_>,
id: EntityId,
frame: Transform,
) -> GeometryResult<NodeId> {
let entity = session.entity(id, id)?;
let view = PointOnCurve::new(id, entity);
let basis_ref = view.basis_curve()?;
let raw_parameter = view.point_parameter()?;
let basis_kind = session.type_name(basis_ref)?;
let curve = lower_curve_node(session, basis_ref, frame)?;
let parameter = scale_parameter(session, &basis_kind, raw_parameter);
session.node_for(
id,
GeometryNode::PointOnCurve(KernelPointOnCurve { curve, parameter }),
)
}
pub fn lower_point_on_surface_node(
session: &mut LoweringSession<'_>,
id: EntityId,
frame: Transform,
) -> GeometryResult<NodeId> {
if let Some(node) = session.memoized(id, KIND, frame) {
return Ok(node);
}
session.enter(id, KIND)?;
let result = build_point_on_surface(session, id, frame);
session.exit(id);
let node = result?;
session.memoize(id, KIND, frame, node);
Ok(node)
}
fn build_point_on_surface(
session: &mut LoweringSession<'_>,
id: EntityId,
frame: Transform,
) -> GeometryResult<NodeId> {
let entity = session.entity(id, id)?;
let view = PointOnSurface::new(id, entity);
let basis_ref = view.basis_surface()?;
let (raw_u, raw_v) = view.parameters()?;
let basis_kind = session.type_name(basis_ref)?;
let surface = lower_surface_node(session, basis_ref, frame)?;
let convert = crate::lower::surface::trim_converter(session, &basis_kind);
let (u, v) = (convert(raw_u), convert(raw_v));
session.node_for(
id,
GeometryNode::PointOnSurface(KernelPointOnSurface { surface, u, v }),
)
}
#[cfg(test)]
mod tests;