forked from 1b-agent/opencadstudio-upstream
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing falls into three parts, and each now has one answer instead of two. NURBS evaluation. truck was carrying B-spline curves and surfaces for the SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview and ACIS spline-surface faces. The kernel now has both, over one de Boor written across however many coordinates a control point holds — so a plane curve and a space curve cannot drift apart, and a surface is the same algorithm applied twice. The rational and the polynomial cases stop being separate types: weights absent means polynomial. The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was built into truck topology purely so it could be sampled back into points. They are sampled through `entities::curve` now, which is where each one's geometry is already defined once and what EXTRUDE and REVOLVE read — so a circle drawn on screen and a circle handed to the Model tab come from the same definition. That retires four of TruckObject's variants and the module is renamed for what it does. SWEEP and LOFT. Both only ever produced a mesh, so both are built from point lists: a band of quads per span, and a lid where a profile closes. Lofting profiles of different densities resamples them by distance rather than by index, so a circle lofted to a square no longer twists. Two things worth noting for anyone reading the old comments. The tolerance globals that lived in the tessellation module were never about truck at all — they are the per-frame chord height, and they move to `curve_tol`. And the rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE no longer holds: those read the curve directly and never look at this channel. The two `automation` test failures are unchanged from before this and are not caused by it. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
1f642bb40a
commit
8c7ebdc9f1
58 files changed
+947
-1761
No files matched your search
+26
-35
@@ -1,20 +1,19 @@
|
||||
use acadrust::entities::Arc;
|
||||
use crate::t;
|
||||
use truck_modeling::{builder, Point3};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_angle_prop as edit_angle, edit_prop as edit, parse_f64, ro_prop as ro,
|
||||
square_grip,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{extrusion_wall_tris, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{extrusion_wall_tris, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
|
||||
const TAU: f64 = std::f64::consts::TAU;
|
||||
|
||||
fn to_truck(arc: &Arc) -> TruckEntity {
|
||||
fn to_render(arc: &Arc) -> RenderEntity {
|
||||
let cx = arc.center.x;
|
||||
let cy = arc.center.y;
|
||||
let cz = arc.center.z;
|
||||
@@ -32,11 +31,11 @@ fn to_truck(arc: &Arc) -> TruckEntity {
|
||||
// Arc points in WCS: centre_wcs + r*cos(a)*Ax + r*sin(a)*Ay
|
||||
let arc_pt = |a: f64| {
|
||||
let (c, s) = (a.cos(), a.sin());
|
||||
Point3::new(
|
||||
[
|
||||
cwx + r * c * ax.0 + r * s * ay.0,
|
||||
cwy + r * c * ax.1 + r * s * ay.1,
|
||||
cwz + r * c * ax.2 + r * s * ay.2,
|
||||
)
|
||||
]
|
||||
};
|
||||
|
||||
// Centre, ends, arc-length midpoint and the quadrants the sweep actually
|
||||
@@ -58,7 +57,7 @@ fn to_truck(arc: &Arc) -> TruckEntity {
|
||||
let base: Vec<[f64; 3]> = (0..=n)
|
||||
.map(|i| {
|
||||
let p = arc_pt(start_a + (end_a - start_a) * (i as f64 / n as f64));
|
||||
[p.x, p.y, p.z]
|
||||
[p[0], p[1], p[2]]
|
||||
})
|
||||
.collect();
|
||||
let mut pts: Vec<[f64; 3]> = Vec::with_capacity((n + 1) * 2 + 8);
|
||||
@@ -68,16 +67,15 @@ fn to_truck(arc: &Arc) -> TruckEntity {
|
||||
pts.push([x + t * nx, y + t * ny, z + t * nz]);
|
||||
}
|
||||
pts.push([f64::NAN; 3]);
|
||||
let ps = arc_pt(sa);
|
||||
pts.push([ps.x, ps.y, ps.z]);
|
||||
pts.push([ps.x + t * nx, ps.y + t * ny, ps.z + t * nz]);
|
||||
pts.push([f64::NAN; 3]);
|
||||
let pe = arc_pt(ea);
|
||||
pts.push([pe.x, pe.y, pe.z]);
|
||||
pts.push([pe.x + t * nx, pe.y + t * ny, pe.z + t * nz]);
|
||||
return TruckEntity {
|
||||
for end in [arc_pt(sa), arc_pt(ea)] {
|
||||
pts.push(end);
|
||||
pts.push([end[0] + t * nx, end[1] + t * ny, end[2] + t * nz]);
|
||||
pts.push([f64::NAN; 3]);
|
||||
}
|
||||
pts.pop();
|
||||
return RenderEntity {
|
||||
pick_tris: extrusion_wall_tris(&base, [t * nx, t * ny, t * nz]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: snap.snap_pts.clone(),
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: vec![],
|
||||
@@ -85,20 +83,13 @@ fn to_truck(arc: &Arc) -> TruckEntity {
|
||||
};
|
||||
}
|
||||
|
||||
// Kept as a truck edge rather than a point list: EXTRUDE, REVOLVE and
|
||||
// SWEEP take their profile and path from `Curve` / `Contour` and have no
|
||||
// arm for `Lines`, so handing them one would quietly stop an arc being
|
||||
// usable as either.
|
||||
let p_start = arc_pt(sa);
|
||||
let p_end = arc_pt(ea);
|
||||
let ccw_end = if ea >= sa { ea } else { ea + TAU };
|
||||
let p_mid = arc_pt(sa + (ccw_end - sa) * 0.5);
|
||||
let v_start = builder::vertex(p_start);
|
||||
let v_end = builder::vertex(p_end);
|
||||
let edge = builder::circle_arc(&v_start, &v_end, p_mid);
|
||||
TruckEntity {
|
||||
// Sampled through the arc's own curve, which is the one definition of
|
||||
// its geometry. EXTRUDE, REVOLVE and SWEEP read that definition directly
|
||||
// rather than this point list, so nothing is lost by drawing from it.
|
||||
let points = crate::entities::curve::curve_points(&crate::entities::curve::arc_curve(arc));
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Curve(edge),
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts: snap.snap_pts.clone(),
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: vec![],
|
||||
@@ -291,9 +282,9 @@ fn apply_grip(arc: &mut Arc, grip_id: usize, apply: GripApply) {
|
||||
arc.center.z += d.z;
|
||||
}
|
||||
(0, GripApply::Absolute(p)) => {
|
||||
arc.center.x = p.x;
|
||||
arc.center.y = p.y;
|
||||
arc.center.z = p.z;
|
||||
arc.center.x = p[0];
|
||||
arc.center.y = p[1];
|
||||
arc.center.z = p[2];
|
||||
}
|
||||
(1..=3, GripApply::Absolute(p)) => {
|
||||
let original = arc.clone();
|
||||
@@ -320,9 +311,9 @@ fn apply_transform(arc: &mut Arc, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Arc {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Arc {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -10,8 +10,8 @@ use crate::entities::text_support::{
|
||||
layout_mtext, resolve_dxf_special_chars, resolve_text_style, text_local_bounds,
|
||||
MTextRenderOpts, MTextVAnchor, ResolvedTextStyle,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
use crate::scene::text::lff;
|
||||
@@ -20,7 +20,7 @@ use crate::t;
|
||||
|
||||
// ── Shared helpers ────────────────────────────────────────────────────────────
|
||||
|
||||
/// Bundle of the fields both attribute kinds carry. Lets the truck builder
|
||||
/// Bundle of the fields both attribute kinds carry. Lets the render builder
|
||||
/// stay generic over ATTDEF vs ATTRIB.
|
||||
struct AttrTextInputs<'a> {
|
||||
value: &'a str,
|
||||
@@ -101,7 +101,7 @@ fn mtext_flag_str(f: MTextFlag) -> &'static str {
|
||||
/// Render text strokes for an attribute, honouring alignment, oblique angle,
|
||||
/// width factor, generation flags (backward / upside-down), text-style
|
||||
/// resolution, and basic multiline splitting on `\n` / `\\P`.
|
||||
fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
fn build_attr_render(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) -> RenderEntity {
|
||||
let normal = (input.normal.x, input.normal.y, input.normal.z);
|
||||
let (wsx, wsy, wsz) = transform::ocs_point_to_wcs(
|
||||
(
|
||||
@@ -218,9 +218,9 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument)
|
||||
});
|
||||
let _ = input.line_count;
|
||||
let _ = input.is_multiline;
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Text(layout.strokes),
|
||||
object: RenderObject::Text(layout.strokes),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -321,9 +321,9 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument)
|
||||
}
|
||||
let _ = input.line_count; // round-trip only — recomputed above
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Text(strokes_all),
|
||||
object: RenderObject::Text(strokes_all),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -333,8 +333,8 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument)
|
||||
|
||||
// ── AttributeDefinition ───────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for AttributeDefinition {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for AttributeDefinition {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
// An attribute definition previews its tag when it has no default
|
||||
// value, so the placeholder is visible where a block will prompt for
|
||||
// input. (Passed as a non-empty value, so it renders as-is.)
|
||||
@@ -343,7 +343,7 @@ impl TruckConvertible for AttributeDefinition {
|
||||
} else {
|
||||
self.default_value.clone()
|
||||
};
|
||||
Some(build_attr_truck(
|
||||
Some(build_attr_render(
|
||||
AttrTextInputs {
|
||||
value: &display_value,
|
||||
insertion_point: self.insertion_point,
|
||||
@@ -622,9 +622,9 @@ impl Transformable for AttributeDefinition {
|
||||
|
||||
// ── AttributeEntity ───────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for AttributeEntity {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(build_attr_truck(
|
||||
impl RenderConvertible for AttributeEntity {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(build_attr_render(
|
||||
AttrTextInputs {
|
||||
value: &self.value,
|
||||
insertion_point: self.insertion_point,
|
||||
|
||||
+11
-11
@@ -5,12 +5,12 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_prop as edit, parse_f64, ro_prop as ro, square_grip,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{extrusion_wall_tris, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{extrusion_wall_tris, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
|
||||
fn to_truck(circle: &Circle) -> TruckEntity {
|
||||
fn to_render(circle: &Circle) -> RenderEntity {
|
||||
let cx = circle.center.x;
|
||||
let cy = circle.center.y;
|
||||
let cz = circle.center.z;
|
||||
@@ -64,9 +64,9 @@ fn to_truck(circle: &Circle) -> TruckEntity {
|
||||
pts.push([f64::NAN; 3]);
|
||||
}
|
||||
}
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: extrusion_wall_tris(&base, [t * nx, t * ny, t * nz]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: vec![],
|
||||
@@ -74,7 +74,7 @@ fn to_truck(circle: &Circle) -> TruckEntity {
|
||||
};
|
||||
}
|
||||
|
||||
// Sampled from the entity's own curve rather than as a truck
|
||||
// Sampled from the entity's own curve rather than as a
|
||||
// `circle_arc` (arc-through-three-points). At large WCS coordinates
|
||||
// (e.g. −1.2M UTM) the three-point fit cancels catastrophically — the
|
||||
// circle comes back with a ~3% radius wobble and uneven segment lengths,
|
||||
@@ -84,9 +84,9 @@ fn to_truck(circle: &Circle) -> TruckEntity {
|
||||
// double-single the shader reconstructs.
|
||||
let pts = crate::entities::curve::curve_points(&curve);
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: vec![],
|
||||
@@ -175,9 +175,9 @@ fn apply_transform(circle: &mut Circle, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Circle {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Circle {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ pub fn parse_angle_deg(value: &str) -> Option<f64> {
|
||||
pub use acadrust::kernel::geom2d::BulgeArc;
|
||||
|
||||
/// Triangulate the solid bands a `wide_fills` returns into the flat WCS f64
|
||||
/// triangle list `TruckEntity::pick_tris` carries, so a wide polyline is
|
||||
/// triangle list `RenderEntity::pick_tris` carries, so a wide polyline is
|
||||
/// selectable across the band it draws and not just along its centreline.
|
||||
///
|
||||
/// `origin` and `fills` are that function's own pair: 2-D offsets from the
|
||||
@@ -616,7 +616,7 @@ pub(crate) fn wide_band_tris(origin: [f64; 2], fills: &[Vec<[f32; 2]>]) -> Vec<[
|
||||
/// thickness (code 39): a vertical wall between every band-boundary point and
|
||||
/// its `thickness`-along-`normal` copy, plus triangulated bottom and top caps.
|
||||
/// Returns `(fill_tris, edge_lines)` as flat WCS f64 lists — the caller wraps
|
||||
/// them in a `TruckEntity` (object = `Lines(edge_lines)`, `fill_tris`, and
|
||||
/// them in a `RenderEntity` (object = `Lines(edge_lines)`, `fill_tris`, and
|
||||
/// `pick_tris = fill_tris`). Shared by LwPolyline and Polyline2D so both wide
|
||||
/// polyline kinds extrude the same solid instead of just their centre-line.
|
||||
///
|
||||
|
||||
@@ -344,7 +344,7 @@ pub fn entity_curve_xy(entity: &EntityType) -> Option<Curve> {
|
||||
/// pair; casting local coordinates on the way in throws away precision the
|
||||
/// shader was built to reconstruct.
|
||||
pub fn curve_points(curve: &PlanarCurve) -> Vec<[f64; 3]> {
|
||||
curve.tessellate_within(crate::scene::convert::truck_tess::current_curve_tol())
|
||||
curve.tessellate_within(crate::scene::convert::curve_tol::current_curve_tol())
|
||||
}
|
||||
|
||||
/// The snap candidates an entity's curve offers, in the two channels the
|
||||
|
||||
@@ -1468,7 +1468,7 @@ fn tessellate_dimension_inner(
|
||||
line_weight_px: f32,
|
||||
anno_scale: f32,
|
||||
// LOD hints — when present, synthesised dim text routes through the
|
||||
// top-level LOD ladder (baseline / greek / full) instead of the truck
|
||||
// top-level LOD ladder (baseline / greek / full) instead of the render
|
||||
// path so far-out drawings collapse to a colored rect or baseline.
|
||||
selected_set: &rustc_hash::FxHashSet<acadrust::Handle>,
|
||||
active_viewport: Option<acadrust::Handle>,
|
||||
@@ -1478,7 +1478,7 @@ fn tessellate_dimension_inner(
|
||||
) -> Vec<WireModel> {
|
||||
let name = handle.value().to_string();
|
||||
// (Baked-block fast path moved up into scene::tessellate_entity so the
|
||||
// recursive call goes through the LOD ladder, not the truck path.)
|
||||
// recursive call goes through the LOD ladder, not the kernel path.)
|
||||
|
||||
let style_name = &dim.base().style_name;
|
||||
let source_style = document.dim_styles.iter().find(|s| {
|
||||
|
||||
+12
-45
@@ -1,5 +1,4 @@
|
||||
use acadrust::entities::Ellipse;
|
||||
use truck_modeling::{builder, BSplineCurve, Curve, Edge, KnotVec, Point3, Wire};
|
||||
|
||||
use crate::entities::curve::CurveSnap;
|
||||
use crate::t;
|
||||
@@ -8,11 +7,11 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_prop as edit, parse_f64, ro_prop as ro, square_grip,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
|
||||
fn to_truck(ell: &Ellipse) -> TruckEntity {
|
||||
fn to_render(ell: &Ellipse) -> RenderEntity {
|
||||
// ELLIPSE is one of the few WCS entities in DXF: `center` (code 10) and
|
||||
// `major_axis` (code 11) are world coordinates already — unlike ARC /
|
||||
// CIRCLE, whose centers are OCS. The converter knows that; this used to
|
||||
@@ -35,9 +34,9 @@ fn to_truck(ell: &Ellipse) -> TruckEntity {
|
||||
// SWEEP read their profile out of `Contour` / `Curve` and have no arm for
|
||||
// a bare point list, so an ellipse handed over as `Lines` would stop
|
||||
// being usable as either.
|
||||
let empty = |snap: CurveSnap| TruckEntity {
|
||||
let empty = |snap: CurveSnap| RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(Vec::new()),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts: snap.snap_pts,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -46,42 +45,14 @@ fn to_truck(ell: &Ellipse) -> TruckEntity {
|
||||
let Some(planar) = curve else {
|
||||
return empty(snap);
|
||||
};
|
||||
let points: Vec<Point3> = crate::entities::curve::curve_points(&planar)
|
||||
.into_iter()
|
||||
.map(|p| Point3::new(p[0], p[1], p[2]))
|
||||
.collect();
|
||||
let points = crate::entities::curve::curve_points(&planar);
|
||||
if points.len() < 2 {
|
||||
return empty(snap);
|
||||
}
|
||||
|
||||
// Closure decided on the points rather than on the stored parameters. A
|
||||
// file that writes an end parameter a hair short of a full turn still
|
||||
// draws a closed ellipse, and an open edge whose two vertices sit on top
|
||||
// of each other is not something a plane can be attached to.
|
||||
let ends_meet = {
|
||||
let (first, last) = (points[0], *points.last().expect("checked non-empty"));
|
||||
let span = first.x.abs().max(first.y.abs()).max(first.z.abs()).max(1.0);
|
||||
let gap = first - last;
|
||||
(gap.x * gap.x + gap.y * gap.y + gap.z * gap.z).sqrt() <= 1e-9 * span
|
||||
};
|
||||
let object = if planar.is_closed() || ends_meet {
|
||||
// Two half-edges rather than one closed edge: a single edge whose
|
||||
// two vertices coincide is not a wire truck will attach a plane to.
|
||||
let split = points.len() / 2;
|
||||
let upper = points[..=split].to_vec();
|
||||
let lower = points[split..].to_vec();
|
||||
let v_pos = builder::vertex(points[0]);
|
||||
let v_neg = builder::vertex(points[split]);
|
||||
let edge_upper = Edge::new(&v_pos, &v_neg, polyline_curve(upper));
|
||||
let edge_lower = Edge::new(&v_neg, &v_pos, polyline_curve(lower));
|
||||
TruckObject::Contour([edge_upper, edge_lower].into_iter().collect::<Wire>())
|
||||
} else {
|
||||
let v_start = builder::vertex(points[0]);
|
||||
let v_end = builder::vertex(*points.last().expect("checked non-empty"));
|
||||
TruckObject::Curve(Edge::new(&v_start, &v_end, polyline_curve(points)))
|
||||
};
|
||||
let object = RenderObject::Lines(points);
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object,
|
||||
snap_pts: snap.snap_pts,
|
||||
@@ -91,15 +62,11 @@ fn to_truck(ell: &Ellipse) -> TruckEntity {
|
||||
}
|
||||
}
|
||||
|
||||
/// A truck curve that passes through every one of `points` in order.
|
||||
/// A curve through every one of `points` in order.
|
||||
///
|
||||
/// Degree one, so the control polygon *is* the curve — the same thing the
|
||||
/// hand-built sampling produced, without restating how a B-spline is put
|
||||
/// together at each site.
|
||||
fn polyline_curve(points: Vec<Point3>) -> Curve {
|
||||
let spans = points.len().saturating_sub(1);
|
||||
Curve::BSplineCurve(BSplineCurve::new(KnotVec::uniform_knot(1, spans), points))
|
||||
}
|
||||
|
||||
fn grips(ell: &Ellipse) -> Vec<GripDef> {
|
||||
let ctr = glam::DVec3::new(ell.center.x, ell.center.y, ell.center.z);
|
||||
@@ -302,9 +269,9 @@ fn apply_transform(ell: &mut Ellipse, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Ellipse {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Ellipse {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_angle_prop, edit_prop, parse_f64, ro_prop, square_grip,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{
|
||||
GripApply, GripDef, PropSection, PropValue, Property,
|
||||
};
|
||||
@@ -373,7 +373,7 @@ fn camera_lines(document: &acadrust::CadDocument, view_handle: Handle) -> Vec<[f
|
||||
points
|
||||
}
|
||||
|
||||
fn to_truck(entity: &ExtendedEntity, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
fn to_render(entity: &ExtendedEntity, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let (points, snaps, keys): (
|
||||
Vec<[f64; 3]>,
|
||||
Vec<(glam::DVec3, SnapHint)>,
|
||||
@@ -455,8 +455,8 @@ fn to_truck(entity: &ExtendedEntity, document: &acadrust::CadDocument) -> Option
|
||||
if points.len() < 2 {
|
||||
return None;
|
||||
}
|
||||
Some(TruckEntity {
|
||||
object: TruckObject::Lines(points),
|
||||
Some(RenderEntity {
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts: snaps,
|
||||
tangent_geoms: Vec::new(),
|
||||
key_vertices: keys,
|
||||
@@ -1520,9 +1520,9 @@ fn apply_transform(entity: &mut ExtendedEntity, requested: &EntityTransform) {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for ExtendedEntity {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
to_truck(self, document)
|
||||
impl RenderConvertible for ExtendedEntity {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
to_render(self, document)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::ro_prop as ro;
|
||||
use crate::entities::traits::{Grippable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::TruckEntity;
|
||||
use crate::entities::traits::{Grippable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::RenderEntity;
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
|
||||
/// Perpendicular distance from `p` to the helix axis (line through
|
||||
@@ -103,9 +103,9 @@ fn apply_transform(helix: &mut Helix, t: &EntityTransform) {
|
||||
Transformable::apply_transform(&mut helix.spline, t);
|
||||
}
|
||||
|
||||
impl TruckConvertible for Helix {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
self.spline.to_truck(document)
|
||||
impl RenderConvertible for Helix {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
self.spline.to_render(document)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_prop as edit, ro_prop as ro, square_grip, stepper_prop as stepper,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
use crate::t;
|
||||
|
||||
// ── TruckConvertible (used for snap/grip key-vertices) ─────────────────────
|
||||
// ── RenderConvertible (used for snap/grip key-vertices) ─────────────────────
|
||||
|
||||
/// Whether a leader draws a horizontal hookline. DWG stores no "hookline
|
||||
/// exists" flag (only the direction bit), so the stored flag alone would drop
|
||||
@@ -44,7 +44,7 @@ fn draws_hookline(leader: &Leader) -> bool {
|
||||
cos < (15.0f64).to_radians().cos()
|
||||
}
|
||||
|
||||
fn to_truck(leader: &Leader) -> TruckEntity {
|
||||
fn to_render(leader: &Leader) -> RenderEntity {
|
||||
let verts = &leader.vertices;
|
||||
let nan = [f64::NAN; 3];
|
||||
let p3 = |v: &acadrust::types::Vector3| -> [f64; 3] { [v.x, v.y, v.z] };
|
||||
@@ -126,9 +126,9 @@ fn to_truck(leader: &Leader) -> TruckEntity {
|
||||
]);
|
||||
}
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(points),
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
@@ -459,12 +459,12 @@ fn apply_transform(leader: &mut Leader, t: &EntityTransform) {
|
||||
|
||||
// ── Trait impls ────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for Leader {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Leader {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.vertices.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(to_truck(self))
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -6,7 +6,7 @@
|
||||
//! same way AutoCAD shows a light symbol.
|
||||
//!
|
||||
//! The glyph is sized in **screen space** (a roughly constant pixel size across
|
||||
//! zoom) via [`relative_truck`], falling back to a small fixed world size when
|
||||
//! zoom) via [`relative_render`], falling back to a small fixed world size when
|
||||
//! no world-per-pixel factor is available (e.g. snapshot tessellation).
|
||||
|
||||
use acadrust::entities::Light;
|
||||
@@ -17,8 +17,8 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_angle_prop, edit_prop as edit, ro_prop, square_grip,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -165,7 +165,7 @@ fn light_wire(l: &Light, r: f64) -> Vec<[f64; 3]> {
|
||||
out
|
||||
}
|
||||
|
||||
fn build(l: &Light, r: f64) -> TruckEntity {
|
||||
fn build(l: &Light, r: f64) -> RenderEntity {
|
||||
let p = pos(l);
|
||||
let snap = glam::DVec3::new(p[0], p[1], p[2]);
|
||||
let mut snap_pts = vec![(snap, SnapHint::Node)];
|
||||
@@ -175,9 +175,9 @@ fn build(l: &Light, r: f64) -> TruckEntity {
|
||||
snap_pts.push((glam::DVec3::new(t[0], t[1], t[2]), SnapHint::Node));
|
||||
key.push(t);
|
||||
}
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(light_wire(l, r)),
|
||||
object: RenderObject::Lines(light_wire(l, r)),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key,
|
||||
@@ -187,12 +187,12 @@ fn build(l: &Light, r: f64) -> TruckEntity {
|
||||
|
||||
/// Viewport-aware glyph: constant on-screen size from the world-per-pixel
|
||||
/// factor. Returns `None` for a non-light entity or when no factor is
|
||||
/// available (the caller then falls back to the fixed-world [`to_truck`]).
|
||||
pub fn relative_truck(
|
||||
/// available (the caller then falls back to the fixed-world [`to_render`]).
|
||||
pub fn relative_render(
|
||||
entity: &EntityType,
|
||||
_document: &acadrust::CadDocument,
|
||||
wpp: Option<f32>,
|
||||
) -> Option<TruckEntity> {
|
||||
) -> Option<RenderEntity> {
|
||||
let EntityType::Light(l) = entity else {
|
||||
return None;
|
||||
};
|
||||
@@ -200,8 +200,8 @@ pub fn relative_truck(
|
||||
Some(build(l, w * GLYPH_PX))
|
||||
}
|
||||
|
||||
impl TruckConvertible for Light {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Light {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(build(self, FIXED_WORLD))
|
||||
}
|
||||
}
|
||||
|
||||
+11
-17
@@ -1,17 +1,16 @@
|
||||
use acadrust::{entities::Line, Entity};
|
||||
use crate::t;
|
||||
use truck_modeling::{builder, Point3};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_prop as edit, parse_f64, ro_prop as ro, square_grip,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{extrusion_wall_tris, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{extrusion_wall_tris, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
|
||||
fn to_truck(line: &Line) -> TruckEntity {
|
||||
fn to_render(line: &Line) -> RenderEntity {
|
||||
// LINE endpoints are stored in WCS — unlike the planar OCS entities
|
||||
// (ARC/CIRCLE/LWPOLYLINE/TEXT), the extrusion normal on a LINE only
|
||||
// orients its thickness sweep. Remapping the endpoints through the
|
||||
@@ -20,9 +19,7 @@ fn to_truck(line: &Line) -> TruckEntity {
|
||||
let normal = (line.normal.x, line.normal.y, line.normal.z);
|
||||
let (sx, sy, sz) = (line.start.x, line.start.y, line.start.z);
|
||||
let (ex, ey, ez) = (line.end.x, line.end.y, line.end.z);
|
||||
let p0 = Point3::new(sx, sy, sz);
|
||||
let p1 = Point3::new(ex, ey, ez);
|
||||
let kv: Vec<[f64; 3]> = vec![[p0.x, p0.y, p0.z], [p1.x, p1.y, p1.z]];
|
||||
let kv: Vec<[f64; 3]> = vec![[sx, sy, sz], [ex, ey, ez]];
|
||||
let tangent = TangentGeom::Line {
|
||||
p1: [kv[0][0] as f32, kv[0][1] as f32, kv[0][2] as f32],
|
||||
p2: [kv[1][0] as f32, kv[1][1] as f32, kv[1][2] as f32],
|
||||
@@ -46,9 +43,9 @@ fn to_truck(line: &Line) -> TruckEntity {
|
||||
kv[1],
|
||||
p1t,
|
||||
];
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: extrusion_wall_tris(&kv, [t * nx, t * ny, t * nz]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: kv,
|
||||
@@ -56,12 +53,9 @@ fn to_truck(line: &Line) -> TruckEntity {
|
||||
};
|
||||
}
|
||||
|
||||
let v0 = builder::vertex(p0);
|
||||
let v1 = builder::vertex(p1);
|
||||
let edge = builder::line(&v0, &v1);
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Curve(edge),
|
||||
object: RenderObject::Lines(kv.clone()),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![tangent],
|
||||
key_vertices: kv,
|
||||
@@ -167,9 +161,9 @@ fn apply_transform(line: &mut Line, t: &EntityTransform) {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Line {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Line {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+37
-42
@@ -1,14 +1,13 @@
|
||||
use acadrust::entities::{LwPolyline, LwVertex};
|
||||
use crate::t;
|
||||
use truck_modeling::{builder, Edge, Point3, Wire};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
edit_prop as edit, parse_f64, rectangle_grip, ro_prop as ro, square_grip,
|
||||
stepper_prop as stepper,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{extrusion_wall_tris, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{extrusion_wall_tris, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
|
||||
@@ -179,7 +178,7 @@ fn thick_segments(
|
||||
normal: (f64, f64, f64),
|
||||
key_verts: Vec<[f64; 3]>,
|
||||
tangents: Vec<TangentGeom>,
|
||||
) -> TruckEntity {
|
||||
) -> RenderEntity {
|
||||
let (nx, ny, nz) = normal;
|
||||
let t = thickness;
|
||||
let off = |p: [f64; 3]| -> [f64; 3] { [p[0] + t * nx, p[1] + t * ny, p[2] + t * nz] };
|
||||
@@ -210,9 +209,9 @@ fn thick_segments(
|
||||
pts.push(off(last));
|
||||
}
|
||||
}
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: extrusion_wall_tris(path_pts, [t * nx, t * ny, t * nz]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
@@ -233,14 +232,14 @@ fn thick_wide_band(
|
||||
normal: (f64, f64, f64),
|
||||
key_verts: Vec<[f64; 3]>,
|
||||
tangents: Vec<TangentGeom>,
|
||||
) -> TruckEntity {
|
||||
) -> RenderEntity {
|
||||
let (origin, fills) = wide_fills(pl);
|
||||
let (fill_tris, lines) =
|
||||
crate::entities::common::thick_band_tube(origin, &fills, thickness, normal, to_wcs);
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: fill_tris.clone(),
|
||||
object: TruckObject::Lines(lines),
|
||||
object: RenderObject::Lines(lines),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
@@ -248,12 +247,12 @@ fn thick_wide_band(
|
||||
}
|
||||
}
|
||||
|
||||
fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
fn to_render(pline: &LwPolyline) -> RenderEntity {
|
||||
let verts = &pline.vertices;
|
||||
if verts.is_empty() {
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Point(builder::vertex(Point3::new(0.0, 0.0, 0.0))),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -265,17 +264,16 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
let normal = (pline.normal.x, pline.normal.y, pline.normal.z);
|
||||
let count = verts.len();
|
||||
let seg_count = if pline.is_closed { count } else { count - 1 };
|
||||
let mut edges: Vec<Edge> = Vec::new();
|
||||
let mut tangents: Vec<TangentGeom> = Vec::new();
|
||||
let mut key_verts: Vec<[f64; 3]> = Vec::new();
|
||||
|
||||
// Convert OCS (x, y, elevation) to WCS Point3.
|
||||
// Convert OCS (x, y, elevation) to a WCS point.
|
||||
let to_wcs = |x: f64, y: f64| -> (f64, f64, f64) {
|
||||
crate::scene::view::transform::ocs_point_to_wcs((x, y, elev), normal)
|
||||
};
|
||||
let to_pt = |v: &LwVertex| -> Point3 {
|
||||
let to_pt = |v: &LwVertex| -> [f64; 3] {
|
||||
let (wx, wy, wz) = to_wcs(v.location.x, v.location.y);
|
||||
Point3::new(wx, wy, wz)
|
||||
[wx, wy, wz]
|
||||
};
|
||||
|
||||
if pline.thickness.abs() > 1e-10 {
|
||||
@@ -345,13 +343,13 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
let p0 = to_pt(v0);
|
||||
let p1 = to_pt(v1);
|
||||
if i == 0 {
|
||||
kv.push([p0.x, p0.y, p0.z]);
|
||||
kv.push([p0[0], p0[1], p0[2]]);
|
||||
}
|
||||
kv.push([p1.x, p1.y, p1.z]);
|
||||
kv.push([p1[0], p1[1], p1[2]]);
|
||||
if v0.bulge.abs() < 1e-9 {
|
||||
tgs.push(TangentGeom::Line {
|
||||
p1: [p0.x as f32, p0.y as f32, p0.z as f32],
|
||||
p2: [p1.x as f32, p1.y as f32, p1.z as f32],
|
||||
p1: [p0[0] as f32, p0[1] as f32, p0[2] as f32],
|
||||
p2: [p1[0] as f32, p1[1] as f32, p1[2] as f32],
|
||||
});
|
||||
} else if let Some(arc) = crate::entities::common::BulgeArc::from_bulge(
|
||||
[v0.location.x, v0.location.y],
|
||||
@@ -368,9 +366,9 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
let (pts, widths) =
|
||||
crate::entities::common::tapered_band_points(&band_verts, pline.is_closed, &to_wcs);
|
||||
let (fill_origin, fills) = wide_fills(pline);
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: crate::entities::common::wide_band_tris(fill_origin, &fills),
|
||||
object: TruckObject::TaperedLines(pts, widths),
|
||||
object: RenderObject::TaperedLines(pts, widths),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tgs,
|
||||
key_vertices: kv,
|
||||
@@ -426,9 +424,9 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
}
|
||||
}
|
||||
let (fill_origin, fills) = wide_fills(pline);
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: crate::entities::common::wide_band_tris(fill_origin, &fills),
|
||||
object: TruckObject::SegmentedLines(pts),
|
||||
object: RenderObject::SegmentedLines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tgs,
|
||||
key_vertices: kv,
|
||||
@@ -444,24 +442,15 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
let bulge = v0.bulge;
|
||||
|
||||
if bulge.abs() < 1e-9 {
|
||||
let tv0 = builder::vertex(p0);
|
||||
let tv1 = builder::vertex(p1);
|
||||
edges.push(builder::line(&tv0, &tv1));
|
||||
tangents.push(TangentGeom::Line {
|
||||
p1: [p0.x as f32, p0.y as f32, p0.z as f32],
|
||||
p2: [p1.x as f32, p1.y as f32, p1.z as f32],
|
||||
p1: [p0[0] as f32, p0[1] as f32, p0[2] as f32],
|
||||
p2: [p1[0] as f32, p1[1] as f32, p1[2] as f32],
|
||||
});
|
||||
} else if let Some(arc) = crate::entities::common::BulgeArc::from_bulge(
|
||||
[v0.location.x, v0.location.y],
|
||||
[v1.location.x, v1.location.y],
|
||||
bulge as f64,
|
||||
) {
|
||||
let mid_s = arc.sample(0.5);
|
||||
let (mid_wx, mid_wy, mid_wz) = to_wcs(mid_s[0], mid_s[1]);
|
||||
let p_mid = Point3::new(mid_wx, mid_wy, mid_wz);
|
||||
let tv0 = builder::vertex(p0);
|
||||
let tv1 = builder::vertex(p1);
|
||||
edges.push(builder::circle_arc(&tv0, &tv1, p_mid));
|
||||
let (wcx, wcy, wcz) = to_wcs(arc.center[0], arc.center[1]);
|
||||
tangents.push(TangentGeom::Circle {
|
||||
center: [wcx as f32, wcy as f32, wcz as f32],
|
||||
@@ -470,15 +459,21 @@ fn to_truck(pline: &LwPolyline) -> TruckEntity {
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
key_verts.push([p0.x, p0.y, p0.z]);
|
||||
key_verts.push([p0[0], p0[1], p0[2]]);
|
||||
}
|
||||
key_verts.push([p1.x, p1.y, p1.z]);
|
||||
key_verts.push([p1[0], p1[1], p1[2]]);
|
||||
}
|
||||
|
||||
let (fill_origin, fills) = wide_fills(pline);
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: crate::entities::common::wide_band_tris(fill_origin, &fills),
|
||||
object: TruckObject::Contour(edges.into_iter().collect::<Wire>()),
|
||||
// Sampled through the polyline's own curve, so a bulge stays an
|
||||
// arc rather than becoming the chord across it.
|
||||
object: RenderObject::Lines(
|
||||
crate::entities::curve::lwpolyline_curve(pline)
|
||||
.map(|planar| crate::entities::curve::curve_points(&planar))
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
@@ -805,9 +800,9 @@ fn apply_transform(pline: &mut LwPolyline, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for LwPolyline {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for LwPolyline {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-18
@@ -4,8 +4,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{parse_f64, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -151,8 +151,8 @@ fn v3f32(v: &acadrust::types::Vector3) -> [f32; 3] {
|
||||
[v.x as f32, v.y as f32, v.z as f32]
|
||||
}
|
||||
|
||||
impl TruckConvertible for Face3D {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Face3D {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let p0 = v3(&self.first_corner);
|
||||
let p1 = v3(&self.second_corner);
|
||||
let p2 = v3(&self.third_corner);
|
||||
@@ -195,9 +195,9 @@ impl TruckConvertible for Face3D {
|
||||
pts = vec![[cx - s, cy, cz], [cx + s, cy, cz]];
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![
|
||||
(Vec3::from(p0f).as_dvec3(), SnapHint::Node),
|
||||
(Vec3::from(p1f).as_dvec3(), SnapHint::Node),
|
||||
@@ -312,17 +312,17 @@ impl Transformable for Face3D {
|
||||
|
||||
// ── PolygonMesh (N×M grid) ────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for PolygonMesh {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for PolygonMesh {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let m = self.m_vertex_count as usize;
|
||||
let n = self.n_vertex_count as usize;
|
||||
if m == 0 || n == 0 || self.vertices.len() < m * n {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(Vec::new()),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -433,15 +433,15 @@ impl Transformable for PolygonMesh {
|
||||
|
||||
// ── PolyfaceMesh (arbitrary faces with 1-based vertex indices) ────────────────
|
||||
|
||||
impl TruckConvertible for PolyfaceMesh {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for PolyfaceMesh {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.vertices.is_empty() || self.faces.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(Vec::new()),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -1064,8 +1064,8 @@ pub(crate) fn tessellate_shaded_mesh(
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Mesh {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Mesh {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.vertices.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -1088,9 +1088,9 @@ impl TruckConvertible for Mesh {
|
||||
)
|
||||
};
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(Vec::new()),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices,
|
||||
|
||||
@@ -3,8 +3,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -204,8 +204,8 @@ pub fn mline_lines(m: &MLine, document: &acadrust::CadDocument) -> Vec<MLineLine
|
||||
out
|
||||
}
|
||||
|
||||
impl TruckConvertible for MLine {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for MLine {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.vertices.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -239,9 +239,9 @@ impl TruckConvertible for MLine {
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key_verts,
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::entities::common::{
|
||||
use crate::entities::text_support::{
|
||||
layout_mtext, resolve_text_style, GlyphBox, MTextColumns, MTextRenderOpts, MTextVAnchor,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
use crate::t;
|
||||
@@ -70,7 +70,7 @@ fn drawing_dir_str(d: &DrawingDirection) -> &'static str {
|
||||
}
|
||||
|
||||
/// Per-visible-character world-space boxes for the MText editor's
|
||||
/// click-to-select preview. Uses the exact same layout opts as `to_truck`
|
||||
/// click-to-select preview. Uses the exact same layout opts as `to_render`
|
||||
/// so the boxes line up with the rendered glyphs.
|
||||
/// The MTEXT string to render: the live re-evaluated value when the entity
|
||||
/// hosts a dynamic field, otherwise its stored (cached) value.
|
||||
@@ -127,7 +127,7 @@ pub fn glyph_boxes(t: &MText, document: &acadrust::CadDocument) -> Vec<GlyphBox>
|
||||
layout.glyph_boxes
|
||||
}
|
||||
|
||||
fn to_truck(t: &MText, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
fn to_render(t: &MText, document: &acadrust::CadDocument) -> RenderEntity {
|
||||
let resolved_style = resolve_text_style(&t.style, document);
|
||||
let attach_h_anchor: f32 = match t.attachment_point {
|
||||
AttachmentPoint::TopCenter
|
||||
@@ -178,9 +178,9 @@ fn to_truck(t: &MText, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
t.insertion_point.y,
|
||||
t.insertion_point.z,
|
||||
);
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Text(layout.strokes),
|
||||
object: RenderObject::Text(layout.strokes),
|
||||
snap_pts: vec![(insertion, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -562,9 +562,9 @@ fn apply_transform(t: &mut MText, tr: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for MText {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self, document))
|
||||
impl RenderConvertible for MText {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self, document))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,12 +57,12 @@ use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
center_grip, edit_angle_prop as edit_angle, edit_prop as edit, num_prop as num_row, ro_prop as ro, square_grip, triangle_grip,
|
||||
};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::{SnapHint, TangentGeom};
|
||||
|
||||
// ── TruckConvertible ────────────────────────────────────────────────────────
|
||||
// ── RenderConvertible ────────────────────────────────────────────────────────
|
||||
|
||||
/// Catmull-Rom spline tessellation through `ctrl` points, `segs_per_span` segments each.
|
||||
/// Operates in f64 so it can be applied to either WCS-direct coordinates (entity path)
|
||||
@@ -93,7 +93,7 @@ pub(crate) fn catmull_rom_pts(ctrl: &[[f64; 3]], segs_per_span: u32) -> Vec<[f64
|
||||
out
|
||||
}
|
||||
|
||||
fn to_truck(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
fn to_render(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let nan = [f64::NAN; 3];
|
||||
let p3 = |v: &acadrust::types::Vector3| -> [f64; 3] { [v.x, v.y, v.z] };
|
||||
|
||||
@@ -327,9 +327,9 @@ fn to_truck(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<TruckE
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(points),
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts,
|
||||
tangent_geoms: tangents,
|
||||
key_vertices: key_verts,
|
||||
@@ -1120,9 +1120,9 @@ fn reflect_xy_direction(dx: &mut f64, dy: &mut f64, p1: DVec3, p2: DVec3) {
|
||||
|
||||
// ── Trait impls ────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for MultiLeader {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
to_truck(self, document)
|
||||
impl RenderConvertible for MultiLeader {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
to_render(self, document)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -2,12 +2,12 @@ use acadrust::entities::{Ole2Frame, OleObjectType};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
fn to_truck(ole: &Ole2Frame) -> TruckEntity {
|
||||
fn to_render(ole: &Ole2Frame) -> RenderEntity {
|
||||
let x0 = ole.upper_left_corner.x;
|
||||
let y0 = ole.lower_right_corner.y;
|
||||
let x1 = ole.lower_right_corner.x;
|
||||
@@ -16,9 +16,9 @@ fn to_truck(ole: &Ole2Frame) -> TruckEntity {
|
||||
|
||||
if (x1 - x0).abs() < 1e-6 && (y1 - y0).abs() < 1e-6 {
|
||||
let s = 0.5_f64;
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(vec![[-s, 0.0, z], [s, 0.0, z]]),
|
||||
object: RenderObject::Lines(vec![[-s, 0.0, z], [s, 0.0, z]]),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -42,7 +42,7 @@ fn to_truck(ole: &Ole2Frame) -> TruckEntity {
|
||||
[x0, y0, z],
|
||||
];
|
||||
let center = glam::DVec3::new(cx, cy, z);
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
// Interior pick surface: the frame selects on a click anywhere
|
||||
// inside, not just on its border.
|
||||
pick_tris: crate::entities::common::quad_pick_tris(&[
|
||||
@@ -51,7 +51,7 @@ fn to_truck(ole: &Ole2Frame) -> TruckEntity {
|
||||
[x1, y1, z],
|
||||
[x0, y1, z],
|
||||
]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(center, SnapHint::Center)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[x0, y0, z], [x1, y1, z]],
|
||||
@@ -168,9 +168,9 @@ fn apply_transform(ole: &mut Ole2Frame, t: &EntityTransform) {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Ole2Frame {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Ole2Frame {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-24
@@ -1,12 +1,11 @@
|
||||
use acadrust::entities::Point;
|
||||
use acadrust::EntityType;
|
||||
use crate::t;
|
||||
use truck_modeling::{builder, Point3};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, parse_f64, square_grip};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -17,7 +16,7 @@ use crate::scene::model::wire_model::SnapHint;
|
||||
const REL_REF_PX: f64 = 600.0;
|
||||
|
||||
/// Resolve a positive (absolute) PDSIZE to a world size. Relative/zero PDSIZE
|
||||
/// is handled by [`relative_truck`] when a world-per-pixel factor is available;
|
||||
/// is handled by [`relative_render`] when a world-per-pixel factor is available;
|
||||
/// without one it falls back to a small fixed world size.
|
||||
fn pdsize_world(pdsize: f64) -> f64 {
|
||||
if pdsize > 0.0 {
|
||||
@@ -27,21 +26,20 @@ fn pdsize_world(pdsize: f64) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the truck entity for a point given the glyph half-size `s` in world
|
||||
/// units. Shared by the header-driven path ([`to_truck`]) and the
|
||||
/// viewport-aware relative path ([`relative_truck`]).
|
||||
fn point_truck(pt: &Point, pdmode: i16, s: f64) -> TruckEntity {
|
||||
/// Build the render entity for a point given the glyph half-size `s` in world
|
||||
/// units. Shared by the header-driven path ([`to_render`]) and the
|
||||
/// viewport-aware relative path ([`relative_render`]).
|
||||
fn point_render(pt: &Point, pdmode: i16, s: f64) -> RenderEntity {
|
||||
// POINT location is stored in WCS (the extrusion normal only orients the
|
||||
// glyph/thickness) — remapping it through the arbitrary-axis OCS moved
|
||||
// mirrored points (normal 0,0,-1) to the wrong side of the drawing.
|
||||
let (wx, wy, wz) = (pt.location.x, pt.location.y, pt.location.z);
|
||||
let snap = glam::DVec3::new(wx, wy, wz);
|
||||
if pdmode == 0 {
|
||||
// Default: a single vertex (driver handles the dot pixel).
|
||||
let p = Point3::new(wx, wy, wz);
|
||||
return TruckEntity {
|
||||
// Default: a single position (the driver sizes the dot in pixels).
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Point(builder::vertex(p)),
|
||||
object: RenderObject::Dot([wx, wy, wz]),
|
||||
snap_pts: vec![(snap, SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -51,18 +49,18 @@ fn point_truck(pt: &Point, pdmode: i16, s: f64) -> TruckEntity {
|
||||
let pts = point_glyph(wx, wy, wz, pdmode, s);
|
||||
if pts.is_empty() {
|
||||
// PDMODE 1 = nothing — emit an empty Lines wire so picking still works.
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(vec![]),
|
||||
object: RenderObject::Lines(vec![]),
|
||||
snap_pts: vec![(snap, SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[wx, wy, wz]],
|
||||
fill_tris: vec![],
|
||||
};
|
||||
}
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(snap, SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[wx, wy, wz]],
|
||||
@@ -75,11 +73,11 @@ fn point_truck(pt: &Point, pdmode: i16, s: f64) -> TruckEntity {
|
||||
/// across zoom. Returns `None` for an absolute PDSIZE, the size-independent
|
||||
/// default dot (PDMODE 0), or when no `wpp` is available — the caller then uses
|
||||
/// the normal header-driven path.
|
||||
pub fn relative_truck(
|
||||
pub fn relative_render(
|
||||
entity: &EntityType,
|
||||
document: &acadrust::CadDocument,
|
||||
wpp: Option<f32>,
|
||||
) -> Option<TruckEntity> {
|
||||
) -> Option<RenderEntity> {
|
||||
let EntityType::Point(pt) = entity else {
|
||||
return None;
|
||||
};
|
||||
@@ -89,7 +87,7 @@ pub fn relative_truck(
|
||||
return None;
|
||||
}
|
||||
let wpp = wpp.filter(|w| *w > 0.0)?;
|
||||
Some(point_truck(pt, pdmode, relative_world_size(pdsize, wpp) * 0.5))
|
||||
Some(point_render(pt, pdmode, relative_world_size(pdsize, wpp) * 0.5))
|
||||
}
|
||||
|
||||
/// Full on-screen glyph size (world units) for a relative (≤ 0) PDSIZE at the
|
||||
@@ -175,10 +173,10 @@ fn point_glyph(cx: f64, cy: f64, z: f64, pdmode: i16, s_half: f64) -> Vec<[f64;
|
||||
pts
|
||||
}
|
||||
|
||||
fn to_truck(pt: &Point, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
fn to_render(pt: &Point, document: &acadrust::CadDocument) -> RenderEntity {
|
||||
let pdmode = document.header.point_display_mode;
|
||||
let s = pdsize_world(document.header.point_display_size) * 0.5;
|
||||
point_truck(pt, pdmode, s)
|
||||
point_render(pt, pdmode, s)
|
||||
}
|
||||
|
||||
fn grips(pt: &Point) -> Vec<GripDef> {
|
||||
@@ -235,9 +233,9 @@ fn apply_transform(pt: &mut Point, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Point {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self, document))
|
||||
impl RenderConvertible for Point {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self, document))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+34
-41
@@ -1,19 +1,18 @@
|
||||
use acadrust::entities::{Polyline, Polyline2D, Polyline3D};
|
||||
use crate::t;
|
||||
use truck_modeling::{builder, Edge, Point3, Wire};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{
|
||||
edit_prop as edit, parse_f64, ro_prop as ro, square_grip, stepper_prop as stepper,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{extrusion_wall_tris, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{extrusion_wall_tris, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::TangentGeom;
|
||||
|
||||
// ── Polyline (old-style 3D heavy polyline) ────────────────────────────────────
|
||||
|
||||
fn tessellate_polyline(pl: &Polyline) -> TruckEntity {
|
||||
fn tessellate_polyline(pl: &Polyline) -> RenderEntity {
|
||||
let pts: Vec<[f64; 3]> = pl
|
||||
.vertices
|
||||
.iter()
|
||||
@@ -26,9 +25,9 @@ fn tessellate_polyline(pl: &Polyline) -> TruckEntity {
|
||||
}
|
||||
|
||||
let key_verts = pts.clone();
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(points),
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key_verts,
|
||||
@@ -36,8 +35,8 @@ fn tessellate_polyline(pl: &Polyline) -> TruckEntity {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Polyline {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Polyline {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(tessellate_polyline(self))
|
||||
}
|
||||
}
|
||||
@@ -196,13 +195,13 @@ pub fn drawn_vertices2d(
|
||||
(kept.len() >= 2).then_some(kept)
|
||||
}
|
||||
|
||||
fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
fn tessellate_polyline2d(pl: &Polyline2D) -> RenderEntity {
|
||||
let filtered = drawn_vertices2d(pl);
|
||||
let verts: &[acadrust::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
|
||||
if verts.is_empty() {
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(vec![]),
|
||||
object: RenderObject::Lines(vec![]),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -214,16 +213,15 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
let normal = (pl.normal.x, pl.normal.y, pl.normal.z);
|
||||
let count = verts.len();
|
||||
let seg_count = if pl.is_closed() { count } else { count - 1 };
|
||||
let mut edges: Vec<Edge> = Vec::new();
|
||||
let mut tangents: Vec<TangentGeom> = Vec::new();
|
||||
let mut key_verts: Vec<[f64; 3]> = Vec::new();
|
||||
|
||||
let to_wcs = |x: f64, y: f64| -> (f64, f64, f64) {
|
||||
crate::scene::view::transform::ocs_point_to_wcs((x, y, elev), normal)
|
||||
};
|
||||
let to_pt = |v: &acadrust::entities::Vertex2D| -> Point3 {
|
||||
let to_pt = |v: &acadrust::entities::Vertex2D| -> [f64; 3] {
|
||||
let (wx, wy, wz) = to_wcs(v.location.x, v.location.y);
|
||||
Point3::new(wx, wy, wz)
|
||||
[wx, wy, wz]
|
||||
};
|
||||
|
||||
if pl.thickness.abs() > 1e-10 {
|
||||
@@ -282,9 +280,9 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
let (origin, fills) = wide_fills(pl);
|
||||
let (fill_tris, lines) =
|
||||
crate::entities::common::thick_band_tube(origin, &fills, t, normal, &to_wcs);
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: fill_tris.clone(),
|
||||
object: TruckObject::Lines(lines),
|
||||
object: RenderObject::Lines(lines),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tgs,
|
||||
key_vertices: kv,
|
||||
@@ -307,9 +305,9 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: extrusion_wall_tris(&path, [t * nx, t * ny, t * nz]),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: tgs,
|
||||
key_vertices: kv,
|
||||
@@ -325,24 +323,15 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
let bulge = v0.bulge;
|
||||
|
||||
if bulge.abs() < 1e-9 {
|
||||
let tv0 = builder::vertex(p0);
|
||||
let tv1 = builder::vertex(p1);
|
||||
edges.push(builder::line(&tv0, &tv1));
|
||||
tangents.push(TangentGeom::Line {
|
||||
p1: [p0.x as f32, p0.y as f32, p0.z as f32],
|
||||
p2: [p1.x as f32, p1.y as f32, p1.z as f32],
|
||||
p1: [p0[0] as f32, p0[1] as f32, p0[2] as f32],
|
||||
p2: [p1[0] as f32, p1[1] as f32, p1[2] as f32],
|
||||
});
|
||||
} else if let Some(arc) = crate::entities::common::BulgeArc::from_bulge(
|
||||
[v0.location.x, v0.location.y],
|
||||
[v1.location.x, v1.location.y],
|
||||
bulge,
|
||||
) {
|
||||
let mid_s = arc.sample(0.5);
|
||||
let (mid_wx, mid_wy, mid_wz) = to_wcs(mid_s[0], mid_s[1]);
|
||||
let p_mid = Point3::new(mid_wx, mid_wy, mid_wz);
|
||||
let tv0 = builder::vertex(p0);
|
||||
let tv1 = builder::vertex(p1);
|
||||
edges.push(builder::circle_arc(&tv0, &tv1, p_mid));
|
||||
let (wcx, wcy, wcz) = to_wcs(arc.center[0], arc.center[1]);
|
||||
tangents.push(TangentGeom::Circle {
|
||||
center: [wcx as f32, wcy as f32, wcz as f32],
|
||||
@@ -351,9 +340,9 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
key_verts.push([p0.x, p0.y, p0.z]);
|
||||
key_verts.push([p0[0], p0[1], p0[2]]);
|
||||
}
|
||||
key_verts.push([p1.x, p1.y, p1.z]);
|
||||
key_verts.push([p1[0], p1[1], p1[2]]);
|
||||
}
|
||||
|
||||
let (fill_origin, fills) = wide_fills(pl);
|
||||
@@ -366,11 +355,15 @@ fn tessellate_polyline2d(pl: &Polyline2D) -> TruckEntity {
|
||||
pl.is_closed(),
|
||||
&to_wcs,
|
||||
);
|
||||
TruckObject::TaperedLines(pts, widths)
|
||||
RenderObject::TaperedLines(pts, widths)
|
||||
}
|
||||
None => TruckObject::Contour(edges.into_iter().collect::<Wire>()),
|
||||
None => RenderObject::Lines(
|
||||
crate::entities::curve::polyline2d_curve(pl)
|
||||
.map(|planar| crate::entities::curve::curve_points(&planar))
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
};
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: crate::entities::common::wide_band_tris(fill_origin, &fills),
|
||||
object,
|
||||
snap_pts: vec![],
|
||||
@@ -416,8 +409,8 @@ fn tapered_band_verts_2d(
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Polyline2D {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Polyline2D {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(tessellate_polyline2d(self))
|
||||
}
|
||||
}
|
||||
@@ -699,7 +692,7 @@ impl Transformable for Polyline2D {
|
||||
|
||||
// ── Polyline3D ────────────────────────────────────────────────────────────────
|
||||
|
||||
fn tessellate_polyline3d(pl: &Polyline3D) -> TruckEntity {
|
||||
fn tessellate_polyline3d(pl: &Polyline3D) -> RenderEntity {
|
||||
let to_pt = |v: &acadrust::entities::Vertex3DPolyline| -> [f64; 3] {
|
||||
[v.position.x, v.position.y, v.position.z]
|
||||
};
|
||||
@@ -724,9 +717,9 @@ fn tessellate_polyline3d(pl: &Polyline3D) -> TruckEntity {
|
||||
points.push(wire_pts[0]);
|
||||
}
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(points),
|
||||
object: RenderObject::Lines(points),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key_verts,
|
||||
@@ -734,8 +727,8 @@ fn tessellate_polyline3d(pl: &Polyline3D) -> TruckEntity {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Polyline3D {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Polyline3D {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(tessellate_polyline3d(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ use crate::t;
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::text_support::{resolve_text_style, text_local_bounds};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::text::lff;
|
||||
|
||||
@@ -67,8 +67,8 @@ fn reflect_vec3(vx: &mut f64, vy: &mut f64, ax: f64, ay: f64, len2: f64) {
|
||||
|
||||
// ── RasterImage ───────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for RasterImage {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for RasterImage {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
@@ -141,11 +141,11 @@ impl TruckConvertible for RasterImage {
|
||||
let resolvable =
|
||||
path.is_empty() || crate::scene::model::image_model::resolve_image(path).is_some();
|
||||
if resolvable {
|
||||
return Some(TruckEntity {
|
||||
return Some(RenderEntity {
|
||||
// Interior pick surface: the image selects on a click anywhere
|
||||
// inside its frame, not just on the border.
|
||||
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
@@ -230,9 +230,9 @@ impl TruckConvertible for RasterImage {
|
||||
});
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
||||
object: TruckObject::Text(groups),
|
||||
object: RenderObject::Text(groups),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
@@ -416,8 +416,8 @@ impl Transformable for RasterImage {
|
||||
|
||||
// ── Wipeout ───────────────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for Wipeout {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Wipeout {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let corners = image_corners(
|
||||
&self.insertion_point,
|
||||
&self.u_vector,
|
||||
@@ -464,11 +464,11 @@ impl TruckConvertible for Wipeout {
|
||||
image_wire(corners, false)
|
||||
};
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
// Interior pick surface — a wipeout reads as a solid patch, so a
|
||||
// click anywhere on it should select it.
|
||||
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
@@ -491,7 +491,7 @@ impl Grippable for Wipeout {
|
||||
let ox = self.insertion_point.x;
|
||||
let oy = self.insertion_point.y;
|
||||
let oz = self.insertion_point.z;
|
||||
// Same image-pixel-space → WCS mapping as `to_truck` so grips
|
||||
// Same image-pixel-space → WCS mapping as `to_render` so grips
|
||||
// sit exactly on the rendered polygon vertices.
|
||||
self.clip_boundary_vertices
|
||||
.iter()
|
||||
|
||||
+10
-10
@@ -3,8 +3,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{center_grip, edit_prop as edit, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
|
||||
/// Display length used when rendering semi-infinite / infinite lines.
|
||||
@@ -12,8 +12,8 @@ const DISPLAY_EXTENT: f64 = 1_000_000.0;
|
||||
|
||||
// ── Ray (semi-infinite line) ──────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for Ray {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Ray {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let bp = self.base_point;
|
||||
let dir = self.direction;
|
||||
// Normalize direction to avoid f32 overflow when DXF stores
|
||||
@@ -29,9 +29,9 @@ impl TruckConvertible for Ray {
|
||||
bp.z + nz * DISPLAY_EXTENT,
|
||||
];
|
||||
let start: [f64; 3] = [bp.x, bp.y, bp.z];
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(vec![start, far]),
|
||||
object: RenderObject::Lines(vec![start, far]),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![start],
|
||||
@@ -151,8 +151,8 @@ impl Transformable for Ray {
|
||||
|
||||
// ── XLine (construction line, infinite) ──────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for XLine {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for XLine {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let bp = self.base_point;
|
||||
let dir = self.direction;
|
||||
let len = (dir.x * dir.x + dir.y * dir.y + dir.z * dir.z).sqrt();
|
||||
@@ -170,9 +170,9 @@ impl TruckConvertible for XLine {
|
||||
bp.y - ny * DISPLAY_EXTENT,
|
||||
bp.z - nz * DISPLAY_EXTENT,
|
||||
];
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(vec![far_neg, far_pos]),
|
||||
object: RenderObject::Lines(vec![far_neg, far_pos]),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[bp.x, bp.y, bp.z]],
|
||||
|
||||
@@ -10,8 +10,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_angle_prop as edit_angle, edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, Property, PropValue};
|
||||
use crate::scene::view::transform;
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
@@ -54,7 +54,7 @@ fn shape_marker(
|
||||
out
|
||||
}
|
||||
|
||||
// ── TruckConvertible ──────────────────────────────────────────────────────────
|
||||
// ── RenderConvertible ──────────────────────────────────────────────────────────
|
||||
|
||||
/// The shape's SHX polylines, resolved through its STYLE's shape file: the
|
||||
/// style by handle (name fallback), the file with the shared path fallbacks
|
||||
@@ -129,8 +129,8 @@ fn shx_polylines(
|
||||
None
|
||||
}
|
||||
|
||||
impl TruckConvertible for Shape {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Shape {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
// SHAPE insertion point is OCS (planar entity) — map through the
|
||||
// arbitrary axis so a mirrored shape's marker lands where it renders.
|
||||
let (ox, oy, oz) = crate::scene::view::transform::ocs_point_to_wcs(
|
||||
@@ -182,9 +182,9 @@ impl TruckConvertible for Shape {
|
||||
}
|
||||
}
|
||||
if !pts.is_empty() {
|
||||
return Some(TruckEntity {
|
||||
return Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[ox, oy, oz]],
|
||||
@@ -203,9 +203,9 @@ impl TruckConvertible for Shape {
|
||||
self.oblique_angle,
|
||||
);
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![[ox, oy, oz]],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SOLID entity — 2D filled quadrilateral (or triangle when p3 == p4).
|
||||
//
|
||||
// Wireframe: the 4 perimeter edges as TruckObject::Lines.
|
||||
// Wireframe: the 4 perimeter edges as RenderObject::Lines.
|
||||
// Filled: two triangles on `fill_tris`, preserving the entity's full WCS
|
||||
// plane both at top level and through block expansion. The scene
|
||||
// keeps a separate 2-D HatchModel only for plot projection; screen
|
||||
@@ -12,8 +12,8 @@ use crate::t;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -72,8 +72,8 @@ pub(crate) fn perimeter_indices(corners: &[[f64; 3]; 4]) -> [usize; 4] {
|
||||
}
|
||||
}
|
||||
|
||||
impl TruckConvertible for Solid {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Solid {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
// SOLID corners are OCS. Map them to WCS, then resolve either the DXF
|
||||
// Z-order or legacy perimeter order before building edges and fill.
|
||||
let corners = wcs_corners(self);
|
||||
@@ -104,9 +104,9 @@ impl TruckConvertible for Solid {
|
||||
// two points coincide and the second triangle degenerates harmlessly.
|
||||
let fill_tris = vec![p0, p1, p2, p0, p2, p3];
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: snap,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: corners.to_vec(),
|
||||
|
||||
+47
-107
@@ -1,17 +1,14 @@
|
||||
use acadrust::entities::Spline;
|
||||
use crate::t;
|
||||
use truck_modeling::{
|
||||
base::{BoundedCurve, ParameterDivision1D, ParametricCurve, Vector4},
|
||||
builder, BSplineCurve, Curve, Edge, KnotVec, NurbsCurve, Point3, Wire,
|
||||
};
|
||||
use acadrust::kernel::space::NurbsCurve3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, parse_f64, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::TruckConvertible;
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::RenderConvertible;
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
|
||||
fn to_truck(spl: &Spline) -> TruckEntity {
|
||||
fn to_render(spl: &Spline) -> RenderEntity {
|
||||
let n = spl.control_points.len();
|
||||
if n < 2 {
|
||||
// A fit-point spline (DWG scenario 2 / R2013+) stores only the points
|
||||
@@ -57,18 +54,18 @@ fn to_truck(spl: &Spline) -> TruckEntity {
|
||||
} else {
|
||||
spl.fit_points.iter().map(|p| [p.x, p.y, p.z]).collect()
|
||||
};
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts,
|
||||
tangent_geoms: vec![],
|
||||
key_vertices,
|
||||
fill_tris: vec![],
|
||||
};
|
||||
}
|
||||
return TruckEntity {
|
||||
return RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Point(builder::vertex(Point3::new(0.0, 0.0, 0.0))),
|
||||
object: RenderObject::Lines(Vec::new()),
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -76,42 +73,6 @@ fn to_truck(spl: &Spline) -> TruckEntity {
|
||||
};
|
||||
}
|
||||
|
||||
let knot_vec = if !spl.knots.is_empty() {
|
||||
KnotVec::from(spl.knots.clone())
|
||||
} else {
|
||||
KnotVec::uniform_knot(spl.degree as usize, n - 1)
|
||||
};
|
||||
|
||||
// Use rational NURBS when weights are provided (circles/conics stored as NURBS).
|
||||
let use_nurbs = !spl.weights.is_empty() && spl.weights.len() == n;
|
||||
let (p_start, p_end, curve) = if use_nurbs {
|
||||
let homo_pts: Vec<Vector4> = spl
|
||||
.control_points
|
||||
.iter()
|
||||
.zip(spl.weights.iter())
|
||||
.map(|(p, &w)| {
|
||||
let w = if w.abs() < 1e-12 { 1.0 } else { w };
|
||||
Vector4::new(p.x * w, p.y * w, p.z * w, w)
|
||||
})
|
||||
.collect();
|
||||
let nurbs = NurbsCurve::new(BSplineCurve::new(knot_vec, homo_pts));
|
||||
let (t0, t1) = nurbs.range_tuple();
|
||||
(nurbs.subs(t0), nurbs.subs(t1), Curve::NurbsCurve(nurbs))
|
||||
} else {
|
||||
let ctrl_pts: Vec<Point3> = spl
|
||||
.control_points
|
||||
.iter()
|
||||
.map(|p| Point3::new(p.x, p.y, p.z))
|
||||
.collect();
|
||||
let bspline = BSplineCurve::new(knot_vec, ctrl_pts);
|
||||
let (t0, t1) = bspline.range_tuple();
|
||||
(
|
||||
bspline.subs(t0),
|
||||
bspline.subs(t1),
|
||||
Curve::BSplineCurve(bspline),
|
||||
)
|
||||
};
|
||||
|
||||
// Snap sources from the spline's own curve. A spline is not a chain of
|
||||
// straight segments, so nothing goes in `key_vertices`: consecutive
|
||||
// entries there are joined and their midpoints offered, and the chord
|
||||
@@ -149,30 +110,27 @@ fn to_truck(spl: &Spline) -> TruckEntity {
|
||||
}
|
||||
};
|
||||
|
||||
// Sampled through the spline's own curve — the same definition EXTRUDE
|
||||
// and REVOLVE read — and closed back onto its start when the flags say
|
||||
// it is periodic and the two ends do not already meet.
|
||||
let is_closed = spl.flags.closed || spl.flags.periodic;
|
||||
let gap = {
|
||||
let dx = (p_end.x - p_start.x) as f32;
|
||||
let dy = (p_end.y - p_start.y) as f32;
|
||||
let dz = (p_end.z - p_start.z) as f32;
|
||||
(dx * dx + dy * dy + dz * dz).sqrt()
|
||||
};
|
||||
let mut points = crate::entities::curve::spline_curve(spl)
|
||||
.map(|planar| crate::entities::curve::curve_points(&planar))
|
||||
.unwrap_or_default();
|
||||
if is_closed {
|
||||
if let (Some(first), Some(last)) = (points.first().copied(), points.last().copied()) {
|
||||
let gap = ((last[0] - first[0]).powi(2)
|
||||
+ (last[1] - first[1]).powi(2)
|
||||
+ (last[2] - first[2]).powi(2))
|
||||
.sqrt();
|
||||
if gap > 1e-6 {
|
||||
points.push(first);
|
||||
}
|
||||
}
|
||||
}
|
||||
let object = RenderObject::Lines(points);
|
||||
|
||||
let object = if is_closed && gap > 1e-6 {
|
||||
let v_start = builder::vertex(p_start);
|
||||
let v_end = builder::vertex(p_end);
|
||||
let v_close = builder::vertex(p_start);
|
||||
let main_edge = Edge::new(&v_start, &v_end, curve);
|
||||
let close_edge = builder::line(&v_end, &v_close);
|
||||
let wire: Wire = [main_edge, close_edge].into_iter().collect();
|
||||
TruckObject::Contour(wire)
|
||||
} else {
|
||||
let v_start = builder::vertex(p_start);
|
||||
let v_end = builder::vertex(p_end);
|
||||
let edge = Edge::new(&v_start, &v_end, curve);
|
||||
TruckObject::Curve(edge)
|
||||
};
|
||||
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object,
|
||||
snap_pts,
|
||||
@@ -199,12 +157,6 @@ pub(crate) fn measurement_polyline(spl: &Spline) -> Vec<[f64; 3]> {
|
||||
if degree == 0 || degree >= count {
|
||||
return spl.control_points.iter().map(|p| [p.x, p.y, p.z]).collect();
|
||||
}
|
||||
let knot_vec = if spl.knots.len() == count + degree + 1 {
|
||||
KnotVec::from(spl.knots.clone())
|
||||
} else {
|
||||
KnotVec::uniform_knot(degree, count - 1)
|
||||
};
|
||||
|
||||
let mut min = [f64::INFINITY; 3];
|
||||
let mut max = [f64::NEG_INFINITY; 3];
|
||||
for point in &spl.control_points {
|
||||
@@ -221,35 +173,23 @@ pub(crate) fn measurement_polyline(spl: &Spline) -> Vec<[f64; 3]> {
|
||||
.sqrt();
|
||||
let tolerance = crate::scene::convert::tess_util::fill_chord_tol(diagonal.max(1.0));
|
||||
|
||||
if spl.weights.len() == count {
|
||||
let controls = spl
|
||||
.control_points
|
||||
// The kernel's space curve holds the rational and the polynomial case
|
||||
// alike — weights absent means polynomial — and samples to a chord
|
||||
// tolerance, refined where the curve bends rather than evenly.
|
||||
let controls: Vec<[f64; 3]> = spl
|
||||
.control_points
|
||||
.iter()
|
||||
.map(|point| [point.x, point.y, point.z])
|
||||
.collect();
|
||||
let weights = (spl.weights.len() == count).then(|| {
|
||||
spl.weights
|
||||
.iter()
|
||||
.zip(&spl.weights)
|
||||
.map(|(point, &weight)| {
|
||||
let weight = if weight.abs() < 1e-12 { 1.0 } else { weight };
|
||||
Vector4::new(
|
||||
point.x * weight,
|
||||
point.y * weight,
|
||||
point.z * weight,
|
||||
weight,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let curve = NurbsCurve::new(BSplineCurve::new(knot_vec, controls));
|
||||
let range = curve.range_tuple();
|
||||
let (_, points) = curve.parameter_division(range, tolerance);
|
||||
points.into_iter().map(|point| [point.x, point.y, point.z]).collect()
|
||||
} else {
|
||||
let controls = spl
|
||||
.control_points
|
||||
.iter()
|
||||
.map(|point| Point3::new(point.x, point.y, point.z))
|
||||
.collect::<Vec<_>>();
|
||||
let curve = BSplineCurve::new(knot_vec, controls);
|
||||
let range = curve.range_tuple();
|
||||
let (_, points) = curve.parameter_division(range, tolerance);
|
||||
points.into_iter().map(|point| [point.x, point.y, point.z]).collect()
|
||||
.map(|weight| if weight.abs() < 1e-12 { 1.0 } else { *weight })
|
||||
.collect()
|
||||
});
|
||||
match NurbsCurve3::new(degree, controls, spl.knots.clone(), weights) {
|
||||
Some(curve) => curve.tessellate_within(tolerance),
|
||||
None => spl.control_points.iter().map(|p| [p.x, p.y, p.z]).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,9 +591,9 @@ fn apply_transform(spline: &mut Spline, t: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Spline {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self))
|
||||
impl RenderConvertible for Spline {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,7 +652,7 @@ impl crate::entities::traits::Grippable for Spline {
|
||||
* 0.5;
|
||||
self.weights.insert(i1, w);
|
||||
}
|
||||
// Clear knots so to_truck rebuilds a uniform knot vector
|
||||
// Clear knots so to_render rebuilds a uniform knot vector
|
||||
// for the new CV count.
|
||||
self.knots.clear();
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ use crate::entities::common::{ro_prop as ro, square_grip};
|
||||
use crate::entities::text_support::{
|
||||
layout_mtext, MTextRenderOpts, MTextVAnchor, ResolvedTextStyle,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, Property, PropValue};
|
||||
use crate::scene::view::transform;
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
@@ -703,8 +703,8 @@ pub(crate) fn block_cell_inserts(
|
||||
inserts
|
||||
}
|
||||
|
||||
impl TruckConvertible for Table {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Table {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.rows.is_empty() || self.columns.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -982,7 +982,7 @@ impl TruckConvertible for Table {
|
||||
});
|
||||
// Flatten TextStroke groups into the table's Lines buffer.
|
||||
// Per-run inline `\C` / `\c` colour is dropped here because the
|
||||
// table emits a single TruckObject::Lines for borders + text;
|
||||
// table emits a single RenderObject::Lines for borders + text;
|
||||
// tracking it would require splitting the table into multiple
|
||||
// WireModels per cell colour. Borders + uniform-coloured runs
|
||||
// honour the entity's outer colour.
|
||||
@@ -1026,9 +1026,9 @@ impl TruckConvertible for Table {
|
||||
[x as f64 + base[0], y as f64 + base[1], z as f64 + base[2]]
|
||||
})
|
||||
.collect();
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts_f64),
|
||||
object: RenderObject::Lines(pts_f64),
|
||||
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
|
||||
+10
-10
@@ -7,8 +7,8 @@ use crate::entities::common::{
|
||||
use crate::entities::text_support::{
|
||||
resolve_dxf_special_chars, resolve_text_style, text_local_bounds,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
|
||||
use crate::scene::text::lff;
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
@@ -52,7 +52,7 @@ pub(crate) fn sync_text_alignment_point(t: &mut Text) {
|
||||
}
|
||||
|
||||
/// Resolved placement of a TEXT run: the baseline-anchored run origin (WCS xy)
|
||||
/// plus every parameter needed to lay the glyphs out. Shared by `to_truck` (the
|
||||
/// plus every parameter needed to lay the glyphs out. Shared by `to_render` (the
|
||||
/// stroke path) and the SDF-quad text collector so both place text identically.
|
||||
pub struct TextPlacement {
|
||||
/// Run-local origin (glyph space `[0,0]` maps here), WCS xy, kept f64.
|
||||
@@ -98,7 +98,7 @@ pub(crate) fn acad_text_encode(value: &str) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
fn to_render(t: &Text, document: &acadrust::CadDocument) -> RenderEntity {
|
||||
let p = text_run_placement(t, document);
|
||||
let snap_pt = glam::DVec3::new(p.wcs_insertion[0], p.wcs_insertion[1], p.wcs_insertion[2]);
|
||||
// Parse `%%` codes via acadrust, re-encoded for the stroke tessellator.
|
||||
@@ -113,9 +113,9 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
&p.font,
|
||||
&value,
|
||||
);
|
||||
TruckEntity {
|
||||
RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Text(vec![TextStroke {
|
||||
object: RenderObject::Text(vec![TextStroke {
|
||||
strokes,
|
||||
origin: p.origin,
|
||||
color: None,
|
||||
@@ -139,7 +139,7 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity {
|
||||
}
|
||||
|
||||
/// Compute a TEXT entity's run placement (origin + layout params). Extracted
|
||||
/// from `to_truck` verbatim so the stroke and SDF-quad paths agree exactly.
|
||||
/// from `to_render` verbatim so the stroke and SDF-quad paths agree exactly.
|
||||
pub fn text_run_placement(t: &Text, document: &acadrust::CadDocument) -> TextPlacement {
|
||||
let normal = (t.normal.x, t.normal.y, t.normal.z);
|
||||
let (wsx, wsy, wsz) = crate::scene::view::transform::ocs_point_to_wcs(
|
||||
@@ -493,9 +493,9 @@ fn apply_transform(t: &mut Text, tr: &EntityTransform) {
|
||||
});
|
||||
}
|
||||
|
||||
impl TruckConvertible for Text {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
Some(to_truck(self, document))
|
||||
impl RenderConvertible for Text {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
Some(to_render(self, document))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use acadrust::types::aci_table::aci_to_rgb;
|
||||
use acadrust::CadDocument;
|
||||
|
||||
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke};
|
||||
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke};
|
||||
use crate::scene::text::font_face::Face;
|
||||
use crate::scene::text::lff;
|
||||
|
||||
|
||||
+10
-10
@@ -2,8 +2,8 @@ use acadrust::entities::Tolerance;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke, TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
use crate::scene::text::lff;
|
||||
@@ -430,10 +430,10 @@ fn tessellate_tolerance(
|
||||
(box_out, cells)
|
||||
}
|
||||
|
||||
// ── TruckConvertible ──────────────────────────────────────────────────────────
|
||||
// ── RenderConvertible ──────────────────────────────────────────────────────────
|
||||
|
||||
impl TruckConvertible for Tolerance {
|
||||
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Tolerance {
|
||||
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
if self.text.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -493,9 +493,9 @@ impl TruckConvertible for Tolerance {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Text(groups),
|
||||
object: RenderObject::Text(groups),
|
||||
snap_pts: vec![(snap_pt, SnapHint::Insertion)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
@@ -845,10 +845,10 @@ mod tests {
|
||||
let mut tol = Tolerance::new();
|
||||
tol.text = "ABC".into();
|
||||
|
||||
let Some(TruckEntity {
|
||||
object: TruckObject::Text(groups),
|
||||
let Some(RenderEntity {
|
||||
object: RenderObject::Text(groups),
|
||||
..
|
||||
}) = tol.to_truck(&doc)
|
||||
}) = tol.to_render(&doc)
|
||||
else {
|
||||
panic!("tolerance produced no text");
|
||||
};
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use acadrust::{CadDocument, EntityType};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::scene::convert::acad_to_truck::TruckEntity;
|
||||
use crate::scene::convert::acad_to_render::RenderEntity;
|
||||
use crate::scene::model::object::{
|
||||
GripApply, GripDef, GripMenuAction, GripMenuItem, PropSection,
|
||||
};
|
||||
use crate::scene::convert::tess_util::FallbackGeometry;
|
||||
|
||||
pub trait TruckConvertible {
|
||||
fn to_truck(&self, document: &CadDocument) -> Option<TruckEntity>;
|
||||
pub trait RenderConvertible {
|
||||
fn to_render(&self, document: &CadDocument) -> Option<RenderEntity>;
|
||||
}
|
||||
|
||||
/// Fallback geometry for entities not routed through the truck topology
|
||||
/// Fallback geometry for entities not routed through the render
|
||||
/// pipeline (Viewport, Insert, Hatch outline, Ole2Frame). Returns absolute
|
||||
/// WCS `f32` points + snap/key vertices the dispatcher wraps into a
|
||||
/// `WireModel`.
|
||||
@@ -162,7 +162,7 @@ pub fn entity_type_name(et: &EntityType) -> &str {
|
||||
}
|
||||
|
||||
pub trait EntityTypeOps {
|
||||
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity>;
|
||||
fn to_render_entity(&self, document: &CadDocument) -> Option<RenderEntity>;
|
||||
fn grips(&self) -> Vec<GripDef>;
|
||||
fn grip_menu(&self, grip_id: usize) -> Vec<GripMenuItem>;
|
||||
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection>;
|
||||
@@ -284,9 +284,9 @@ macro_rules! impl_entity_basics_with_text_styles {
|
||||
}
|
||||
|
||||
impl EntityTypeOps for EntityType {
|
||||
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity> {
|
||||
fn to_render_entity(&self, document: &CadDocument) -> Option<RenderEntity> {
|
||||
dispatch!(self,
|
||||
|e| TruckConvertible::to_truck(e, document),
|
||||
|e| RenderConvertible::to_render(e, document),
|
||||
[
|
||||
Point, Line, Circle, Arc, Ellipse, Spline, LwPolyline,
|
||||
Polyline, Polyline2D, Polyline3D, Ray, XLine, RasterImage,
|
||||
|
||||
+11
-11
@@ -10,8 +10,8 @@ use glam::DVec3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{center_grip, edit_angle_prop as edit_angle, edit_prop as edit, ro_prop as ro, square_grip};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
||||
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
||||
use crate::scene::convert::acad_to_render::{RenderEntity, RenderObject};
|
||||
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
use crate::scene::model::wire_model::SnapHint;
|
||||
|
||||
@@ -37,7 +37,7 @@ fn cross_wire(origin: [f64; 3], size: f64) -> Vec<[f64; 3]> {
|
||||
]
|
||||
}
|
||||
|
||||
// ── TruckConvertible ──────────────────────────────────────────────────────────
|
||||
// ── RenderConvertible ──────────────────────────────────────────────────────────
|
||||
|
||||
/// The underlay's page rectangle in world space (CCW from the insertion),
|
||||
/// when its definition resolves and the page rasterises: page inches × the
|
||||
@@ -71,8 +71,8 @@ fn page_quad(
|
||||
])
|
||||
}
|
||||
|
||||
impl TruckConvertible for Underlay {
|
||||
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
||||
impl RenderConvertible for Underlay {
|
||||
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
||||
let origin = v3(&self.insertion_point);
|
||||
let _origin_f32 = v3f32(&self.insertion_point);
|
||||
|
||||
@@ -90,9 +90,9 @@ impl TruckConvertible for Underlay {
|
||||
// selects on a click anywhere inside, not just on its outline.
|
||||
let ring: Vec<[f64; 3]> = world_verts.iter().map(|v| [v.x, v.y, v.z]).collect();
|
||||
let pick_tris = crate::entities::mesh::triangulate_planar(&ring);
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris,
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key,
|
||||
@@ -103,9 +103,9 @@ impl TruckConvertible for Underlay {
|
||||
// visible extent instead of a lone cross under the raster.
|
||||
let pts = vec![q[0], q[1], q[2], q[3], q[0]];
|
||||
let pick_tris = crate::entities::mesh::triangulate_planar(&q.to_vec());
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris,
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: q.to_vec(),
|
||||
@@ -114,9 +114,9 @@ impl TruckConvertible for Underlay {
|
||||
} else {
|
||||
// No clip boundary: draw a cross at insertion point.
|
||||
let pts = cross_wire(origin, 1.0);
|
||||
Some(TruckEntity {
|
||||
Some(RenderEntity {
|
||||
pick_tris: Vec::new(),
|
||||
object: TruckObject::Lines(pts),
|
||||
object: RenderObject::Lines(pts),
|
||||
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![origin],
|
||||
|
||||
Reference in new issue
Block a user