#![allow(clippy::must_use_candidate)]
use crate::RefGraph;
use crate::StepModel;
use crate::scene::{Ctx, Scene};
use crate::generated::model as m;
impl Scene<'_> {
pub fn all_solids(&self) -> impl Iterator<Item = Solid<'_>> + '_ {
let cx = self.ctx();
let manifold = (0..cx.model.manifold_solid_brep_arena.items.len())
.map(move |i| Solid::from_id(cx, m::ManifoldSolidBrepId(i)));
let with_voids = (0..cx.model.brep_with_voids_arena.items.len())
.map(move |i| Solid::from_void_id(cx, m::BrepWithVoidsId(i)));
manifold.chain(with_voids)
}
pub fn all_faces(&self) -> impl Iterator<Item = Face<'_>> + '_ {
let cx = self.ctx();
let advanced = (0..cx.model.advanced_face_arena.items.len()).map(move |i| Face {
cx,
which: FaceImpl::Advanced(m::AdvancedFaceId(i)),
});
let surfaces = (0..cx.model.face_surface_arena.items.len()).map(move |i| Face {
cx,
which: FaceImpl::Surface(m::FaceSurfaceId(i)),
});
advanced.chain(surfaces)
}
pub fn all_edges(&self) -> impl Iterator<Item = Edge<'_>> + '_ {
let cx = self.ctx();
(0..cx.model.edge_curve_arena.items.len()).map(move |i| Edge {
cx,
id: m::EdgeCurveId(i),
})
}
pub fn all_vertices(&self) -> impl Iterator<Item = Vertex<'_>> + '_ {
let cx = self.ctx();
(0..cx.model.vertex_point_arena.items.len()).map(move |i| Vertex {
cx,
id: m::VertexPointId(i),
})
}
pub fn all_points(&self) -> impl Iterator<Item = Point<'_>> + '_ {
let cx = self.ctx();
(0..cx.model.cartesian_point_arena.items.len()).map(move |i| Point {
cx,
id: m::CartesianPointId(i),
})
}
}
#[derive(Clone, Copy)]
pub struct Solid<'m> {
cx: Ctx<'m>,
which: SolidImpl,
}
#[derive(Clone, Copy)]
enum SolidImpl {
Manifold(m::ManifoldSolidBrepId),
WithVoids(m::BrepWithVoidsId),
}
impl<'m> Solid<'m> {
pub(crate) fn from_id(cx: Ctx<'m>, id: m::ManifoldSolidBrepId) -> Self {
Solid {
cx,
which: SolidImpl::Manifold(id),
}
}
pub(crate) fn from_void_id(cx: Ctx<'m>, id: m::BrepWithVoidsId) -> Self {
Solid {
cx,
which: SolidImpl::WithVoids(id),
}
}
fn name_and_outer(&self) -> (&'m str, &'m m::ClosedShellRef) {
match self.which {
SolidImpl::Manifold(i) => {
let s = self.cx.model.manifold_solid_brep_arena.get(i.0);
(&s.name, &s.outer)
}
SolidImpl::WithVoids(i) => {
let s = self.cx.model.brep_with_voids_arena.get(i.0);
(&s.name, &s.outer)
}
}
}
pub fn name(&self) -> &'m str {
self.name_and_outer().0
}
pub fn key(&self) -> m::EntityKey {
match self.which {
SolidImpl::Manifold(i) => m::EntityKey::ManifoldSolidBrep(i),
SolidImpl::WithVoids(i) => m::EntityKey::BrepWithVoids(i),
}
}
pub fn color(&self) -> Option<crate::scene::presentation::Rgb> {
crate::scene::presentation::colour_of(self.cx, self.key())
}
pub fn transparency(&self) -> Option<f64> {
crate::scene::presentation::transparency_of(self.cx, self.key())
}
pub fn layer(&self) -> Option<&'m str> {
crate::scene::presentation::layer_of(self.cx, self.key())
}
pub fn is_visible(&self) -> bool {
crate::scene::presentation::is_visible(self.cx, self.key())
}
pub fn faces(&self) -> impl Iterator<Item = Face<'m>> + 'm {
let cx = self.cx;
resolve_closed_shell(cx.model, self.name_and_outer().1)
.into_iter()
.flat_map(|shell| shell.cfs_faces.iter())
.filter_map(move |fr| Face::from_ref(cx, fr))
}
pub fn voids(&self) -> Vec<Vec<Face<'m>>> {
let cx = self.cx;
let SolidImpl::WithVoids(id) = self.which else {
return Vec::new();
};
cx.model
.brep_with_voids_arena
.get(id.0)
.voids
.iter()
.map(|ocs| {
let shell = match ocs {
m::OrientedClosedShellRef::OrientedClosedShell(o) => resolve_closed_shell(
cx.model,
&cx.model
.oriented_closed_shell_arena
.get(o.0)
.closed_shell_element,
),
m::OrientedClosedShellRef::Complex(_) => None,
};
shell
.into_iter()
.flat_map(|s| s.cfs_faces.iter())
.filter_map(|fr| Face::from_ref(cx, fr))
.collect()
})
.collect()
}
}
#[derive(Clone, Copy)]
enum FaceImpl {
Advanced(m::AdvancedFaceId),
Surface(m::FaceSurfaceId),
}
#[derive(Clone, Copy)]
pub struct Face<'m> {
cx: Ctx<'m>,
which: FaceImpl,
}
impl<'m> Face<'m> {
pub(crate) fn from_advanced_face(cx: Ctx<'m>, id: m::AdvancedFaceId) -> Self {
Face {
cx,
which: FaceImpl::Advanced(id),
}
}
fn from_ref(cx: Ctx<'m>, r: &m::FaceRef) -> Option<Self> {
match r {
m::FaceRef::AdvancedFace(i) => Some(Face {
cx,
which: FaceImpl::Advanced(*i),
}),
m::FaceRef::FaceSurface(i) => Some(Face {
cx,
which: FaceImpl::Surface(*i),
}),
m::FaceRef::Face(_) | m::FaceRef::Complex(_) => None,
}
}
fn parts(&self) -> (&'m str, &'m [m::FaceBoundRef], &'m m::SurfaceRef, bool) {
match self.which {
FaceImpl::Advanced(i) => {
let f = self.cx.model.advanced_face_arena.get(i.0);
(&f.name, &f.bounds, &f.face_geometry, f.same_sense)
}
FaceImpl::Surface(i) => {
let f = self.cx.model.face_surface_arena.get(i.0);
(&f.name, &f.bounds, &f.face_geometry, f.same_sense)
}
}
}
pub fn name(&self) -> &'m str {
self.parts().0
}
pub fn same_sense(&self) -> bool {
self.parts().3
}
pub fn surface(&self) -> Surface<'m> {
Surface {
cx: self.cx,
r: self.parts().2,
}
}
pub fn bounds(&self) -> impl Iterator<Item = Bound<'m>> + 'm {
let cx = self.cx;
self.parts()
.1
.iter()
.filter_map(move |br| Bound::from_ref(cx, br))
}
fn boundary_points(&self) -> Vec<[f64; 3]> {
let mut points = Vec::new();
for bound in self.bounds() {
for edge in bound.edges() {
if let Some(n) = edge.to_nurbs() {
points.extend(n.control_points);
} else {
for v in [edge.start(), edge.end()].into_iter().flatten() {
if let Some(pt) = v.point() {
points.push(pt.xyz());
}
}
}
}
}
points
}
pub fn to_nurbs(&self) -> Option<crate::scene::nurbs::NurbsSurface> {
if let Some(n) = self.surface().to_nurbs() {
return Some(n);
}
let cx = self.cx;
let pts = self.boundary_points();
match self.surface().kind() {
SurfaceKind::Plane(p) => crate::scene::nurbs::plane_patch(cx, p, &pts),
SurfaceKind::Cylindrical(c) => {
crate::scene::nurbs::cylinder_cone_patch(cx, &c.position, c.radius, 0.0, &pts)
}
SurfaceKind::Conical(c) => crate::scene::nurbs::cylinder_cone_patch(
cx,
&c.position,
c.radius,
c.semi_angle,
&pts,
),
SurfaceKind::LinearExtrusion(s) => {
let profile = Curve::from_curve_ref(cx, &s.swept_curve).to_nurbs()?;
crate::scene::nurbs::extrude_patch(cx, &profile, &s.extrusion_axis, &pts)
}
SurfaceKind::Revolution(s) => {
let CurveKind::Line(line) = Curve::from_curve_ref(cx, &s.swept_curve).kind() else {
return None;
};
let frame = crate::scene::nurbs::axis1_frame(cx, &s.axis_position)?;
let seg = crate::scene::nurbs::revolved_line_segment(cx, line, frame, &pts)?;
Some(crate::scene::nurbs::revolve_curve(&seg, frame))
}
_ => None,
}
}
pub fn key(&self) -> m::EntityKey {
match self.which {
FaceImpl::Advanced(i) => m::EntityKey::AdvancedFace(i),
FaceImpl::Surface(i) => m::EntityKey::FaceSurface(i),
}
}
pub fn color(&self) -> Option<crate::scene::presentation::Rgb> {
crate::scene::presentation::colour_of(self.cx, self.key())
}
pub fn transparency(&self) -> Option<f64> {
crate::scene::presentation::transparency_of(self.cx, self.key())
}
pub fn layer(&self) -> Option<&'m str> {
crate::scene::presentation::layer_of(self.cx, self.key())
}
pub fn is_visible(&self) -> bool {
crate::scene::presentation::is_visible(self.cx, self.key())
}
pub fn solid(&self) -> Option<Solid<'m>> {
let rg = self.cx.ref_graph();
for &r in rg.referrers(self.key()) {
if let m::EntityKey::ClosedShell(cs) = r {
if let Some(which) = closed_shell_to_solid(rg, cs) {
return Some(Solid { cx: self.cx, which });
}
}
}
None
}
}
#[derive(Clone, Copy)]
pub struct Surface<'m> {
cx: Ctx<'m>,
r: &'m m::SurfaceRef,
}
#[derive(Clone, Copy, Debug)]
pub enum SurfaceKind<'m> {
Plane(&'m m::Plane),
Cylindrical(&'m m::CylindricalSurface),
Conical(&'m m::ConicalSurface),
Spherical(&'m m::SphericalSurface),
Toroidal(&'m m::ToroidalSurface),
BSpline(&'m m::BSplineSurface),
BSplineWithKnots(&'m m::BSplineSurfaceWithKnots),
LinearExtrusion(&'m m::SurfaceOfLinearExtrusion),
Revolution(&'m m::SurfaceOfRevolution),
QuasiUniform(&'m m::QuasiUniformSurface),
Uniform(&'m m::UniformSurface),
Bezier(&'m m::BezierSurface),
Other(&'static str),
}
impl<'m> Surface<'m> {
pub fn key(&self) -> m::EntityKey {
self.r.entity_key()
}
pub fn to_nurbs(&self) -> Option<crate::scene::nurbs::NurbsSurface> {
let cx = self.cx;
match self.r {
m::SurfaceRef::SphericalSurface(i) => {
crate::scene::nurbs::sphere_to_nurbs(cx, cx.model.spherical_surface_arena.get(i.0))
}
m::SurfaceRef::ToroidalSurface(i) => {
crate::scene::nurbs::torus_to_nurbs(cx, cx.model.toroidal_surface_arena.get(i.0))
}
m::SurfaceRef::BSplineSurfaceWithKnots(i) => {
crate::scene::nurbs::bspline_surf_wk_to_nurbs(
cx,
cx.model.b_spline_surface_with_knots_arena.get(i.0),
)
}
m::SurfaceRef::Complex(i) => crate::scene::nurbs::complex_bspline_surface_to_nurbs(
cx,
&cx.model.complex_unit_arena.get(i.0).parts,
),
m::SurfaceRef::SurfaceOfRevolution(i) => {
let s = cx.model.surface_of_revolution_arena.get(i.0);
let profile = Curve::from_curve_ref(cx, &s.swept_curve).to_nurbs()?;
let frame = crate::scene::nurbs::axis1_frame(cx, &s.axis_position)?;
Some(crate::scene::nurbs::revolve_curve(&profile, frame))
}
m::SurfaceRef::UniformSurface(i) => {
let s = cx.model.uniform_surface_arena.get(i.0);
crate::scene::nurbs::uniform_family_surface_to_nurbs(
cx,
(s.u_degree, s.v_degree),
&s.control_points_list,
crate::scene::nurbs::KnotFamily::Uniform,
)
}
m::SurfaceRef::QuasiUniformSurface(i) => {
let s = cx.model.quasi_uniform_surface_arena.get(i.0);
crate::scene::nurbs::uniform_family_surface_to_nurbs(
cx,
(s.u_degree, s.v_degree),
&s.control_points_list,
crate::scene::nurbs::KnotFamily::QuasiUniform,
)
}
m::SurfaceRef::BezierSurface(i) => {
let s = cx.model.bezier_surface_arena.get(i.0);
crate::scene::nurbs::uniform_family_surface_to_nurbs(
cx,
(s.u_degree, s.v_degree),
&s.control_points_list,
crate::scene::nurbs::KnotFamily::Bezier,
)
}
_ => None,
}
}
pub fn kind(&self) -> SurfaceKind<'m> {
let model = self.cx.model;
match self.r {
m::SurfaceRef::Plane(i) => SurfaceKind::Plane(model.plane_arena.get(i.0)),
m::SurfaceRef::CylindricalSurface(i) => {
SurfaceKind::Cylindrical(model.cylindrical_surface_arena.get(i.0))
}
m::SurfaceRef::ConicalSurface(i) => {
SurfaceKind::Conical(model.conical_surface_arena.get(i.0))
}
m::SurfaceRef::SphericalSurface(i) => {
SurfaceKind::Spherical(model.spherical_surface_arena.get(i.0))
}
m::SurfaceRef::ToroidalSurface(i) => {
SurfaceKind::Toroidal(model.toroidal_surface_arena.get(i.0))
}
m::SurfaceRef::BSplineSurface(i) => {
SurfaceKind::BSpline(model.b_spline_surface_arena.get(i.0))
}
m::SurfaceRef::BSplineSurfaceWithKnots(i) => {
SurfaceKind::BSplineWithKnots(model.b_spline_surface_with_knots_arena.get(i.0))
}
m::SurfaceRef::BezierSurface(i) => {
SurfaceKind::Bezier(model.bezier_surface_arena.get(i.0))
}
m::SurfaceRef::BoundedSurface(_) => SurfaceKind::Other("BOUNDED_SURFACE"),
m::SurfaceRef::DegenerateToroidalSurface(_) => {
SurfaceKind::Other("DEGENERATE_TOROIDAL_SURFACE")
}
m::SurfaceRef::ElementarySurface(_) => SurfaceKind::Other("ELEMENTARY_SURFACE"),
m::SurfaceRef::OffsetSurface(_) => SurfaceKind::Other("OFFSET_SURFACE"),
m::SurfaceRef::QuasiUniformSurface(i) => {
SurfaceKind::QuasiUniform(model.quasi_uniform_surface_arena.get(i.0))
}
m::SurfaceRef::RationalBSplineSurface(_) => {
SurfaceKind::Other("RATIONAL_B_SPLINE_SURFACE")
}
m::SurfaceRef::Surface(_) => SurfaceKind::Other("SURFACE"),
m::SurfaceRef::SurfaceOfLinearExtrusion(i) => {
SurfaceKind::LinearExtrusion(model.surface_of_linear_extrusion_arena.get(i.0))
}
m::SurfaceRef::SurfaceOfRevolution(i) => {
SurfaceKind::Revolution(model.surface_of_revolution_arena.get(i.0))
}
m::SurfaceRef::SweptSurface(_) => SurfaceKind::Other("SWEPT_SURFACE"),
m::SurfaceRef::UniformSurface(i) => {
SurfaceKind::Uniform(model.uniform_surface_arena.get(i.0))
}
m::SurfaceRef::Complex(_) => SurfaceKind::Other("COMPLEX"),
}
}
}
#[derive(Clone, Copy)]
enum BoundImpl {
Inner(m::FaceBoundId),
Outer(m::FaceOuterBoundId),
}
#[derive(Clone, Copy)]
pub struct Bound<'m> {
cx: Ctx<'m>,
which: BoundImpl,
}
impl<'m> Bound<'m> {
fn from_ref(cx: Ctx<'m>, r: &m::FaceBoundRef) -> Option<Self> {
match r {
m::FaceBoundRef::FaceBound(i) => Some(Bound {
cx,
which: BoundImpl::Inner(*i),
}),
m::FaceBoundRef::FaceOuterBound(i) => Some(Bound {
cx,
which: BoundImpl::Outer(*i),
}),
m::FaceBoundRef::Complex(_) => None,
}
}
pub fn is_outer(&self) -> bool {
matches!(self.which, BoundImpl::Outer(_))
}
pub fn key(&self) -> m::EntityKey {
match self.which {
BoundImpl::Inner(i) => m::EntityKey::FaceBound(i),
BoundImpl::Outer(i) => m::EntityKey::FaceOuterBound(i),
}
}
fn loop_ref(&self) -> &'m m::LoopRef {
match self.which {
BoundImpl::Inner(i) => &self.cx.model.face_bound_arena.get(i.0).bound,
BoundImpl::Outer(i) => &self.cx.model.face_outer_bound_arena.get(i.0).bound,
}
}
pub fn orientation(&self) -> bool {
match self.which {
BoundImpl::Inner(i) => self.cx.model.face_bound_arena.get(i.0).orientation,
BoundImpl::Outer(i) => self.cx.model.face_outer_bound_arena.get(i.0).orientation,
}
}
pub fn edges(&self) -> impl Iterator<Item = Edge<'m>> + 'm {
self.oriented_edges().map(|(e, _)| e)
}
pub fn oriented_edges(&self) -> impl Iterator<Item = (Edge<'m>, bool)> + 'm {
let cx = self.cx;
resolve_edge_loop(cx.model, self.loop_ref())
.into_iter()
.flat_map(|el| el.edge_list.iter())
.filter_map(move |oer| {
let oe = resolve_oriented_edge(cx.model, oer)?;
Some((Edge::from_edge_ref(cx, &oe.edge_element)?, oe.orientation))
})
}
}
#[derive(Clone, Copy)]
pub struct Edge<'m> {
cx: Ctx<'m>,
id: m::EdgeCurveId,
}
impl<'m> Edge<'m> {
pub(crate) fn from_id(cx: Ctx<'m>, id: m::EdgeCurveId) -> Self {
Edge { cx, id }
}
fn from_edge_ref(cx: Ctx<'m>, r: &m::EdgeRef) -> Option<Self> {
match r {
m::EdgeRef::EdgeCurve(i) => Some(Edge { cx, id: *i }),
m::EdgeRef::Edge(_) | m::EdgeRef::OrientedEdge(_) | m::EdgeRef::Complex(_) => None,
}
}
fn raw(&self) -> &'m m::EdgeCurve {
self.cx.model.edge_curve_arena.get(self.id.0)
}
pub fn key(&self) -> m::EntityKey {
m::EntityKey::EdgeCurve(self.id)
}
pub fn start(&self) -> Option<Vertex<'m>> {
Vertex::from_ref(self.cx, &self.raw().edge_start)
}
pub fn end(&self) -> Option<Vertex<'m>> {
Vertex::from_ref(self.cx, &self.raw().edge_end)
}
pub fn curve(&self) -> Curve<'m> {
Curve::from_curve_ref(self.cx, &self.raw().edge_geometry)
}
pub fn same_sense(&self) -> bool {
self.raw().same_sense
}
pub fn to_nurbs(&self) -> Option<crate::scene::nurbs::NurbsCurve> {
let cx = self.cx;
let coords = |v: Option<Vertex<'m>>| Some(v?.point()?.xyz());
let (Some(p0), Some(p1)) = (coords(self.start()), coords(self.end())) else {
cx.warn("EDGE_CURVE.to_nurbs: unresolved edge vertex".to_owned());
return None;
};
let raw = self.raw();
crate::scene::nurbs::edge_to_nurbs(cx, &raw.edge_geometry, p0, p1, raw.same_sense)
}
}
#[derive(Clone, Copy)]
pub struct Curve<'m> {
cx: Ctx<'m>,
which: CurveImpl,
}
#[derive(Clone, Copy, Debug)]
pub enum CurveKind<'m> {
Line(&'m m::Line),
Circle(&'m m::Circle),
Ellipse(&'m m::Ellipse),
BSpline(&'m m::BSplineCurve),
BSplineWithKnots(&'m m::BSplineCurveWithKnots),
Trimmed(&'m m::TrimmedCurve),
Polyline(&'m m::Polyline),
Composite(&'m m::CompositeCurve),
QuasiUniform(&'m m::QuasiUniformCurve),
Uniform(&'m m::UniformCurve),
Bezier(&'m m::BezierCurve),
SurfaceCurve(&'m m::SurfaceCurve),
SeamCurve(&'m m::SeamCurve),
BoundedSurfaceCurve(&'m m::BoundedSurfaceCurve),
IntersectionCurve(&'m m::IntersectionCurve),
Other(&'static str),
}
macro_rules! curve_impl {
($( $V:ident, $id:ident );+ $(;)?) => {
#[derive(Clone, Copy)]
enum CurveImpl {
$( $V(m::$id), )+
Complex(m::ComplexUnitId),
}
impl<'m> Curve<'m> {
pub fn key(&self) -> m::EntityKey {
match self.which {
$( CurveImpl::$V(i) => m::EntityKey::$V(i), )+
CurveImpl::Complex(i) => m::EntityKey::ComplexUnit(i),
}
}
pub(crate) fn from_curve_ref(cx: Ctx<'m>, r: &m::CurveRef) -> Self {
let which = match r {
$( m::CurveRef::$V(i) => CurveImpl::$V(*i), )+
m::CurveRef::Complex(i) => CurveImpl::Complex(*i),
};
Curve { cx, which }
}
pub(crate) fn from_model_item(
cx: Ctx<'m>,
r: &m::GeometricModelItemRef,
) -> Option<Self> {
let which = match r {
$( m::GeometricModelItemRef::$V(i) => CurveImpl::$V(*i), )+
_ => return None,
};
Some(Curve { cx, which })
}
}
};
}
curve_impl! {
BSplineCurve, BSplineCurveId;
BSplineCurveWithKnots, BSplineCurveWithKnotsId;
BezierCurve, BezierCurveId;
BoundedCurve, BoundedCurveId;
BoundedPcurve, BoundedPcurveId;
BoundedSurfaceCurve, BoundedSurfaceCurveId;
Circle, CircleId;
CompositeCurve, CompositeCurveId;
Conic, ConicId;
Curve, CurveId;
Ellipse, EllipseId;
Hyperbola, HyperbolaId;
IntersectionCurve, IntersectionCurveId;
Line, LineId;
Pcurve, PcurveId;
Polyline, PolylineId;
QuasiUniformCurve, QuasiUniformCurveId;
RationalBSplineCurve, RationalBSplineCurveId;
SeamCurve, SeamCurveId;
SurfaceCurve, SurfaceCurveId;
TrimmedCurve, TrimmedCurveId;
UniformCurve, UniformCurveId;
}
impl<'m> Curve<'m> {
pub fn color(&self) -> Option<crate::scene::presentation::Rgb> {
crate::scene::presentation::curve_colour_of(self.cx, self.key())
}
pub fn width(&self) -> Option<f64> {
crate::scene::presentation::curve_width_of(self.cx, self.key())
}
pub fn line_font(&self) -> Option<&'m str> {
crate::scene::presentation::curve_font_of(self.cx, self.key())
}
pub fn to_nurbs(&self) -> Option<crate::scene::nurbs::NurbsCurve> {
let cx = self.cx;
match self.which {
CurveImpl::Circle(i) => {
crate::scene::nurbs::circle_to_nurbs(cx, cx.model.circle_arena.get(i.0))
}
CurveImpl::Ellipse(i) => {
crate::scene::nurbs::ellipse_to_nurbs(cx, cx.model.ellipse_arena.get(i.0))
}
CurveImpl::BSplineCurveWithKnots(i) => crate::scene::nurbs::bspline_wk_to_nurbs(
cx,
cx.model.b_spline_curve_with_knots_arena.get(i.0),
),
CurveImpl::Complex(i) => crate::scene::nurbs::complex_bspline_curve_to_nurbs(
cx,
&cx.model.complex_unit_arena.get(i.0).parts,
),
CurveImpl::TrimmedCurve(i) => {
crate::scene::nurbs::trimmed_to_nurbs(cx, cx.model.trimmed_curve_arena.get(i.0))
}
CurveImpl::UniformCurve(i) => {
let c = cx.model.uniform_curve_arena.get(i.0);
crate::scene::nurbs::uniform_family_curve_to_nurbs(
cx,
c.degree,
&c.control_points_list,
crate::scene::nurbs::KnotFamily::Uniform,
)
}
CurveImpl::QuasiUniformCurve(i) => {
let c = cx.model.quasi_uniform_curve_arena.get(i.0);
crate::scene::nurbs::uniform_family_curve_to_nurbs(
cx,
c.degree,
&c.control_points_list,
crate::scene::nurbs::KnotFamily::QuasiUniform,
)
}
CurveImpl::BezierCurve(i) => {
let c = cx.model.bezier_curve_arena.get(i.0);
crate::scene::nurbs::uniform_family_curve_to_nurbs(
cx,
c.degree,
&c.control_points_list,
crate::scene::nurbs::KnotFamily::Bezier,
)
}
CurveImpl::Polyline(i) => {
crate::scene::nurbs::polyline_to_nurbs(cx, cx.model.polyline_arena.get(i.0))
}
CurveImpl::CompositeCurve(i) => {
crate::scene::nurbs::composite_to_nurbs(cx, cx.model.composite_curve_arena.get(i.0))
}
CurveImpl::SurfaceCurve(i) => crate::scene::nurbs::surface_curve_3d_to_nurbs(
cx,
&cx.model.surface_curve_arena.get(i.0).curve_3d,
),
CurveImpl::SeamCurve(i) => crate::scene::nurbs::surface_curve_3d_to_nurbs(
cx,
&cx.model.seam_curve_arena.get(i.0).curve_3d,
),
CurveImpl::BoundedSurfaceCurve(i) => crate::scene::nurbs::surface_curve_3d_to_nurbs(
cx,
&cx.model.bounded_surface_curve_arena.get(i.0).curve_3d,
),
CurveImpl::IntersectionCurve(i) => crate::scene::nurbs::surface_curve_3d_to_nurbs(
cx,
&cx.model.intersection_curve_arena.get(i.0).curve_3d,
),
_ => None,
}
}
pub fn kind(&self) -> CurveKind<'m> {
let model = self.cx.model;
match self.which {
CurveImpl::Line(i) => CurveKind::Line(model.line_arena.get(i.0)),
CurveImpl::Circle(i) => CurveKind::Circle(model.circle_arena.get(i.0)),
CurveImpl::Ellipse(i) => CurveKind::Ellipse(model.ellipse_arena.get(i.0)),
CurveImpl::BSplineCurve(i) => CurveKind::BSpline(model.b_spline_curve_arena.get(i.0)),
CurveImpl::BSplineCurveWithKnots(i) => {
CurveKind::BSplineWithKnots(model.b_spline_curve_with_knots_arena.get(i.0))
}
CurveImpl::TrimmedCurve(i) => CurveKind::Trimmed(model.trimmed_curve_arena.get(i.0)),
CurveImpl::BezierCurve(i) => CurveKind::Bezier(model.bezier_curve_arena.get(i.0)),
CurveImpl::BoundedCurve(_) => CurveKind::Other("BOUNDED_CURVE"),
CurveImpl::BoundedPcurve(_) => CurveKind::Other("BOUNDED_PCURVE"),
CurveImpl::BoundedSurfaceCurve(i) => {
CurveKind::BoundedSurfaceCurve(model.bounded_surface_curve_arena.get(i.0))
}
CurveImpl::CompositeCurve(i) => {
CurveKind::Composite(model.composite_curve_arena.get(i.0))
}
CurveImpl::Conic(_) => CurveKind::Other("CONIC"),
CurveImpl::Curve(_) => CurveKind::Other("CURVE"),
CurveImpl::Hyperbola(_) => CurveKind::Other("HYPERBOLA"),
CurveImpl::IntersectionCurve(i) => {
CurveKind::IntersectionCurve(model.intersection_curve_arena.get(i.0))
}
CurveImpl::Pcurve(_) => CurveKind::Other("PCURVE"),
CurveImpl::Polyline(i) => CurveKind::Polyline(model.polyline_arena.get(i.0)),
CurveImpl::QuasiUniformCurve(i) => {
CurveKind::QuasiUniform(model.quasi_uniform_curve_arena.get(i.0))
}
CurveImpl::RationalBSplineCurve(_) => CurveKind::Other("RATIONAL_B_SPLINE_CURVE"),
CurveImpl::SeamCurve(i) => CurveKind::SeamCurve(model.seam_curve_arena.get(i.0)),
CurveImpl::SurfaceCurve(i) => {
CurveKind::SurfaceCurve(model.surface_curve_arena.get(i.0))
}
CurveImpl::UniformCurve(i) => CurveKind::Uniform(model.uniform_curve_arena.get(i.0)),
CurveImpl::Complex(_) => CurveKind::Other("COMPLEX"),
}
}
}
#[derive(Clone, Copy)]
pub struct Vertex<'m> {
cx: Ctx<'m>,
id: m::VertexPointId,
}
impl<'m> Vertex<'m> {
fn from_ref(cx: Ctx<'m>, r: &m::VertexRef) -> Option<Self> {
match r {
m::VertexRef::VertexPoint(i) => Some(Vertex { cx, id: *i }),
m::VertexRef::Vertex(_) | m::VertexRef::Complex(_) => None,
}
}
pub fn key(&self) -> m::EntityKey {
m::EntityKey::VertexPoint(self.id)
}
pub fn point(&self) -> Option<Point<'m>> {
let r = &self
.cx
.model
.vertex_point_arena
.get(self.id.0)
.vertex_geometry;
match r {
m::PointRef::CartesianPoint(i) => Some(Point {
cx: self.cx,
id: *i,
}),
m::PointRef::ApllPoint(_)
| m::PointRef::ApllPointWithSurface(_)
| m::PointRef::Point(_)
| m::PointRef::Complex(_) => None,
}
}
pub fn edges(&self) -> impl Iterator<Item = Edge<'m>> + 'm {
let cx = self.cx;
let rg = cx.ref_graph();
let mut out: Vec<Edge<'m>> = Vec::new();
for &r in rg.referrers(m::EntityKey::VertexPoint(self.id)) {
if let m::EntityKey::EdgeCurve(eid) = r {
if !out.iter().any(|e| e.id == eid) {
out.push(Edge { cx, id: eid });
}
}
}
out.into_iter()
}
}
#[derive(Clone, Copy)]
pub struct Point<'m> {
cx: Ctx<'m>,
id: m::CartesianPointId,
}
impl<'m> Point<'m> {
pub(crate) fn from_id(cx: Ctx<'m>, id: m::CartesianPointId) -> Self {
Point { cx, id }
}
pub fn key(&self) -> m::EntityKey {
m::EntityKey::CartesianPoint(self.id)
}
pub fn xyz(&self) -> [f64; 3] {
let c = self.coords();
[
c.first().copied().unwrap_or(0.0),
c.get(1).copied().unwrap_or(0.0),
c.get(2).copied().unwrap_or(0.0),
]
}
pub fn coords(&self) -> &'m [f64] {
&self
.cx
.model
.cartesian_point_arena
.get(self.id.0)
.coordinates
}
}
fn closed_shell_to_solid(rg: &RefGraph, cs: m::ClosedShellId) -> Option<SolidImpl> {
for &r in rg.referrers(m::EntityKey::ClosedShell(cs)) {
match r {
m::EntityKey::ManifoldSolidBrep(msb) => return Some(SolidImpl::Manifold(msb)),
m::EntityKey::BrepWithVoids(bwv) => return Some(SolidImpl::WithVoids(bwv)),
m::EntityKey::OrientedClosedShell(ocs) => {
for &r2 in rg.referrers(m::EntityKey::OrientedClosedShell(ocs)) {
match r2 {
m::EntityKey::ManifoldSolidBrep(msb) => {
return Some(SolidImpl::Manifold(msb));
}
m::EntityKey::BrepWithVoids(bwv) => return Some(SolidImpl::WithVoids(bwv)),
_ => {}
}
}
}
_ => {}
}
}
None
}
fn resolve_closed_shell<'m>(
model: &'m StepModel,
r: &m::ClosedShellRef,
) -> Option<&'m m::ClosedShell> {
match r {
m::ClosedShellRef::ClosedShell(i) => Some(model.closed_shell_arena.get(i.0)),
m::ClosedShellRef::OrientedClosedShell(i) => {
let oc = model.oriented_closed_shell_arena.get(i.0);
resolve_closed_shell(model, &oc.closed_shell_element)
}
m::ClosedShellRef::Complex(_) => None,
}
}
fn resolve_edge_loop<'m>(model: &'m StepModel, r: &m::LoopRef) -> Option<&'m m::EdgeLoop> {
match r {
m::LoopRef::EdgeLoop(i) => Some(model.edge_loop_arena.get(i.0)),
m::LoopRef::Loop(_)
| m::LoopRef::PolyLoop(_)
| m::LoopRef::VertexLoop(_)
| m::LoopRef::Complex(_) => None,
}
}
fn resolve_oriented_edge<'m>(
model: &'m StepModel,
r: &m::OrientedEdgeRef,
) -> Option<&'m m::OrientedEdge> {
match r {
m::OrientedEdgeRef::OrientedEdge(i) => Some(model.oriented_edge_arena.get(i.0)),
m::OrientedEdgeRef::Complex(_) => None,
}
}