feat: node graph overlay; move to opencadcodec/opencadkernel/opencadgraph

The codec and kernel repositories and crates are renamed opencadcodec and
opencadkernel. Inside OCS they are depended on under short keys, so code
reads `codec::`, `kernel::` and the new `graph::` (opencadgraph, the node
graph engine). File-format and protocol spellings stay as they were: the
ACIS product id `acadrust`, the ACADRUST_* switches and the plugin
version keys `acadrust_version` / `acadrust_source`.

A button left of MCP on the command line opens a translucent node graph
over the viewport, with a palette of object, input, math, logic, list,
text and geometry nodes added by click or drag. An object node owns
drawing entities and its rows are the Properties panel's own rows for
them: the single-object page is extracted from refresh_properties as
entity_property_sections, values use the control protocol's
property_json, and writes go through set_property_value with a property
target override, so the panel, MCP and the graph share one read/write
path. A list reaching an object row makes one entity per element. Each
graph action is one undo step; the canvas pans and zooms.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-25 07:34:23 +03:00
1 parent 56c04408d6
commit f537aff75c
430 files changed
+9925 -8540

No files matched your search

+10 -10
View File
@@ -1,4 +1,4 @@
use acadrust::entities::Arc;
use codec::entities::Arc;
use crate::t;
use crate::command::EntityTransform;
@@ -136,7 +136,7 @@ pub(crate) fn refit_grips(
let Some(c) = plane.project(points[2].to_array()) else {
return false;
};
let Some(fit) = cadkernel::geom2d::arc_through_points(a, b, c) else {
let Some(fit) = kernel::geom2d::arc_through_points(a, b, c) else {
return false;
};
@@ -246,7 +246,7 @@ fn apply_geom_prop(arc: &mut Arc, field: &str, value: &str) {
"end_angle" => arc.end_angle = v.to_radians(),
"normal_x" | "normal_y" | "normal_z" => {
let center = arc.center_wcs();
let mut normal = cadkernel::space::Vec3::new(arc.normal.x, arc.normal.y, arc.normal.z);
let mut normal = kernel::space::Vec3::new(arc.normal.x, arc.normal.y, arc.normal.z);
match field {
"normal_x" => normal.x = v,
"normal_y" => normal.y = v,
@@ -254,12 +254,12 @@ fn apply_geom_prop(arc: &mut Arc, field: &str, value: &str) {
_ => {}
}
if let Some(normal) = normal.normalize() {
arc.normal = acadrust::types::Vector3::new(normal.x, normal.y, normal.z);
arc.normal = codec::types::Vector3::new(normal.x, normal.y, normal.z);
let (x, y, z) = crate::scene::view::transform::wcs_point_to_ocs(
(center.x, center.y, center.z),
(normal.x, normal.y, normal.z),
);
arc.center = acadrust::types::Vector3::new(x, y, z);
arc.center = codec::types::Vector3::new(x, y, z);
}
}
_ => {}
@@ -312,7 +312,7 @@ fn apply_transform(arc: &mut Arc, t: &EntityTransform) {
}
impl RenderConvertible for Arc {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
@@ -382,7 +382,7 @@ impl crate::entities::traits::Grippable for Arc {
action: crate::scene::model::object::GripMenuAction,
point: glam::DVec3,
) -> Option<f64> {
use cadkernel::geom2d::{Circle as KernelCircle, Curve as KernelCurve, Vec2};
use kernel::geom2d::{Circle as KernelCircle, Curve as KernelCurve, Vec2};
use crate::scene::model::object::GripMenuAction as A;
if self.radius <= 1.0e-9 {
return None;
@@ -484,7 +484,7 @@ impl crate::entities::traits::Transformable for Arc {
}
}
impl crate::entities::traits::MassPropsCalc for acadrust::entities::Arc {
impl crate::entities::traits::MassPropsCalc for codec::entities::Arc {
fn mass_props(&self) -> crate::entities::traits::MassProps {
let curve = crate::entities::curve::arc_curve(self);
let area = curve.curve.chord_closed_area().unwrap_or(0.0).abs();
@@ -511,8 +511,8 @@ mod tests {
#[test]
fn midpoint_grip_drives_radius_and_arc_length_in_entity_plane() {
let mut arc = Arc::default();
arc.center = acadrust::types::Vector3::new(1.0, 2.0, 3.0);
arc.normal = acadrust::types::Vector3::new(0.0, 1.0, 0.0);
arc.center = codec::types::Vector3::new(1.0, 2.0, 3.0);
arc.normal = codec::types::Vector3::new(0.0, 1.0, 0.0);
arc.radius = 2.0;
arc.start_angle = 0.0;
arc.end_angle = std::f64::consts::FRAC_PI_2;
+9 -9
View File
@@ -1,8 +1,8 @@
use acadrust::entities::attribute_definition::{
use codec::entities::attribute_definition::{
HorizontalAlignment as AHA, MTextFlag, VerticalAlignment as AVA,
};
use acadrust::entities::{AttributeDefinition, AttributeEntity};
use acadrust::types::Vector3;
use codec::entities::{AttributeDefinition, AttributeEntity};
use codec::types::Vector3;
use crate::command::EntityTransform;
use crate::entities::common::{edit_angle_prop as edit_angle, edit_prop as edit, parse_f64, ro_prop as ro, square_grip};
@@ -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_render(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) -> RenderEntity {
fn build_attr_render(input: AttrTextInputs<'_>, document: &codec::CadDocument) -> RenderEntity {
let normal = (input.normal.x, input.normal.y, input.normal.z);
let (wsx, wsy, wsz) = transform::ocs_point_to_wcs(
(
@@ -290,7 +290,7 @@ fn build_attr_render(input: AttrTextInputs<'_>, document: &acadrust::CadDocument
anchor_f64[0] - (anchor_local_x as f64 * cos_r - local_y_for_line as f64 * sin_r),
anchor_f64[1] - (anchor_local_x as f64 * sin_r + local_y_for_line as f64 * cos_r),
];
// Parse `%%` codes through acadrust (same as TEXT), re-encoded for the
// Parse `%%` codes through opencadcodec (same as TEXT), re-encoded for the
// stroke tessellator, so attribute text shares the one parser.
let encoded = crate::entities::text::acad_text_encode(line);
let (strokes, fill_tris) = lff::tessellate_text_ex(
@@ -338,7 +338,7 @@ fn build_attr_render(input: AttrTextInputs<'_>, document: &acadrust::CadDocument
// ── AttributeDefinition ───────────────────────────────────────────────────────
impl RenderConvertible for AttributeDefinition {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::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.)
@@ -627,7 +627,7 @@ impl Transformable for AttributeDefinition {
// ── AttributeEntity ───────────────────────────────────────────────────────────
impl RenderConvertible for AttributeEntity {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(build_attr_render(
AttrTextInputs {
value: &self.value,
@@ -874,7 +874,7 @@ impl Transformable for AttributeEntity {
}
}
impl crate::entities::traits::TextContent for acadrust::entities::AttributeDefinition {
impl crate::entities::traits::TextContent for codec::entities::AttributeDefinition {
fn text_content(&self) -> Option<String> {
Some(self.default_value.clone())
}
@@ -886,7 +886,7 @@ impl crate::entities::traits::TextContent for acadrust::entities::AttributeDefin
}
}
impl crate::entities::traits::TextContent for acadrust::entities::AttributeEntity {
impl crate::entities::traits::TextContent for codec::entities::AttributeEntity {
fn text_content(&self) -> Option<String> {
Some(self.get_value().to_string())
}
+8 -8
View File
@@ -1,4 +1,4 @@
use acadrust::entities::Circle;
use codec::entities::Circle;
use crate::t;
use crate::command::EntityTransform;
@@ -129,11 +129,11 @@ fn to_render(circle: &Circle) -> RenderEntity {
/// Zoom-aware render converter for EntityType::Circle.
pub fn relative_render(
entity: &acadrust::EntityType,
_document: &acadrust::CadDocument,
entity: &codec::EntityType,
_document: &codec::CadDocument,
wpp: Option<f32>,
) -> Option<RenderEntity> {
let acadrust::EntityType::Circle(circle) = entity else {
let codec::EntityType::Circle(circle) = entity else {
return None;
};
Some(to_render_with_wpp(circle, wpp))
@@ -204,7 +204,7 @@ fn apply_geom_prop(circle: &mut Circle, field: &str, value: &str) {
"area" if v > 0.0 => circle.radius = (v / PI).sqrt(),
"normal_x" | "normal_y" | "normal_z" => {
let center = circle.center_wcs();
let mut normal = cadkernel::space::Vec3::new(
let mut normal = kernel::space::Vec3::new(
circle.normal.x,
circle.normal.y,
circle.normal.z,
@@ -216,12 +216,12 @@ fn apply_geom_prop(circle: &mut Circle, field: &str, value: &str) {
_ => {}
}
if let Some(normal) = normal.normalize() {
circle.normal = acadrust::types::Vector3::new(normal.x, normal.y, normal.z);
circle.normal = codec::types::Vector3::new(normal.x, normal.y, normal.z);
let (x, y, z) = crate::scene::view::transform::wcs_point_to_ocs(
(center.x, center.y, center.z),
(normal.x, normal.y, normal.z),
);
circle.center = acadrust::types::Vector3::new(x, y, z);
circle.center = codec::types::Vector3::new(x, y, z);
}
}
_ => {}
@@ -273,7 +273,7 @@ fn apply_transform(circle: &mut Circle, t: &EntityTransform) {
}
impl RenderConvertible for Circle {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
+8 -8
View File
@@ -34,7 +34,7 @@ impl UnitContext {
/// The settings as this drawing holds them. Every place that formats or
/// reads a number seeds the context from here, so none of them can be
/// working from a different idea of the drawing's conventions.
pub fn from_header(header: &acadrust::document::HeaderVariables) -> Self {
pub fn from_header(header: &codec::document::HeaderVariables) -> Self {
Self {
lunits: header.linear_unit_format,
luprec: header.linear_unit_precision,
@@ -71,7 +71,7 @@ thread_local! {
}
/// Record which text styles fix their height, from the drawing's style table.
pub fn set_fixed_text_heights(document: &acadrust::CadDocument) {
pub fn set_fixed_text_heights(document: &codec::CadDocument) {
FIXED_TEXT_HEIGHTS.with(|cell| {
let mut map = cell.borrow_mut();
map.clear();
@@ -754,7 +754,7 @@ fn parse_angle_deg_unbounded(value: &str) -> Option<f64> {
/// Re-exported rather than imported at each call site so the twelve modules
/// that already reach for `entities::common::BulgeArc` keep working, and so
/// there is one obvious place to see that the maths moved out.
pub use cadkernel::geom2d::BulgeArc;
pub use kernel::geom2d::BulgeArc;
/// Convert a 2D BulgeArc into a 3D TangentGeom::Arc with its world center,
/// plane axes, radius, and counter-clockwise start/end sweep angles.
@@ -944,7 +944,7 @@ pub(crate) fn tapered_band_points(
if bulge.abs() < 1e-9 {
push(p1[0], p1[1], ew0 as f32);
} else if let Some(arc) = BulgeArc::from_bulge(p0, p1, bulge) {
let samples = arc.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE);
let samples = arc.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE);
let segments = samples.len().saturating_sub(1).max(1);
for (index, s) in samples.into_iter().enumerate().skip(1) {
let t = index as f64 / segments as f64;
@@ -970,10 +970,10 @@ pub(crate) fn wide_band_outline(
restart_per_segment: bool,
to_wcs: &dyn Fn(f64, f64) -> (f64, f64, f64),
) -> WideBandOutline {
let source = cadkernel::geom2d::Polyline {
let source = kernel::geom2d::Polyline {
vertices: verts
.iter()
.map(|(position, bulge, _, _)| cadkernel::geom2d::PolylineVertex {
.map(|(position, bulge, _, _)| kernel::geom2d::PolylineVertex {
position: *position,
bulge: *bulge,
})
@@ -990,10 +990,10 @@ pub(crate) fn wide_band_outline(
.take(segment_count)
.map(|(_, _, start, end)| [*start, *end])
.collect();
let boundary = cadkernel::geom2d::polyline_band_boundary(
let boundary = kernel::geom2d::polyline_band_boundary(
&source,
&widths,
cadkernel::tessellation::DEFAULT_ANGLE,
kernel::tessellation::DEFAULT_ANGLE,
);
let mut points = Vec::new();
let mut stations = Vec::new();
+19 -19
View File
@@ -28,17 +28,17 @@
//! curves. They keep their own paths and this returns `None` for them, which
//! is what lets a caller ask about any entity without checking first.
use acadrust::entities::{
use codec::entities::{
Arc as ArcEnt, Circle as CircleEnt, Ellipse as EllipseEnt, LwPolyline as LwPolylineEnt,
Polyline2D, Spline as SplineEnt,
};
use acadrust::types::Vector3;
use acadrust::EntityType;
use cadkernel::geom2d::{
use codec::types::Vector3;
use codec::EntityType;
use kernel::geom2d::{
characteristic_points, Arc, Circle, Curve, Ellipse, EllipseArc, Line, Polyline, PolylineVertex,
Ray, SnapKind, Transform, XLine,
};
use cadkernel::space::{are_coplanar, coplanarity_tolerance, PlanarCurve, Plane, Vec3};
use kernel::space::{are_coplanar, coplanarity_tolerance, PlanarCurve, Plane, Vec3};
use crate::modules::draw::modify::spline_ops::spline_to_nurbs_on;
use crate::scene::model::wire_model::SnapHint;
@@ -109,12 +109,12 @@ pub fn entity_curve(entity: &EntityType) -> Option<PlanarCurve> {
/// Exact spatial source geometry for commands that traverse nonplanar curves.
/// Curve construction and arc-length calculations remain in the kernel.
pub fn entity_spatial_measurement(entity: &EntityType) -> Option<cadkernel::space::ArcLengthCurve3> {
use cadkernel::space::{ArcLengthCurve3, NurbsCurve3};
pub fn entity_spatial_measurement(entity: &EntityType) -> Option<kernel::space::ArcLengthCurve3> {
use kernel::space::{ArcLengthCurve3, NurbsCurve3};
let curve = match entity {
EntityType::Polyline3D(polyline) => {
if polyline.flags.spline_fit {
use acadrust::entities::polyline3d::SmoothSurfaceType;
use codec::entities::polyline3d::SmoothSurfaceType;
let degree = match polyline.smooth_type {
SmoothSurfaceType::QuadraticBSpline => 2,
SmoothSurfaceType::CubicBSpline | SmoothSurfaceType::Bezier => 3,
@@ -463,7 +463,7 @@ pub fn entity_with_lwpolyline_world_xy(entity: &EntityType) -> EntityType {
/// World-space wire points sampled by the kernel's angular policy.
pub fn curve_points(curve: &PlanarCurve) -> Vec<[f64; 3]> {
curve.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
curve.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
}
/// The snap candidates an entity's curve offers, in the two channels the
@@ -530,9 +530,9 @@ fn normalized(normal: Vector3) -> Vector3 {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::lwpolyline::LwVertex;
use acadrust::entities::{Line as LineEnt, Ray as RayEnt, XLine as XLineEnt};
use acadrust::types::Vector2;
use codec::entities::lwpolyline::LwVertex;
use codec::entities::{Line as LineEnt, Ray as RayEnt, XLine as XLineEnt};
use codec::types::Vector2;
use std::f64::consts::{FRAC_PI_2, PI, TAU};
fn v3(x: f64, y: f64, z: f64) -> Vector3 {
@@ -726,8 +726,8 @@ mod tests {
#[test]
fn spatial_polyline_measurement_uses_unflagged_fit_controls() {
use acadrust::entities::polyline3d::SmoothSurfaceType;
use acadrust::entities::{Polyline3D, Vertex3DPolyline};
use codec::entities::polyline3d::SmoothSurfaceType;
use codec::entities::{Polyline3D, Vertex3DPolyline};
let mut polyline = Polyline3D::new();
polyline.flags.spline_fit = true;
@@ -849,12 +849,12 @@ mod tests {
/// where it happens rather than the next time somebody reaches for it.
#[test]
fn the_solid_layer_and_the_acis_bridge_are_reachable() {
let solid = cadkernel::brep::make::cuboid([0.0; 3], [1.0; 3])
let solid = kernel::brep::make::cuboid([0.0; 3], [1.0; 3])
.expect("the kernel builds its own primitives");
assert!(solid.validate().is_empty());
assert_eq!(solid.euler_characteristic(), 2);
let document = acadrust::entities::acis::types::SatDocument::new();
let (bodies, loss) = cadkernel::acis::lift(&document);
let document = codec::entities::acis::types::SatDocument::new();
let (bodies, loss) = kernel::acis::lift(&document);
assert!(bodies.is_empty() && loss.is_empty(), "an empty document lifts to nothing");
}
@@ -886,14 +886,14 @@ mod tests {
ray.base_point = v3(1.0, 1.0, 0.0);
ray.direction = v3(2.0, 0.0, 0.0);
let curve = entity_curve(&EntityType::Ray(ray)).unwrap();
assert_eq!(curve.extent(), cadkernel::geom2d::Extent::Forward);
assert_eq!(curve.extent(), kernel::geom2d::Extent::Forward);
assert_eq!(curve.point_at(1.0), [3.0, 1.0, 0.0]);
let mut line = XLineEnt::default();
line.base_point = v3(0.0, 0.0, 0.0);
line.direction = v3(0.0, 3.0, 0.0);
let curve = entity_curve(&EntityType::XLine(line)).unwrap();
assert_eq!(curve.extent(), cadkernel::geom2d::Extent::Infinite);
assert_eq!(curve.extent(), kernel::geom2d::Extent::Infinite);
assert_eq!(curve.point_at(-1.0), [0.0, -3.0, 0.0]);
}
}
+4 -4
View File
@@ -7,9 +7,9 @@
//! an override over the style default, so editing one of these rows writes here
//! and the change round-trips to file.
use acadrust::types::Color;
use acadrust::xdata::{ExtendedData, XDataValue};
use acadrust::{CadDocument, EntityType, Handle};
use codec::types::Color;
use codec::xdata::{ExtendedData, XDataValue};
use codec::{CadDocument, EntityType, Handle};
// DXF group codes of the dimension variables surfaced on the leader panel.
pub const DIMSCALE: i16 = 40; // overall scale (real)
@@ -284,7 +284,7 @@ pub fn set_on_entity(entity: &mut EntityType, code: i16, value: Option<XDataValu
}
}
if let Some(vals) = values {
let mut record = acadrust::xdata::ExtendedDataRecord::new(app);
let mut record = codec::xdata::ExtendedDataRecord::new(app);
for v in vals {
record.add_value(v);
}
+82 -82
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{
use codec::entities::{
Dimension, DimensionAligned, DimensionAngular2Ln, DimensionAngular3Pt, DimensionArc,
DimensionBase, DimensionDiameter, DimensionLargeRadial, DimensionLinear, DimensionOrdinate,
DimensionRadius,
@@ -34,7 +34,7 @@ pub(crate) fn normalize_scripted_dimension(dim: &mut Dimension) {
dim.base_mut().actual_measurement = dim.measurement();
}
fn dimension_definition_point(dim: &Dimension) -> acadrust::types::Vector3 {
fn dimension_definition_point(dim: &Dimension) -> codec::types::Vector3 {
match dim {
Dimension::Aligned(d) => d.definition_point,
Dimension::Linear(d) => d.definition_point,
@@ -308,9 +308,9 @@ fn properties(dim: &Dimension) -> Vec<PropSection> {
}
fn linear_like_props(
first: acadrust::types::Vector3,
second: acadrust::types::Vector3,
definition: acadrust::types::Vector3,
first: codec::types::Vector3,
second: codec::types::Vector3,
definition: codec::types::Vector3,
) -> Vec<crate::scene::model::object::Property> {
vec![
edit(t!("First X").as_ref(), "first_x", first.x),
@@ -326,8 +326,8 @@ fn linear_like_props(
}
fn radius_like_props(
center: acadrust::types::Vector3,
point: acadrust::types::Vector3,
center: codec::types::Vector3,
point: codec::types::Vector3,
) -> Vec<crate::scene::model::object::Property> {
vec![
edit(t!("Center X").as_ref(), "center_x", center.x),
@@ -340,10 +340,10 @@ fn radius_like_props(
}
fn angular_props(
vertex: acadrust::types::Vector3,
first: acadrust::types::Vector3,
second: acadrust::types::Vector3,
definition: acadrust::types::Vector3,
vertex: codec::types::Vector3,
first: codec::types::Vector3,
second: codec::types::Vector3,
definition: codec::types::Vector3,
) -> Vec<crate::scene::model::object::Property> {
vec![
edit(t!("Vertex X").as_ref(), "vertex_x", vertex.x),
@@ -482,7 +482,7 @@ fn apply_linear_fields_aligned(d: &mut DimensionAligned, field: &str, value: &st
let delta = angle - old_angle;
let origin_x = d.first_point.x;
let origin_y = d.first_point.y;
let rotate = |point: &mut acadrust::types::Vector3| {
let rotate = |point: &mut codec::types::Vector3| {
let x = point.x - origin_x;
let y = point.y - origin_y;
let (sin, cos) = delta.sin_cos();
@@ -530,9 +530,9 @@ fn apply_linear_fields_linear(d: &mut DimensionLinear, field: &str, value: &str)
}
fn apply_linear_common(
first: &mut acadrust::types::Vector3,
second: &mut acadrust::types::Vector3,
definition: &mut acadrust::types::Vector3,
first: &mut codec::types::Vector3,
second: &mut codec::types::Vector3,
definition: &mut codec::types::Vector3,
field: &str,
value: &str,
) {
@@ -583,8 +583,8 @@ fn apply_diameter_fields(d: &mut DimensionDiameter, field: &str, value: &str) {
}
fn apply_radius_common(
center: &mut acadrust::types::Vector3,
point: &mut acadrust::types::Vector3,
center: &mut codec::types::Vector3,
point: &mut codec::types::Vector3,
field: &str,
value: &str,
) {
@@ -646,10 +646,10 @@ fn apply_angular3_fields(d: &mut DimensionAngular3Pt, field: &str, value: &str)
}
fn apply_angular_common(
vertex: &mut acadrust::types::Vector3,
first: &mut acadrust::types::Vector3,
second: &mut acadrust::types::Vector3,
definition: &mut acadrust::types::Vector3,
vertex: &mut codec::types::Vector3,
first: &mut codec::types::Vector3,
second: &mut codec::types::Vector3,
definition: &mut codec::types::Vector3,
field: &str,
value: &str,
) {
@@ -772,7 +772,7 @@ fn apply_large_radial_fields(d: &mut DimensionLargeRadial, field: &str, value: &
};
let delta = angle - large_radial_rotation(d);
let origin = d.definition_point;
let rotate = |point: &mut acadrust::types::Vector3| {
let rotate = |point: &mut codec::types::Vector3| {
let x = point.x - origin.x;
let y = point.y - origin.y;
let (sin, cos) = delta.sin_cos();
@@ -842,7 +842,7 @@ fn large_radial_rotation(d: &DimensionLargeRadial) -> f64 {
fn apply_transform(dim: &mut Dimension, t: &EntityTransform) {
crate::scene::view::transform::apply_standard_entity_transform(dim, t, |entity, p1, p2| {
acadrust::Entity::apply_transform(
codec::Entity::apply_transform(
entity,
&crate::scene::view::transform::reflection_about_xy_line(p1, p2),
);
@@ -869,23 +869,23 @@ impl Transformable for Dimension {
/// f64 variant for grip positions — grips must not round UTM-scale
/// coordinates through f32 before the world-offset subtraction.
fn dv3(v: &acadrust::types::Vector3) -> glam::DVec3 {
fn dv3(v: &codec::types::Vector3) -> glam::DVec3 {
glam::DVec3::new(v.x, v.y, v.z)
}
fn set_v3(target: &mut acadrust::types::Vector3, p: DVec3) {
fn set_v3(target: &mut codec::types::Vector3, p: DVec3) {
target.x = p.x;
target.y = p.y;
target.z = p.z;
}
fn translate_v3(target: &mut acadrust::types::Vector3, d: DVec3) {
fn translate_v3(target: &mut codec::types::Vector3, d: DVec3) {
target.x += d.x;
target.y += d.y;
target.z += d.z;
}
fn apply_to_v3(target: &mut acadrust::types::Vector3, apply: &GripApply) {
fn apply_to_v3(target: &mut codec::types::Vector3, apply: &GripApply) {
match apply {
GripApply::Absolute(p) => set_v3(target, *p),
GripApply::Translate(d) => translate_v3(target, *d),
@@ -1542,9 +1542,9 @@ impl Grippable for Dimension {
// `normalized_or`, `entity_z`, `offset_snap_pts`) lives in
// `scene::convert::tessellate` and is reused by Leader / MultiLeader too.
use acadrust::entities::{MText, Text};
use acadrust::tables::DimStyle;
use acadrust::types::{Color as AcadColor, Vector3};
use codec::entities::{MText, Text};
use codec::tables::DimStyle;
use codec::types::{Color as AcadColor, Vector3};
pub(crate) fn resolved_dimension_style(
source: &DimStyle,
@@ -1703,7 +1703,7 @@ fn calculated_dimlfac(dimension: &Dimension) -> Option<f64> {
.get_record("ACAD_DIMASSOC_CALC_DIMLFAC")
.and_then(|record| {
record.values.iter().find_map(|value| match value {
acadrust::xdata::XDataValue::Real(factor) if factor.is_finite() => Some(*factor),
codec::xdata::XDataValue::Real(factor) if factor.is_finite() => Some(*factor),
_ => None,
})
})
@@ -1717,7 +1717,7 @@ pub(crate) fn dimension_in_paper_space(dimension: &Dimension, document: &CadDocu
}
document.objects.values().any(|object| {
matches!(object,
acadrust::objects::ObjectType::Layout(layout)
codec::objects::ObjectType::Layout(layout)
if layout.name != "Model" && layout.block_record == owner
)
}) || document.block_records.iter().any(|block| {
@@ -3339,7 +3339,7 @@ fn choice_value(
}
}
fn block_name(document: &CadDocument, handle: acadrust::Handle, fallback: &str) -> String {
fn block_name(document: &CadDocument, handle: codec::Handle, fallback: &str) -> String {
if handle.is_null() {
return "Closed filled".to_string();
}
@@ -3351,7 +3351,7 @@ fn block_name(document: &CadDocument, handle: acadrust::Handle, fallback: &str)
.unwrap_or_else(|| fallback.to_string())
}
fn linetype_name(document: &CadDocument, handle: acadrust::Handle) -> String {
fn linetype_name(document: &CadDocument, handle: codec::Handle) -> String {
document
.line_types
.iter()
@@ -3371,7 +3371,7 @@ fn linear_unit_label(value: i16) -> &'static str {
}
}
use acadrust::{CadDocument, EntityType, Handle};
use codec::{CadDocument, EntityType, Handle};
use crate::scene::convert::tess_util::aci_to_rgba;
use crate::scene::convert::tessellate::{
@@ -3389,10 +3389,10 @@ fn apply_dimension_breaks(
.objects
.values()
.filter_map(|object| {
let acadrust::objects::ObjectType::DataObject(object) = object else {
let codec::objects::ObjectType::DataObject(object) = object else {
return None;
};
let acadrust::objects::DataObjectData::BreakData(data) = &object.data
let codec::objects::DataObjectData::BreakData(data) = &object.data
else {
return None;
};
@@ -3487,7 +3487,7 @@ fn dimension_jog_point(dimension: &Dimension) -> Option<Vec3> {
.get_record("ACAD_DSTYLE_DIMJAG_POSITION")
.and_then(|record| {
record.values.iter().rev().find_map(|value| match value {
acadrust::xdata::XDataValue::Point3D(point) => Some(vec3_local(*point)),
codec::xdata::XDataValue::Point3D(point) => Some(vec3_local(*point)),
_ => None,
})
})
@@ -3515,14 +3515,14 @@ fn apply_dimension_jog(
})
.collect::<Vec<_>>();
let coordinates = segments.iter().map(|(_, segment)| *segment).collect::<Vec<_>>();
let Some((candidate, center)) = cadkernel::space::nearest_segment_point(
let Some((candidate, center)) = kernel::space::nearest_segment_point(
&coordinates,
requested.to_array().map(f64::from),
) else {
return;
};
let target = segments[candidate].0;
let Some(jog) = cadkernel::space::dimension_jog_points(
let Some(jog) = kernel::space::dimension_jog_points(
coordinates[candidate],
center,
normal.to_array().map(f64::from),
@@ -3571,8 +3571,8 @@ pub trait DimensionTess {
entity_color: [f32; 4],
line_weight_px: f32,
anno_scale: f32,
selected_set: &rustc_hash::FxHashSet<acadrust::Handle>,
active_viewport: Option<acadrust::Handle>,
selected_set: &rustc_hash::FxHashSet<codec::Handle>,
active_viewport: Option<codec::Handle>,
bg_color: [f32; 4],
view_aabb: Option<[f32; 4]>,
world_per_pixel: Option<f32>,
@@ -3588,8 +3588,8 @@ impl DimensionTess for Dimension {
entity_color: [f32; 4],
line_weight_px: f32,
anno_scale: f32,
selected_set: &rustc_hash::FxHashSet<acadrust::Handle>,
active_viewport: Option<acadrust::Handle>,
selected_set: &rustc_hash::FxHashSet<codec::Handle>,
active_viewport: Option<codec::Handle>,
bg_color: [f32; 4],
view_aabb: Option<[f32; 4]>,
world_per_pixel: Option<f32>,
@@ -3622,8 +3622,8 @@ fn tessellate_dimension_inner(
// LOD hints — when present, synthesised dim text routes through the
// 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>,
selected_set: &rustc_hash::FxHashSet<codec::Handle>,
active_viewport: Option<codec::Handle>,
bg_color: [f32; 4],
view_aabb: Option<[f32; 4]>,
world_per_pixel: Option<f32>,
@@ -4374,7 +4374,7 @@ fn tessellate_dimension_inner(
/// The Properties panel reads and writes these same overrides, so the renderer
/// has to consult them or an edited colour shows in the panel and nowhere else.
fn dim_color_index(
xd: &acadrust::xdata::ExtendedData,
xd: &codec::xdata::ExtendedData,
code: i16,
inherited: i16,
) -> i16 {
@@ -4406,7 +4406,7 @@ fn resolve_dim_lineweight_px(code: i16, fallback_px: f32) -> f32 {
/// resolve it to a (pattern_length, pattern) pair compatible with WireModel.
fn resolve_pattern_by_handle(
doc: &CadDocument,
handle: acadrust::types::Handle,
handle: codec::types::Handle,
scale: f32,
) -> (f32, [f32; 8]) {
if handle.is_null() {
@@ -4457,8 +4457,8 @@ fn dimtmove_leader_endpoints(
let linear = |first: Vec3, second: Vec3, definition: Vec3, axis: [f64; 2]| {
let bounds = text.break_box?;
let xy = |point: Vec3| [point.x as f64, point.y as f64];
let (leader, under_text) = cadkernel::geom2d::linear_dimension_leader(
cadkernel::geom2d::Line { start: xy(first), end: xy(second) },
let (leader, under_text) = kernel::geom2d::linear_dimension_leader(
kernel::geom2d::Line { start: xy(first), end: xy(second) },
xy(definition),
axis,
xy(txt),
@@ -4513,13 +4513,13 @@ fn dimtmove_leader_endpoints(
jogged_radial_break(chord, jog, override_center, d.jog_angle as f32);
let curves = [(chord, near), (near, far), (far, override_center)].map(
|(start, end)| {
cadkernel::geom2d::Curve::Line(cadkernel::geom2d::Line {
kernel::geom2d::Curve::Line(kernel::geom2d::Line {
start: [start.x as f64, start.y as f64],
end: [end.x as f64, end.y as f64],
})
},
);
let (_, closest) = cadkernel::geom2d::nearest_of(
let (_, closest) = kernel::geom2d::nearest_of(
curves.iter(),
[txt.x as f64, txt.y as f64],
)?;
@@ -5069,11 +5069,11 @@ fn add_segment_with_text_break(
add_segment(points, start, end);
return;
};
let segment_curve = cadkernel::geom2d::Curve::Line(cadkernel::geom2d::Line {
let segment_curve = kernel::geom2d::Curve::Line(kernel::geom2d::Line {
start: [start.x as f64, start.y as f64],
end: [end.x as f64, end.y as f64],
});
let tolerance = cadkernel::geom2d::Tolerance::new((length as f64 * 1.0e-9).max(1.0e-9));
let tolerance = kernel::geom2d::Tolerance::new((length as f64 * 1.0e-9).max(1.0e-9));
let inside = |padding: f32| {
let (sin, cos) = text_break.rotation.sin_cos();
let x_axis = Vec3::new(cos as f32, sin as f32, 0.0);
@@ -5089,13 +5089,13 @@ fn add_segment_with_text_break(
let boundary: Vec<_> = (0..4)
.map(|index| {
let next = (index + 1) % 4;
cadkernel::geom2d::Curve::Line(cadkernel::geom2d::Line {
kernel::geom2d::Curve::Line(kernel::geom2d::Line {
start: [corners[index].x as f64, corners[index].y as f64],
end: [corners[next].x as f64, corners[next].y as f64],
})
})
.collect();
cadkernel::geom2d::inside_spans(&boundary, &segment_curve, tolerance)
kernel::geom2d::inside_spans(&boundary, &segment_curve, tolerance)
};
if inside(0.0).is_empty() {
add_segment(points, start, end);
@@ -5567,7 +5567,7 @@ fn two_line_angle_frame(
arc_point: Vec3,
) -> Option<(Vec3, f32, f32)> {
let (u, v) = (a2 - a1, b2 - b1);
let (t, _) = cadkernel::geom2d::line_line(
let (t, _) = kernel::geom2d::line_line(
[a1.x as f64, a1.y as f64],
[u.x as f64, u.y as f64],
[b1.x as f64, b1.y as f64],
@@ -6125,13 +6125,13 @@ fn sample_angular_arc(vertex: Vec3, radius: f32, start: f32, sweep: f32) -> Vec<
} else {
(end, start, true)
};
let mut points: Vec<_> = cadkernel::geom2d::tessellate::arc(
let mut points: Vec<_> = kernel::geom2d::tessellate::arc(
[vertex.x as f64, vertex.y as f64],
radius as f64,
from as f64,
to as f64,
vertex.z as f64,
cadkernel::geom2d::tessellate::DEFAULT_SEGMENTS_PER_RADIAN,
kernel::geom2d::tessellate::DEFAULT_SEGMENTS_PER_RADIAN,
)
.into_iter()
.map(|point| Vec3::new(point[0] as f32, point[1] as f32, point[2] as f32))
@@ -6143,8 +6143,8 @@ fn sample_angular_arc(vertex: Vec3, radius: f32, start: f32, sweep: f32) -> Vec<
}
fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> {
let lv = |v: acadrust::types::Vector3| glam::DVec3::new(v.x, v.y, v.z);
let node = |v: acadrust::types::Vector3| (lv(v), SnapHint::Node);
let lv = |v: codec::types::Vector3| glam::DVec3::new(v.x, v.y, v.z);
let node = |v: codec::types::Vector3| (lv(v), SnapHint::Node);
match dim {
Dimension::Linear(d) => vec![
node(d.first_point),
@@ -6299,8 +6299,8 @@ fn dimension_text_entity(
// (`\f`, `\C`, `\H`, `\S`, brace scopes, …). Otherwise stay on the Text
// path — single-line dim text doesn't need the full MText pipeline.
if value_has_mtext_codes(&value) {
use acadrust::entities::dimension::AttachmentPointType as DA;
use acadrust::entities::AttachmentPoint as MA;
use codec::entities::dimension::AttachmentPointType as DA;
use codec::entities::AttachmentPoint as MA;
let attachment_point = match base.attachment_point {
DA::TopLeft => MA::TopLeft,
DA::TopCenter => MA::TopCenter,
@@ -6353,13 +6353,13 @@ fn dimension_text_entity(
}
fn attachment_to_text_align(
attach: acadrust::entities::dimension::AttachmentPointType,
attach: codec::entities::dimension::AttachmentPointType,
) -> (
acadrust::entities::text::TextHorizontalAlignment,
acadrust::entities::text::TextVerticalAlignment,
codec::entities::text::TextHorizontalAlignment,
codec::entities::text::TextVerticalAlignment,
) {
use acadrust::entities::dimension::AttachmentPointType as A;
use acadrust::entities::text::{TextHorizontalAlignment as H, TextVerticalAlignment as V};
use codec::entities::dimension::AttachmentPointType as A;
use codec::entities::text::{TextHorizontalAlignment as H, TextVerticalAlignment as V};
match attach {
A::TopLeft => (H::Left, V::Top),
A::TopCenter => (H::Center, V::Top),
@@ -6961,7 +6961,7 @@ fn dimension_tolerance_entity(
mtext.height = tol_height;
mtext.rotation = rot;
mtext.style = primary_style;
mtext.attachment_point = acadrust::entities::AttachmentPoint::MiddleCenter;
mtext.attachment_point = codec::entities::AttachmentPoint::MiddleCenter;
mtext.common = primary_common;
return Some(EntityType::MText(mtext));
}
@@ -6971,8 +6971,8 @@ fn dimension_tolerance_entity(
.with_rotation(rot);
t.style = primary_style;
t.common = primary_common;
t.horizontal_alignment = acadrust::entities::text::TextHorizontalAlignment::Center;
t.vertical_alignment = acadrust::entities::text::TextVerticalAlignment::Middle;
t.horizontal_alignment = codec::entities::text::TextHorizontalAlignment::Center;
t.vertical_alignment = codec::entities::text::TextVerticalAlignment::Middle;
Some(EntityType::Text(t))
}
@@ -8132,7 +8132,7 @@ pub(crate) fn dimension_text_grip_position(
#[cfg(test)]
mod dimtad_tests {
use super::text_on_dim_line;
use acadrust::types::Vector3;
use codec::types::Vector3;
fn v(x: f64, y: f64) -> Vector3 {
Vector3::new(x, y, 0.0)
@@ -8205,7 +8205,7 @@ mod dimtad_tests {
#[cfg(test)]
mod angular_unit_tests {
use super::format_angular_value;
use acadrust::tables::DimStyle;
use codec::tables::DimStyle;
fn style(dimaunit: i16, dimadec: i16) -> DimStyle {
let mut s = DimStyle::standard();
@@ -8241,7 +8241,7 @@ mod angular_unit_tests {
mod dim_color_override_tests {
use super::dim_color_index;
use crate::entities::dim_override::{DIMCLRD, DIMCLRE, DIMCLRT};
use acadrust::xdata::{ExtendedData, ExtendedDataRecord, XDataValue};
use codec::xdata::{ExtendedData, ExtendedDataRecord, XDataValue};
// An ACAD/DSTYLE record holding the overrides the Properties panel writes.
fn xdata(overrides: &[(i16, i16)]) -> ExtendedData {
@@ -8362,8 +8362,8 @@ mod arch_format_tests {
#[cfg(test)]
mod dimtmove_leader_tests {
use super::*;
use acadrust::entities::DimensionLinear;
use acadrust::types::Vector3;
use codec::entities::DimensionLinear;
use codec::types::Vector3;
fn v(x: f64, y: f64) -> Vector3 {
Vector3::new(x, y, 0.0)
@@ -8427,7 +8427,7 @@ mod dimtmove_leader_tests {
/// Radius dimensions draw no leader (unchanged).
#[test]
fn radius_has_no_leader() {
let r = acadrust::entities::DimensionRadius::new(v(0.0, 0.0), v(0.0, 5.0));
let r = codec::entities::DimensionRadius::new(v(0.0, 0.0), v(0.0, 5.0));
assert!(dimtmove_leader_endpoints(&Dimension::Radius(r), layout(vec3_local(v(0.0, 8.0)), 2.0)).is_none());
}
@@ -8448,7 +8448,7 @@ mod dimtmove_leader_tests {
#[cfg(test)]
mod linear_transform_tests {
use super::*;
use acadrust::entities::DimensionLinear;
use codec::entities::DimensionLinear;
use std::f64::consts::FRAC_PI_2;
/// A horizontal linear dimension measuring 10 units along X.
@@ -8685,7 +8685,7 @@ mod linear_transform_tests {
#[cfg(test)]
mod limits_format_tests {
use super::*;
use acadrust::entities::DimensionLinear;
use codec::entities::DimensionLinear;
/// A horizontal linear dimension measuring 10 units along X.
fn horizontal() -> Dimension {
@@ -8835,7 +8835,7 @@ mod limits_format_tests {
// with the vertex measures nothing; the stored angle keeps the text.
#[test]
fn degenerate_angular_dimension_reports_its_stored_angle() {
use acadrust::entities::DimensionAngular3Pt;
use codec::entities::DimensionAngular3Pt;
let mut d = DimensionAngular3Pt::default();
d.angle_vertex = Vector3::new(6.0, 4.85, 0.0);
d.first_point = d.angle_vertex;
@@ -8906,7 +8906,7 @@ mod limits_format_tests {
#[cfg(test)]
mod layout_parity_tests {
use super::*;
use acadrust::entities::{DimensionDiameter, DimensionLinear, DimensionRadius};
use codec::entities::{DimensionDiameter, DimensionLinear, DimensionRadius};
use glam::DVec3;
/// A document whose Standard style has imperial sizes and horizontal text.
@@ -9028,7 +9028,7 @@ mod layout_parity_tests {
// applied factor; zero means the dimension reads its sheet distance.
#[test]
fn negative_dimlfac_follows_the_recorded_association_factor() {
use acadrust::xdata::{ExtendedDataRecord, XDataValue};
use codec::xdata::{ExtendedDataRecord, XDataValue};
let document = CadDocument::new();
let mut source = style(&document);
source.dimlfac = -4.0;
+10 -10
View File
@@ -1,8 +1,8 @@
use acadrust::entities::Ellipse;
use cadkernel::geom2d::{
use codec::entities::Ellipse;
use kernel::geom2d::{
Curve as KernelCurve, EllipseArc as KernelEllipseArc, Tolerance, Vec2 as KernelVec2,
};
use cadkernel::space::PlanarCurve;
use kernel::space::PlanarCurve;
use crate::entities::curve::CurveSnap;
use crate::t;
@@ -228,17 +228,17 @@ fn apply_geom_prop(ell: &mut Ellipse, field: &str, value: &str) {
"normal_z" => normal[2] = v,
_ => {}
}
let Some(normal) = cadkernel::space::Vec3::from(normal).normalize() else {
let Some(normal) = kernel::space::Vec3::from(normal).normalize() else {
return;
};
let Some(major) = cadkernel::space::reorient_axis_to_plane(
let Some(major) = kernel::space::reorient_axis_to_plane(
[ell.major_axis.x, ell.major_axis.y, ell.major_axis.z],
normal.to_array(),
) else {
return;
};
ell.normal = acadrust::types::Vector3::new(normal.x, normal.y, normal.z);
ell.major_axis = acadrust::types::Vector3::new(major[0], major[1], major[2]);
ell.normal = codec::types::Vector3::new(normal.x, normal.y, normal.z);
ell.major_axis = codec::types::Vector3::new(major[0], major[1], major[2]);
}
_ => {}
}
@@ -356,14 +356,14 @@ fn apply_transform(ell: &mut Ellipse, t: &EntityTransform) {
}
impl RenderConvertible for Ellipse {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
crate::impl_entity_basics!(Ellipse);
impl crate::entities::traits::MassPropsCalc for acadrust::entities::Ellipse {
impl crate::entities::traits::MassPropsCalc for codec::entities::Ellipse {
fn mass_props(&self) -> crate::entities::traits::MassProps {
use std::f64::consts::{PI, TAU};
let e = self;
@@ -440,7 +440,7 @@ mod grip_tests {
e.minor_axis_ratio = ratio;
e
}
fn xy_len(v: &acadrust::entities::Ellipse) -> f64 {
fn xy_len(v: &codec::entities::Ellipse) -> f64 {
(v.major_axis.x * v.major_axis.x + v.major_axis.y * v.major_axis.y).sqrt()
}
+12 -12
View File
@@ -1,9 +1,9 @@
use acadrust::entities::{
use codec::entities::{
ArcAlignedTextData, ExtendedEntity, ExtendedEntityData, GeoPositionMarkerData,
PointCloudData, PointCloudExData, RemoteTextData, SectionObjectData,
};
use acadrust::types::{Handle, Transform, Vector3};
use acadrust::xdata::{ExtendedDataRecord, XDataValue};
use codec::types::{Handle, Transform, Vector3};
use codec::xdata::{ExtendedDataRecord, XDataValue};
use crate::t;
use crate::command::EntityTransform;
@@ -502,7 +502,7 @@ pub(crate) fn point_cloud_frame_lines(entity: &ExtendedEntity) -> Option<Vec<[f6
}
}
fn camera_lines(document: &acadrust::CadDocument, view_handle: Handle) -> Vec<[f64; 3]> {
fn camera_lines(document: &codec::CadDocument, view_handle: Handle) -> Vec<[f64; 3]> {
let Some(view) = document.views.iter().find(|view| view.handle == view_handle) else {
return Vec::new();
};
@@ -536,7 +536,7 @@ fn camera_lines(document: &acadrust::CadDocument, view_handle: Handle) -> Vec<[f
points
}
fn to_render(entity: &ExtendedEntity, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(entity: &ExtendedEntity, document: &codec::CadDocument) -> Option<RenderEntity> {
let (points, snaps, keys): (
Vec<[f64; 3]>,
Vec<(glam::DVec3, SnapHint)>,
@@ -1165,7 +1165,7 @@ fn point_cloud_ex_properties(data: &PointCloudExData) -> Vec<PropSection> {
}
fn semantic_properties(
properties: &[acadrust::objects::SemanticProperty],
properties: &[codec::objects::SemanticProperty],
) -> String {
properties
.iter()
@@ -1180,7 +1180,7 @@ fn semantic_properties(
}
fn reference_properties(
references: &[acadrust::objects::ProxyObjectReference],
references: &[codec::objects::ProxyObjectReference],
) -> String {
references
.iter()
@@ -2019,11 +2019,11 @@ fn apply_transform(entity: &mut ExtendedEntity, requested: &EntityTransform) {
data.radius *= scale;
data.landing_gap *= scale;
if let Some(text) = data.embedded_mtext.as_mut() {
acadrust::Entity::apply_transform(text, &transform);
codec::Entity::apply_transform(text, &transform);
}
}
ExtendedEntityData::CoordinationModel(data) => {
let mut matrix = acadrust::types::Matrix4::zero();
let mut matrix = codec::types::Matrix4::zero();
for row in 0..4 {
for column in 0..4 {
matrix.m[row][column] = data.transform[row * 4 + column];
@@ -2120,7 +2120,7 @@ fn apply_transform(entity: &mut ExtendedEntity, requested: &EntityTransform) {
}
impl RenderConvertible for ExtendedEntity {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
to_render(self, document)
}
}
@@ -2208,8 +2208,8 @@ impl Transformable for ExtendedEntity {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::EntityCommon;
use acadrust::types::Color;
use codec::entities::EntityCommon;
use codec::types::Color;
#[test]
fn reselecting_slice_keeps_its_depth() {
+6 -6
View File
@@ -1,15 +1,15 @@
//! Host-side glue for dynamic text field evaluation.
//!
//! The field language (DIESEL + AcVar), the field structure/linkage, and all
//! date math live in the reader library ([`acadrust::fields`]). OCS only
//! date math live in the reader library ([`codec::fields`]). OCS only
//! supplies the **environment** — the current clock, OS login and environment
//! variables — through [`FieldContext`]. A DWG library must stay deterministic
//! and platform-neutral, so the one genuinely system-specific bit (reading the
//! clock / OS user) lives here in the app instead.
use acadrust::fields::FieldContext;
use acadrust::types::Handle;
use acadrust::CadDocument;
use codec::fields::FieldContext;
use codec::types::Handle;
use codec::CadDocument;
/// OCS's environment provider for field evaluation.
struct OcsFieldContext;
@@ -50,7 +50,7 @@ impl FieldContext for OcsFieldContext {
/// Re-evaluate the field hosted by entity `host` (usually an MTEXT), or `None`
/// to keep the cached text. Thin wrapper over the library engine.
pub fn resolve(document: &CadDocument, host: Handle) -> Option<String> {
acadrust::fields::resolve(document, host, &OcsFieldContext)
codec::fields::resolve(document, host, &OcsFieldContext)
}
pub fn resolve_handle(
@@ -58,7 +58,7 @@ pub fn resolve_handle(
field: Handle,
host: Handle,
) -> Option<String> {
acadrust::fields::resolve_handle(document, field, host, &OcsFieldContext)
codec::fields::resolve_handle(document, field, host, &OcsFieldContext)
}
/// Seconds since the Unix epoch. Native uses the system clock; wasm uses the JS
+40 -40
View File
@@ -1,5 +1,5 @@
use acadrust::entities::{BoundaryEdge, Hatch};
use cadkernel::geom2d::{
use codec::entities::{BoundaryEdge, Hatch};
use kernel::geom2d::{
Arc as KernelArc, Curve as KernelCurve, Ellipse as KernelEllipse,
EllipseArc as KernelEllipseArc, Line as KernelLine, NurbsCurve as KernelNurbs,
Parameterization, Polyline as KernelPolyline, PolylineVertex as KernelVertex,
@@ -28,20 +28,20 @@ pub(crate) fn boundary_area(h: &Hatch) -> f64 {
path_areas.push(path_area.abs());
rings.push(crate::scene::hatch_path_ring(path).unwrap_or_default());
}
let depths = cadkernel::geom2d::ring_nesting_depths(&rings);
let depths = kernel::geom2d::ring_nesting_depths(&rings);
path_areas
.into_iter()
.zip(depths)
.filter_map(|(area, depth)| match h.style {
acadrust::entities::HatchStyleType::Normal => {
codec::entities::HatchStyleType::Normal => {
Some(if depth % 2 == 0 { area } else { -area })
}
acadrust::entities::HatchStyleType::Outer if depth <= 1 => {
codec::entities::HatchStyleType::Outer if depth <= 1 => {
Some(if depth == 0 { area } else { -area })
}
acadrust::entities::HatchStyleType::Outer => None,
acadrust::entities::HatchStyleType::Ignore if depth == 0 => Some(area),
acadrust::entities::HatchStyleType::Ignore => None,
codec::entities::HatchStyleType::Outer => None,
codec::entities::HatchStyleType::Ignore if depth == 0 => Some(area),
codec::entities::HatchStyleType::Ignore => None,
})
.sum::<f64>()
.abs()
@@ -186,7 +186,7 @@ fn boundary_centroid(h: &Hatch) -> Option<(f64, f64)> {
/// Pattern lines loaded from DXF/DWG are rendered prebaked, so their metadata
/// scale is not applied again by the renderer.
pub(crate) fn scale_pattern_geometry(
pattern: &mut acadrust::entities::HatchPattern,
pattern: &mut codec::entities::HatchPattern,
factor: f64,
) {
let (origin_x, origin_y) = (0.0, 0.0);
@@ -204,7 +204,7 @@ pub(crate) fn scale_pattern_geometry(
/// Rotate a catalog pattern about its intrinsic coordinate origin.
/// This keeps the line angle, base point and world-space offset in sync.
pub(crate) fn rotate_pattern_geometry(
pattern: &mut acadrust::entities::HatchPattern,
pattern: &mut codec::entities::HatchPattern,
angle: f64,
) {
let (sin, cos) = angle.sin_cos();
@@ -225,7 +225,7 @@ pub(crate) fn rotate_pattern_geometry(
/// Move every stored line by the same amount, preserving the pattern phase.
pub(crate) fn translate_pattern_geometry(
pattern: &mut acadrust::entities::HatchPattern,
pattern: &mut codec::entities::HatchPattern,
dx: f64,
dy: f64,
) {
@@ -238,30 +238,30 @@ pub(crate) fn translate_pattern_geometry(
/// Read the hatch background colour from its `HATCHBACKGROUNDCOLOR` extended
/// data (group 1071, packed true colour: high byte = colour method, low three =
/// RGB). `None` when unset or not a true-colour value.
pub fn background_color(h: &Hatch) -> Option<acadrust::types::Color> {
pub fn background_color(h: &Hatch) -> Option<codec::types::Color> {
let rec = h.common.extended_data.get_record("HATCHBACKGROUNDCOLOR")?;
let raw = rec.values.iter().find_map(|v| match v {
acadrust::xdata::XDataValue::Integer32(n) => Some(*n as u32),
codec::xdata::XDataValue::Integer32(n) => Some(*n as u32),
_ => None,
})?;
match (raw >> 24) & 0xFF {
// Colour-method byte: C0 = ByLayer, C1 = ByBlock, C2 = true colour,
// C3 = ACI index.
0xC0 => Some(acadrust::types::Color::ByLayer),
0xC1 => Some(acadrust::types::Color::ByBlock),
0xC2 => Some(acadrust::types::Color::Rgb {
0xC0 => Some(codec::types::Color::ByLayer),
0xC1 => Some(codec::types::Color::ByBlock),
0xC2 => Some(codec::types::Color::Rgb {
r: ((raw >> 16) & 0xFF) as u8,
g: ((raw >> 8) & 0xFF) as u8,
b: (raw & 0xFF) as u8,
}),
0xC3 => Some(acadrust::types::Color::Index((raw & 0xFF) as u8)),
0xC3 => Some(codec::types::Color::Index((raw & 0xFF) as u8)),
_ => None,
}
}
/// Pack an RGB colour into a `HATCHBACKGROUNDCOLOR` group-1071 true-colour word.
pub fn pack_background_color(c: &acadrust::types::Color) -> i32 {
use acadrust::types::Color;
pub fn pack_background_color(c: &codec::types::Color) -> i32 {
use codec::types::Color;
(match c {
Color::ByLayer => 0xC0000000u32,
Color::ByBlock => 0xC1000000u32,
@@ -275,8 +275,8 @@ pub fn pack_background_color(c: &acadrust::types::Color) -> i32 {
/// Replace (or insert) the hatch's `HATCHBACKGROUNDCOLOR` extended-data record,
/// preserving every other application's records.
pub fn set_background_color(h: &mut Hatch, c: &acadrust::types::Color) {
use acadrust::xdata::{ExtendedDataRecord, XDataValue};
pub fn set_background_color(h: &mut Hatch, c: &codec::types::Color) {
use codec::xdata::{ExtendedDataRecord, XDataValue};
const APP: &str = "HATCHBACKGROUNDCOLOR";
let kept: Vec<ExtendedDataRecord> = h
.common
@@ -298,7 +298,7 @@ pub fn set_background_color(h: &mut Hatch, c: &acadrust::types::Color) {
/// Remove the hatch's `HATCHBACKGROUNDCOLOR` extended-data record (background
/// off), preserving every other application's records.
pub fn clear_background_color(h: &mut Hatch) {
use acadrust::xdata::ExtendedDataRecord;
use codec::xdata::ExtendedDataRecord;
const APP: &str = "HATCHBACKGROUNDCOLOR";
let kept: Vec<ExtendedDataRecord> = h
.common
@@ -343,18 +343,18 @@ fn associative_property(h: &Hatch) -> Property {
fn properties(h: &Hatch) -> Vec<PropSection> {
let pattern_type = match h.pattern_type {
acadrust::entities::HatchPatternType::Predefined => "Predefined",
acadrust::entities::HatchPatternType::UserDefined => "User Defined",
acadrust::entities::HatchPatternType::Custom => "Custom",
codec::entities::HatchPatternType::Predefined => "Predefined",
codec::entities::HatchPatternType::UserDefined => "User Defined",
codec::entities::HatchPatternType::Custom => "Custom",
};
let style = match h.style {
acadrust::entities::HatchStyleType::Normal => "Normal",
acadrust::entities::HatchStyleType::Outer => "Outer",
acadrust::entities::HatchStyleType::Ignore => "Ignore",
codec::entities::HatchStyleType::Normal => "Normal",
codec::entities::HatchStyleType::Outer => "Outer",
codec::entities::HatchStyleType::Ignore => "Ignore",
};
let area = boundary_area(h);
let g = &h.gradient_color;
let default_col = acadrust::types::Color::Index(7);
let default_col = codec::types::Color::Index(7);
let grad_c1 = g.colors.first().map(|e| e.color).unwrap_or(default_col);
let grad_c2 = g.colors.get(1).map(|e| e.color).unwrap_or(default_col);
let bg_on = background_color(h).is_some();
@@ -499,7 +499,7 @@ fn properties(h: &Hatch) -> Vec<PropSection> {
));
if matches!(
h.pattern_type,
acadrust::entities::HatchPatternType::UserDefined
codec::entities::HatchPatternType::UserDefined
) {
pattern_props.push(spacing_row);
pattern_props.push(double_row);
@@ -555,7 +555,7 @@ fn properties(h: &Hatch) -> Vec<PropSection> {
}
fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
use acadrust::entities::{HatchPatternType, HatchStyleType};
use codec::entities::{HatchPatternType, HatchStyleType};
// Non-numeric fields (bool toggles / enum choices) — handled before the
// f64 parse below, which would otherwise reject their string values.
match field {
@@ -566,7 +566,7 @@ fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
if background_color(h).is_some() {
clear_background_color(h);
} else {
set_background_color(h, &acadrust::types::Color::ByLayer);
set_background_color(h, &codec::types::Color::ByLayer);
}
return;
}
@@ -611,7 +611,7 @@ fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
match requested {
HatchPatternType::UserDefined => {
// Rebuild user-defined geometry from its parameters.
h.pattern = acadrust::entities::HatchPattern::new("_USER");
h.pattern = codec::entities::HatchPattern::new("_USER");
}
HatchPatternType::Predefined => {
if let Some(entry) =
@@ -700,7 +700,7 @@ fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
h.pattern_scale = v;
if matches!(
h.pattern_type,
acadrust::entities::HatchPatternType::UserDefined
codec::entities::HatchPatternType::UserDefined
) {
h.pattern.lines.clear();
h.pattern.name = "_USER".to_string();
@@ -709,11 +709,11 @@ fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
// Origin rows are relative offsets and return to zero after commit.
"origin_x" => {
let origin = h.pattern_origin();
h.set_pattern_origin(acadrust::types::Vector2::new(origin.x + v, origin.y));
h.set_pattern_origin(codec::types::Vector2::new(origin.x + v, origin.y));
}
"origin_y" => {
let origin = h.pattern_origin();
h.set_pattern_origin(acadrust::types::Vector2::new(origin.x, origin.y + v));
h.set_pattern_origin(codec::types::Vector2::new(origin.x, origin.y + v));
}
"iso_pen_width" if v > 0.0 => {
let old = h.pattern_scale;
@@ -731,7 +731,7 @@ fn apply_transform(h: &mut Hatch, t: &EntityTransform) {
crate::scene::view::transform::apply_standard_entity_transform(h, t, |entity, p1, p2| {
// Keep boundary directions, angles, and sweeps consistent.
let t = crate::scene::view::transform::reflection_about_xy_line(p1, p2);
acadrust::entities::Entity::apply_transform(entity, &t);
codec::entities::Entity::apply_transform(entity, &t);
});
}
@@ -859,7 +859,7 @@ impl Grippable for Hatch {
GripApply::Translate(delta) => (delta.x, delta.y),
};
let origin = self.pattern_origin();
self.set_pattern_origin(acadrust::types::Vector2::new(origin.x + dx, origin.y + dy));
self.set_pattern_origin(codec::types::Vector2::new(origin.x + dx, origin.y + dy));
return;
}
id += 1;
@@ -989,7 +989,7 @@ impl Grippable for Hatch {
boundary_centroid(self),
self.pattern.lines.first().map(|line| (line.base_point.x, line.base_point.y)),
) {
self.set_pattern_origin(acadrust::types::Vector2::new(gx, gy));
self.set_pattern_origin(codec::types::Vector2::new(gx, gy));
}
}
}
@@ -1055,7 +1055,7 @@ impl FallbackTess for Hatch {
continue;
};
let local = curve
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE);
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE);
if local.len() < 2 {
continue;
}
+7 -7
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{Helix, HelixConstraint, Spline};
use acadrust::types::Vector3;
use cadkernel::space::{HelixCurve, HelixDirection, NurbsCurve3, Vec3};
use codec::entities::{Helix, HelixConstraint, Spline};
use codec::types::Vector3;
use kernel::space::{HelixCurve, HelixDirection, NurbsCurve3, Vec3};
use glam::DVec3;
use crate::command::EntityTransform;
@@ -451,7 +451,7 @@ fn apply_grip(helix: &mut Helix, grip_id: usize, apply: GripApply) {
fn apply_transform(helix: &mut Helix, transform: &EntityTransform) {
match transform {
EntityTransform::Translate(delta) => {
acadrust::Entity::translate(helix, Vector3::new(delta.x, delta.y, delta.z));
codec::Entity::translate(helix, Vector3::new(delta.x, delta.y, delta.z));
}
EntityTransform::Rotate { center, axis, angle_rad } => {
crate::scene::view::transform::apply_standard_transform(
@@ -470,14 +470,14 @@ fn apply_transform(helix: &mut Helix, transform: &EntityTransform) {
*p2,
*working_normal,
);
acadrust::Entity::apply_transform(helix, &reflection);
codec::Entity::apply_transform(helix, &reflection);
}
EntityTransform::Affine(value) => acadrust::Entity::apply_transform(helix, value),
EntityTransform::Affine(value) => codec::Entity::apply_transform(helix, value),
}
}
impl RenderConvertible for Helix {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
self.spline.to_render(document)
}
}
+17 -17
View File
@@ -1,6 +1,6 @@
use acadrust::entities::Insert;
use acadrust::types::{Matrix3, Transform, Vector3};
use acadrust::{CadDocument, EntityType, Handle};
use codec::entities::Insert;
use codec::types::{Matrix3, Transform, Vector3};
use codec::{CadDocument, EntityType, Handle};
use glam::Vec3;
use crate::command::EntityTransform;
@@ -23,7 +23,7 @@ const ATTRIBUTE_GRIP_BASE: usize = 1;
/// attribute belongs to the block definition rather than this insert, and a
/// locked position cannot be dragged. Visibility is a separate question: an
/// invisible attribute that ATTMODE 2 displays is grippable while it shows.
fn attribute_is_movable(att: &acadrust::entities::AttributeEntity) -> bool {
fn attribute_is_movable(att: &codec::entities::AttributeEntity) -> bool {
!att.flags.constant && !att.lock_position && !att.flags.locked_position
}
@@ -58,7 +58,7 @@ pub(crate) fn unscale_attribute_grip(
fn attribute_is_render_visible(
document: &CadDocument,
visibility: i16,
attribute: &acadrust::entities::AttributeEntity,
attribute: &codec::entities::AttributeEntity,
) -> bool {
let layer_visible = document
.layers
@@ -89,7 +89,7 @@ fn insert_attribute_block_scale(
fn scale_attribute_for_insert(
insert: &Insert,
attribute: &mut acadrust::entities::AttributeEntity,
attribute: &mut codec::entities::AttributeEntity,
block_scale: f64,
) {
if (block_scale - 1.0).abs() <= 1.0e-6 {
@@ -241,7 +241,7 @@ fn apply_geom_prop(ins: &mut Insert, field: &str, value: &str) {
}
let delta = ocs * ins.insert_point - old_world;
for att in &mut ins.attributes {
acadrust::Entity::translate(att, delta);
codec::Entity::translate(att, delta);
}
}
// Single Scale row shown while "Uniform scale" is checked (#427).
@@ -281,7 +281,7 @@ fn apply_grip(ins: &mut Insert, grip_id: usize, apply: GripApply) {
// world delta — otherwise a grip-drag leaves the attribute text behind (#255).
let delta = world - old_world;
for att in &mut ins.attributes {
acadrust::Entity::translate(att, delta);
codec::Entity::translate(att, delta);
}
}
@@ -296,7 +296,7 @@ fn apply_transform(ins: &mut Insert, t: &EntityTransform) {
let ux = dx / len;
let uy = dy / len;
let mirror = acadrust::types::Matrix4 {
let mirror = codec::types::Matrix4 {
m: [
[2.0 * ux * ux - 1.0, 2.0 * ux * uy, 0.0, 0.0],
[2.0 * ux * uy, 2.0 * uy * uy - 1.0, 0.0, 0.0],
@@ -311,7 +311,7 @@ fn apply_transform(ins: &mut Insert, t: &EntityTransform) {
p1.y as f64,
0.0,
)));
acadrust::Entity::apply_transform(entity, &t);
codec::Entity::apply_transform(entity, &t);
});
}
@@ -343,8 +343,8 @@ impl crate::entities::traits::FallbackTess for Insert {
}
}
pub(crate) fn insert_attribute_entities(
document: &acadrust::CadDocument,
insert: &acadrust::entities::Insert,
document: &codec::CadDocument,
insert: &codec::entities::Insert,
annotation_scale: f32,
scale_policy: crate::scene::BlockScalePolicy,
) -> Vec<EntityType> {
@@ -367,8 +367,8 @@ pub(crate) fn insert_attribute_entities(
pub(crate) fn append_insert_attribute_wires(
wires: &mut Vec<WireModel>,
document: &acadrust::CadDocument,
ins: &acadrust::entities::Insert,
document: &codec::CadDocument,
ins: &codec::entities::Insert,
insert_handle: Handle,
sel: bool,
ins_color: [f32; 4],
@@ -458,9 +458,9 @@ pub(crate) fn append_insert_attribute_wires(
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::AttributeEntity;
use acadrust::tables::Layer;
use acadrust::xdata::ExtendedDataRecord;
use codec::entities::AttributeEntity;
use codec::tables::Layer;
use codec::xdata::ExtendedDataRecord;
fn attribute(tag: &str, x: f64, y: f64) -> AttributeEntity {
let mut att = AttributeEntity::new(tag.to_string(), format!("{tag}-value"));
+17 -17
View File
@@ -1,5 +1,5 @@
use acadrust::entities::{HooklineDirection, Leader, LeaderCreationType, LeaderPathType};
use acadrust::Entity;
use codec::entities::{HooklineDirection, Leader, LeaderCreationType, LeaderPathType};
use codec::Entity;
use glam::Vec3;
use crate::command::EntityTransform;
@@ -47,8 +47,8 @@ fn draws_hookline(leader: &Leader) -> bool {
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] };
let p3f = |v: &acadrust::types::Vector3| -> [f32; 3] { [v.x as f32, v.y as f32, v.z as f32] };
let p3 = |v: &codec::types::Vector3| -> [f64; 3] { [v.x, v.y, v.z] };
let p3f = |v: &codec::types::Vector3| -> [f32; 3] { [v.x as f32, v.y as f32, v.z as f32] };
let mut points: Vec<[f64; 3]> = Vec::new();
let mut tangents: Vec<TangentGeom> = Vec::new();
@@ -169,12 +169,12 @@ fn apply_grip(leader: &mut Leader, grip_id: usize, apply: GripApply) {
let old_end = leader.vertices[n - 1];
let delta = match apply {
GripApply::Absolute(p) => acadrust::types::Vector3::new(
GripApply::Absolute(p) => codec::types::Vector3::new(
p.x as f64 - old_elbow.x,
p.y as f64 - old_elbow.y,
p.z as f64 - old_elbow.z,
),
GripApply::Translate(d) => acadrust::types::Vector3::new(
GripApply::Translate(d) => codec::types::Vector3::new(
d.x as f64,
d.y as f64,
d.z as f64,
@@ -227,7 +227,7 @@ fn apply_grip(leader: &mut Leader, grip_id: usize, apply: GripApply) {
}
}
} else if let GripApply::Translate(d) = apply {
leader.translate(acadrust::types::Vector3::new(
leader.translate(codec::types::Vector3::new(
d.x as f64,
d.y as f64,
d.z as f64,
@@ -512,7 +512,7 @@ fn apply_transform(leader: &mut Leader, t: &EntityTransform) {
// ── Trait impls ────────────────────────────────────────────────────────────
impl RenderConvertible for Leader {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
if self.vertices.is_empty() {
return None;
}
@@ -570,7 +570,7 @@ impl crate::entities::traits::Grippable for Leader {
}
let v0 = &self.vertices[grip_id];
let v1 = &self.vertices[i1];
let mid = acadrust::types::Vector3::new(
let mid = codec::types::Vector3::new(
(v0.x + v1.x) * 0.5,
(v0.y + v1.y) * 0.5,
(v0.z + v1.z) * 0.5,
@@ -608,8 +608,8 @@ impl crate::entities::traits::Transformable for Leader {
pub trait LeaderTess {
fn tessellate(
&self,
document: &acadrust::CadDocument,
handle: acadrust::Handle,
document: &codec::CadDocument,
handle: codec::Handle,
selected: bool,
entity_color: [f32; 4],
line_weight_px: f32,
@@ -620,8 +620,8 @@ pub trait LeaderTess {
impl LeaderTess for Leader {
fn tessellate(
&self,
document: &acadrust::CadDocument,
handle: acadrust::Handle,
document: &codec::CadDocument,
handle: codec::Handle,
selected: bool,
entity_color: [f32; 4],
line_weight_px: f32,
@@ -650,7 +650,7 @@ impl LeaderTess for Leader {
});
match dim_clr {
Some(idx) if idx != 0 && idx != 256 => crate::scene::convert::tess_util::aci_to_rgba(
&acadrust::types::Color::from_index(idx),
&codec::types::Color::from_index(idx),
),
_ => entity_color,
}
@@ -659,12 +659,12 @@ impl LeaderTess for Leader {
// ByBlock / Default and no override keep the resolved weight passed in.
let line_weight_px = match dov::int(xd, dov::DIMLWD) {
Some(lwd) if lwd >= 0 => crate::scene::view::render::lineweight_to_px(
&acadrust::types::LineWeight::from_value(lwd),
&codec::types::LineWeight::from_value(lwd),
),
_ => line_weight_px,
};
let name = handle.value().to_string();
let p3 = |v: &acadrust::types::Vector3| -> [f32; 3] {
let p3 = |v: &codec::types::Vector3| -> [f32; 3] {
[(v.x) as f32, (v.y) as f32, (v.z) as f32]
};
@@ -822,7 +822,7 @@ impl LeaderTess for Leader {
.unwrap_or(0);
if dimtad != 0 {
let mt = match document.get_entity(self.annotation_handle) {
Some(acadrust::entities::EntityType::MText(mt)) => {
Some(codec::entities::EntityType::MText(mt)) => {
Some((mt.extents_width, mt.insertion_point.x))
}
_ => None,
+5 -5
View File
@@ -1,7 +1,7 @@
//! Light entity display glyph (point / spot / distant).
//!
//! Lights are nonprint helper entities: the DWG reader decodes the source
//! position and aim point (see `acadrust`'s `Light`); here we synthesize a
//! position and aim point (see `opencadcodec`'s `Light`); here we synthesize a
//! wireframe glyph so the light is visible and selectable in the editor, the
//! same way AutoCAD shows a light symbol.
//!
@@ -9,8 +9,8 @@
//! 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;
use acadrust::EntityType;
use codec::entities::Light;
use codec::EntityType;
use crate::t;
use crate::command::EntityTransform;
@@ -190,7 +190,7 @@ fn build(l: &Light, r: f64) -> RenderEntity {
/// available (the caller then falls back to the fixed-world [`to_render`]).
pub fn relative_render(
entity: &EntityType,
_document: &acadrust::CadDocument,
_document: &codec::CadDocument,
wpp: Option<f32>,
) -> Option<RenderEntity> {
let EntityType::Light(l) = entity else {
@@ -201,7 +201,7 @@ pub fn relative_render(
}
impl RenderConvertible for Light {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(build(self, FIXED_WORLD))
}
}
+37 -37
View File
@@ -1,4 +1,4 @@
use acadrust::{entities::Line, Entity};
use codec::{entities::Line, Entity};
use crate::t;
use crate::command::EntityTransform;
@@ -13,7 +13,7 @@ use crate::scene::model::wire_model::TangentGeom;
fn to_render(line: &Line) -> RenderEntity {
if let Some(association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
let segments = crate::scene::centermark::render_segments(&association);
let mut points = Vec::with_capacity(segments.len() * 3);
@@ -97,7 +97,7 @@ fn to_render(line: &Line) -> RenderEntity {
fn grips(line: &Line) -> Vec<GripDef> {
if let Some(association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
let center = crate::scene::centermark::dvec(association.center);
let directions = crate::scene::centermark::mark_directions(&association);
@@ -124,7 +124,7 @@ fn grips(line: &Line) -> Vec<GripDef> {
let e = glam::DVec3::new(line.end.x, line.end.y, line.end.z);
let m = (s + e) * 0.5;
if let Some(association) =
acadrust::entities::CenterLineAssociation::read(&line.common.extended_data)
codec::entities::CenterLineAssociation::read(&line.common.extended_data)
{
let direction = (e - s).normalize_or(glam::DVec3::X);
let base_start = s + direction * association.start_extension;
@@ -142,7 +142,7 @@ fn grips(line: &Line) -> Vec<GripDef> {
fn properties(line: &Line) -> Vec<PropSection> {
if let Some(association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
use crate::scene::model::object::{PropValue, Property};
return vec![PropSection {
@@ -172,7 +172,7 @@ fn properties(line: &Line) -> Vec<PropSection> {
}];
}
if let Some(association) =
acadrust::entities::CenterLineAssociation::read(&line.common.extended_data)
codec::entities::CenterLineAssociation::read(&line.common.extended_data)
{
return vec![PropSection {
title: t!("Geometry").into_owned(),
@@ -223,7 +223,7 @@ fn properties(line: &Line) -> Vec<PropSection> {
fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
if let Some(mut association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
match field {
"centermark_show_extension" => {
@@ -256,7 +256,7 @@ fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
return;
};
if let Some(mut association) =
acadrust::entities::CenterLineAssociation::read(&line.common.extended_data)
codec::entities::CenterLineAssociation::read(&line.common.extended_data)
{
if !v.is_finite() || v < 0.0 {
return;
@@ -268,13 +268,13 @@ fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
"centerline_start_extension" => {
let delta = v - association.start_extension;
let moved = start - direction * delta;
line.start = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.start = codec::types::Vector3::new(moved.x, moved.y, moved.z);
association.start_extension = v;
}
"centerline_end_extension" => {
let delta = v - association.end_extension;
let moved = end + direction * delta;
line.end = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.end = codec::types::Vector3::new(moved.x, moved.y, moved.z);
association.end_extension = v;
}
_ => return,
@@ -299,7 +299,7 @@ fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
}
if normal.is_finite() && normal.length_squared() > 1.0e-18 {
let normal = normal.normalize();
line.normal = acadrust::types::Vector3::new(normal.x, normal.y, normal.z);
line.normal = codec::types::Vector3::new(normal.x, normal.y, normal.z);
}
}
_ => {}
@@ -308,16 +308,16 @@ fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
fn apply_grip(line: &mut Line, grip_id: usize, apply: GripApply) {
if let Some(mut association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
let center = crate::scene::centermark::dvec(association.center);
let directions = crate::scene::centermark::mark_directions(&association);
match (grip_id, apply) {
(0, GripApply::Translate(delta)) => {
let moved = center + delta;
association.center = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
association.center = codec::types::Vector3::new(moved.x, moved.y, moved.z);
let origin = crate::scene::centermark::dvec(association.plane_origin) + delta;
association.plane_origin = acadrust::types::Vector3::new(origin.x, origin.y, origin.z);
association.plane_origin = codec::types::Vector3::new(origin.x, origin.y, origin.z);
association.associated = false;
}
(id @ 1..=4, GripApply::Absolute(point)) => {
@@ -339,7 +339,7 @@ fn apply_grip(line: &mut Line, grip_id: usize, apply: GripApply) {
return;
}
if let Some(mut association) =
acadrust::entities::CenterLineAssociation::read(&line.common.extended_data)
codec::entities::CenterLineAssociation::read(&line.common.extended_data)
{
let start = glam::DVec3::new(line.start.x, line.start.y, line.start.z);
let end = glam::DVec3::new(line.end.x, line.end.y, line.end.z);
@@ -351,13 +351,13 @@ fn apply_grip(line: &mut Line, grip_id: usize, apply: GripApply) {
let delta = (point - base_start).dot(direction);
association.start_length_adjustment -= delta;
let moved = start + direction * delta;
line.start = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.start = codec::types::Vector3::new(moved.x, moved.y, moved.z);
}
(1, GripApply::Absolute(point)) => {
let delta = (point - base_end).dot(direction);
association.end_length_adjustment += delta;
let moved = end + direction * delta;
line.end = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.end = codec::types::Vector3::new(moved.x, moved.y, moved.z);
}
(2, GripApply::Translate(delta)) => {
line.start.x += delta.x;
@@ -372,13 +372,13 @@ fn apply_grip(line: &mut Line, grip_id: usize, apply: GripApply) {
let total = (base_start - point).dot(direction).max(0.0);
association.start_extension = total;
let moved = base_start - direction * association.start_extension;
line.start = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.start = codec::types::Vector3::new(moved.x, moved.y, moved.z);
}
(4, GripApply::Absolute(point)) => {
let total = (point - base_end).dot(direction).max(0.0);
association.end_extension = total;
let moved = base_end + direction * association.end_extension;
line.end = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
line.end = codec::types::Vector3::new(moved.x, moved.y, moved.z);
}
_ => return,
}
@@ -411,7 +411,7 @@ fn apply_grip(line: &mut Line, grip_id: usize, apply: GripApply) {
fn apply_plain_transform(line: &mut Line, t: &EntityTransform) {
match t {
EntityTransform::Translate(d) => {
line.translate(acadrust::types::Vector3::new(d.x, d.y, d.z));
line.translate(codec::types::Vector3::new(d.x, d.y, d.z));
}
EntityTransform::Rotate { center, axis, angle_rad } => {
crate::scene::view::transform::apply_standard_transform(line, *center, *axis, *angle_rad);
@@ -420,7 +420,7 @@ fn apply_plain_transform(line: &mut Line, t: &EntityTransform) {
crate::scene::view::transform::apply_standard_scale(line, *center, *factor);
}
EntityTransform::Mirror { p1, p2, working_normal } => {
acadrust::Entity::apply_transform(
codec::Entity::apply_transform(
line,
&crate::scene::view::transform::reflection_about_working_line(
*p1, *p2, *working_normal,
@@ -428,20 +428,20 @@ fn apply_plain_transform(line: &mut Line, t: &EntityTransform) {
);
}
EntityTransform::Affine(transform) => {
acadrust::Entity::apply_transform(line, transform);
codec::Entity::apply_transform(line, transform);
}
}
}
fn apply_transform(line: &mut Line, t: &EntityTransform) {
if let Some(mut association) =
acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data)
codec::entities::CenterMarkAssociation::read(&line.common.extended_data)
{
if let EntityTransform::Translate(delta) = t {
let center = crate::scene::centermark::dvec(association.center) + *delta;
association.center = acadrust::types::Vector3::new(center.x, center.y, center.z);
association.center = codec::types::Vector3::new(center.x, center.y, center.z);
let origin = crate::scene::centermark::dvec(association.plane_origin) + *delta;
association.plane_origin = acadrust::types::Vector3::new(origin.x, origin.y, origin.z);
association.plane_origin = codec::types::Vector3::new(origin.x, origin.y, origin.z);
association.associated = false;
crate::scene::centermark::update_carrier(line, &association);
return;
@@ -450,12 +450,12 @@ fn apply_transform(line: &mut Line, t: &EntityTransform) {
let x = crate::scene::centermark::dvec(association.plane_x).normalize_or(glam::DVec3::X);
let y = crate::scene::centermark::dvec(association.plane_y).normalize_or(glam::DVec3::Y);
let mut x_basis = Line::from_points(
acadrust::types::Vector3::new(center.x, center.y, center.z),
acadrust::types::Vector3::new(center.x + x.x, center.y + x.y, center.z + x.z),
codec::types::Vector3::new(center.x, center.y, center.z),
codec::types::Vector3::new(center.x + x.x, center.y + x.y, center.z + x.z),
);
let mut y_basis = Line::from_points(
acadrust::types::Vector3::new(center.x, center.y, center.z),
acadrust::types::Vector3::new(center.x + y.x, center.y + y.y, center.z + y.z),
codec::types::Vector3::new(center.x, center.y, center.z),
codec::types::Vector3::new(center.x + y.x, center.y + y.y, center.z + y.z),
);
apply_plain_transform(&mut x_basis, t);
apply_plain_transform(&mut y_basis, t);
@@ -463,14 +463,14 @@ fn apply_transform(line: &mut Line, t: &EntityTransform) {
let moved_x = glam::DVec3::new(x_basis.end.x, x_basis.end.y, x_basis.end.z) - moved;
let moved_y = glam::DVec3::new(y_basis.end.x, y_basis.end.y, y_basis.end.z) - moved;
let scale = ((moved_x.length() + moved_y.length()) * 0.5).max(1.0e-12);
association.center = acadrust::types::Vector3::new(moved.x, moved.y, moved.z);
association.center = codec::types::Vector3::new(moved.x, moved.y, moved.z);
association.plane_origin = association.center;
association.plane_x = acadrust::types::Vector3::new(
association.plane_x = codec::types::Vector3::new(
moved_x.normalize_or(x).x,
moved_x.normalize_or(x).y,
moved_x.normalize_or(x).z,
);
association.plane_y = acadrust::types::Vector3::new(
association.plane_y = codec::types::Vector3::new(
moved_y.normalize_or(y).x,
moved_y.normalize_or(y).y,
moved_y.normalize_or(y).z,
@@ -487,7 +487,7 @@ fn apply_transform(line: &mut Line, t: &EntityTransform) {
return;
}
if let Some(mut association) =
acadrust::entities::CenterLineAssociation::read(&line.common.extended_data)
codec::entities::CenterLineAssociation::read(&line.common.extended_data)
{
association.associated = false;
association.write(&mut line.common.extended_data);
@@ -496,7 +496,7 @@ fn apply_transform(line: &mut Line, t: &EntityTransform) {
}
impl RenderConvertible for Line {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
@@ -510,8 +510,8 @@ impl crate::entities::traits::Grippable for Line {
}
fn grip_menu(&self, grip_id: usize) -> Vec<crate::scene::model::object::GripMenuItem> {
use crate::scene::model::object::{GripMenuAction, GripMenuItem};
if acadrust::entities::CenterMarkAssociation::read(&self.common.extended_data).is_some()
|| acadrust::entities::CenterLineAssociation::read(&self.common.extended_data).is_some()
if codec::entities::CenterMarkAssociation::read(&self.common.extended_data).is_some()
|| codec::entities::CenterLineAssociation::read(&self.common.extended_data).is_some()
{
return vec![GripMenuItem {
label: "Stretch",
@@ -632,7 +632,7 @@ impl crate::entities::traits::Transformable for Line {
}
}
impl crate::entities::traits::MassPropsCalc for acadrust::entities::Line {
impl crate::entities::traits::MassPropsCalc for codec::entities::Line {
fn mass_props(&self) -> crate::entities::traits::MassProps {
let dx = self.end.x - self.start.x;
let dy = self.end.y - self.start.y;
+26 -26
View File
@@ -1,5 +1,5 @@
use acadrust::entities::{LwPolyline, LwVertex};
use cadkernel::geom2d::{
use codec::entities::{LwPolyline, LwVertex};
use kernel::geom2d::{
signed_area, Curve, Polyline, PolylineVertex, RectangleFrame, Tolerance, Vec2,
};
@@ -149,12 +149,12 @@ fn split_bulges_from_point(
/// ensures this placement originated from an arc, so straight-segment Add
/// Vertex remains two straight segments when the cursor moves off the chord.
pub(crate) fn refit_added_arc_vertex(
entity: &mut acadrust::EntityType,
entity: &mut codec::EntityType,
vertex_id: usize,
original_bulge: f64,
) {
match entity {
acadrust::EntityType::LwPolyline(polyline) => {
codec::EntityType::LwPolyline(polyline) => {
let n = polyline.vertices.len();
if vertex_id == 0 || vertex_id >= n {
return;
@@ -179,7 +179,7 @@ pub(crate) fn refit_added_arc_vertex(
polyline.vertices[prev].bulge = first.clamp(-1e6, 1e6);
polyline.vertices[vertex_id].bulge = second.clamp(-1e6, 1e6);
}
acadrust::EntityType::Polyline2D(polyline) => {
codec::EntityType::Polyline2D(polyline) => {
let n = polyline.vertices.len();
if vertex_id == 0 || vertex_id >= n {
return;
@@ -379,7 +379,7 @@ fn to_render(pline: &LwPolyline, fill_mode: bool) -> RenderEntity {
{
tgs.push(crate::entities::common::bulge_arc_to_tangent(&arc, &to_wcs, normal));
for s in arc
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
.into_iter()
.skip(1)
{
@@ -479,7 +479,7 @@ fn to_render(pline: &LwPolyline, fill_mode: bool) -> RenderEntity {
crate::entities::common::BulgeArc::from_bulge([ox0, oy0], [ox1, oy1], bulge)
{
for s in arc
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
.into_iter()
.skip(1)
{
@@ -592,10 +592,10 @@ fn centerline_metadata(
/// Split at vertex `idx`: a closed polyline re-opens there (one piece); an
/// open one splits into two (interior vertices only). `None` when invalid.
pub(crate) fn break_at_vertex(
p: &acadrust::LwPolyline,
p: &codec::LwPolyline,
idx: usize,
) -> Option<Vec<acadrust::EntityType>> {
use acadrust::EntityType;
) -> Option<Vec<codec::EntityType>> {
use codec::EntityType;
let n = p.vertices.len();
if n < 3 || idx >= n {
return None;
@@ -605,7 +605,7 @@ pub(crate) fn break_at_vertex(
verts.extend_from_slice(&p.vertices[idx..]);
verts.extend_from_slice(&p.vertices[..=idx]);
let mut out = p.clone();
out.common.handle = acadrust::Handle::NULL;
out.common.handle = codec::Handle::NULL;
out.is_closed = false;
out.vertices = verts;
return Some(vec![EntityType::LwPolyline(out)]);
@@ -614,13 +614,13 @@ pub(crate) fn break_at_vertex(
return None;
}
let mut a = p.clone();
a.common.handle = acadrust::Handle::NULL;
a.common.handle = codec::Handle::NULL;
a.vertices = p.vertices[..=idx].to_vec();
if let Some(last) = a.vertices.last_mut() {
last.bulge = 0.0;
}
let mut b = p.clone();
b.common.handle = acadrust::Handle::NULL;
b.common.handle = codec::Handle::NULL;
b.vertices = p.vertices[idx..].to_vec();
Some(vec![EntityType::LwPolyline(a), EntityType::LwPolyline(b)])
}
@@ -888,7 +888,7 @@ fn set_revision_cloud_arc_length(pline: &mut LwPolyline, requested: f64) {
pub(crate) fn rectangle_frame(
pline: &LwPolyline,
) -> Option<(RectangleFrame, cadkernel::space::Plane)> {
) -> Option<(RectangleFrame, kernel::space::Plane)> {
let planar = crate::entities::curve::lwpolyline_curve(pline)?;
let Curve::Polyline(polyline) = &planar.curve else {
return None;
@@ -1183,7 +1183,7 @@ fn edit_polyline_geometry(
let mut geometry = kernel_polyline(polyline);
if edit(&mut geometry) {
for (target, source) in polyline.vertices.iter_mut().zip(geometry.vertices) {
target.location = acadrust::types::Vector2::new(source.position[0], source.position[1]);
target.location = codec::types::Vector2::new(source.position[0], source.position[1]);
target.bulge = source.bulge;
}
}
@@ -1191,7 +1191,7 @@ fn edit_polyline_geometry(
fn move_segment_parallel(polyline: &mut LwPolyline, segment: usize, offset: f64) {
edit_polyline_geometry(polyline, |geometry| {
cadkernel::geom2d::move_polyline_segment_parallel(geometry, segment, offset)
kernel::geom2d::move_polyline_segment_parallel(geometry, segment, offset)
});
}
@@ -1200,7 +1200,7 @@ fn resize_arc_concentrically(polyline: &mut LwPolyline, segment: usize, offset:
edit_polyline_geometry(polyline, |geometry| {
geometry
.segment_arc(segment)
.is_some_and(|arc| cadkernel::geom2d::resize_polyline_arc(
.is_some_and(|arc| kernel::geom2d::resize_polyline_arc(
geometry,
segment,
arc.radius + offset,
@@ -1210,7 +1210,7 @@ fn resize_arc_concentrically(polyline: &mut LwPolyline, segment: usize, offset:
fn resize_arc_segment_radius(polyline: &mut LwPolyline, segment: usize, radius: f64) {
edit_polyline_geometry(polyline, |geometry| {
cadkernel::geom2d::resize_polyline_arc(geometry, segment, radius)
kernel::geom2d::resize_polyline_arc(geometry, segment, radius)
});
}
fn apply_transform(pline: &mut LwPolyline, t: &EntityTransform) {
@@ -1225,7 +1225,7 @@ fn apply_transform(pline: &mut LwPolyline, t: &EntityTransform) {
}
impl RenderConvertible for LwPolyline {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self, document.header.fill_mode))
}
}
@@ -1372,7 +1372,7 @@ impl crate::entities::traits::Grippable for LwPolyline {
let seg = grip_id.checked_sub(n)?;
let plane = crate::entities::curve::lwpolyline_curve(self)?.plane;
let point = Vec2::from(plane.project(point.to_array())?);
return cadkernel::geom2d::polyline_arc_radius_from_point(
return kernel::geom2d::polyline_arc_radius_from_point(
&kernel_polyline(self),
seg,
point.into(),
@@ -1383,7 +1383,7 @@ impl crate::entities::traits::Grippable for LwPolyline {
let seg = grip_id.checked_sub(n)?;
let plane = crate::entities::curve::lwpolyline_curve(self)?.plane;
let point = Vec2::from(plane.project(point.to_array())?);
return cadkernel::geom2d::polyline_segment_parallel_offset(
return kernel::geom2d::polyline_segment_parallel_offset(
&kernel_polyline(self),
seg,
point.into(),
@@ -1458,7 +1458,7 @@ impl crate::entities::traits::Grippable for LwPolyline {
if signed_distance.abs() <= Tolerance::default().linear() {
return;
}
let direction = acadrust::types::Vector2::new(axis[0], axis[1])
let direction = codec::types::Vector2::new(axis[0], axis[1])
* signed_distance.signum();
self.vertices[i0].location = self.vertices[o0].location + direction * value;
self.vertices[i1].location = self.vertices[o1].location + direction * value;
@@ -1571,7 +1571,7 @@ impl crate::entities::traits::Transformable for LwPolyline {
/// first vertex), so the relative-to-eye hatch fill keeps sub-unit precision at
/// UTM-scale coordinates — building them in absolute f32 collapsed the band into
/// a string of squares far from the origin.
pub(crate) fn wide_fills(pl: &acadrust::entities::LwPolyline) -> ([f64; 2], Vec<Vec<[f32; 2]>>) {
pub(crate) fn wide_fills(pl: &codec::entities::LwPolyline) -> ([f64; 2], Vec<Vec<[f32; 2]>>) {
// Codes 43 / 40 / 41 store the band's FULL width, and
// `polyline_segment_fill` offsets ±hw about the centreline — so halve it.
// Feeding the stored width in whole draws every wide polyline twice as wide
@@ -1616,7 +1616,7 @@ pub(crate) fn wide_fills(pl: &acadrust::entities::LwPolyline) -> ([f64; 2], Vec<
(origin, out)
}
impl crate::entities::traits::MassPropsCalc for acadrust::entities::LwPolyline {
impl crate::entities::traits::MassPropsCalc for codec::entities::LwPolyline {
fn mass_props(&self) -> crate::entities::traits::MassProps {
let p = self;
let n = p.vertices.len();
@@ -1657,8 +1657,8 @@ mod tests {
use crate::entities::traits::{Grippable, PropertyEditable};
use crate::scene::model::object::GripMenuAction;
use acadrust::entities::{LwPolyline, LwVertex};
use acadrust::{Vector2, Vector3};
use codec::entities::{LwPolyline, LwVertex};
use codec::{Vector2, Vector3};
fn make_test_lwpolyline(count: usize, constant_width: f64) -> LwPolyline {
let mut pl = LwPolyline::default();
+26 -26
View File
@@ -8,8 +8,8 @@
/// strings, block names) or placement (positions, rotations of the object
/// itself). Text formatting crosses TEXT ↔ MTEXT; the dimension style crosses
/// Dimension / Leader / Tolerance.
pub fn match_special_props(src: &acadrust::EntityType, dst: &mut acadrust::EntityType) {
use acadrust::EntityType as E;
pub fn match_special_props(src: &codec::EntityType, dst: &mut codec::EntityType) {
use codec::EntityType as E;
// Text-ish source formatting.
let text_fmt = match src {
@@ -290,8 +290,8 @@ pub struct PolylineMatchStyle {
}
impl PolylineMatchStyle {
pub fn from_entity(entity: &acadrust::EntityType) -> Option<Self> {
use acadrust::EntityType as E;
pub fn from_entity(entity: &codec::EntityType) -> Option<Self> {
use codec::EntityType as E;
match entity {
E::LwPolyline(poly) => {
@@ -329,7 +329,7 @@ impl PolylineMatchStyle {
};
Some(Self {
plinegen: poly.flags.bits()
& acadrust::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits()
& codec::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits()
!= 0,
widths,
})
@@ -338,8 +338,8 @@ impl PolylineMatchStyle {
}
}
pub fn apply_to(&self, entity: &mut acadrust::EntityType) {
use acadrust::EntityType as E;
pub fn apply_to(&self, entity: &mut codec::EntityType) {
use codec::EntityType as E;
match entity {
E::LwPolyline(poly) => {
@@ -360,13 +360,13 @@ impl PolylineMatchStyle {
}
E::Polyline2D(poly) => {
let mut bits = poly.flags.bits();
let flag = acadrust::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits();
let flag = codec::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits();
if self.plinegen {
bits |= flag;
} else {
bits &= !flag;
}
poly.flags = acadrust::entities::PolylineFlags::from_bits(bits);
poly.flags = codec::entities::PolylineFlags::from_bits(bits);
let sampled = resample_widths(&self.widths, poly.vertices.len());
let first = sampled.first().copied().unwrap_or((0.0, 0.0));
let can_use_defaults = widths_are_same(&sampled);
@@ -440,9 +440,9 @@ pub enum MatchLayerError {
/// that resolve to nothing are skipped. Lock-filtering, undo, dirty-state and
/// command-line echo stay caller-side in `handle_match_entity_layer`.
pub fn match_layer_kernel(
doc: &mut acadrust::CadDocument,
dest: &[acadrust::Handle],
src: acadrust::Handle,
doc: &mut codec::CadDocument,
dest: &[codec::Handle],
src: codec::Handle,
) -> Result<usize, MatchLayerError> {
let layer = doc
.get_entity(src)
@@ -508,8 +508,8 @@ impl Default for MatchOpts {
/// stay caller-side; lock-filtering, undo, dirty-state, selection and echo
/// stay caller-side too.
pub fn match_properties_kernel(
src: &acadrust::EntityType,
dst: &mut acadrust::EntityType,
src: &codec::EntityType,
dst: &mut codec::EntityType,
opts: &MatchOpts,
) {
if opts.copy_common {
@@ -553,19 +553,19 @@ pub fn match_properties_kernel(
mod match_layer_kernel_tests {
use super::{MatchLayerError, match_layer_kernel};
fn line_on(layer: &str) -> acadrust::EntityType {
let mut line = acadrust::entities::Line::new();
fn line_on(layer: &str) -> codec::EntityType {
let mut line = codec::entities::Line::new();
line.common.layer = layer.to_string();
acadrust::EntityType::Line(line)
codec::EntityType::Line(line)
}
fn layer_of(doc: &acadrust::CadDocument, handle: acadrust::Handle) -> String {
fn layer_of(doc: &codec::CadDocument, handle: codec::Handle) -> String {
doc.get_entity(handle).unwrap().common().layer.clone()
}
#[test]
fn copies_src_layer_onto_every_dest_and_returns_count() {
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
let src = doc.add_entity(line_on("WALLS")).unwrap();
let a = doc.add_entity(line_on("0")).unwrap();
let b = doc.add_entity(line_on("0")).unwrap();
@@ -580,7 +580,7 @@ mod match_layer_kernel_tests {
#[test]
fn missing_src_errors_and_leaves_dest_untouched() {
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
let dest = doc.add_entity(line_on("0")).unwrap();
let missing = doc.allocate_handle();
@@ -592,7 +592,7 @@ mod match_layer_kernel_tests {
#[test]
fn skips_missing_dest_handles_but_counts_the_rest() {
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
let src = doc.add_entity(line_on("WALLS")).unwrap();
let dest = doc.add_entity(line_on("0")).unwrap();
let missing = doc.allocate_handle();
@@ -607,10 +607,10 @@ mod match_layer_kernel_tests {
#[cfg(test)]
mod match_properties_kernel_tests {
use super::{MatchOpts, match_properties_kernel};
use acadrust::EntityType;
use codec::EntityType;
fn line_src() -> EntityType {
let mut line = acadrust::entities::Line::new();
let mut line = codec::entities::Line::new();
line.common.layer = "WALLS".to_string();
line.common.linetype_scale = 2.5;
line.thickness = 1.25;
@@ -618,7 +618,7 @@ mod match_properties_kernel_tests {
}
fn line_dst() -> EntityType {
let mut line = acadrust::entities::Line::new();
let mut line = codec::entities::Line::new();
line.common.layer = "0".to_string();
line.common.linetype_scale = 1.0;
line.thickness = 0.0;
@@ -643,12 +643,12 @@ mod match_properties_kernel_tests {
#[test]
fn transfers_text_style_via_special_props_flag() {
let mut src_text = acadrust::entities::Text::new();
let mut src_text = codec::entities::Text::new();
src_text.value = "SRC".into();
src_text.style = "BIG".into();
src_text.height = 5.0;
let src = EntityType::Text(src_text);
let mut dst_text = acadrust::entities::Text::new();
let mut dst_text = codec::entities::Text::new();
dst_text.value = "DST".into();
let mut dst = EntityType::Text(dst_text);
+28 -28
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{mesh::Mesh, polygon_mesh::PolygonMesh, Face3D, PolyfaceMesh};
use cadkernel::geom2d::{triangulate, Tolerance};
use cadkernel::space::{polygon, NurbsSurface3, Plane, Vec3 as KernelVec3};
use codec::entities::{mesh::Mesh, polygon_mesh::PolygonMesh, Face3D, PolyfaceMesh};
use kernel::geom2d::{triangulate, Tolerance};
use kernel::space::{polygon, NurbsSurface3, Plane, Vec3 as KernelVec3};
use glam::Vec3;
use crate::command::EntityTransform;
@@ -57,15 +57,15 @@ pub(crate) fn triangulate_planar(poly: &[[f64; 3]]) -> Vec<[f64; 3]> {
// ── Face3D ────────────────────────────────────────────────────────────────────
fn v3(v: &acadrust::types::Vector3) -> [f64; 3] {
fn v3(v: &codec::types::Vector3) -> [f64; 3] {
[v.x, v.y, v.z]
}
fn dvec3(v: &acadrust::types::Vector3) -> glam::DVec3 {
fn dvec3(v: &codec::types::Vector3) -> glam::DVec3 {
glam::DVec3::new(v.x, v.y, v.z)
}
fn v3f32(v: &acadrust::types::Vector3) -> [f32; 3] {
fn v3f32(v: &codec::types::Vector3) -> [f32; 3] {
[v.x as f32, v.y as f32, v.z as f32]
}
@@ -94,7 +94,7 @@ fn face3d_fill(corners: [[f64; 3]; 4]) -> Vec<[f64; 3]> {
}
impl RenderConvertible for Face3D {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
let p0 = v3(&self.first_corner);
let p1 = v3(&self.second_corner);
let p2 = v3(&self.third_corner);
@@ -292,7 +292,7 @@ impl Transformable for Face3D {
// ── PolygonMesh (N×M grid) ────────────────────────────────────────────────────
fn polygon_mesh_display(mesh: &PolygonMesh) -> (Vec<[f64; 3]>, usize, usize) {
use acadrust::entities::polygon_mesh::SurfaceSmoothType;
use codec::entities::polygon_mesh::SurfaceSmoothType;
let m = mesh.m_vertex_count.max(0) as usize;
let n = mesh.n_vertex_count.max(0) as usize;
@@ -354,7 +354,7 @@ fn polygon_mesh_display(mesh: &PolygonMesh) -> (Vec<[f64; 3]>, usize, usize) {
}
impl RenderConvertible for PolygonMesh {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
let (vertices, m, n) = polygon_mesh_display(self);
if m == 0 || n == 0 || vertices.len() < m * n {
return None;
@@ -439,7 +439,7 @@ impl Grippable for PolygonMesh {
impl PropertyEditable for PolygonMesh {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
use acadrust::entities::polygon_mesh::SurfaceSmoothType;
use codec::entities::polygon_mesh::SurfaceSmoothType;
let smooth = match self.smooth_type {
SurfaceSmoothType::NoSmooth => "None",
@@ -523,7 +523,7 @@ impl PropertyEditable for PolygonMesh {
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
use acadrust::entities::polygon_mesh::{PolygonMeshFlags, SurfaceSmoothType};
use codec::entities::polygon_mesh::{PolygonMeshFlags, SurfaceSmoothType};
let bool_value = |current: bool| {
if value == "toggle" {
@@ -617,7 +617,7 @@ impl Transformable for PolygonMesh {
// ── PolyfaceMesh (arbitrary faces with 1-based vertex indices) ────────────────
impl RenderConvertible for PolyfaceMesh {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
if self.vertices.is_empty() || self.faces.is_empty() {
return None;
}
@@ -668,10 +668,10 @@ impl Grippable for PolyfaceMesh {
impl PropertyEditable for PolyfaceMesh {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let smooth = match self.smooth_surface {
acadrust::entities::PolyfaceSmoothType::None => "None",
acadrust::entities::PolyfaceSmoothType::Quadratic => "Quadratic",
acadrust::entities::PolyfaceSmoothType::Cubic => "Cubic",
acadrust::entities::PolyfaceSmoothType::Bezier => "Bezier",
codec::entities::PolyfaceSmoothType::None => "None",
codec::entities::PolyfaceSmoothType::Quadratic => "Quadratic",
codec::entities::PolyfaceSmoothType::Cubic => "Cubic",
codec::entities::PolyfaceSmoothType::Bezier => "Bezier",
};
let first = self.vertices.first();
vec![
@@ -994,13 +994,13 @@ fn display_mesh(mesh: &Mesh) -> RefinedMesh {
/// Convert a closed indexed mesh entity to an exact planar-faced B-rep.
/// Open, non-manifold, non-planar, and degenerate meshes return `None` so a
/// modelling command can leave the source untouched.
pub(crate) fn closed_mesh_body(entity: &acadrust::EntityType) -> Option<cadkernel::brep::Body> {
pub(crate) fn closed_mesh_body(entity: &codec::EntityType) -> Option<kernel::brep::Body> {
match entity {
acadrust::EntityType::Mesh(mesh) => {
codec::EntityType::Mesh(mesh) => {
let base = base_refined_mesh(mesh);
cadkernel::brep::make::faceted_solid(&base.vertices, &base.faces)
kernel::brep::make::faceted_solid(&base.vertices, &base.faces)
}
acadrust::EntityType::PolygonMesh(mesh) => {
codec::EntityType::PolygonMesh(mesh) => {
if !mesh.is_closed_m() || !mesh.is_closed_n() {
return None;
}
@@ -1026,9 +1026,9 @@ pub(crate) fn closed_mesh_body(entity: &acadrust::EntityType) -> Option<cadkerne
]);
}
}
cadkernel::brep::make::faceted_solid(&vertices, &faces)
kernel::brep::make::faceted_solid(&vertices, &faces)
}
acadrust::EntityType::PolyfaceMesh(mesh) => {
codec::EntityType::PolyfaceMesh(mesh) => {
let vertices = mesh
.vertices
.iter()
@@ -1046,7 +1046,7 @@ pub(crate) fn closed_mesh_body(entity: &acadrust::EntityType) -> Option<cadkerne
(indices.len() >= 3).then_some(indices)
})
.collect::<Vec<_>>();
cadkernel::brep::make::faceted_solid(&vertices, &faces)
kernel::brep::make::faceted_solid(&vertices, &faces)
}
_ => None,
}
@@ -1191,13 +1191,13 @@ fn make_mesh_lod_set(
/// pipeline. The retained wire entity carries snaps/grips only; fill, normals,
/// depth, materials and face colours live in `MeshLodSet`.
pub(crate) fn tessellate_shaded_mesh(
entity: &acadrust::EntityType,
entity: &codec::EntityType,
color: [f32; 4],
) -> Option<crate::scene::model::mesh_model::MeshLodSet> {
use std::collections::HashSet;
match entity {
acadrust::EntityType::Mesh(mesh) => {
codec::EntityType::Mesh(mesh) => {
let display = display_mesh(mesh);
let mut edges = HashSet::new();
for face in &display.faces {
@@ -1214,7 +1214,7 @@ pub(crate) fn tessellate_shaded_mesh(
&[],
)
}
acadrust::EntityType::PolygonMesh(mesh) => {
codec::EntityType::PolygonMesh(mesh) => {
let (vertices, m, n) = polygon_mesh_display(mesh);
if m == 0 || n == 0 || vertices.len() < m.saturating_mul(n) {
return None;
@@ -1248,7 +1248,7 @@ pub(crate) fn tessellate_shaded_mesh(
&[],
)
}
acadrust::EntityType::PolyfaceMesh(mesh) => {
codec::EntityType::PolyfaceMesh(mesh) => {
let vertices: Vec<[f64; 3]> = mesh
.vertices
.iter()
@@ -1296,7 +1296,7 @@ pub(crate) fn tessellate_shaded_mesh(
}
impl RenderConvertible for Mesh {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
if self.vertices.is_empty() {
return None;
}
+66 -66
View File
@@ -1,7 +1,7 @@
use acadrust::entities::{MLine, MLineFlags, MLineSegment};
use acadrust::types::Vector3;
use cadkernel::geom2d::{intersect::line_line, Vec2};
use cadkernel::space::Plane;
use codec::entities::{MLine, MLineFlags, MLineSegment};
use codec::types::Vector3;
use kernel::geom2d::{intersect::line_line, Vec2};
use kernel::space::Plane;
use crate::command::EntityTransform;
use crate::entities::common::{edit_prop as edit, ro_prop, square_grip};
@@ -14,7 +14,7 @@ use crate::t;
/// One styled line or cap of a multiline.
pub struct MLineLine {
pub points: Vec<[f64; 3]>,
pub color: acadrust::types::Color,
pub color: codec::types::Color,
pub linetype: String,
}
@@ -38,19 +38,19 @@ pub(crate) fn rebuild_mline_geometry(mline: &mut MLine) -> bool {
let axis = points
.windows(2)
.find_map(|pair| {
(cadkernel::space::Vec3::from(pair[1]) - cadkernel::space::Vec3::from(pair[0]))
(kernel::space::Vec3::from(pair[1]) - kernel::space::Vec3::from(pair[0]))
.normalize()
.map(cadkernel::space::Vec3::to_array)
.map(kernel::space::Vec3::to_array)
})
.or_else(|| {
mline.is_closed()
.then(|| {
(cadkernel::space::Vec3::from(points[0])
- cadkernel::space::Vec3::from(points[count - 1]))
(kernel::space::Vec3::from(points[0])
- kernel::space::Vec3::from(points[count - 1]))
.normalize()
})
.flatten()
.map(cadkernel::space::Vec3::to_array)
.map(kernel::space::Vec3::to_array)
});
let Some(plane) = axis.and_then(|axis| {
Plane::orthonormal(
@@ -130,7 +130,7 @@ pub(crate) fn rebuild_mline_geometry(mline: &mut MLine) -> bool {
fn adjusted_mline_endpoint(
mline: &MLine,
style: &acadrust::objects::MLineStyle,
style: &codec::objects::MLineStyle,
vertex: usize,
point: [f64; 3],
) -> [f64; 3] {
@@ -139,7 +139,7 @@ fn adjusted_mline_endpoint(
} else {
style.end_angle
};
let Some(tangent) = cadkernel::space::Vec3::new(
let Some(tangent) = kernel::space::Vec3::new(
mline.vertices[vertex].direction.x,
mline.vertices[vertex].direction.y,
mline.vertices[vertex].direction.z,
@@ -149,23 +149,23 @@ fn adjusted_mline_endpoint(
return point;
};
let Some(normal) =
cadkernel::space::Vec3::new(mline.normal.x, mline.normal.y, mline.normal.z).normalize()
kernel::space::Vec3::new(mline.normal.x, mline.normal.y, mline.normal.z).normalize()
else {
return point;
};
let Some(transverse) = normal.cross(tangent).normalize() else {
return point;
};
let base = cadkernel::space::Vec3::new(
let base = kernel::space::Vec3::new(
mline.vertices[vertex].position.x,
mline.vertices[vertex].position.y,
mline.vertices[vertex].position.z,
);
let current = cadkernel::space::Vec3::from(point);
let current = kernel::space::Vec3::from(point);
let tangent = if angle.tan().abs() > 1.0e-9 {
tangent * ((current - base).dot(transverse) / angle.tan())
} else {
cadkernel::space::Vec3::ZERO
kernel::space::Vec3::ZERO
};
(current + tangent).to_array()
}
@@ -344,7 +344,7 @@ fn mline_element_endpoints(
mline: &MLine,
vertex: usize,
element: usize,
) -> Option<(cadkernel::space::Vec3, cadkernel::space::Vec3)> {
) -> Option<(kernel::space::Vec3, kernel::space::Vec3)> {
let next = if vertex + 1 < mline.vertices.len() {
vertex + 1
} else if mline.is_closed() {
@@ -355,12 +355,12 @@ fn mline_element_endpoints(
let point = |index: usize| {
let vertex = mline.vertices.get(index)?;
let offset = vertex.segments.get(element)?.parameters.first().copied()?;
let position = cadkernel::space::Vec3::new(
let position = kernel::space::Vec3::new(
vertex.position.x,
vertex.position.y,
vertex.position.z,
);
let miter = cadkernel::space::Vec3::new(vertex.miter.x, vertex.miter.y, vertex.miter.z);
let miter = kernel::space::Vec3::new(vertex.miter.x, vertex.miter.y, vertex.miter.z);
Some(position + miter * offset)
};
Some((point(vertex)?, point(next)?))
@@ -425,7 +425,7 @@ fn restore_shifted_mline_segment(
pub(crate) fn normalize_scripted_mline(
old: Option<&MLine>,
new: &mut MLine,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
) -> Result<(), String> {
let style = resolved_mline_style(new, document)
.ok_or_else(|| format!("MLine style {:?} does not exist", new.style_name))?;
@@ -470,9 +470,9 @@ pub(crate) fn normalize_scripted_mline(
/// Resolve a multiline into styled parallel lines in WCS.
pub fn resolved_mline_style<'a>(
m: &MLine,
document: &'a acadrust::CadDocument,
) -> Option<&'a acadrust::objects::MLineStyle> {
use acadrust::objects::ObjectType;
document: &'a codec::CadDocument,
) -> Option<&'a codec::objects::MLineStyle> {
use codec::objects::ObjectType;
m.style_handle
.and_then(|handle| match document.objects.get(&handle) {
@@ -491,23 +491,23 @@ pub fn resolved_mline_style<'a>(
})
}
pub fn mline_lines(m: &MLine, document: &acadrust::CadDocument) -> Vec<MLineLine> {
pub fn mline_lines(m: &MLine, document: &codec::CadDocument) -> Vec<MLineLine> {
mline_lines_resolved(m, resolved_mline_style(m, document))
}
pub fn mline_lines_with_style(
m: &MLine,
style: &acadrust::objects::MLineStyle,
style: &codec::objects::MLineStyle,
) -> Vec<MLineLine> {
mline_lines_resolved(m, Some(style))
}
fn mline_lines_resolved(
m: &MLine,
style: Option<&acadrust::objects::MLineStyle>,
style: Option<&codec::objects::MLineStyle>,
) -> Vec<MLineLine> {
use acadrust::entities::{MLineFlags, MLineJustification};
use acadrust::types::Color;
use codec::entities::{MLineFlags, MLineJustification};
use codec::types::Color;
if m.vertices.is_empty() {
return Vec::new();
@@ -553,8 +553,8 @@ fn mline_lines_resolved(
};
let off_pt = |vi: usize, d: f64| -> [f64; 3] {
let v = &m.vertices[vi];
(cadkernel::space::Vec3::new(v.position.x, v.position.y, v.position.z)
+ cadkernel::space::Vec3::new(v.miter.x, v.miter.y, v.miter.z) * d)
(kernel::space::Vec3::new(v.position.x, v.position.y, v.position.z)
+ kernel::space::Vec3::new(v.miter.x, v.miter.y, v.miter.z) * d)
.to_array()
};
let endpoint_pt = |vi: usize, ei: usize| -> [f64; 3] {
@@ -587,8 +587,8 @@ fn mline_lines_resolved(
} else {
off_pt(wi, elem_off(wi, ei))
};
let a = cadkernel::space::Vec3::from(a);
let b = cadkernel::space::Vec3::from(b);
let a = kernel::space::Vec3::from(a);
let b = kernel::space::Vec3::from(b);
let segment = b - a;
let len = segment.length();
let Some(direction) = segment.normalize() else {
@@ -735,33 +735,33 @@ fn semicircle_cap(
direction: [f64; 3],
start: bool,
) -> Vec<[f64; 3]> {
let first = cadkernel::space::Vec3::from(first);
let second = cadkernel::space::Vec3::from(second);
let first = kernel::space::Vec3::from(first);
let second = kernel::space::Vec3::from(second);
let center = (first + second) * 0.5;
let transverse = (first - second) * 0.5;
let radius = transverse.length();
let Some(x_axis) = transverse.normalize() else {
return Vec::new();
};
let Some(direction) = cadkernel::space::Vec3::from(direction).normalize() else {
let Some(direction) = kernel::space::Vec3::from(direction).normalize() else {
return Vec::new();
};
let y_axis = if start { -direction } else { direction };
cadkernel::space::PlanarCurve::new(
kernel::space::PlanarCurve::new(
Plane::from_axes(center.to_array(), x_axis.to_array(), y_axis.to_array()),
cadkernel::geom2d::Curve::Arc(cadkernel::geom2d::Arc {
kernel::geom2d::Curve::Arc(kernel::geom2d::Arc {
centre: [0.0, 0.0],
radius,
start_angle: 0.0,
end_angle: std::f64::consts::PI,
}),
)
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
}
pub fn mline_fill_triangles_with_style(
m: &MLine,
style: &acadrust::objects::MLineStyle,
style: &codec::objects::MLineStyle,
) -> Vec<[f64; 3]> {
if !style.flags.fill_on || m.vertices.len() < 2 || style.elements.len() < 2 {
return Vec::new();
@@ -795,9 +795,9 @@ pub fn mline_fill_triangles_with_style(
.map(|element| element.offset)
.fold(f64::NEG_INFINITY, f64::max);
let shift = match m.justification {
acadrust::entities::MLineJustification::Top => -maximum,
acadrust::entities::MLineJustification::Zero => 0.0,
acadrust::entities::MLineJustification::Bottom => -minimum,
codec::entities::MLineJustification::Top => -maximum,
codec::entities::MLineJustification::Zero => 0.0,
codec::entities::MLineJustification::Bottom => -minimum,
};
let offset_point = |vertex: usize, element: usize, endpoint: bool| -> [f64; 3] {
let item = &m.vertices[vertex];
@@ -807,11 +807,11 @@ pub fn mline_fill_triangles_with_style(
.and_then(|segment| segment.parameters.first())
.copied()
.unwrap_or((style.elements[element].offset + shift) * m.scale_factor);
let point = (cadkernel::space::Vec3::new(
let point = (kernel::space::Vec3::new(
item.position.x,
item.position.y,
item.position.z,
) + cadkernel::space::Vec3::new(item.miter.x, item.miter.y, item.miter.z) * distance)
) + kernel::space::Vec3::new(item.miter.x, item.miter.y, item.miter.z) * distance)
.to_array();
if endpoint {
adjusted_mline_endpoint(m, style, vertex, point)
@@ -830,18 +830,18 @@ pub fn mline_fill_triangles_with_style(
let next = (vertex + 1) % m.vertices.len();
let start_endpoint = !closed && vertex == 0;
let end_endpoint = !closed && next + 1 == m.vertices.len();
let low_start = cadkernel::space::Vec3::from(offset_point(
let low_start = kernel::space::Vec3::from(offset_point(
vertex,
low_index,
start_endpoint,
));
let low_end = cadkernel::space::Vec3::from(offset_point(next, low_index, end_endpoint));
let high_start = cadkernel::space::Vec3::from(offset_point(
let low_end = kernel::space::Vec3::from(offset_point(next, low_index, end_endpoint));
let high_start = kernel::space::Vec3::from(offset_point(
vertex,
high_index,
start_endpoint,
));
let high_end = cadkernel::space::Vec3::from(offset_point(next, high_index, end_endpoint));
let high_end = kernel::space::Vec3::from(offset_point(next, high_index, end_endpoint));
let low_length = low_start.distance(low_end);
let high_length = high_start.distance(high_end);
if low_length <= 1.0e-12 || high_length <= 1.0e-12 {
@@ -879,7 +879,7 @@ pub fn mline_fill_triangles_with_style(
}
impl RenderConvertible for MLine {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
if self.vertices.is_empty() {
return None;
}
@@ -941,13 +941,13 @@ impl Grippable for MLine {
return;
};
let position = match apply {
GripApply::Translate(delta) => acadrust::types::Vector3::new(
GripApply::Translate(delta) => codec::types::Vector3::new(
vertex.position.x + delta.x as f64,
vertex.position.y + delta.y as f64,
vertex.position.z + delta.z as f64,
),
GripApply::Absolute(point) => {
acadrust::types::Vector3::new(point.x as f64, point.y as f64, point.z as f64)
codec::types::Vector3::new(point.x as f64, point.y as f64, point.z as f64)
}
};
let count = self.vertices.len();
@@ -1039,7 +1039,7 @@ impl Grippable for MLine {
new_v.position.x = (v0.position.x + v1.position.x) * 0.5;
new_v.position.y = (v0.position.y + v1.position.y) * 0.5;
new_v.position.z = (v0.position.z + v1.position.z) * 0.5;
let point = cadkernel::space::Vec3::new(
let point = kernel::space::Vec3::new(
new_v.position.x,
new_v.position.y,
new_v.position.z,
@@ -1233,9 +1233,9 @@ impl Grippable for MLine {
impl PropertyEditable for MLine {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let just_str = match self.justification {
acadrust::entities::MLineJustification::Top => "Top",
acadrust::entities::MLineJustification::Zero => "Zero",
acadrust::entities::MLineJustification::Bottom => "Bottom",
codec::entities::MLineJustification::Top => "Top",
codec::entities::MLineJustification::Zero => "Zero",
codec::entities::MLineJustification::Bottom => "Bottom",
};
vec![PropSection {
title: t!("Misc").into_owned(),
@@ -1261,13 +1261,13 @@ impl PropertyEditable for MLine {
match field {
"ml_closed" => {
let closed = if value == "toggle" {
!self.flags.contains(acadrust::entities::MLineFlags::CLOSED)
!self.flags.contains(codec::entities::MLineFlags::CLOSED)
} else {
value == "true"
};
let offsets = mline_perpendicular_offsets(self);
self.flags.set(
acadrust::entities::MLineFlags::CLOSED,
codec::entities::MLineFlags::CLOSED,
closed && self.vertices.len() >= 3,
);
rebuild_mline_geometry(self);
@@ -1276,9 +1276,9 @@ impl PropertyEditable for MLine {
}
"ml_justification" => {
self.justification = match value {
"Top" => acadrust::entities::MLineJustification::Top,
"Bottom" => acadrust::entities::MLineJustification::Bottom,
_ => acadrust::entities::MLineJustification::Zero,
"Top" => codec::entities::MLineJustification::Top,
"Bottom" => codec::entities::MLineJustification::Bottom,
_ => codec::entities::MLineJustification::Zero,
};
return;
}
@@ -1329,16 +1329,16 @@ fn set_mline_scale(mline: &mut MLine, scale: f64) {
fn mline_vertex_factor(mline: &MLine, index: usize) -> f64 {
let vertex = &mline.vertices[index];
let normal = cadkernel::space::Vec3::new(mline.normal.x, mline.normal.y, mline.normal.z)
let normal = kernel::space::Vec3::new(mline.normal.x, mline.normal.y, mline.normal.z)
.normalize()
.unwrap_or(cadkernel::space::Vec3::Z);
.unwrap_or(kernel::space::Vec3::Z);
let direction =
cadkernel::space::Vec3::new(vertex.direction.x, vertex.direction.y, vertex.direction.z)
kernel::space::Vec3::new(vertex.direction.x, vertex.direction.y, vertex.direction.z)
.normalize()
.unwrap_or(cadkernel::space::Vec3::X);
let miter = cadkernel::space::Vec3::new(vertex.miter.x, vertex.miter.y, vertex.miter.z)
.unwrap_or(kernel::space::Vec3::X);
let miter = kernel::space::Vec3::new(vertex.miter.x, vertex.miter.y, vertex.miter.z)
.normalize()
.unwrap_or(cadkernel::space::Vec3::Y);
.unwrap_or(kernel::space::Vec3::Y);
miter.dot(normal.cross(direction)).abs().max(1.0e-9)
}
+12 -12
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{AttachmentPoint, DrawingDirection, MText};
use codec::entities::{AttachmentPoint, DrawingDirection, MText};
use crate::command::EntityTransform;
use crate::entities::common::{
@@ -84,11 +84,11 @@ fn drawing_dir_str(d: &DrawingDirection) -> &'static str {
/// 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.
fn display_value(t: &MText, document: &acadrust::CadDocument) -> String {
fn display_value(t: &MText, document: &codec::CadDocument) -> String {
crate::entities::field::resolve(document, t.common.handle).unwrap_or_else(|| t.value.clone())
}
pub fn glyph_boxes(t: &MText, document: &acadrust::CadDocument) -> Vec<GlyphBox> {
pub fn glyph_boxes(t: &MText, document: &codec::CadDocument) -> Vec<GlyphBox> {
let resolved_style = resolve_text_style(&t.style, document);
let attach_h_anchor: f32 = match t.attachment_point {
AttachmentPoint::TopCenter
@@ -132,7 +132,7 @@ pub fn glyph_boxes(t: &MText, document: &acadrust::CadDocument) -> Vec<GlyphBox>
line_spacing_factor: t.line_spacing_factor as f32,
exact_line_spacing: matches!(
t.line_spacing_style,
acadrust::entities::LineSpacingStyle::Exactly
codec::entities::LineSpacingStyle::Exactly
),
rectangle_height: t.rectangle_height.unwrap_or(0.0) as f32,
vertical_text: matches!(t.drawing_direction, DrawingDirection::TopToBottom)
@@ -144,7 +144,7 @@ pub fn glyph_boxes(t: &MText, document: &acadrust::CadDocument) -> Vec<GlyphBox>
layout.glyph_boxes
}
fn to_render(t: &MText, document: &acadrust::CadDocument) -> RenderEntity {
fn to_render(t: &MText, document: &codec::CadDocument) -> RenderEntity {
let resolved_style = resolve_text_style(&t.style, document);
let attach_h_anchor: f32 = match t.attachment_point {
AttachmentPoint::TopCenter
@@ -188,7 +188,7 @@ fn to_render(t: &MText, document: &acadrust::CadDocument) -> RenderEntity {
line_spacing_factor: t.line_spacing_factor as f32,
exact_line_spacing: matches!(
t.line_spacing_style,
acadrust::entities::LineSpacingStyle::Exactly
codec::entities::LineSpacingStyle::Exactly
),
rectangle_height: t.rectangle_height.unwrap_or(0.0) as f32,
vertical_text: matches!(t.drawing_direction, DrawingDirection::TopToBottom)
@@ -294,7 +294,7 @@ fn grips(t: &MText) -> Vec<GripDef> {
result
}
fn columns_str(c: &acadrust::entities::MTextColumnData) -> &'static str {
fn columns_str(c: &codec::entities::MTextColumnData) -> &'static str {
match c.column_type {
1 => "Static",
2 => "Dynamic",
@@ -384,7 +384,7 @@ fn properties(t: &MText, text_style_names: &[String]) -> Vec<PropSection> {
field: "line_space_style",
value: PropValue::Choice {
selected: match t.line_spacing_style {
acadrust::entities::LineSpacingStyle::Exactly => "Exactly",
codec::entities::LineSpacingStyle::Exactly => "Exactly",
_ => "At least",
}
.to_string(),
@@ -498,8 +498,8 @@ fn apply_geom_prop(t: &mut MText, field: &str, value: &str) {
}
"line_space_style" => {
t.line_spacing_style = match value {
"Exactly" => acadrust::entities::LineSpacingStyle::Exactly,
"At least" => acadrust::entities::LineSpacingStyle::AtLeast,
"Exactly" => codec::entities::LineSpacingStyle::Exactly,
"At least" => codec::entities::LineSpacingStyle::AtLeast,
_ => return,
};
return;
@@ -659,7 +659,7 @@ fn apply_transform(t: &mut MText, tr: &EntityTransform) {
}
impl RenderConvertible for MText {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self, document))
}
}
@@ -746,7 +746,7 @@ impl Transformable for MText {
}
}
impl crate::entities::traits::TextContent for acadrust::entities::MText {
impl crate::entities::traits::TextContent for codec::entities::MText {
fn text_content(&self) -> Option<String> {
Some(self.value.clone())
}
+48 -48
View File
@@ -1,9 +1,9 @@
use acadrust::entities::{
use codec::entities::{
BlockContentConnectionType, FlowDirectionType, LeaderContentType, LineSpacingStyle,
MultiLeader, MultiLeaderPathType, MultiLeaderPropertyOverrideFlags, TextAlignmentType,
TextAttachmentDirectionType, TextAttachmentType,
};
use cadkernel::geom2d::Transform;
use kernel::geom2d::Transform;
use crate::entities::text_support::{
layout_mtext, resolve_text_style, MTextRenderOpts, MTextVAnchor, ResolvedTextStyle,
@@ -36,7 +36,7 @@ use glam::DVec3;
/// vertically-attached leaders (picked by which side the leader comes from),
/// the left attachment otherwise. Shared by the render and the grips.
pub(crate) fn active_vertical_attachment(ml: &MultiLeader) -> TextAttachmentType {
use acadrust::entities::multileader::TextAttachmentDirectionType;
use codec::entities::multileader::TextAttachmentDirectionType;
match ml.text_attachment_direction {
TextAttachmentDirectionType::Vertical => {
let from_top = ml
@@ -95,9 +95,9 @@ pub(crate) fn catmull_rom_pts(ctrl: &[[f64; 3]], segs_per_span: u32) -> Vec<[f64
out
}
fn to_render(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(ml: &MultiLeader, document: &codec::CadDocument) -> Option<RenderEntity> {
let nan = [f64::NAN; 3];
let p3 = |v: &acadrust::types::Vector3| -> [f64; 3] { [v.x, v.y, v.z] };
let p3 = |v: &codec::types::Vector3| -> [f64; 3] { [v.x, v.y, v.z] };
let arrow_size = ml.context.arrowhead_size;
let draw_arrow = arrow_size > 0.0;
@@ -185,9 +185,9 @@ fn to_render(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<Rende
// Side-anchored on the leader-facing edge so the text reads
// outward; flips live with the leader/text side.
attach_h_anchor: match ctx.text_attachment_point {
acadrust::entities::multileader::TextAttachmentPointType::Left => 0.0,
acadrust::entities::multileader::TextAttachmentPointType::Center => 0.5,
acadrust::entities::multileader::TextAttachmentPointType::Right => 1.0,
codec::entities::multileader::TextAttachmentPointType::Left => 0.0,
codec::entities::multileader::TextAttachmentPointType::Center => 0.5,
codec::entities::multileader::TextAttachmentPointType::Right => 1.0,
},
v_anchor: mleader_v_anchor(
if text_sign >= 0.0 {
@@ -199,7 +199,7 @@ fn to_render(ml: &MultiLeader, document: &acadrust::CadDocument) -> Option<Rende
line_spacing_factor: ctx.line_spacing_factor as f32,
exact_line_spacing: matches!(
ctx.line_spacing_style,
acadrust::entities::LineSpacingStyle::Exactly
codec::entities::LineSpacingStyle::Exactly
),
rectangle_height: 0.0,
vertical_text: false,
@@ -391,12 +391,12 @@ fn text_box_geom(ml: &MultiLeader) -> ([f64; 2], [f64; 3]) {
}
let vertical = matches!(
ctx.text_flow_direction,
acadrust::entities::multileader::FlowDirectionType::Vertical
codec::entities::multileader::FlowDirectionType::Vertical
);
let h_anchor: f32 = match ctx.text_attachment_point {
acadrust::entities::multileader::TextAttachmentPointType::Left => 0.0,
acadrust::entities::multileader::TextAttachmentPointType::Center => 0.5,
acadrust::entities::multileader::TextAttachmentPointType::Right => 1.0,
codec::entities::multileader::TextAttachmentPointType::Left => 0.0,
codec::entities::multileader::TextAttachmentPointType::Center => 0.5,
codec::entities::multileader::TextAttachmentPointType::Right => 1.0,
};
let (dir_v, k) = crate::entities::text_support::flow_grip_axis(
rot,
@@ -434,7 +434,7 @@ fn text_box_geom(ml: &MultiLeader) -> ([f64; 2], [f64; 3]) {
line_spacing_factor: ctx.line_spacing_factor as f32,
exact_line_spacing: matches!(
ctx.line_spacing_style,
acadrust::entities::LineSpacingStyle::Exactly
codec::entities::LineSpacingStyle::Exactly
),
rectangle_height: 0.0,
vertical_text: vertical,
@@ -534,7 +534,7 @@ fn mleader_landing_geom(
}
fn set_mleader_text_location(ml: &mut MultiLeader, location: DVec3) {
let location = acadrust::types::Vector3::new(location.x, location.y, location.z);
let location = codec::types::Vector3::new(location.x, location.y, location.z);
ml.context.text_location = location;
ml.context.content_base_point = location;
}
@@ -704,9 +704,9 @@ fn apply_grip(
old_sign
};
ml.context.text_attachment_point = if new_sign >= 0.0 {
acadrust::entities::multileader::TextAttachmentPointType::Left
codec::entities::multileader::TextAttachmentPointType::Left
} else {
acadrust::entities::multileader::TextAttachmentPointType::Right
codec::entities::multileader::TextAttachmentPointType::Right
};
set_mleader_text_location(ml, target + axis * (new_sign * (dogleg + gap)));
@@ -872,7 +872,7 @@ fn choice(label: &str, field: &'static str, selected: &str, opts: &[&str]) -> Pr
}
}
fn hexh(h: Option<acadrust::Handle>) -> String {
fn hexh(h: Option<codec::Handle>) -> String {
match h {
Some(h) if !h.is_null() => format!("{:X}", h.value()),
_ => "(none)".to_string(),
@@ -1135,7 +1135,7 @@ fn apply_geom_prop(ml: &mut MultiLeader, field: &str, value: &str) {
for line in &mut root.lines {
line.path_type = ml.path_type;
line.override_flags.insert(
acadrust::entities::LeaderLinePropertyOverrideFlags::PATH_TYPE,
codec::entities::LeaderLinePropertyOverrideFlags::PATH_TYPE,
);
}
}
@@ -1215,7 +1215,7 @@ fn apply_geom_prop(ml: &mut MultiLeader, field: &str, value: &str) {
for line in &mut root.lines {
line.arrowhead_size = v;
line.override_flags.insert(
acadrust::entities::LeaderLinePropertyOverrideFlags::ARROWHEAD_SIZE,
codec::entities::LeaderLinePropertyOverrideFlags::ARROWHEAD_SIZE,
);
}
}
@@ -1288,7 +1288,7 @@ fn apply_geom_prop(ml: &mut MultiLeader, field: &str, value: &str) {
"block_scale" => {
if let Some(v) = f64(value) {
if v > 0.0 {
ml.block_scale = acadrust::types::Vector3::new(v, v, v);
ml.block_scale = codec::types::Vector3::new(v, v, v);
ml.context.block_content_scale = ml.block_scale;
ml.property_override_flags
.insert(MultiLeaderPropertyOverrideFlags::BLOCK_CONTENT_SCALE);
@@ -1395,7 +1395,7 @@ fn apply_geom_prop(ml: &mut MultiLeader, field: &str, value: &str) {
"text_rotation" => {
if let Some(v) = f64(value) {
ml.context.text_rotation = v.to_radians();
ml.context.text_direction = acadrust::types::Vector3::new(
ml.context.text_direction = codec::types::Vector3::new(
ml.context.text_rotation.cos(),
ml.context.text_rotation.sin(),
0.0,
@@ -1434,7 +1434,7 @@ fn place_content_after_landing(ml: &mut MultiLeader) {
(1.0, 0.0)
};
let distance = root.landing_distance.max(0.0) + ml.context.landing_gap.max(0.0);
let location = acadrust::types::Vector3::new(
let location = codec::types::Vector3::new(
root.connection_point.x + ux * distance,
root.connection_point.y + uy * distance,
root.connection_point.z,
@@ -1546,7 +1546,7 @@ fn reflect_xy_direction(dx: &mut f64, dy: &mut f64, p1: DVec3, p2: DVec3) {
// ── Trait impls ────────────────────────────────────────────────────────────
impl RenderConvertible for MultiLeader {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
to_render(self, document)
}
}
@@ -1640,7 +1640,7 @@ impl crate::entities::traits::Grippable for MultiLeader {
use crate::scene::model::object::GripMenuAction as A;
// Locate the (root, line) and vertex position owning this grip id.
let mut idx = 0usize;
let mut loc: Option<(usize, usize, acadrust::types::Vector3)> = None;
let mut loc: Option<(usize, usize, codec::types::Vector3)> = None;
'find: for (ri, root) in self.context.leader_roots.iter().enumerate() {
for (li, line) in root.lines.iter().enumerate() {
let n = line.points.len();
@@ -1675,7 +1675,7 @@ impl crate::entities::traits::Grippable for MultiLeader {
// below the picked vertex; the user drags it to the final spot.
let _ = ri;
let off = self.text_height.max(1.0) * 4.0;
let arrow = acadrust::types::Vector3::new(vpos.x, vpos.y - off, vpos.z);
let arrow = codec::types::Vector3::new(vpos.x, vpos.y - off, vpos.z);
if let Some(root) = self.context.leader_roots.last_mut() {
root.create_line(vec![arrow]);
}
@@ -1701,9 +1701,9 @@ impl crate::entities::traits::Transformable for MultiLeader {
}
pub(crate) fn block_content_insert(
document: &acadrust::CadDocument,
document: &codec::CadDocument,
ml: &MultiLeader,
) -> Option<acadrust::entities::Insert> {
) -> Option<codec::entities::Insert> {
if ml.content_type != LeaderContentType::Block || !ml.context.has_block_contents {
return None;
}
@@ -1742,7 +1742,7 @@ pub(crate) fn block_content_insert(
insertion.y -= rotated[1];
}
}
let mut insert = acadrust::entities::Insert::new(record.name.clone(), insertion);
let mut insert = codec::entities::Insert::new(record.name.clone(), insertion);
insert.set_x_scale(ml.block_scale.x);
insert.set_y_scale(ml.block_scale.y);
insert.set_z_scale(ml.block_scale.z);
@@ -1762,14 +1762,14 @@ pub(crate) fn block_content_insert(
pub trait MultiLeaderTess {
fn tessellate(
&self,
document: &acadrust::CadDocument,
handle: acadrust::Handle,
document: &codec::CadDocument,
handle: codec::Handle,
selected: bool,
entity_color: [f32; 4],
line_weight_px: f32,
anno_scale: f32,
active_viewport: Option<acadrust::Handle>,
annotation_scale_handle: Option<acadrust::Handle>,
active_viewport: Option<codec::Handle>,
annotation_scale_handle: Option<codec::Handle>,
block_cache: Option<&crate::scene::cache::block_cache::BlockCache>,
view_aabb: Option<[f32; 4]>,
world_per_pixel: Option<f32>,
@@ -1780,14 +1780,14 @@ pub trait MultiLeaderTess {
impl MultiLeaderTess for MultiLeader {
fn tessellate(
&self,
document: &acadrust::CadDocument,
handle: acadrust::Handle,
document: &codec::CadDocument,
handle: codec::Handle,
selected: bool,
entity_color: [f32; 4],
line_weight_px: f32,
anno_scale: f32,
active_viewport: Option<acadrust::Handle>,
annotation_scale_handle: Option<acadrust::Handle>,
active_viewport: Option<codec::Handle>,
annotation_scale_handle: Option<codec::Handle>,
block_cache: Option<&crate::scene::cache::block_cache::BlockCache>,
view_aabb: Option<[f32; 4]>,
world_per_pixel: Option<f32>,
@@ -1810,7 +1810,7 @@ impl MultiLeaderTess for MultiLeader {
// (ByLayer/ByBlock/Default) fall through to the entity's already-resolved
// pixel width.
let leader_lw_px = match ml.line_weight {
acadrust::types::LineWeight::Value(v) if v >= 0 => (v as f32 / 100.0) * (96.0 / 25.4),
codec::types::LineWeight::Value(v) if v >= 0 => (v as f32 / 100.0) * (96.0 / 25.4),
_ => line_weight_px,
};
// ml.line_type_handle — resolve via line_types table by handle and apply
@@ -1835,7 +1835,7 @@ impl MultiLeaderTess for MultiLeader {
let name = handle.value().to_string();
let nan = [f32::NAN; 3];
let p3 = |v: &acadrust::types::Vector3| -> [f32; 3] {
let p3 = |v: &codec::types::Vector3| -> [f32; 3] {
[(v.x) as f32, (v.y) as f32, (v.z) as f32]
};
@@ -1909,7 +1909,7 @@ impl MultiLeaderTess for MultiLeader {
let anchor = root.connection_point;
let k = context_scale_correction as f64;
text_loc_w = acadrust::types::Vector3::new(
text_loc_w = codec::types::Vector3::new(
anchor.x
+ (text_loc_w.x - anchor.x) * k,
anchor.y
@@ -2014,7 +2014,7 @@ impl MultiLeaderTess for MultiLeader {
// Vertically attached leaders meet the text edge directly.
let vertical_attach = matches!(
ml.text_attachment_direction,
acadrust::entities::multileader::TextAttachmentDirectionType::Vertical
codec::entities::multileader::TextAttachmentDirectionType::Vertical
);
if ml.enable_landing
&& ml.enable_dogleg
@@ -2107,7 +2107,7 @@ impl MultiLeaderTess for MultiLeader {
fill_tris_low: Vec::new(),
});
let host = acadrust::EntityType::MultiLeader(ml.clone());
let host = codec::EntityType::MultiLeader(ml.clone());
for block_use in crate::scene::render_graph::entity_render_block_uses(document, &host, 1.0)
.into_iter()
.filter(|block_use| {
@@ -2218,7 +2218,7 @@ impl MultiLeaderTess for MultiLeader {
// The stored text attachment point is the insertion's horizontal
// anchor within the text block (Left/Center/Right) — honour it
// instead of guessing from the leader side.
use acadrust::entities::multileader::{
use codec::entities::multileader::{
TextAttachmentDirectionType,
};
// The context's attachment point exists in every DWG version;
@@ -2258,13 +2258,13 @@ impl MultiLeaderTess for MultiLeader {
line_spacing_factor: ctx.line_spacing_factor as f32,
exact_line_spacing: matches!(
ctx.line_spacing_style,
acadrust::entities::LineSpacingStyle::Exactly
codec::entities::LineSpacingStyle::Exactly
),
rectangle_height: 0.0,
// Vertical flow (top-to-bottom) is stored per-context.
vertical_text: matches!(
ctx.text_flow_direction,
acadrust::entities::multileader::FlowDirectionType::Vertical
codec::entities::multileader::FlowDirectionType::Vertical
),
want_glyph_boxes: false,
});
@@ -2425,7 +2425,7 @@ impl MultiLeaderTess for MultiLeader {
// the leader visually continues under the text, so draw a rule the
// full text width at the attached line, in the leader's colour.
{
use acadrust::entities::multileader::TextAttachmentType as TA;
use codec::entities::multileader::TextAttachmentType as TA;
let ul_lines: Option<Vec<usize>> = match vertical_attach {
TA::BottomOfTopLineUnderlineTopLine => Some(vec![0]),
TA::BottomOfTopLineUnderlineAll => {
@@ -2636,7 +2636,7 @@ impl MultiLeaderTess for MultiLeader {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::CadDocument;
use codec::CadDocument;
#[test]
fn test_mleader_arabic_text_tessellation() {
@@ -2649,7 +2649,7 @@ mod tests {
let wires = ml.tessellate(
&doc,
acadrust::Handle::default(),
codec::Handle::default(),
false,
[1.0, 1.0, 1.0, 1.0],
1.0,
+6 -6
View File
@@ -7,16 +7,16 @@
//!
//! Co-located so adding a new variant only requires updating one file.
use acadrust::EntityType;
use codec::EntityType;
/// Mixed-case display name shown to the user in panels, tooltips, etc.
pub fn ui_name(e: &EntityType) -> &'static str {
match e {
EntityType::Point(_) => "Point",
EntityType::Line(line)
if acadrust::entities::CenterMarkAssociation::read(&line.common.extended_data).is_some() => "Center Mark",
if codec::entities::CenterMarkAssociation::read(&line.common.extended_data).is_some() => "Center Mark",
EntityType::Line(line)
if acadrust::entities::CenterLineAssociation::read(&line.common.extended_data).is_some() => "Center Line",
if codec::entities::CenterLineAssociation::read(&line.common.extended_data).is_some() => "Center Line",
EntityType::Line(_) => "Line",
EntityType::Circle(_) => "Circle",
EntityType::Arc(_) => "Arc",
@@ -69,7 +69,7 @@ pub fn ui_name(e: &EntityType) -> &'static str {
EntityType::Extended(extended)
if matches!(
extended.data,
acadrust::entities::ExtendedEntityData::SectionObject(_)
codec::entities::ExtendedEntityData::SectionObject(_)
) => "Section Plane",
EntityType::Extended(_) => "Extended Entity",
EntityType::Seqend(_) => "Seqend",
@@ -86,7 +86,7 @@ pub fn ui_name_or_class(e: &EntityType) -> String {
if let EntityType::Extended(entity) = e {
if matches!(
entity.data,
acadrust::entities::ExtendedEntityData::SectionObject(_)
codec::entities::ExtendedEntityData::SectionObject(_)
) {
return "Section Plane".to_string();
}
@@ -163,7 +163,7 @@ pub fn dxf_name(e: &EntityType) -> &'static str {
EntityType::Extended(extended)
if matches!(
extended.data,
acadrust::entities::ExtendedEntityData::SectionObject(_)
codec::entities::ExtendedEntityData::SectionObject(_)
) => "SECTIONOBJECT",
_ => "ENTITY",
}
+26 -26
View File
@@ -5,11 +5,11 @@
//! OCS is the selected entity's semantic/property view, while the evaluated
//! entity geometry continues through the normal render pipeline.
use acadrust::objects::{
use codec::objects::{
AssociativeData, BlockEvalValue, DynamicBlockData, ObjectType,
SolidHistoryNodeBase, SolidHistoryOperation,
};
use acadrust::{CadDocument, EntityType, Handle};
use codec::{CadDocument, EntityType, Handle};
use crate::scene::model::object::{PropSection, PropValue, Property};
@@ -39,16 +39,16 @@ pub fn build_cache(document: &CadDocument) -> ObjectDataCache {
ObjectType::Associative(_) => associative_objects.push(*handle),
ObjectType::GeoData(_) => geo_objects.push(*handle),
ObjectType::ClassObject(value) => match &value.data {
acadrust::objects::ClassObjectData::LightList(list) => {
codec::objects::ClassObjectData::LightList(list) => {
ordered_lights.extend(list.lights.iter().map(|entry| entry.handle));
}
acadrust::objects::ClassObjectData::Sun(_) => sun_objects.push(*handle),
acadrust::objects::ClassObjectData::RenderEnvironment(_) => {
codec::objects::ClassObjectData::Sun(_) => sun_objects.push(*handle),
codec::objects::ClassObjectData::RenderEnvironment(_) => {
render_environments.push(*handle);
}
acadrust::objects::ClassObjectData::RenderSettings(_)
| acadrust::objects::ClassObjectData::MentalRayRenderSettings(_)
| acadrust::objects::ClassObjectData::RapidRtRenderSettings(_) => {
codec::objects::ClassObjectData::RenderSettings(_)
| codec::objects::ClassObjectData::MentalRayRenderSettings(_)
| codec::objects::ClassObjectData::RapidRtRenderSettings(_) => {
render_settings.push(*handle);
}
_ => {}
@@ -219,19 +219,19 @@ fn history_base_text(base: &SolidHistoryNodeBase) -> String {
)
}
fn embedded_name(value: Option<&acadrust::entities::EmbeddedEntity>) -> &'static str {
fn embedded_name(value: Option<&codec::entities::EmbeddedEntity>) -> &'static str {
match value {
Some(acadrust::entities::EmbeddedEntity::Point(_)) => "Point",
Some(acadrust::entities::EmbeddedEntity::Line(_)) => "Line",
Some(acadrust::entities::EmbeddedEntity::Arc(_)) => "Arc",
Some(acadrust::entities::EmbeddedEntity::Circle(_)) => "Circle",
Some(acadrust::entities::EmbeddedEntity::Ellipse(_)) => "Ellipse",
Some(acadrust::entities::EmbeddedEntity::Spline(_)) => "Spline",
Some(acadrust::entities::EmbeddedEntity::LwPolyline(_)) => "Polyline",
Some(acadrust::entities::EmbeddedEntity::Region(_)) => "Region",
Some(acadrust::entities::EmbeddedEntity::Ray(_)) => "Ray",
Some(acadrust::entities::EmbeddedEntity::XLine(_)) => "XLine",
Some(acadrust::entities::EmbeddedEntity::Unknown { .. }) => "Unknown",
Some(codec::entities::EmbeddedEntity::Point(_)) => "Point",
Some(codec::entities::EmbeddedEntity::Line(_)) => "Line",
Some(codec::entities::EmbeddedEntity::Arc(_)) => "Arc",
Some(codec::entities::EmbeddedEntity::Circle(_)) => "Circle",
Some(codec::entities::EmbeddedEntity::Ellipse(_)) => "Ellipse",
Some(codec::entities::EmbeddedEntity::Spline(_)) => "Spline",
Some(codec::entities::EmbeddedEntity::LwPolyline(_)) => "Polyline",
Some(codec::entities::EmbeddedEntity::Region(_)) => "Region",
Some(codec::entities::EmbeddedEntity::Ray(_)) => "Ray",
Some(codec::entities::EmbeddedEntity::XLine(_)) => "XLine",
Some(codec::entities::EmbeddedEntity::Unknown { .. }) => "Unknown",
None => "None",
}
}
@@ -1028,9 +1028,9 @@ where
}
fn class_object_section(
data: &acadrust::objects::ClassObjectData,
data: &codec::objects::ClassObjectData,
) -> Option<PropSection> {
use acadrust::objects::ClassObjectData;
use codec::objects::ClassObjectData;
let section = match data {
ClassObjectData::Empty => return None,
@@ -2066,9 +2066,9 @@ fn class_object_section(
}
fn semantic_property_text(
value: &acadrust::objects::SemanticPropertyValue,
value: &codec::objects::SemanticPropertyValue,
) -> String {
use acadrust::objects::SemanticPropertyValue;
use codec::objects::SemanticPropertyValue;
match value {
SemanticPropertyValue::Text(value) => preview_text(value, 512),
SemanticPropertyValue::Bool(value) => value.to_string(),
@@ -2085,7 +2085,7 @@ fn semantic_property_text(
fn auxiliary_object_property(
object: &ObjectType,
) -> Option<Property> {
use acadrust::objects::DataObjectData;
use codec::objects::DataObjectData;
let (label, value) = match object {
ObjectType::TableContent(table) => (
@@ -2255,7 +2255,7 @@ fn auxiliary_object_property(
/// Drawing-level standard object data prepared on the file-open worker.
fn build_document_sections(document: &CadDocument) -> Vec<PropSection> {
use acadrust::objects::ClassObjectData;
use codec::objects::ClassObjectData;
let mut sections = vec![PropSection {
title: "Drawing".to_string(),
+3 -3
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{Ole2Frame, OleObjectType};
use codec::entities::{Ole2Frame, OleObjectType};
use crate::command::EntityTransform;
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
@@ -162,14 +162,14 @@ fn apply_transform(ole: &mut Ole2Frame, t: &EntityTransform) {
ole.lower_right_corner.y = scale(ole.lower_right_corner.y, center.y as f64);
}
EntityTransform::Affine(transform) => {
acadrust::Entity::apply_transform(ole, transform);
codec::Entity::apply_transform(ole, transform);
}
_ => {}
}
}
impl RenderConvertible for Ole2Frame {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
+11 -11
View File
@@ -1,7 +1,7 @@
use acadrust::entities::Point;
use acadrust::EntityType;
use cadkernel::geom2d::{Circle, Curve, Line};
use cadkernel::space::{curve::bezier_points, PlanarCurve, Plane, Vec3};
use codec::entities::Point;
use codec::EntityType;
use kernel::geom2d::{Circle, Curve, Line};
use kernel::space::{curve::bezier_points, PlanarCurve, Plane, Vec3};
use crate::t;
use crate::command::EntityTransform;
@@ -74,7 +74,7 @@ fn point_render(pt: &Point, pdmode: i16, s: f64) -> RenderEntity {
/// so zooming and resizing do not require retessellation.
pub fn relative_render(
entity: &EntityType,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
_wpp: Option<f32>,
) -> Option<RenderEntity> {
let EntityType::Point(pt) = entity else {
@@ -100,7 +100,7 @@ pub fn relative_world_size(pdsize: f64, wpp: f32, viewport_height_px: f32) -> f6
/// viewport scaling. A zero PDSIZE means the standard five-percent size.
pub fn relative_marker_spec(
entity: &EntityType,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
) -> Option<PointMarker> {
let EntityType::Point(pt) = entity else {
return None;
@@ -238,7 +238,7 @@ fn effective_pdmode(pt: &Point, pdmode: i16) -> i16 {
}
}
fn to_render(pt: &Point, document: &acadrust::CadDocument) -> RenderEntity {
fn to_render(pt: &Point, document: &codec::CadDocument) -> RenderEntity {
let pdmode = effective_pdmode(pt, document.header.point_display_mode);
let s = pdsize_world(document.header.point_display_size) * 0.5;
point_render(pt, pdmode, s)
@@ -299,7 +299,7 @@ fn apply_transform(pt: &mut Point, t: &EntityTransform) {
}
impl RenderConvertible for Point {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self, document))
}
}
@@ -313,13 +313,13 @@ mod tests {
fn point_on(layer: &str) -> Point {
let mut pt = Point::default();
pt.common.layer = layer.to_string();
pt.location = acadrust::types::Vector3::new(1.0, 2.0, 0.0);
pt.location = codec::types::Vector3::new(1.0, 2.0, 0.0);
pt
}
#[test]
fn definition_points_ignore_the_point_style() {
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
doc.header.point_display_mode = 34;
doc.header.point_display_size = 2.0;
@@ -340,7 +340,7 @@ mod tests {
#[test]
fn definition_points_ignore_the_point_style_at_relative_pdsize() {
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
doc.header.point_display_mode = 34;
doc.header.point_display_size = -5.0;
+34 -34
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{Polyline, Polyline2D, Polyline3D};
use codec::entities::{Polyline, Polyline2D, Polyline3D};
use crate::t;
use crate::command::EntityTransform;
@@ -10,7 +10,7 @@ use crate::entities::traits::{Grippable, PropertyEditable, Transformable, Render
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;
use cadkernel::space::{NurbsCurve3, Vec3};
use kernel::space::{NurbsCurve3, Vec3};
// ── Polyline (old-style 3D heavy polyline) ────────────────────────────────────
@@ -38,7 +38,7 @@ fn tessellate_polyline(pl: &Polyline) -> RenderEntity {
}
impl RenderConvertible for Polyline {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(tessellate_polyline(self))
}
}
@@ -178,8 +178,8 @@ impl Transformable for Polyline {
/// falls back to the stored vertices rather than drawing nothing.
pub fn drawn_vertices2d(
pl: &Polyline2D,
) -> Option<Vec<acadrust::entities::Vertex2D>> {
use acadrust::entities::polyline::VertexFlags;
) -> Option<Vec<codec::entities::Vertex2D>> {
use codec::entities::polyline::VertexFlags;
let has_fit = pl.vertices.iter().any(|v| {
v.flags.bits()
& (VertexFlags::SPLINE_VERTEX.bits() | VertexFlags::EXTRA_VERTEX.bits())
@@ -199,7 +199,7 @@ pub fn drawn_vertices2d(
fn tessellate_polyline2d(pl: &Polyline2D, fill_mode: bool) -> RenderEntity {
let filtered = drawn_vertices2d(pl);
let verts: &[acadrust::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
let verts: &[codec::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
if verts.is_empty() {
return RenderEntity {
pick_tris: Vec::new(),
@@ -221,14 +221,14 @@ fn tessellate_polyline2d(pl: &Polyline2D, fill_mode: bool) -> RenderEntity {
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| -> [f64; 3] {
let to_pt = |v: &codec::entities::Vertex2D| -> [f64; 3] {
let (wx, wy, wz) = to_wcs(v.location.x, v.location.y);
[wx, wy, wz]
};
if !fill_mode {
let continuous = pl.flags.bits()
& acadrust::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits()
& codec::entities::PolylineFlags::LINETYPE_CONTINUOUS.bits()
!= 0;
let mut boundary = crate::entities::common::wide_band_outline(
&band_verts_2d(pl),
@@ -298,7 +298,7 @@ fn tessellate_polyline2d(pl: &Polyline2D, fill_mode: bool) -> RenderEntity {
{
tgs.push(crate::entities::common::bulge_arc_to_tangent(&arc, &to_wcs, normal));
for s in arc
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
.into_iter()
.skip(1)
{
@@ -414,12 +414,12 @@ fn tessellate_polyline2d(pl: &Polyline2D, fill_mode: bool) -> RenderEntity {
/// Effective segment widths for a Polyline2D band.
fn band_verts_2d(
pl: &acadrust::entities::Polyline2D,
pl: &codec::entities::Polyline2D,
) -> Vec<([f64; 2], f64, f64, f64)> {
let default_start = pl.start_width;
let default_end = pl.end_width;
let filtered = drawn_vertices2d(pl);
let verts: &[acadrust::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
let verts: &[codec::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
verts
.iter()
.map(|v| {
@@ -453,7 +453,7 @@ fn tapered_band_verts_2d(
}
fn centerline_metadata_2d(
verts: &[acadrust::entities::Vertex2D],
verts: &[codec::entities::Vertex2D],
closed: bool,
to_wcs: &dyn Fn(f64, f64) -> (f64, f64, f64),
normal: (f64, f64, f64),
@@ -492,7 +492,7 @@ fn centerline_metadata_2d(
}
impl RenderConvertible for Polyline2D {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(tessellate_polyline2d(self, document.header.fill_mode))
}
}
@@ -610,7 +610,7 @@ impl Grippable for Polyline2D {
}
pub(crate) fn polyline2d_vertex_segment_widths(
vertex: &acadrust::entities::Vertex2D,
vertex: &codec::entities::Vertex2D,
default_start: f64,
default_end: f64,
) -> (f64, f64) {
@@ -623,7 +623,7 @@ pub(crate) fn polyline2d_vertex_segment_widths(
pub(crate) fn polyline2d_global_width(pline: &Polyline2D) -> Option<f64> {
let filtered = drawn_vertices2d(pline);
let verts: &[acadrust::entities::Vertex2D] =
let verts: &[codec::entities::Vertex2D] =
filtered.as_deref().unwrap_or(&pline.vertices);
let count = verts.len();
let seg_count = if pline.is_closed() {
@@ -834,7 +834,7 @@ impl PropertyEditable for Polyline2D {
} else {
self.flags.bits() & !128
};
self.flags = acadrust::entities::polyline::PolylineFlags::from_bits(bits);
self.flags = codec::entities::polyline::PolylineFlags::from_bits(bits);
}
_ => {}
}
@@ -900,7 +900,7 @@ pub(crate) fn polyline3d_control_vertex_count(pl: &Polyline3D) -> usize {
polyline3d_control_indices(pl).len()
}
pub(crate) fn polyline3d_controls(pl: &Polyline3D) -> Vec<acadrust::entities::Vertex3DPolyline> {
pub(crate) fn polyline3d_controls(pl: &Polyline3D) -> Vec<codec::entities::Vertex3DPolyline> {
polyline3d_control_indices(pl)
.into_iter()
.filter_map(|index| pl.vertices.get(index).cloned())
@@ -955,7 +955,7 @@ fn polyline3d_spline_samples(
} else {
NurbsCurve3::new(degree, controls.to_vec(), Vec::new(), None)?
};
let mut samples = curve.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE);
let mut samples = curve.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE);
if closed
&& samples.len() >= 2
&& Vec3::from(samples[0]).distance(Vec3::from(samples[samples.len() - 1])) <= 1.0e-9
@@ -966,7 +966,7 @@ fn polyline3d_spline_samples(
}
fn rebuild_polyline3d_fit(pl: &mut Polyline3D) -> bool {
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
use codec::entities::polyline3d::SmoothSurfaceType as SST;
let mut controls = polyline3d_controls(pl);
if pl.smooth_type == SST::None {
@@ -1009,7 +1009,7 @@ fn rebuild_polyline3d_fit(pl: &mut Polyline3D) -> bool {
.map(|vertex| vertex.layer.clone())
.unwrap_or_else(|| "0".to_string());
let curve_vertices = samples.into_iter().map(|point| {
let mut vertex = acadrust::entities::Vertex3DPolyline::from_xyz(
let mut vertex = codec::entities::Vertex3DPolyline::from_xyz(
point[0], point[1], point[2],
);
vertex.layer = vertex_layer.clone();
@@ -1023,7 +1023,7 @@ fn rebuild_polyline3d_fit(pl: &mut Polyline3D) -> bool {
}
fn tessellate_polyline3d(pl: &Polyline3D) -> RenderEntity {
let to_pt = |v: &acadrust::entities::Vertex3DPolyline| -> [f64; 3] {
let to_pt = |v: &codec::entities::Vertex3DPolyline| -> [f64; 3] {
[v.position.x, v.position.y, v.position.z]
};
@@ -1068,7 +1068,7 @@ fn tessellate_polyline3d(pl: &Polyline3D) -> RenderEntity {
}
impl RenderConvertible for Polyline3D {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(tessellate_polyline3d(self))
}
}
@@ -1104,7 +1104,7 @@ impl Grippable for Polyline3D {
}
}
if self.smooth_type
!= acadrust::entities::polyline3d::SmoothSurfaceType::None
!= codec::entities::polyline3d::SmoothSurfaceType::None
{
let _ = rebuild_polyline3d_fit(self);
}
@@ -1113,7 +1113,7 @@ impl Grippable for Polyline3D {
fn grip_menu(&self, _grip_id: usize) -> Vec<crate::scene::model::object::GripMenuItem> {
use crate::scene::model::object::{GripMenuAction, GripMenuItem};
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
use codec::entities::polyline3d::SmoothSurfaceType as SST;
let mut items = vec![
GripMenuItem {
@@ -1142,7 +1142,7 @@ impl Grippable for Polyline3D {
fn apply_grip_menu(&mut self, grip_id: usize, action: crate::scene::model::object::GripMenuAction) {
use crate::scene::model::object::GripMenuAction as A;
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
use codec::entities::polyline3d::SmoothSurfaceType as SST;
let mut controls = polyline3d_controls(self);
let n = controls.len();
@@ -1161,7 +1161,7 @@ impl Grippable for Polyline3D {
new_v.position.y = next.y;
new_v.position.z = next.z;
}
new_v.handle = acadrust::Handle::NULL;
new_v.handle = codec::Handle::NULL;
controls.push(new_v);
} else {
let i1 = (grip_id + 1) % n;
@@ -1175,7 +1175,7 @@ impl Grippable for Polyline3D {
new_v.position.x = midpoint.x;
new_v.position.y = midpoint.y;
new_v.position.z = midpoint.z;
new_v.handle = acadrust::Handle::NULL;
new_v.handle = codec::Handle::NULL;
controls.insert(grip_id + 1, new_v);
}
self.vertices = controls;
@@ -1201,7 +1201,7 @@ impl Grippable for Polyline3D {
impl PropertyEditable for Polyline3D {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
use codec::entities::polyline3d::SmoothSurfaceType as SST;
let control_indices = polyline3d_control_indices(self);
let n = control_indices.len();
let vi = if n == 0 {
@@ -1297,13 +1297,13 @@ impl PropertyEditable for Polyline3D {
self.open();
}
if self.smooth_type
!= acadrust::entities::polyline3d::SmoothSurfaceType::None
!= codec::entities::polyline3d::SmoothSurfaceType::None
{
let _ = rebuild_polyline3d_fit(self);
}
}
"pl3_smooth" => {
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
use codec::entities::polyline3d::SmoothSurfaceType as SST;
let next = match value {
"None" => SST::None,
"Quadratic" => SST::QuadraticBSpline,
@@ -1372,13 +1372,13 @@ impl Transformable for Polyline3D {
/// Solid-fill bands for a wide Polyline2D, plus the `world_origin` they are
/// relative to (the first vertex). See `lwpolyline::wide_fills` — offsets are
/// f32 from `origin` so the band stays precise at UTM-scale coordinates.
pub(crate) fn wide_fills(pl: &acadrust::entities::Polyline2D) -> ([f64; 2], Vec<Vec<[f32; 2]>>) {
pub(crate) fn wide_fills(pl: &codec::entities::Polyline2D) -> ([f64; 2], Vec<Vec<[f32; 2]>>) {
// The stored widths are the band's FULL width and `polyline_segment_fill`
// offsets ±hw about the centreline — halve them. See `lwpolyline::wide_fills`.
let hw_default_start = pl.start_width as f32 * 0.5;
let hw_default_end = pl.end_width as f32 * 0.5;
let filtered = drawn_vertices2d(pl);
let verts: &[acadrust::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
let verts: &[codec::entities::Vertex2D] = filtered.as_deref().unwrap_or(&pl.vertices);
let n = verts.len();
if n < 2 {
return ([0.0; 2], vec![]);
@@ -1423,8 +1423,8 @@ pub(crate) fn wide_fills(pl: &acadrust::entities::Polyline2D) -> ([f64; 2], Vec<
mod tests {
use super::*;
use crate::entities::traits::PropertyEditable;
use acadrust::entities::{Polyline2D, Vertex2D};
use acadrust::Vector3;
use codec::entities::{Polyline2D, Vertex2D};
use codec::Vector3;
fn make_test_polyline2d(count: usize, start_w: f64, end_w: f64) -> Polyline2D {
let mut pl = Polyline2D::default();
+39 -39
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{RasterImage, Wipeout};
use codec::entities::{RasterImage, Wipeout};
use crate::t;
use crate::command::EntityTransform;
@@ -24,9 +24,9 @@ use crate::scene::text::lff;
/// p2 = origin + U*W + V*H
/// p3 = origin + V*H
fn image_corners(
origin: &acadrust::types::Vector3,
u: &acadrust::types::Vector3,
v: &acadrust::types::Vector3,
origin: &codec::types::Vector3,
u: &codec::types::Vector3,
v: &codec::types::Vector3,
w: f64,
h: f64,
) -> [[f64; 3]; 4] {
@@ -72,7 +72,7 @@ fn reflect_vec3(vx: &mut f64, vy: &mut f64, ax: f64, ay: f64, len2: f64) {
// ── RasterImage ───────────────────────────────────────────────────────────────
impl RenderConvertible for RasterImage {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
let corners = image_corners(
&self.insertion_point,
&self.u_vector,
@@ -106,7 +106,7 @@ impl RenderConvertible for RasterImage {
let pts = if self.clipping_enabled {
let cb = &self.clip_boundary;
match cb.clip_type {
acadrust::entities::ClipType::Polygonal if cb.vertices.len() >= 3 => {
codec::entities::ClipType::Polygonal if cb.vertices.len() >= 3 => {
let mut poly: Vec<[f64; 3]> =
cb.vertices.iter().map(|v| px_to_world(v.x, ih - v.y)).collect();
if let Some(&first) = poly.first() {
@@ -114,7 +114,7 @@ impl RenderConvertible for RasterImage {
}
poly
}
acadrust::entities::ClipType::Rectangular if cb.vertices.len() >= 2 => {
codec::entities::ClipType::Rectangular if cb.vertices.len() >= 2 => {
let v0 = &cb.vertices[0];
let v1 = &cb.vertices[1];
let (xa, xb) = (v0.x.min(v1.x), v0.x.max(v1.x));
@@ -288,11 +288,11 @@ impl PropertyEditable for RasterImage {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let rotation_deg = self.u_vector.y.atan2(self.u_vector.x).to_degrees();
let scale = self.u_vector.length();
let show_image = self.flags.contains(acadrust::entities::ImageDisplayFlags::SHOW_IMAGE);
let show_image = self.flags.contains(codec::entities::ImageDisplayFlags::SHOW_IMAGE);
let show_clipped = self
.flags
.contains(acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY);
let clip_inverted = self.clip_boundary.clip_mode == acadrust::entities::ClipMode::Inside;
.contains(codec::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY);
let clip_inverted = self.clip_boundary.clip_mode == codec::entities::ClipMode::Inside;
let transparency = self.common.transparency.to_string();
vec![
PropSection {
@@ -348,7 +348,7 @@ impl PropertyEditable for RasterImage {
match field {
"ri_show_image" => {
let on = if value == "toggle" {
!self.flags.contains(acadrust::entities::ImageDisplayFlags::SHOW_IMAGE)
!self.flags.contains(codec::entities::ImageDisplayFlags::SHOW_IMAGE)
} else {
value == "true"
};
@@ -359,27 +359,27 @@ impl PropertyEditable for RasterImage {
let on = if value == "toggle" {
!self
.flags
.contains(acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY)
.contains(codec::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY)
} else {
value == "true"
};
if on {
self.flags |= acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
self.flags |= codec::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
} else {
self.flags &= !acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
self.flags &= !codec::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
}
return;
}
"ri_clip_inverted" => {
let on = if value == "toggle" {
self.clip_boundary.clip_mode != acadrust::entities::ClipMode::Inside
self.clip_boundary.clip_mode != codec::entities::ClipMode::Inside
} else {
value == "true"
};
self.clip_boundary.clip_mode = if on {
acadrust::entities::ClipMode::Inside
codec::entities::ClipMode::Inside
} else {
acadrust::entities::ClipMode::Outside
codec::entities::ClipMode::Outside
};
return;
}
@@ -427,18 +427,18 @@ fn wipeout_is_polygonal(wipeout: &Wipeout) -> bool {
&& wipeout.clip_boundary_vertices.len() >= 3
&& matches!(
wipeout.clip_type,
acadrust::entities::WipeoutClipType::Polygonal
codec::entities::WipeoutClipType::Polygonal
)
}
fn wipeout_clip_to_world(wipeout: &Wipeout, point: &acadrust::types::Vector2) -> [f64; 3] {
fn wipeout_clip_to_world(wipeout: &Wipeout, point: &codec::types::Vector2) -> [f64; 3] {
let x = point.x + wipeout.size.x * 0.5;
let y = wipeout.size.y * 0.5 - point.y;
wipeout_plane(wipeout).point_at([x, y])
}
fn wipeout_plane(wipeout: &Wipeout) -> cadkernel::space::Plane {
cadkernel::space::Plane::from_axes(
fn wipeout_plane(wipeout: &Wipeout) -> kernel::space::Plane {
kernel::space::Plane::from_axes(
[
wipeout.insertion_point.x,
wipeout.insertion_point.y,
@@ -476,7 +476,7 @@ fn wipeout_boundary(wipeout: &Wipeout) -> Vec<[f64; 3]> {
}
}
fn wipeout_axis_length(axis: &acadrust::types::Vector3, size: f64) -> f64 {
fn wipeout_axis_length(axis: &codec::types::Vector3, size: f64) -> f64 {
(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z).sqrt() * size.abs()
}
@@ -485,7 +485,7 @@ fn wipeout_pick_rings(wipeout: &Wipeout) -> Vec<Vec<[f64; 3]>> {
if wipeout_is_polygonal(wipeout)
&& matches!(
wipeout.clip_mode,
acadrust::entities::WipeoutClipMode::Inside
codec::entities::WipeoutClipMode::Inside
)
{
vec![
@@ -504,16 +504,16 @@ fn wipeout_pick_rings(wipeout: &Wipeout) -> Vec<Vec<[f64; 3]>> {
}
}
fn wipeout_world_to_clip(wipeout: &Wipeout, world: [f64; 3]) -> Option<acadrust::types::Vector2> {
fn wipeout_world_to_clip(wipeout: &Wipeout, world: [f64; 3]) -> Option<codec::types::Vector2> {
let [x, y] = wipeout_plane(wipeout).project(world)?;
Some(acadrust::types::Vector2::new(
Some(codec::types::Vector2::new(
x - wipeout.size.x * 0.5,
wipeout.size.y * 0.5 - y,
))
}
impl RenderConvertible for Wipeout {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
let boundary = wipeout_boundary(self);
let mut pts = boundary.clone();
if let Some(&first) = pts.first() {
@@ -521,9 +521,9 @@ impl RenderConvertible for Wipeout {
}
Some(RenderEntity {
pick_tris: cadkernel::space::polygon::triangulate_rings(
pick_tris: kernel::space::polygon::triangulate_rings(
&wipeout_pick_rings(self),
cadkernel::geom2d::Tolerance::default(),
kernel::geom2d::Tolerance::default(),
),
object: RenderObject::Lines(pts),
snap_pts: boundary
@@ -602,7 +602,7 @@ impl Grippable for Wipeout {
if u_hat == glam::DVec3::ZERO || v_hat == glam::DVec3::ZERO {
return;
}
let resize_plane = cadkernel::space::Plane::from_axes(
let resize_plane = kernel::space::Plane::from_axes(
[0.0; 3],
u_hat.to_array(),
v_hat.to_array(),
@@ -649,19 +649,19 @@ impl Grippable for Wipeout {
_ => return,
};
if width.abs() > 1e-9 && height.abs() > 1e-9 {
self.insertion_point = acadrust::types::Vector3::new(
self.insertion_point = codec::types::Vector3::new(
insertion.x,
insertion.y,
insertion.z,
);
let sx = self.size.x.abs().max(1e-9);
let sy = self.size.y.abs().max(1e-9);
self.u_vector = acadrust::types::Vector3::new(
self.u_vector = codec::types::Vector3::new(
u_hat.x * width / sx,
u_hat.y * width / sx,
u_hat.z * width / sx,
);
self.v_vector = acadrust::types::Vector3::new(
self.v_vector = codec::types::Vector3::new(
v_hat.x * height / sy,
v_hat.y * height / sy,
v_hat.z * height / sy,
@@ -672,13 +672,13 @@ impl Grippable for Wipeout {
impl PropertyEditable for Wipeout {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let show_image = self.flags.contains(acadrust::entities::WipeoutDisplayFlags::SHOW_IMAGE);
let show_image = self.flags.contains(codec::entities::WipeoutDisplayFlags::SHOW_IMAGE);
let show_clipped = self
.flags
.contains(acadrust::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY);
.contains(codec::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY);
let bg_transparency = self
.flags
.contains(acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON);
.contains(codec::entities::WipeoutDisplayFlags::TRANSPARENCY_ON);
let width = wipeout_axis_length(&self.u_vector, self.size.x);
let height = wipeout_axis_length(&self.v_vector, self.size.y);
let rotation = self.u_vector.y.atan2(self.u_vector.x).to_degrees();
@@ -740,8 +740,8 @@ impl PropertyEditable for Wipeout {
let rotation = glam::DQuat::from_axis_angle(normal, angle);
let u = rotation * u;
let v = rotation * v;
self.u_vector = acadrust::types::Vector3::new(u.x, u.y, u.z);
self.v_vector = acadrust::types::Vector3::new(v.x, v.y, v.z);
self.u_vector = codec::types::Vector3::new(u.x, u.y, u.z);
self.v_vector = codec::types::Vector3::new(v.x, v.y, v.z);
return;
}
@@ -806,8 +806,8 @@ mod wipeout_property_tests {
([1.0, 0.0, 1.0], [0.0, 1.0, 0.0], 45.0),
] {
let mut wipeout = Wipeout::new();
wipeout.u_vector = acadrust::types::Vector3::new(u[0], u[1], u[2]);
wipeout.v_vector = acadrust::types::Vector3::new(v[0], v[1], v[2]);
wipeout.u_vector = codec::types::Vector3::new(u[0], u[1], u[2]);
wipeout.v_vector = codec::types::Vector3::new(v[0], v[1], v[2]);
let lengths = (wipeout.u_vector.length(), wipeout.v_vector.length());
wipeout.apply_geom_prop("wo_rotation", &target.to_string());
+3 -3
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{Ray, XLine};
use codec::entities::{Ray, XLine};
use crate::t;
use crate::command::EntityTransform;
@@ -16,7 +16,7 @@ const DISPLAY_EXTENT: f64 = 1_000_000.0;
// ── Ray (semi-infinite line) ──────────────────────────────────────────────────
impl RenderConvertible for Ray {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
let bp = self.base_point;
let dir = self.direction;
// Normalize direction to avoid f32 overflow when DXF stores
@@ -158,7 +158,7 @@ impl Transformable for Ray {
// ── XLine (construction line, infinite) ──────────────────────────────────────
impl RenderConvertible for XLine {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::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();
+4 -4
View File
@@ -5,7 +5,7 @@
// but apply the SHAPE's own rotation / oblique / width factor so the marker
// gives a rough indication of the glyph orientation.
use acadrust::entities::Shape;
use codec::entities::Shape;
use crate::t;
use crate::command::EntityTransform;
@@ -62,7 +62,7 @@ fn shape_marker(
/// absolute paths are the norm in traded files).
fn shx_polylines(
shape: &Shape,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
) -> Option<crate::scene::text::shx::ShapePolylines> {
let base = document
.source_path
@@ -74,7 +74,7 @@ fn shx_polylines(
// Resolve the glyph from one style's shape (.shx) file, preferring the
// shape NUMBER but falling back to the NAME — a DXF SHAPE carries only the
// name (code 2), so its `shape_number` is 0.
let try_style = |style: &acadrust::tables::TextStyle| {
let try_style = |style: &codec::tables::TextStyle| {
let font = style.font_file.trim();
if font.is_empty() {
return None;
@@ -130,7 +130,7 @@ fn shx_polylines(
}
impl RenderConvertible for Shape {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::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(
+19 -19
View File
@@ -1,6 +1,6 @@
// SOLID geometry comes from the kernel; entity coordinates stay in WCS here.
use acadrust::entities::Solid;
use codec::entities::Solid;
use crate::t;
use crate::command::EntityTransform;
@@ -30,7 +30,7 @@ fn dvec3(v: [f64; 3]) -> glam::DVec3 {
pub(crate) fn wcs_corners(solid: &Solid) -> [[f64; 3]; 4] {
let n = normal_tuple(solid);
let w = |v: &acadrust::types::Vector3| {
let w = |v: &codec::types::Vector3| {
let (x, y, z) = crate::scene::view::transform::ocs_point_to_wcs((v.x, v.y, v.z), n);
[x, y, z]
};
@@ -80,7 +80,7 @@ fn boundary_edges(points: &[[f64; 3]]) -> Vec<Edge> {
}
fn kernel_tolerance(points: &[[f64; 3]]) -> f64 {
let tolerance = cadkernel::space::coplanarity_tolerance(points);
let tolerance = kernel::space::coplanarity_tolerance(points);
// Corners whose extent overflows f64 give an infinite tolerance, which
// `Tolerance::new` rejects by panicking.
if tolerance.is_finite() {
@@ -95,7 +95,7 @@ fn extrusion_body(
base: &[[f64; 3]],
tolerance: f64,
profile_valid: bool,
) -> Option<cadkernel::brep::Body> {
) -> Option<kernel::brep::Body> {
if solid.thickness.abs() <= 1.0e-10 || !profile_valid {
return None;
}
@@ -107,7 +107,7 @@ fn extrusion_body(
.skip(1)
.map(|point| glam::DVec3::from_array(*point) - origin)
.find(|axis| axis.length() > tolerance)?;
let plane = cadkernel::space::Plane::orthonormal(
let plane = kernel::space::Plane::orthonormal(
base[0],
axis.to_array(),
normal.to_array(),
@@ -124,13 +124,13 @@ fn extrusion_body(
.collect::<Option<Vec<_>>>()?;
let profile = (0..projected.len())
.map(|index| {
cadkernel::geom2d::Curve::Line(cadkernel::geom2d::Line {
kernel::geom2d::Curve::Line(kernel::geom2d::Line {
start: projected[index],
end: projected[(index + 1) % projected.len()],
})
})
.collect::<Vec<_>>();
cadkernel::brep::extrude(
kernel::brep::extrude(
plane,
&profile,
(normal * solid.thickness).to_array(),
@@ -140,9 +140,9 @@ fn extrusion_body(
fn solid_geometry(solid: &Solid) -> Option<SolidGeometry> {
let base = boundary(solid);
let tolerance = kernel_tolerance(&base);
let fill_tris = cadkernel::space::polygon::triangulate(
let fill_tris = kernel::space::polygon::triangulate(
&base,
cadkernel::geom2d::Tolerance::new(tolerance),
kernel::geom2d::Tolerance::new(tolerance),
);
if solid.thickness.abs() <= 1.0e-10 {
return Some(SolidGeometry {
@@ -158,10 +158,10 @@ fn solid_geometry(solid: &Solid) -> Option<SolidGeometry> {
extruded: false,
});
};
let mesh = cadkernel::brep::mesh::tessellate(
let mesh = kernel::brep::mesh::tessellate(
&body,
cadkernel::brep::mesh::TessellationTolerance::new(
cadkernel::tessellation::DEFAULT_ANGLE,
kernel::brep::mesh::TessellationTolerance::new(
kernel::tessellation::DEFAULT_ANGLE,
tolerance,
),
);
@@ -188,21 +188,21 @@ fn solid_geometry(solid: &Solid) -> Option<SolidGeometry> {
})
}
pub(crate) fn wcs_bounds(solid: &Solid) -> Option<cadkernel::brep::Aabb> {
pub(crate) fn wcs_bounds(solid: &Solid) -> Option<kernel::brep::Aabb> {
let base = boundary(solid);
let tolerance = kernel_tolerance(&base);
let profile_valid = !cadkernel::space::polygon::triangulate(
let profile_valid = !kernel::space::polygon::triangulate(
&base,
cadkernel::geom2d::Tolerance::new(tolerance),
kernel::geom2d::Tolerance::new(tolerance),
)
.is_empty();
extrusion_body(solid, &base, tolerance, profile_valid)
.and_then(|body| cadkernel::brep::body_bounds(&body))
.or_else(|| cadkernel::brep::Aabb::around(base))
.and_then(|body| kernel::brep::body_bounds(&body))
.or_else(|| kernel::brep::Aabb::around(base))
}
impl RenderConvertible for Solid {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
let geometry = solid_geometry(self)?;
let mut lines = Vec::new();
for &(start, end) in &geometry.edges {
@@ -377,7 +377,7 @@ impl Transformable for Solid {
#[cfg(test)]
mod overflow_tests {
use super::*;
use acadrust::types::Vector3;
use codec::types::Vector3;
/// Corners 1e308 apart overflow the coplanarity tolerance to infinity,
/// which the kernel's `Tolerance::new` rejects by panicking.
+56 -56
View File
@@ -2,9 +2,9 @@
//
// Shared grips and properties for modeler entities.
use acadrust::entities::{Body, Region, Solid3D, Surface};
use acadrust::xdata::{ExtendedDataRecord, XDataValue};
use cadkernel::space::polygon;
use codec::entities::{Body, Region, Solid3D, Surface};
use codec::xdata::{ExtendedDataRecord, XDataValue};
use kernel::space::polygon;
use crate::t;
use crate::command::EntityTransform;
use crate::entities::common::{
@@ -14,7 +14,7 @@ use crate::entities::traits::{Grippable, PropertyEditable, Transformable};
use crate::scene::model::object::{GripApply, GripDef, PropSection};
/// Shared transform for the ACIS volume entities. Translate / rotate / scale
/// delegate to acadrust (which composes the move into the solid's ACIS
/// delegate to opencadcodec (which composes the move into the solid's ACIS
/// placement), and mirror delegates via a reflection transform. Without this
/// the entity dispatcher treated solids as non-transformable, so a moved or
/// pasted solid stayed at its original ACIS placement.
@@ -24,7 +24,7 @@ macro_rules! impl_acis_transformable {
fn apply_transform(&mut self, t: &EntityTransform) {
crate::scene::view::transform::apply_standard_entity_transform(self, t, |e, p1, p2| {
let m = crate::scene::view::transform::reflection_about_xy_line(p1, p2);
acadrust::Entity::apply_transform(e, &m);
codec::Entity::apply_transform(e, &m);
});
}
}
@@ -37,14 +37,14 @@ impl_acis_transformable!(Surface);
// ── shared helpers ────────────────────────────────────────────────────────────
fn dvec3(v: &acadrust::types::Vector3) -> glam::DVec3 {
fn dvec3(v: &codec::types::Vector3) -> glam::DVec3 {
glam::DVec3::new(v.x, v.y, v.z)
}
fn translate_acis_entity<T: acadrust::Entity>(entity: &mut T, d: glam::DVec3) {
acadrust::Entity::translate(
fn translate_acis_entity<T: codec::Entity>(entity: &mut T, d: glam::DVec3) {
codec::Entity::translate(
entity,
acadrust::types::Vector3::new(d.x, d.y, d.z),
codec::types::Vector3::new(d.x, d.y, d.z),
);
}
@@ -117,7 +117,7 @@ pub(crate) fn surface_isoline_counts(surface: &Surface) -> [usize; 2] {
]
}
fn handle_text(handle: Option<acadrust::Handle>) -> String {
fn handle_text(handle: Option<codec::Handle>) -> String {
handle
.filter(|handle| handle.is_valid())
.map(|handle| format!("{:X}", handle.value()))
@@ -125,20 +125,20 @@ fn handle_text(handle: Option<acadrust::Handle>) -> String {
}
fn acis_sections(
acis: &acadrust::entities::AcisData,
wires: &[acadrust::entities::Wire],
silhouettes: &[acadrust::entities::Silhouette],
history: Option<acadrust::Handle>,
acis: &codec::entities::AcisData,
wires: &[codec::entities::Wire],
silhouettes: &[codec::entities::Silhouette],
history: Option<codec::Handle>,
) -> Vec<PropSection> {
let mut wire_types = [0usize; 5];
let mut transformed = 0usize;
let mut points = 0usize;
for wire in wires {
let index = match wire.wire_type {
acadrust::entities::WireType::Silhouette => 1,
acadrust::entities::WireType::VisibleEdge => 2,
acadrust::entities::WireType::HiddenEdge => 3,
acadrust::entities::WireType::Isoline => 4,
codec::entities::WireType::Silhouette => 1,
codec::entities::WireType::VisibleEdge => 2,
codec::entities::WireType::HiddenEdge => 3,
codec::entities::WireType::Isoline => 4,
_ => 0,
};
wire_types[index] += 1;
@@ -245,7 +245,7 @@ fn acis_sections(
]
}
fn position_section(prefix: &str, p: &acadrust::types::Vector3) -> PropSection {
fn position_section(prefix: &str, p: &codec::types::Vector3) -> PropSection {
let fields = match prefix {
"rgn" => ["rgn_px", "rgn_py", "rgn_pz"],
"bdy" => ["bdy_px", "bdy_py", "bdy_pz"],
@@ -268,8 +268,8 @@ fn region_area_perimeter(region: &Region) -> (f64, f64) {
let (plane, loops, true) = crate::scene::model::presspull_model::profile_geometry(
&EntityType::Region(region.clone()),
)? else { return None; };
let unit = cadkernel::space::Plane::orthonormal(plane.origin, plane.x_axis, plane.normal()?)?;
let transform = cadkernel::geom2d::Transform {
let unit = kernel::space::Plane::orthonormal(plane.origin, plane.x_axis, plane.normal()?)?;
let transform = kernel::geom2d::Transform {
origin: unit.project(plane.origin)?.into(),
x_axis: unit.project_vector(plane.x_axis)?.into(),
y_axis: unit.project_vector(plane.y_axis)?.into(),
@@ -332,13 +332,13 @@ impl PropertyEditable for Solid3D {
return;
};
let delta = match field {
"s3d_px" => acadrust::types::Vector3::new(v - self.point_of_reference.x, 0.0, 0.0),
"s3d_py" => acadrust::types::Vector3::new(0.0, v - self.point_of_reference.y, 0.0),
"s3d_pz" => acadrust::types::Vector3::new(0.0, 0.0, v - self.point_of_reference.z),
"s3d_px" => codec::types::Vector3::new(v - self.point_of_reference.x, 0.0, 0.0),
"s3d_py" => codec::types::Vector3::new(0.0, v - self.point_of_reference.y, 0.0),
"s3d_pz" => codec::types::Vector3::new(0.0, 0.0, v - self.point_of_reference.z),
_ => return,
};
if delta != acadrust::types::Vector3::ZERO {
acadrust::Entity::translate(self, delta);
if delta != codec::types::Vector3::ZERO {
codec::Entity::translate(self, delta);
}
}
}
@@ -412,35 +412,35 @@ impl PropertyEditable for Body {
return;
};
let delta = match field {
"bdy_px" => acadrust::types::Vector3::new(v - self.point_of_reference.x, 0.0, 0.0),
"bdy_py" => acadrust::types::Vector3::new(0.0, v - self.point_of_reference.y, 0.0),
"bdy_pz" => acadrust::types::Vector3::new(0.0, 0.0, v - self.point_of_reference.z),
"bdy_px" => codec::types::Vector3::new(v - self.point_of_reference.x, 0.0, 0.0),
"bdy_py" => codec::types::Vector3::new(0.0, v - self.point_of_reference.y, 0.0),
"bdy_pz" => codec::types::Vector3::new(0.0, 0.0, v - self.point_of_reference.z),
_ => return,
};
if delta != acadrust::types::Vector3::ZERO {
acadrust::Entity::translate(self, delta);
if delta != codec::types::Vector3::ZERO {
codec::Entity::translate(self, delta);
}
}
}
fn embedded_name(entity: Option<&acadrust::entities::EmbeddedEntity>) -> &'static str {
fn embedded_name(entity: Option<&codec::entities::EmbeddedEntity>) -> &'static str {
match entity {
Some(acadrust::entities::EmbeddedEntity::Point(_)) => "Point",
Some(acadrust::entities::EmbeddedEntity::Line(_)) => "Line",
Some(acadrust::entities::EmbeddedEntity::Arc(_)) => "Arc",
Some(acadrust::entities::EmbeddedEntity::Circle(_)) => "Circle",
Some(acadrust::entities::EmbeddedEntity::Ellipse(_)) => "Ellipse",
Some(acadrust::entities::EmbeddedEntity::Spline(_)) => "Spline",
Some(acadrust::entities::EmbeddedEntity::LwPolyline(_)) => "Polyline",
Some(acadrust::entities::EmbeddedEntity::Region(_)) => "Region",
Some(acadrust::entities::EmbeddedEntity::Ray(_)) => "Ray",
Some(acadrust::entities::EmbeddedEntity::XLine(_)) => "XLine",
Some(acadrust::entities::EmbeddedEntity::Unknown { .. }) => "Unknown",
Some(codec::entities::EmbeddedEntity::Point(_)) => "Point",
Some(codec::entities::EmbeddedEntity::Line(_)) => "Line",
Some(codec::entities::EmbeddedEntity::Arc(_)) => "Arc",
Some(codec::entities::EmbeddedEntity::Circle(_)) => "Circle",
Some(codec::entities::EmbeddedEntity::Ellipse(_)) => "Ellipse",
Some(codec::entities::EmbeddedEntity::Spline(_)) => "Spline",
Some(codec::entities::EmbeddedEntity::LwPolyline(_)) => "Polyline",
Some(codec::entities::EmbeddedEntity::Region(_)) => "Region",
Some(codec::entities::EmbeddedEntity::Ray(_)) => "Ray",
Some(codec::entities::EmbeddedEntity::XLine(_)) => "XLine",
Some(codec::entities::EmbeddedEntity::Unknown { .. }) => "Unknown",
None => "None",
}
}
fn vector_text(vector: &acadrust::types::Vector3) -> String {
fn vector_text(vector: &codec::types::Vector3) -> String {
format!("{:.6}, {:.6}, {:.6}", vector.x, vector.y, vector.z)
}
@@ -457,7 +457,7 @@ fn matrix_text(matrix: &[f64; 16]) -> String {
.join(" ")
}
fn sweep_options_text(options: &acadrust::entities::SurfaceSweepOptions) -> String {
fn sweep_options_text(options: &codec::entities::SurfaceSweepOptions) -> String {
format!(
"draft {:.6} ({:.6}→{:.6}); twist {:.6}; scale {:.6}; align {:.6}; solid {}; flags {}/{}; align-start {}; bank {}; base {}; sweep-xform {}; path-xform {}; ref {}",
options.draft_angle,
@@ -479,7 +479,7 @@ fn sweep_options_text(options: &acadrust::entities::SurfaceSweepOptions) -> Stri
}
fn surface_construction_section(surface: &Surface) -> PropSection {
use acadrust::entities::SurfaceData;
use codec::entities::SurfaceData;
let mut props = vec![
ro(t!("Kind").as_ref(), "srf_kind", format!("{:?}", surface.kind)),
ro(t!("Modeler Format").as_ref(),
@@ -724,9 +724,9 @@ fn surface_construction_section(surface: &Surface) -> PropSection {
}
}
fn translate_surface(surface: &mut Surface, delta: acadrust::types::Vector3) {
fn translate_surface(surface: &mut Surface, delta: codec::types::Vector3) {
let before = surface.point_of_reference;
acadrust::Entity::translate(surface, delta);
codec::Entity::translate(surface, delta);
if surface.point_of_reference == before {
surface.point_of_reference = before + delta;
}
@@ -744,7 +744,7 @@ impl Grippable for Surface {
if let GripApply::Translate(delta) = apply {
translate_surface(
self,
acadrust::types::Vector3::new(delta.x, delta.y, delta.z),
codec::types::Vector3::new(delta.x, delta.y, delta.z),
);
}
}
@@ -791,24 +791,24 @@ impl PropertyEditable for Surface {
return;
};
let delta = match field {
"srf_px" => acadrust::types::Vector3::new(
"srf_px" => codec::types::Vector3::new(
value - self.point_of_reference.x,
0.0,
0.0,
),
"srf_py" => acadrust::types::Vector3::new(
"srf_py" => codec::types::Vector3::new(
0.0,
value - self.point_of_reference.y,
0.0,
),
"srf_pz" => acadrust::types::Vector3::new(
"srf_pz" => codec::types::Vector3::new(
0.0,
0.0,
value - self.point_of_reference.z,
),
_ => return,
};
if delta != acadrust::types::Vector3::ZERO {
if delta != codec::types::Vector3::ZERO {
translate_surface(self, delta);
}
}
@@ -822,13 +822,13 @@ impl PropertyEditable for Surface {
use crate::scene::model::mesh_model::MeshLodSet;
use crate::scene::convert::solid3d_tess;
use acadrust::{types::Vector3, EntityType};
use codec::{types::Vector3, EntityType};
const DISPLAY_DEFLECTION_COEFFICIENT: f64 = 2.5e-4;
/// Shared world-space chord tolerance for solid display.
pub fn display_deflection(
header: &acadrust::document::HeaderVariables,
header: &codec::document::HeaderVariables,
facet_res: f64,
) -> Option<f64> {
let low = header.model_space_extents_min;
@@ -911,7 +911,7 @@ pub fn tessellate_volume(
#[cfg(test)]
mod tests {
use super::*;
use cadkernel::geom2d::{Curve, Line};
use kernel::geom2d::{Curve, Line};
fn ring(points: &[[f64; 2]]) -> Vec<Curve> {
points.iter().copied().zip(points.iter().copied().cycle().skip(1))
+53 -53
View File
@@ -1,6 +1,6 @@
use acadrust::entities::Spline;
use cadkernel::geom2d::Curve as KernelCurve;
use cadkernel::space::{NurbsCurve3, Parameterization};
use codec::entities::Spline;
use kernel::geom2d::Curve as KernelCurve;
use kernel::space::{NurbsCurve3, Parameterization};
use crate::command::EntityTransform;
use crate::entities::common::{
@@ -44,7 +44,7 @@ pub(crate) fn fit_nurbs3(spline: &Spline) -> Option<NurbsCurve3> {
if spline.flags.closed && points.first() != points.last() {
if let Some(first) = points.first().copied() { points.push(first); }
}
let tangent = |value: acadrust::types::Vector3| {
let tangent = |value: codec::types::Vector3| {
let value = [value.x, value.y, value.z];
(value.iter().map(|component| component * component).sum::<f64>() > 1e-18)
.then_some(value)
@@ -115,7 +115,7 @@ pub(crate) fn replace_with_nurbs(spline: &mut Spline, curve: &NurbsCurve3) {
spline.degree = curve.degree() as i32;
spline.knots = curve.knots().to_vec();
spline.control_points = curve.control_points().iter()
.map(|point| acadrust::types::Vector3::new(point[0], point[1], point[2])).collect();
.map(|point| codec::types::Vector3::new(point[0], point[1], point[2])).collect();
spline.weights = curve.weights().to_vec();
if !fit_points.is_empty() {
if let (Some(first), Some(point)) = (fit_points.first_mut(), spline.control_points.first()) {
@@ -126,8 +126,8 @@ pub(crate) fn replace_with_nurbs(spline: &mut Spline, curve: &NurbsCurve3) {
}
}
spline.fit_points = fit_points;
spline.begin_tangent = acadrust::types::Vector3::ZERO;
spline.end_tangent = acadrust::types::Vector3::ZERO;
spline.begin_tangent = codec::types::Vector3::ZERO;
spline.end_tangent = codec::types::Vector3::ZERO;
spline.flags.rational = spline.weights.windows(2)
.any(|pair| (pair[0] - pair[1]).abs() > 1e-12);
spline.flags.closed = false;
@@ -140,9 +140,9 @@ pub(crate) fn replace_with_nurbs(spline: &mut Spline, curve: &NurbsCurve3) {
/// constraints, not control-hull vertices, so their box can exclude the curve.
/// The shared kernel reconstructs the same spatial interpolation used by the
/// curve consumers, then its control hull bounds every point of that curve.
pub(crate) fn fit_geometry_bounds(spline: &Spline) -> Option<cadkernel::brep::Aabb> {
pub(crate) fn fit_geometry_bounds(spline: &Spline) -> Option<kernel::brep::Aabb> {
let curve = fit_nurbs3(spline)?;
cadkernel::brep::Aabb::around(curve.control_points().iter().copied())
kernel::brep::Aabb::around(curve.control_points().iter().copied())
}
fn to_render(spl: &Spline) -> RenderEntity {
let n = spl.control_points.len();
@@ -326,7 +326,7 @@ pub(crate) fn measurement_polyline(spl: &Spline) -> Vec<[f64; 3]> {
});
match NurbsCurve3::new(degree, controls, spl.knots.clone(), weights) {
Some(curve) => {
curve.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE)
curve.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE)
}
None => spl.control_points.iter().map(|p| [p.x, p.y, p.z]).collect(),
}
@@ -335,7 +335,7 @@ pub(crate) fn measurement_polyline(spl: &Spline) -> Vec<[f64; 3]> {
/// Sample a Catmull-Rom spline through `pts` into a dense polyline. The curve
/// passes through every input point; open ends use reflected phantom points so
/// they don't kink, closed curves wrap around.
fn catmull_rom_polyline(pts: &[acadrust::types::Vector3], closed: bool) -> Vec<[f64; 3]> {
fn catmull_rom_polyline(pts: &[codec::types::Vector3], closed: bool) -> Vec<[f64; 3]> {
let n = pts.len();
if n < 2 {
return pts.iter().map(|p| [p.x, p.y, p.z]).collect();
@@ -395,10 +395,10 @@ fn catmull_rom_polyline(pts: &[acadrust::types::Vector3], closed: bool) -> Vec<[
}
q
};
let sampled = cadkernel::tessellation::sample_curve3_angle(
let sampled = kernel::tessellation::sample_curve3_angle(
point_at,
tangent_at,
cadkernel::tessellation::DEFAULT_ANGLE,
kernel::tessellation::DEFAULT_ANGLE,
);
out.extend(sampled.into_iter().skip(usize::from(seg > 0)));
}
@@ -453,10 +453,10 @@ fn fit_spline_polyline(spl: &Spline) -> Vec<[f64; 3]> {
}
q
};
let sampled = cadkernel::tessellation::sample_curve3_angle(
let sampled = kernel::tessellation::sample_curve3_angle(
point_at,
tangent_at,
cadkernel::tessellation::DEFAULT_ANGLE,
kernel::tessellation::DEFAULT_ANGLE,
);
out.extend(sampled.into_iter().skip(usize::from(i > 0)));
}
@@ -475,7 +475,7 @@ fn periodic_fit_spline_polyline(spl: &Spline) -> Vec<[f64; 3]> {
_ => Parameterization::Chord,
};
NurbsCurve3::interpolate_periodic(&points, parameterization)
.map(|curve| curve.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE))
.map(|curve| curve.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE))
.unwrap_or_else(|| catmull_rom_polyline(&spl.fit_points, true))
}
@@ -505,7 +505,7 @@ fn fit_spline_slopes(spl: &Spline, p: &[[f64; 3]]) -> Option<(Vec<f64>, [Vec<f64
}
let h: Vec<f64> = (0..n - 1).map(|i| (t[i + 1] - t[i]).max(1e-9)).collect();
let nonzero = |v: &acadrust::types::Vector3| v.x * v.x + v.y * v.y + v.z * v.z > 1e-18;
let nonzero = |v: &codec::types::Vector3| v.x * v.x + v.y * v.y + v.z * v.z > 1e-18;
let begin = nonzero(&spl.begin_tangent).then(|| {
[
spl.begin_tangent.x,
@@ -576,7 +576,7 @@ fn thomas_solve(a: &[f64], b: &[f64], c: &[f64], d: &mut [f64]) {
pub(crate) const SPLINE_MODE_GRIP_ID: usize = usize::MAX - 1;
fn control_vertices(spline: &Spline) -> Vec<acadrust::types::Vector3> {
fn control_vertices(spline: &Spline) -> Vec<codec::types::Vector3> {
if !uses_fit_method(spline) {
return spline.control_points.clone();
}
@@ -591,7 +591,7 @@ fn control_vertices(spline: &Spline) -> Vec<acadrust::types::Vector3> {
.iter()
.map(|point| {
let point = planar.plane.point_at(*point);
acadrust::types::Vector3::new(point[0], point[1], point[2])
codec::types::Vector3::new(point[0], point[1], point[2])
})
.collect()
}
@@ -633,8 +633,8 @@ fn convert_to_control_method(spline: &mut Spline) -> bool {
let valid = spline.control_points.len() >= 2;
if valid {
spline.fit_points.clear();
spline.begin_tangent = acadrust::types::Vector3::ZERO;
spline.end_tangent = acadrust::types::Vector3::ZERO;
spline.begin_tangent = codec::types::Vector3::ZERO;
spline.end_tangent = codec::types::Vector3::ZERO;
spline.dwg_flags1 &= !1;
spline.dxf_flags &= !(32 | 1024);
}
@@ -653,7 +653,7 @@ fn convert_to_control_method(spline: &mut Spline) -> bool {
.iter()
.map(|point| {
let point = planar.plane.point_at(*point);
acadrust::types::Vector3::new(point[0], point[1], point[2])
codec::types::Vector3::new(point[0], point[1], point[2])
})
.collect();
spline.weights = if curve.is_rational() {
@@ -664,8 +664,8 @@ fn convert_to_control_method(spline: &mut Spline) -> bool {
spline.flags.rational = curve.is_rational();
spline.flags.planar = true;
spline.fit_points.clear();
spline.begin_tangent = acadrust::types::Vector3::ZERO;
spline.end_tangent = acadrust::types::Vector3::ZERO;
spline.begin_tangent = codec::types::Vector3::ZERO;
spline.end_tangent = codec::types::Vector3::ZERO;
true
}
@@ -685,7 +685,7 @@ fn convert_to_fit_method(spline: &mut Spline) -> bool {
true
}
fn derived_fit_points(spline: &Spline) -> Vec<acadrust::types::Vector3> {
fn derived_fit_points(spline: &Spline) -> Vec<codec::types::Vector3> {
if spline.flags.closed || spline.flags.periodic {
return Vec::new();
}
@@ -713,7 +713,7 @@ fn derived_fit_points(spline: &Spline) -> Vec<acadrust::types::Vector3> {
.into_iter()
.map(|parameter| {
let point = curve.point_at_knot(parameter);
acadrust::types::Vector3::new(point[0], point[1], point[2])
codec::types::Vector3::new(point[0], point[1], point[2])
})
.collect()
}
@@ -1167,7 +1167,7 @@ fn apply_transform(spline: &mut Spline, t: &EntityTransform) {
*p2,
*working_normal,
);
acadrust::Entity::apply_transform(spline, &transform);
codec::Entity::apply_transform(spline, &transform);
spline.flags.planar = crate::entities::curve::spline_is_planar(spline);
return;
}
@@ -1183,7 +1183,7 @@ fn apply_transform(spline: &mut Spline, t: &EntityTransform) {
}
impl RenderConvertible for Spline {
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, _document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render(self))
}
}
@@ -1286,11 +1286,11 @@ mod tests {
let mut spline = Spline::default();
spline.degree = 3;
spline.control_points = vec![
acadrust::types::Vector3::new(0.0, 0.0, 0.0),
acadrust::types::Vector3::new(1.0, 2.0, 0.0),
acadrust::types::Vector3::new(3.0, 3.0, 1.0),
acadrust::types::Vector3::new(5.0, 2.0, 0.0),
acadrust::types::Vector3::new(6.0, 0.0, 1.0),
codec::types::Vector3::new(0.0, 0.0, 0.0),
codec::types::Vector3::new(1.0, 2.0, 0.0),
codec::types::Vector3::new(3.0, 3.0, 1.0),
codec::types::Vector3::new(5.0, 2.0, 0.0),
codec::types::Vector3::new(6.0, 0.0, 1.0),
];
spline.knots = vec![0.0, 0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0, 1.0];
let pts = spline_knot_points(&spline);
@@ -1313,9 +1313,9 @@ mod tests {
let mut spline = Spline::default();
spline.degree = 3;
spline.fit_points = vec![
acadrust::types::Vector3::new(0.0, 0.0, 0.0),
acadrust::types::Vector3::new(4.0, 0.0, 1.0),
acadrust::types::Vector3::new(4.0, 3.0, 2.0),
codec::types::Vector3::new(0.0, 0.0, 0.0),
codec::types::Vector3::new(4.0, 0.0, 1.0),
codec::types::Vector3::new(4.0, 3.0, 2.0),
];
assert!(spline_knot_points(&spline).is_empty());
}
@@ -1325,12 +1325,12 @@ mod tests {
let mut spline = Spline::default();
spline.degree = 3;
spline.flags.closed = true;
spline.control_points.push(acadrust::types::Vector3::ZERO);
spline.control_points.push(codec::types::Vector3::ZERO);
spline.fit_points = vec![
acadrust::types::Vector3::new(0.0, 0.0, 0.0),
acadrust::types::Vector3::new(4.0, 0.0, 1.0),
acadrust::types::Vector3::new(4.0, 3.0, 2.0),
acadrust::types::Vector3::new(0.0, 3.0, 1.0),
codec::types::Vector3::new(0.0, 0.0, 0.0),
codec::types::Vector3::new(4.0, 0.0, 1.0),
codec::types::Vector3::new(4.0, 3.0, 2.0),
codec::types::Vector3::new(0.0, 3.0, 1.0),
];
let bounds = fit_geometry_bounds(&spline).unwrap();
@@ -1349,8 +1349,8 @@ mod tests {
fn fit_tolerance_is_editable_and_rejects_invalid_values() {
let mut spline = Spline::default();
spline.fit_points = vec![
acadrust::types::Vector3::ZERO,
acadrust::types::Vector3::new(1.0, 0.0, 0.0),
codec::types::Vector3::ZERO,
codec::types::Vector3::new(1.0, 0.0, 0.0),
];
spline.fit_tolerance = 0.25;
@@ -1373,8 +1373,8 @@ mod tests {
fn tangent_properties_edit_only_the_stored_component() {
let mut spline = Spline::default();
spline.fit_points = vec![
acadrust::types::Vector3::ZERO,
acadrust::types::Vector3::new(1.0, 1.0, 0.0),
codec::types::Vector3::ZERO,
codec::types::Vector3::new(1.0, 1.0, 0.0),
];
let start_y = properties(&spline)
@@ -1387,7 +1387,7 @@ mod tests {
apply_geom_prop(&mut spline, "start_tan_y", "2.5");
assert_eq!(
spline.begin_tangent,
acadrust::types::Vector3::new(0.0, 2.5, 0.0)
codec::types::Vector3::new(0.0, 2.5, 0.0)
);
}
@@ -1396,12 +1396,12 @@ mod tests {
let mut spline = Spline::default();
spline.degree = 3;
spline.control_points = vec![
acadrust::types::Vector3::new(0.0, 0.0, 0.0),
acadrust::types::Vector3::new(1.0, 3.0, 0.0),
acadrust::types::Vector3::new(4.0, 3.0, 0.0),
acadrust::types::Vector3::new(5.0, 0.0, 0.0),
codec::types::Vector3::new(0.0, 0.0, 0.0),
codec::types::Vector3::new(1.0, 3.0, 0.0),
codec::types::Vector3::new(4.0, 3.0, 0.0),
codec::types::Vector3::new(5.0, 0.0, 0.0),
];
spline.knots = cadkernel::space::clamped_uniform_knots(3, 4);
spline.knots = kernel::space::clamped_uniform_knots(3, 4);
let before = nurbs3(&spline).unwrap().point_at(0.37);
assert!(prepare_fit_point_view(&mut spline));
@@ -1411,8 +1411,8 @@ mod tests {
assert!(!uses_fit_method(&spline));
let after = nurbs3(&spline).unwrap().point_at(0.37);
assert!(
cadkernel::space::Vec3::from(before)
.distance(cadkernel::space::Vec3::from(after))
kernel::space::Vec3::from(before)
.distance(kernel::space::Vec3::from(after))
< 1.0e-12
);
}
+143 -143
View File
@@ -1,4 +1,4 @@
use acadrust::entities::Table;
use codec::entities::Table;
use glam::Vec3;
use crate::command::EntityTransform;
@@ -34,7 +34,7 @@ fn prop_current_cell_active() -> bool {
PROPERTY_CELL_ACTIVE.with(std::cell::Cell::get)
}
fn v3(v: &acadrust::types::Vector3) -> Vec3 {
fn v3(v: &codec::types::Vector3) -> Vec3 {
Vec3::new(v.x as f32, v.y as f32, v.z as f32)
}
@@ -89,11 +89,11 @@ fn merged_owner_and_span(
pub(crate) fn style_for_property<'a>(
table: &'a Table,
row: &'a acadrust::entities::table::TableRow,
row: &'a codec::entities::table::TableRow,
column: usize,
cell: &'a acadrust::entities::table::TableCell,
property: acadrust::entities::table::CellStylePropertyFlags,
) -> Option<&'a acadrust::entities::table::CellStyle> {
cell: &'a codec::entities::table::TableCell,
property: codec::entities::table::CellStylePropertyFlags,
) -> Option<&'a codec::entities::table::CellStyle> {
let column_style = table
.columns
.get(column)
@@ -116,11 +116,11 @@ pub(crate) fn style_for_property<'a>(
fn style_for_border<'a>(
table: &'a Table,
row: &'a acadrust::entities::table::TableRow,
row: &'a codec::entities::table::TableRow,
column: usize,
cell: &'a acadrust::entities::table::TableCell,
edge: acadrust::entities::table::CellEdgeFlags,
) -> Option<&'a acadrust::entities::table::CellStyle> {
cell: &'a codec::entities::table::TableCell,
edge: codec::entities::table::CellEdgeFlags,
) -> Option<&'a codec::entities::table::CellStyle> {
let column_style = table
.columns
.get(column)
@@ -138,7 +138,7 @@ fn style_for_border<'a>(
pub(crate) fn resolved_title_suppressed(
table: &Table,
table_style: Option<&acadrust::objects::TableStyle>,
table_style: Option<&codec::objects::TableStyle>,
) -> bool {
table
.legacy_style_override
@@ -150,7 +150,7 @@ pub(crate) fn resolved_title_suppressed(
pub(crate) fn resolved_header_suppressed(
table: &Table,
table_style: Option<&acadrust::objects::TableStyle>,
table_style: Option<&codec::objects::TableStyle>,
) -> bool {
table
.legacy_style_override
@@ -162,9 +162,9 @@ pub(crate) fn resolved_header_suppressed(
pub(crate) fn resolved_flow_up(
table: &Table,
table_style: Option<&acadrust::objects::TableStyle>,
table_style: Option<&codec::objects::TableStyle>,
) -> bool {
use acadrust::entities::table::CellStylePropertyFlags;
use codec::entities::table::CellStylePropertyFlags;
table
.legacy_style_override
@@ -182,14 +182,14 @@ pub(crate) fn resolved_flow_up(
.unwrap_or_else(|| {
matches!(
table_style.map(|style| style.flow_direction),
Some(acadrust::objects::TableFlowDirection::Up)
Some(codec::objects::TableFlowDirection::Up)
)
})
}
pub(crate) fn resolved_table_margins(
table: &Table,
table_style: Option<&acadrust::objects::TableStyle>,
table_style: Option<&codec::objects::TableStyle>,
) -> (f64, f64) {
let horizontal = table
.legacy_style_override
@@ -235,7 +235,7 @@ fn table_break_segments(
row_offsets: &[f32],
scale: f32,
) -> Vec<TableBreakSegment> {
use acadrust::entities::table::BreakOptionFlags;
use codec::entities::table::BreakOptionFlags;
let insertion = v3(&table.insertion_point);
if table.rows.is_empty() {
@@ -249,7 +249,7 @@ fn table_break_segments(
}];
}
let offset_to_world = |offset: &acadrust::types::Vector3| insertion + v3(offset);
let offset_to_world = |offset: &codec::types::Vector3| insertion + v3(offset);
let mut cached: Vec<_> = table
.break_ranges
.iter()
@@ -319,13 +319,13 @@ fn table_break_segments(
table.total_height() as f32 * scale + spacing
};
match table.break_flow_direction {
acadrust::entities::table::BreakFlowDirection::Left => {
codec::entities::table::BreakFlowDirection::Left => {
insertion - h * segment as f32 * horizontal_step
}
acadrust::entities::table::BreakFlowDirection::Vertical => {
codec::entities::table::BreakFlowDirection::Vertical => {
insertion + down * segment as f32 * vertical_step
}
acadrust::entities::table::BreakFlowDirection::Right => {
codec::entities::table::BreakFlowDirection::Right => {
insertion + h * segment as f32 * horizontal_step
}
}
@@ -378,7 +378,7 @@ fn break_frames_for_row(
top_label_rows: usize,
bottom_label_rows: usize,
) -> Vec<(Vec3, f32)> {
use acadrust::entities::table::BreakOptionFlags;
use codec::entities::table::BreakOptionFlags;
let segments = table_break_segments(table, h, down, row_offsets, scale);
let Some((segment_index, segment)) = segments
@@ -450,12 +450,12 @@ fn break_frames_for_row(
frames
}
fn format_cell_value(value: &acadrust::entities::table::CellValue) -> String {
fn format_cell_value(value: &codec::entities::table::CellValue) -> String {
let display = value.display();
if !display.is_empty() {
return display.to_string();
}
use acadrust::entities::table::CellValueType;
use codec::entities::table::CellValueType;
match value.value_type {
CellValueType::Long => format!("{}", value.numeric_value as i64),
CellValueType::Double | CellValueType::Date => format!("{}", value.numeric_value),
@@ -542,7 +542,7 @@ fn evaluate_table_formula(table: &Table, expression: &str) -> Option<String> {
fn fallback_content_centers(
bounds: [f32; 4],
sizes: &[(f32, f32)],
layout: acadrust::entities::table::ContentLayoutFlags,
layout: codec::entities::table::ContentLayoutFlags,
alignment: i32,
horizontal_spacing: f32,
vertical_spacing: f32,
@@ -556,13 +556,13 @@ fn fallback_content_centers(
let vert = ((alignment - 1) / 3) + 1;
let mut rows: Vec<Vec<usize>> = Vec::new();
if layout.contains(
acadrust::entities::table::ContentLayoutFlags::STACKED_VERTICAL,
codec::entities::table::ContentLayoutFlags::STACKED_VERTICAL,
) {
for index in 0..sizes.len() {
rows.push(vec![index]);
}
} else if layout.contains(
acadrust::entities::table::ContentLayoutFlags::STACKED_HORIZONTAL,
codec::entities::table::ContentLayoutFlags::STACKED_HORIZONTAL,
) {
rows.push((0..sizes.len()).collect());
} else {
@@ -623,9 +623,9 @@ fn fallback_content_centers(
}
fn content_display_value(
document: &acadrust::CadDocument,
document: &codec::CadDocument,
table: &Table,
content: &acadrust::entities::table::CellContent,
content: &codec::entities::table::CellContent,
) -> String {
if let Some(handle) = content.field_handle {
if let Some(value) =
@@ -633,7 +633,7 @@ fn content_display_value(
{
return value;
}
if let Some(acadrust::objects::ObjectType::Field(field)) = document.objects.get(&handle) {
if let Some(codec::objects::ObjectType::Field(field)) = document.objects.get(&handle) {
if !field.value_string.is_empty() {
return field.value_string.clone();
}
@@ -648,13 +648,13 @@ fn content_display_value(
}
fn resolved_content_geometry(
document: &acadrust::CadDocument,
document: &codec::CadDocument,
table: &Table,
row: usize,
column: usize,
cell: &acadrust::entities::table::TableCell,
cell: &codec::entities::table::TableCell,
content_index: usize,
) -> Option<acadrust::entities::table::CellContentGeometry> {
) -> Option<codec::entities::table::CellContentGeometry> {
if let Some(geometry) = cell
.contents
.get(content_index)
@@ -669,10 +669,10 @@ fn resolved_content_geometry(
let flat_index = row
.saturating_mul(table.columns.len())
.saturating_add(column);
if let Some(acadrust::objects::ObjectType::DataObject(object)) =
if let Some(codec::objects::ObjectType::DataObject(object)) =
document.objects.get(&handle)
{
if let acadrust::objects::DataObjectData::TableGeometry(geometry) =
if let codec::objects::DataObjectData::TableGeometry(geometry) =
&object.data
{
return geometry
@@ -683,10 +683,10 @@ fn resolved_content_geometry(
}
}
document.objects.values().find_map(|object| {
let acadrust::objects::ObjectType::DataObject(object) = object else {
let codec::objects::ObjectType::DataObject(object) = object else {
return None;
};
let acadrust::objects::DataObjectData::TableGeometry(geometry) =
let codec::objects::DataObjectData::TableGeometry(geometry) =
&object.data
else {
return None;
@@ -702,12 +702,12 @@ fn resolved_content_geometry(
pub(crate) fn block_cell_inserts(
table: &Table,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
anno_scale: f32,
) -> Vec<acadrust::entities::Insert> {
use acadrust::entities::table::ContentLayoutFlags;
use acadrust::entities::{AttributeEntity, EntityType, Insert};
use acadrust::types::Vector3;
) -> Vec<codec::entities::Insert> {
use codec::entities::table::ContentLayoutFlags;
use codec::entities::{AttributeEntity, EntityType, Insert};
use codec::types::Vector3;
if table.rows.is_empty() || table.columns.is_empty() {
return Vec::new();
@@ -715,7 +715,7 @@ pub(crate) fn block_cell_inserts(
let (h, down) = table_axes(table);
let table_style = table.table_style_handle.and_then(|handle| {
document.objects.get(&handle).and_then(|object| match object {
acadrust::objects::ObjectType::TableStyle(style) => Some(style),
codec::objects::ObjectType::TableStyle(style) => Some(style),
_ => None,
})
});
@@ -771,7 +771,7 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::CONTENT_LAYOUT,
codec::entities::table::CellStylePropertyFlags::CONTENT_LAYOUT,
);
let layout = layout_style
.map(|style| style.layout_flags)
@@ -822,14 +822,14 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::BLOCK_SCALE,
codec::entities::table::CellStylePropertyFlags::BLOCK_SCALE,
);
let style_scale = scale_style
.map(|style| style.scale)
.filter(|scale| scale.abs() > 1e-9)
.unwrap_or(1.0);
let content_scale = if content.format_property_flags
& acadrust::entities::table::CellStylePropertyFlags::BLOCK_SCALE.bits() as i32
& codec::entities::table::CellStylePropertyFlags::BLOCK_SCALE.bits() as i32
!= 0
&& content.scale.abs() > 1e-9
{
@@ -840,7 +840,7 @@ pub(crate) fn block_cell_inserts(
1.0
};
let mut scale = if content.format_property_flags
& acadrust::entities::table::CellStylePropertyFlags::BLOCK_SCALE.bits() as i32
& codec::entities::table::CellStylePropertyFlags::BLOCK_SCALE.bits() as i32
!= 0
{
content_scale
@@ -853,12 +853,12 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::AUTO_SCALE,
codec::entities::table::CellStylePropertyFlags::AUTO_SCALE,
)
.is_some_and(|style| {
style
.property_flags
.contains(acadrust::entities::table::CellStylePropertyFlags::AUTO_SCALE)
.contains(codec::entities::table::CellStylePropertyFlags::AUTO_SCALE)
});
let mut block_min =
Vector3::new(f64::MAX, f64::MAX, f64::MAX);
@@ -894,7 +894,7 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
codec::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
)
.map(|style| style.margin_left)
.unwrap_or(0.0);
@@ -903,7 +903,7 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
codec::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
)
.map(|style| style.margin_right)
.unwrap_or(0.0);
@@ -912,7 +912,7 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_TOP,
codec::entities::table::CellStylePropertyFlags::MARGIN_TOP,
)
.map(|style| style.margin_top)
.unwrap_or(0.0);
@@ -921,7 +921,7 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
codec::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
)
.map(|style| style.margin_bottom)
.unwrap_or(0.0);
@@ -940,10 +940,10 @@ pub(crate) fn block_cell_inserts(
row,
column_index,
cell,
acadrust::entities::table::CellStylePropertyFlags::ROTATION,
codec::entities::table::CellStylePropertyFlags::ROTATION,
);
let content_rotation_explicit = content.format_property_flags
& acadrust::entities::table::CellStylePropertyFlags::ROTATION.bits() as i32
& codec::entities::table::CellStylePropertyFlags::ROTATION.bits() as i32
!= 0;
let content_rotation = if content_rotation_explicit {
content.rotation
@@ -1005,7 +1005,7 @@ pub(crate) fn block_cell_inserts(
};
let mut entity =
AttributeEntity::from_definition(definition, Some(attribute.value.clone()));
acadrust::Entity::apply_transform(
codec::Entity::apply_transform(
&mut entity,
&crate::scene::render_graph::insert_transform(document, &insert),
);
@@ -1020,7 +1020,7 @@ pub(crate) fn block_cell_inserts(
}
impl RenderConvertible for Table {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
if self.rows.is_empty() || self.columns.is_empty() {
return None;
}
@@ -1143,20 +1143,20 @@ impl RenderConvertible for Table {
// Row classification: row 0 is Title (when not suppressed), row 1 is
// Header (when not suppressed), everything else is Data. The two
// suppressed flags shift the leading rows down to Data.
let lookup_style = |h: acadrust::Handle| -> Option<&acadrust::tables::TextStyle> {
let lookup_style = |h: codec::Handle| -> Option<&codec::tables::TextStyle> {
document.text_styles.iter().find(|s| s.handle == h)
};
let table_style: Option<&acadrust::objects::TableStyle> =
let table_style: Option<&codec::objects::TableStyle> =
self.table_style_handle.and_then(|h| {
document.objects.get(&h).and_then(|obj| match obj {
acadrust::objects::ObjectType::TableStyle(ts) => Some(ts),
codec::objects::ObjectType::TableStyle(ts) => Some(ts),
_ => None,
})
});
let title_suppressed = resolved_title_suppressed(self, table_style);
let header_suppressed = resolved_header_suppressed(self, table_style);
let font_for_handle = |handle: Option<acadrust::Handle>| -> Option<String> {
let font_for_handle = |handle: Option<codec::Handle>| -> Option<String> {
handle.and_then(|h| lookup_style(h)).and_then(|s| {
let mut font_name = if !s.true_type_font.trim().is_empty() {
s.true_type_font.trim().to_string()
@@ -1185,7 +1185,7 @@ impl RenderConvertible for Table {
// Build a ResolvedTextStyle for the cell — needed by the shared MText
// pipeline so inline `\W`, `\Q`, etc. compose with the style baseline.
let resolved_style_for_handle =
|handle: Option<acadrust::Handle>, font_name: String| -> ResolvedTextStyle {
|handle: Option<codec::Handle>, font_name: String| -> ResolvedTextStyle {
let style = handle.and_then(|h| lookup_style(h));
ResolvedTextStyle {
font_name,
@@ -1206,7 +1206,7 @@ impl RenderConvertible for Table {
let row_mid = (row_top + row_bot) * 0.5;
// Pick the appropriate row_style from TableStyle for this row's role.
let row_style: Option<&acadrust::objects::RowCellStyle> = table_style.map(|ts| {
let row_style: Option<&codec::objects::RowCellStyle> = table_style.map(|ts| {
let kind = match (title_suppressed, header_suppressed, ri) {
(false, _, 0) => 0, // title
(false, false, 1) => 1, // header
@@ -1359,7 +1359,7 @@ impl RenderConvertible for Table {
/// Builds colored geometry for tables without a stored display block.
pub fn tessellate_table(
tab: &Table,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
selected: bool,
entity_color: [f32; 4],
line_weight_px: f32,
@@ -1370,7 +1370,7 @@ pub fn tessellate_table(
) -> Vec<crate::scene::model::wire_model::WireModel> {
use crate::scene::convert::tess_util::aci_to_rgba;
use crate::scene::model::wire_model::WireModel;
use acadrust::types::Color;
use codec::types::Color;
use rustc_hash::FxHashMap as HashMap;
if tab.rows.is_empty() || tab.columns.is_empty() {
@@ -1398,19 +1398,19 @@ pub fn tessellate_table(
(c[3] * 255.0) as u8,
]
};
let lw_px = |w: &acadrust::types::LineWeight| -> f32 {
let lw_px = |w: &codec::types::LineWeight| -> f32 {
match w {
acadrust::types::LineWeight::Value(v) if *v >= 0 => (*v as f32 / 100.0) * (96.0 / 25.4),
codec::types::LineWeight::Value(v) if *v >= 0 => (*v as f32 / 100.0) * (96.0 / 25.4),
_ => line_weight_px,
}
};
let (h, v_down) = table_axes(tab);
// Flow direction: `Up` stacks rows upward instead of downward.
let table_style: Option<&acadrust::objects::TableStyle> =
let table_style: Option<&codec::objects::TableStyle> =
tab.table_style_handle.and_then(|h| {
document.objects.get(&h).and_then(|obj| match obj {
acadrust::objects::ObjectType::TableStyle(ts) => Some(ts),
codec::objects::ObjectType::TableStyle(ts) => Some(ts),
_ => None,
})
});
@@ -1428,10 +1428,10 @@ pub fn tessellate_table(
let h_margin = horizontal_margin as f32 * anno_scale;
let v_margin = vertical_margin as f32 * anno_scale;
let lookup_style = |hh: acadrust::Handle| -> Option<&acadrust::tables::TextStyle> {
let lookup_style = |hh: codec::Handle| -> Option<&codec::tables::TextStyle> {
document.text_styles.iter().find(|s| s.handle == hh)
};
let font_for_handle = |handle: Option<acadrust::Handle>| -> Option<String> {
let font_for_handle = |handle: Option<codec::Handle>| -> Option<String> {
handle.and_then(lookup_style).and_then(|s| {
let mut font_name = if !s.true_type_font.trim().is_empty() {
s.true_type_font.trim().to_string()
@@ -1454,7 +1454,7 @@ pub fn tessellate_table(
})
};
let resolved_style_for_handle =
|handle: Option<acadrust::Handle>, font_name: String| -> ResolvedTextStyle {
|handle: Option<codec::Handle>, font_name: String| -> ResolvedTextStyle {
let style = handle.and_then(lookup_style);
ResolvedTextStyle {
font_name,
@@ -1506,7 +1506,7 @@ pub fn tessellate_table(
let normal = v3(&tab.normal).normalize_or(Vec3::Z);
for (ri, row) in tab.rows.iter().enumerate() {
let row_style: Option<&acadrust::objects::RowCellStyle> = table_style.map(|ts| {
let row_style: Option<&codec::objects::RowCellStyle> = table_style.map(|ts| {
let kind = match (title_suppressed, header_suppressed, ri) {
(false, _, 0) => 0,
(false, false, 1) => 1,
@@ -1560,7 +1560,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::BACKGROUND_COLOR,
codec::entities::table::CellStylePropertyFlags::BACKGROUND_COLOR,
);
let (fill_on, fill_color) = if let Some(cs) = fill_style {
(cs.fill_enabled, cs.background_color)
@@ -1584,10 +1584,10 @@ pub fn tessellate_table(
// (top, right, bottom, left)
let edge = |which: u8| -> (bool, [f32; 4], f32) {
let edge_flag = match which {
0 => acadrust::entities::table::CellEdgeFlags::TOP,
1 => acadrust::entities::table::CellEdgeFlags::RIGHT,
2 => acadrust::entities::table::CellEdgeFlags::BOTTOM,
_ => acadrust::entities::table::CellEdgeFlags::LEFT,
0 => codec::entities::table::CellEdgeFlags::TOP,
1 => codec::entities::table::CellEdgeFlags::RIGHT,
2 => codec::entities::table::CellEdgeFlags::BOTTOM,
_ => codec::entities::table::CellEdgeFlags::LEFT,
};
if let Some(cs) = style_for_border(tab, row, ci, cell, edge_flag) {
let b = match which {
@@ -1660,7 +1660,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
codec::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
)
.map(|style| style.text_height as f32)
.or_else(|| row_style.map(|style| style.text_height as f32))
@@ -1672,7 +1672,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
codec::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
)
.map(|style| style.margin_left as f32 * anno_scale)
.unwrap_or(h_margin.max(fallback_text_height * 0.5));
@@ -1681,7 +1681,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
codec::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
)
.map(|style| style.margin_right as f32 * anno_scale)
.unwrap_or(h_margin.max(fallback_text_height * 0.5));
@@ -1690,7 +1690,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_TOP,
codec::entities::table::CellStylePropertyFlags::MARGIN_TOP,
)
.map(|style| style.margin_top as f32 * anno_scale)
.unwrap_or(v_margin.max(fallback_text_height * 0.5));
@@ -1699,7 +1699,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
codec::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
)
.map(|style| style.margin_bottom as f32 * anno_scale)
.unwrap_or(v_margin.max(fallback_text_height * 0.5));
@@ -1708,16 +1708,16 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::CONTENT_LAYOUT,
codec::entities::table::CellStylePropertyFlags::CONTENT_LAYOUT,
)
.map(|style| style.layout_flags)
.unwrap_or(acadrust::entities::table::ContentLayoutFlags::FLOW);
.unwrap_or(codec::entities::table::ContentLayoutFlags::FLOW);
let fallback_alignment = style_for_property(
tab,
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::ALIGNMENT,
codec::entities::table::CellStylePropertyFlags::ALIGNMENT,
)
.map(|style| style.alignment)
.or_else(|| row_style.map(|style| style.alignment as i32))
@@ -1727,7 +1727,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_HORIZONTAL_SPACING,
codec::entities::table::CellStylePropertyFlags::MARGIN_HORIZONTAL_SPACING,
)
.map(|style| style.horizontal_spacing as f32 * anno_scale)
.unwrap_or(0.0);
@@ -1736,7 +1736,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_VERTICAL_SPACING,
codec::entities::table::CellStylePropertyFlags::MARGIN_VERTICAL_SPACING,
)
.map(|style| style.vertical_spacing as f32 * anno_scale)
.unwrap_or(0.0);
@@ -1781,7 +1781,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
codec::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
);
let cell_h = (content.text_height > 1e-6)
.then_some(content.text_height)
@@ -1803,7 +1803,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
codec::entities::table::CellStylePropertyFlags::MARGIN_LEFT,
)
.map(|style| style.margin_left as f32 * anno_scale)
.filter(|margin| *margin > 1e-6)
@@ -1813,7 +1813,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
codec::entities::table::CellStylePropertyFlags::MARGIN_RIGHT,
)
.map(|style| style.margin_right as f32 * anno_scale)
.filter(|margin| *margin > 1e-6)
@@ -1823,7 +1823,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_TOP,
codec::entities::table::CellStylePropertyFlags::MARGIN_TOP,
)
.map(|style| style.margin_top as f32 * anno_scale)
.filter(|margin| *margin > 1e-6)
@@ -1833,7 +1833,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
codec::entities::table::CellStylePropertyFlags::MARGIN_BOTTOM,
)
.map(|style| style.margin_bottom as f32 * anno_scale)
.filter(|margin| *margin > 1e-6)
@@ -1844,7 +1844,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::TEXT_STYLE,
codec::entities::table::CellStylePropertyFlags::TEXT_STYLE,
)
.and_then(|style| style.text_style_handle)
})
@@ -1860,7 +1860,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::ALIGNMENT,
codec::entities::table::CellStylePropertyFlags::ALIGNMENT,
)
.map(|style| style.alignment)
.filter(|alignment| *alignment != 0)
@@ -1908,7 +1908,7 @@ pub fn tessellate_table(
+ v_flow * y_offset
+ normal * z_offset;
let content_rotation_explicit = content.format_property_flags
& acadrust::entities::table::CellStylePropertyFlags::ROTATION.bits() as i32
& codec::entities::table::CellStylePropertyFlags::ROTATION.bits() as i32
!= 0;
let rot = if content_rotation_explicit {
content.rotation as f32
@@ -1918,7 +1918,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::ROTATION,
codec::entities::table::CellStylePropertyFlags::ROTATION,
)
.map(|style| style.rotation as f32)
.unwrap_or(cell.rotation as f32)
@@ -1951,7 +1951,7 @@ pub fn tessellate_table(
row,
ci,
cell,
acadrust::entities::table::CellStylePropertyFlags::CONTENT_COLOR,
codec::entities::table::CellStylePropertyFlags::CONTENT_COLOR,
) {
resolve_col(&style.content_color, entity_color)
} else if let Some(style) = row_style {
@@ -2216,7 +2216,7 @@ impl Grippable for Table {
} else if grip_id >= 2000 {
if let Some(data) = self.break_data.get_mut(grip_id - 2000) {
let offset = point - origin;
data.position = acadrust::types::Vector3::new(offset.x, offset.y, offset.z);
data.position = codec::types::Vector3::new(offset.x, offset.y, offset.z);
}
}
}
@@ -2225,7 +2225,7 @@ impl Grippable for Table {
impl PropertyEditable for Table {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
use crate::entities::common::edit_prop as edit;
use acadrust::entities::table::{BreakOptionFlags, CellStateFlags, CellStylePropertyFlags};
use codec::entities::table::{BreakOptionFlags, CellStateFlags, CellStylePropertyFlags};
let bool_text = |value: bool| if value { t!("Yes") } else { t!("No") }.into_owned();
let toggle = |label: &str, field: &'static str, value: bool, enabled: bool| -> Property {
Property {
@@ -2272,16 +2272,16 @@ impl PropertyEditable for Table {
},
}
};
let color_text = |color: acadrust::types::Color| match color {
acadrust::types::Color::None => "None".to_string(),
acadrust::types::Color::ByLayer => "ByLayer".to_string(),
acadrust::types::Color::ByBlock => "ByBlock".to_string(),
acadrust::types::Color::Index(index) => index.to_string(),
acadrust::types::Color::Rgb { r, g, b } => format!("{r},{g},{b}"),
let color_text = |color: codec::types::Color| match color {
codec::types::Color::None => "None".to_string(),
codec::types::Color::ByLayer => "ByLayer".to_string(),
codec::types::Color::ByBlock => "ByBlock".to_string(),
codec::types::Color::Index(index) => index.to_string(),
codec::types::Color::Rgb { r, g, b } => format!("{r},{g},{b}"),
};
let color = |label: &str,
field: &'static str,
value: acadrust::types::Color,
value: codec::types::Color,
enabled: bool|
-> Property {
Property {
@@ -2506,18 +2506,18 @@ impl PropertyEditable for Table {
if prop_current_cell_active() {
let cell_type = match cell.map(|cell| cell.cell_type) {
Some(acadrust::entities::table::CellType::Block) => "Block",
Some(codec::entities::table::CellType::Block) => "Block",
_ => "Text",
};
let data_type = cell
.and_then(|cell| cell.contents.first())
.map(|content| match content.value.value_type {
acadrust::entities::table::CellValueType::Long => "Integer",
acadrust::entities::table::CellValueType::Double => "Decimal",
acadrust::entities::table::CellValueType::Date => "Date",
acadrust::entities::table::CellValueType::Point2D => "Point 2D",
acadrust::entities::table::CellValueType::Point3D => "Point 3D",
acadrust::entities::table::CellValueType::Handle => "Handle",
codec::entities::table::CellValueType::Long => "Integer",
codec::entities::table::CellValueType::Double => "Decimal",
codec::entities::table::CellValueType::Date => "Date",
codec::entities::table::CellValueType::Point2D => "Point 2D",
codec::entities::table::CellValueType::Point3D => "Point 3D",
codec::entities::table::CellValueType::Handle => "Handle",
_ => "Text",
})
.unwrap_or("Text");
@@ -2627,7 +2627,7 @@ impl PropertyEditable for Table {
"tbl_cell_content_color",
style_for(CellStylePropertyFlags::CONTENT_COLOR)
.map(|style| style.content_color)
.unwrap_or(acadrust::types::Color::ByBlock),
.unwrap_or(codec::types::Color::ByBlock),
format_editable,
),
color(
@@ -2635,7 +2635,7 @@ impl PropertyEditable for Table {
"tbl_cell_background_color",
style_for(CellStylePropertyFlags::BACKGROUND_COLOR)
.map(|style| style.background_color)
.unwrap_or(acadrust::types::Color::ByBlock),
.unwrap_or(codec::types::Color::ByBlock),
format_editable,
),
choice(
@@ -2711,7 +2711,7 @@ impl PropertyEditable for Table {
row,
cell_column,
cell,
acadrust::entities::table::CellEdgeFlags::TOP,
codec::entities::table::CellEdgeFlags::TOP,
)
})
})
@@ -2729,7 +2729,7 @@ impl PropertyEditable for Table {
row,
cell_column,
cell,
acadrust::entities::table::CellEdgeFlags::RIGHT,
codec::entities::table::CellEdgeFlags::RIGHT,
)
})
})
@@ -2747,7 +2747,7 @@ impl PropertyEditable for Table {
row,
cell_column,
cell,
acadrust::entities::table::CellEdgeFlags::BOTTOM,
codec::entities::table::CellEdgeFlags::BOTTOM,
)
})
})
@@ -2765,7 +2765,7 @@ impl PropertyEditable for Table {
row,
cell_column,
cell,
acadrust::entities::table::CellEdgeFlags::LEFT,
codec::entities::table::CellEdgeFlags::LEFT,
)
})
})
@@ -2796,9 +2796,9 @@ impl PropertyEditable for Table {
t!("Direction").as_ref(),
"tbl_break_direction",
match self.break_flow_direction {
acadrust::entities::table::BreakFlowDirection::Right => "Right",
acadrust::entities::table::BreakFlowDirection::Left => "Left",
acadrust::entities::table::BreakFlowDirection::Vertical => "Down",
codec::entities::table::BreakFlowDirection::Right => "Right",
codec::entities::table::BreakFlowDirection::Left => "Left",
codec::entities::table::BreakFlowDirection::Vertical => "Down",
}
.to_string(),
vec!["Right".into(), "Left".into(), "Down".into()],
@@ -2851,7 +2851,7 @@ impl PropertyEditable for Table {
fn apply_geom_prop(&mut self, field: &str, value: &str) {
use crate::entities::common::parse_f64;
use acadrust::entities::table::{
use codec::entities::table::{
BreakOptionFlags, CellStateFlags, CellStyle, CellStylePropertyFlags,
};
let flag = match field {
@@ -2950,9 +2950,9 @@ impl PropertyEditable for Table {
}
if let Some(cell) = self.cell_mut(row, column) {
cell.cell_type = if value.trim().eq_ignore_ascii_case("block") {
acadrust::entities::table::CellType::Block
codec::entities::table::CellType::Block
} else {
acadrust::entities::table::CellType::Text
codec::entities::table::CellType::Text
};
}
return;
@@ -2976,7 +2976,7 @@ impl PropertyEditable for Table {
let style = cell.style.get_or_insert_with(CellStyle::new);
style.alignment = alignment;
style.property_flags.insert(
acadrust::entities::table::CellStylePropertyFlags::ALIGNMENT,
codec::entities::table::CellStylePropertyFlags::ALIGNMENT,
);
}
return;
@@ -3019,13 +3019,13 @@ impl PropertyEditable for Table {
}
if let Some(content) = cell.contents.first_mut() {
content.value.value_type = match value.trim().to_ascii_uppercase().as_str() {
"INTEGER" => acadrust::entities::table::CellValueType::Long,
"DECIMAL" => acadrust::entities::table::CellValueType::Double,
"DATE" => acadrust::entities::table::CellValueType::Date,
"POINT 2D" => acadrust::entities::table::CellValueType::Point2D,
"POINT 3D" => acadrust::entities::table::CellValueType::Point3D,
"HANDLE" => acadrust::entities::table::CellValueType::Handle,
_ => acadrust::entities::table::CellValueType::String,
"INTEGER" => codec::entities::table::CellValueType::Long,
"DECIMAL" => codec::entities::table::CellValueType::Double,
"DATE" => codec::entities::table::CellValueType::Date,
"POINT 2D" => codec::entities::table::CellValueType::Point2D,
"POINT 3D" => codec::entities::table::CellValueType::Point3D,
"HANDLE" => codec::entities::table::CellValueType::Handle,
_ => codec::entities::table::CellValueType::String,
};
content.value.raw_type_code = content.value.value_type as i32;
}
@@ -3044,7 +3044,7 @@ impl PropertyEditable for Table {
let style = cell.style.get_or_insert_with(CellStyle::new);
style.value_format = value.to_string();
style.property_flags.insert(
acadrust::entities::table::CellStylePropertyFlags::DATA_FORMAT,
codec::entities::table::CellStylePropertyFlags::DATA_FORMAT,
);
}
return;
@@ -3061,7 +3061,7 @@ impl PropertyEditable for Table {
value == "true"
};
style.property_flags.insert(
acadrust::entities::table::CellStylePropertyFlags::BACKGROUND_COLOR,
codec::entities::table::CellStylePropertyFlags::BACKGROUND_COLOR,
);
}
return;
@@ -3074,7 +3074,7 @@ impl PropertyEditable for Table {
return;
}
if let Some(cell) = self.cell_mut(row, column) {
use acadrust::entities::table::{
use codec::entities::table::{
BorderPropertyFlags, CellEdgeFlags,
};
let style = cell.style.get_or_insert_with(CellStyle::new);
@@ -3131,11 +3131,11 @@ impl PropertyEditable for Table {
return;
}
self.break_flow_direction = match value.trim().to_ascii_uppercase().as_str() {
"LEFT" => acadrust::entities::table::BreakFlowDirection::Left,
"LEFT" => codec::entities::table::BreakFlowDirection::Left,
"DOWN" | "VERTICAL" => {
acadrust::entities::table::BreakFlowDirection::Vertical
codec::entities::table::BreakFlowDirection::Vertical
}
_ => acadrust::entities::table::BreakFlowDirection::Right,
_ => codec::entities::table::BreakFlowDirection::Right,
};
self.break_ranges.clear();
}
@@ -3241,7 +3241,7 @@ impl PropertyEditable for Table {
let style = cell.style.get_or_insert_with(CellStyle::new);
style.text_height = number;
style.property_flags.insert(
acadrust::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
codec::entities::table::CellStylePropertyFlags::TEXT_HEIGHT,
);
}
}
@@ -3294,8 +3294,8 @@ impl PropertyEditable for Table {
.contains(BreakOptionFlags::ALLOW_MANUAL_HEIGHTS) =>
{
if self.break_data.is_empty() {
self.break_data.push(acadrust::entities::table::TableBreakData {
position: acadrust::types::Vector3::ZERO,
self.break_data.push(codec::entities::table::TableBreakData {
position: codec::types::Vector3::ZERO,
height: number,
flags: 0,
});
+12 -12
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{Text, TextHorizontalAlignment as HA, TextVerticalAlignment as VA};
use codec::entities::{Text, TextHorizontalAlignment as HA, TextVerticalAlignment as VA};
use crate::command::EntityTransform;
use crate::entities::common::{
@@ -52,7 +52,7 @@ pub(crate) fn sync_text_alignment_point(t: &mut Text) {
* t.width_factor.abs().max(0.01)
* t.value.chars().count().max(1) as f64
* 0.6;
t.alignment_point = Some(acadrust::types::Vector3::new(
t.alignment_point = Some(codec::types::Vector3::new(
t.insertion_point.x + t.rotation.cos() * span,
t.insertion_point.y + t.rotation.sin() * span,
t.insertion_point.z,
@@ -100,13 +100,13 @@ pub struct TextPlacement {
pub wcs_insertion: [f64; 3],
}
/// Parse a TEXT value's `%%` control codes through acadrust's `parse_plain_text`
/// Parse a TEXT value's `%%` control codes through opencadcodec's `parse_plain_text`
/// (the same parser MTEXT uses), then re-encode into the stroke tessellator's
/// inline grammar: specials arrive resolved to Unicode, and `%%u`/`%%o`
/// underline/overline become `\L…\l` / `\O…\o` decoration markers. This keeps
/// TEXT parsing in acadrust rather than OCS's own tokenizer.
/// TEXT parsing in opencadcodec rather than OCS's own tokenizer.
pub(crate) fn acad_text_encode(value: &str) -> String {
use acadrust::entities::mtext_format::parse_plain_text;
use codec::entities::mtext_format::parse_plain_text;
let doc = parse_plain_text(value);
let mut out = String::new();
for para in &doc.paragraphs {
@@ -132,12 +132,12 @@ pub(crate) fn acad_text_encode(value: &str) -> String {
pub(crate) fn to_render_at_scale(
t: &Text,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
annotation_scale: f32,
) -> RenderEntity {
let p = text_run_placement_at_scale(t, document, annotation_scale);
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.
// Parse `%%` codes via opencadcodec, re-encoded for the stroke tessellator.
let value = acad_text_encode(&p.value);
// Strokes are in glyph-local space (origin = [0,0]).
let (strokes, fill_tris) = lff::tessellate_text_ex(
@@ -179,7 +179,7 @@ pub(crate) fn to_render_at_scale(
/// from `to_render` verbatim so the stroke and SDF-quad paths agree exactly.
pub fn text_run_placement_at_scale(
t: &Text,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
annotation_scale: f32,
) -> TextPlacement {
let annotation_scale = if annotation_scale.is_finite() && annotation_scale > 1.0e-9 {
@@ -647,7 +647,7 @@ fn apply_transform(t: &mut Text, tr: &EntityTransform) {
}
impl RenderConvertible for Text {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
Some(to_render_at_scale(self, document, 1.0))
}
}
@@ -721,10 +721,10 @@ mod tests {
let mut t = Text::default();
t.value = "بسم الله".to_string();
t.height = 2.5;
t.insertion_point = acadrust::types::Vector3::new(10.0, 20.0, 0.0);
t.insertion_point = codec::types::Vector3::new(10.0, 20.0, 0.0);
t.horizontal_alignment = HA::Left;
let doc = acadrust::CadDocument::default();
let doc = codec::CadDocument::default();
let placement = text_run_placement_at_scale(&t, &doc, 1.0);
// For Arabic text with default HA::Left, origin should be shifted left
@@ -749,7 +749,7 @@ impl Transformable for Text {
}
}
impl crate::entities::traits::TextContent for acadrust::entities::Text {
impl crate::entities::traits::TextContent for codec::entities::Text {
fn text_content(&self) -> Option<String> {
Some(self.value.clone())
}
+11 -11
View File
@@ -1,5 +1,5 @@
use acadrust::types::aci_table::aci_to_rgb;
use acadrust::CadDocument;
use codec::types::aci_table::aci_to_rgb;
use codec::CadDocument;
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke};
use crate::scene::text::font_face::Face;
@@ -488,24 +488,24 @@ fn font_stem(name: &str) -> String {
.to_string()
}
/// Parse an MTEXT string into the layout's `Vec<MTextLine>`, using acadrust's
/// Parse an MTEXT string into the layout's `Vec<MTextLine>`, using opencadcodec's
/// structured `mtext_format::parse_mtext` — OCS keeps only the layout engine
/// (`layout_mtext` and callers read `MTextLine`/`RunState`), not a second MTEXT
/// inline parser.
///
/// Representation notes:
/// - DXF `%%d`/`%%p`/`%%c` arrive already resolved to Unicode from acadrust;
/// - DXF `%%d`/`%%p`/`%%c` arrive already resolved to Unicode from opencadcodec;
/// the stroke tokenizer treats those as ordinary glyphs.
/// - Stacking (`\S`) is flattened inline to `num<sep>den` (`^` for limit, else
/// `/`) since the stroke path has no fraction layout.
/// - `\H`: a relative factor (`\Hx`) applies directly; an absolute height is
/// divided by the entity height. See `acadrust::…::MTextScalar`.
/// divided by the entity height. See `codec::…::MTextScalar`.
pub fn adapt_mtext_paragraphs(
s: &str,
entity_height: f32,
trim_blank_edges: bool,
) -> Vec<MTextLine> {
use acadrust::entities::mtext_format::{
use codec::entities::mtext_format::{
parse_mtext, MTextColor, MTextLineAlignment, MTextLineSpacing, MTextParagraphAlignment,
MTextScalar, ParagraphProperties, SpanProperties, StackingType,
};
@@ -598,7 +598,7 @@ pub fn adapt_mtext_paragraphs(
.tab_stops
.iter()
.map(|ts| {
use acadrust::entities::mtext_format::TabStop as ATab;
use codec::entities::mtext_format::TabStop as ATab;
let kind = match ts {
ATab::Left(_) => TabKind::Left,
ATab::Center(_) => TabKind::Center,
@@ -719,7 +719,7 @@ pub fn adapt_mtext_paragraphs(
// `measure_mtext_chars`, `word_wrap`) were removed when every text-bearing
// entity switched to the run-aware pipeline below. The pipeline now owns
// per-run width measurement and word-wrap; MTEXT inline parsing now comes from
// acadrust via `adapt_mtext_paragraphs`. The supported surface for callers is
// opencadcodec via `adapt_mtext_paragraphs`. The supported surface for callers is
// `adapt_mtext_paragraphs`, `layout_mtext`, `mtext_line_count`,
// `text_local_bounds`, and `resolve_dxf_special_chars`.
@@ -733,7 +733,7 @@ pub fn adapt_mtext_paragraphs(
// it carries inline codes).
//
// The pipeline mirrors the MTEXT renderer:
// 1. Parse — via `adapt_mtext_paragraphs` (acadrust `parse_mtext`).
// 1. Parse — via `adapt_mtext_paragraphs` (opencadcodec `parse_mtext`).
// 2. Atomise — turn each MTextLine.runs into a flat sequence of atoms
// (Word / Space / Tab) so the wrapper operates at break boundaries
// while keeping per-character formatting state.
@@ -1431,7 +1431,7 @@ pub fn layout_mtext(opts: &MTextRenderOpts) -> MTextLayout {
char_offset: word_start,
});
}
// A literal tab (acadrust keeps `^I` / `\t` as a tab
// A literal tab (opencadcodec keeps `^I` / `\t` as a tab
// char in the span) advances to the paragraph's next
// tab stop, aligning the field that follows it.
atoms.push(LayoutAtom {
@@ -2822,7 +2822,7 @@ mod adapter_tests {
#[test]
fn relative_height_is_a_factor() {
// `\H2x;` multiplies the current height → height_mul 2.0, independent of
// the entity height. (This is the case that needed acadrust's MTextScalar.)
// the entity height. (This is the case that needed opencadcodec's MTextScalar.)
let (_, st) = first_run(&adapt_mtext_paragraphs("\\H2x;big", 2.5, true));
assert!((st.height_mul - 2.0).abs() < 1e-4, "got {}", st.height_mul);
}
+19 -19
View File
@@ -1,4 +1,4 @@
use acadrust::entities::Tolerance;
use codec::entities::Tolerance;
use crate::command::EntityTransform;
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
@@ -155,8 +155,8 @@ pub(crate) fn symbol_font_switch(inner: &str) -> Option<char> {
/// every DWG-read tolerance to "Standard" and pick the wrong metrics.
pub(crate) fn resolve_dim_style<'a>(
tol: &Tolerance,
doc: &'a acadrust::CadDocument,
) -> Option<&'a acadrust::tables::DimStyle> {
doc: &'a codec::CadDocument,
) -> Option<&'a codec::tables::DimStyle> {
if let Some(h) = tol.dimension_style_handle {
if !h.is_null() {
if let Some(s) = doc.dim_styles.iter().find(|s| s.handle == h) {
@@ -269,7 +269,7 @@ struct TolCell {
/// `GlyphRun` so the cell renders as SDF text (frame stays geometry).
fn tessellate_tolerance(
tol: &Tolerance,
doc: &acadrust::CadDocument,
doc: &codec::CadDocument,
) -> (Vec<Vec<[f32; 2]>>, Vec<TolCell>) {
if tol.text.is_empty() {
return (vec![], vec![]);
@@ -444,7 +444,7 @@ fn tessellate_tolerance(
pub(crate) fn preview_strokes(
tol: &Tolerance,
doc: &acadrust::CadDocument,
doc: &codec::CadDocument,
) -> Vec<Vec<[f32; 2]>> {
tessellate_tolerance(tol, doc).0
}
@@ -463,7 +463,7 @@ fn frame_basis(tol: &Tolerance) -> (glam::DVec3, glam::DVec3) {
// ── RenderConvertible ──────────────────────────────────────────────────────────
impl RenderConvertible for Tolerance {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
if self.text.is_empty() {
return None;
}
@@ -493,12 +493,12 @@ impl RenderConvertible for Tolerance {
let explicit_color = |index: Option<i16>| {
index.filter(|value| !matches!(value, 0 | 256)).map(|value| {
let [red, green, blue, _] = crate::scene::convert::tess_util::aci_to_rgba(
&acadrust::types::Color::from_index(value),
&codec::types::Color::from_index(value),
);
[red, green, blue]
})
};
let color_value = |color: &acadrust::types::Color| {
let color_value = |color: &codec::types::Color| {
let [red, green, blue, _] =
crate::scene::convert::tess_util::aci_to_rgba(color);
[red, green, blue]
@@ -784,9 +784,9 @@ mod tests {
/// non-zero default, so trusting that field drew the frame ~10x too small.
#[test]
fn the_frame_is_sized_from_the_dimension_style_not_the_entity_default() {
use acadrust::tables::DimStyle;
let mut doc = acadrust::CadDocument::new();
let handle = acadrust::Handle::from(0x27_u64);
use codec::tables::DimStyle;
let mut doc = codec::CadDocument::new();
let handle = codec::Handle::from(0x27_u64);
let mut style = DimStyle::new("ISO-25");
style.handle = handle;
style.dimtxt = 2.5;
@@ -817,11 +817,11 @@ mod tests {
/// 0.42; reading the style alone drew the frame several times too large.
#[test]
fn an_entity_override_beats_its_dimension_style() {
use acadrust::tables::DimStyle;
use acadrust::xdata::XDataValue;
use codec::tables::DimStyle;
use codec::xdata::XDataValue;
let mut doc = acadrust::CadDocument::new();
let handle = acadrust::Handle::from(0x27_u64);
let mut doc = codec::CadDocument::new();
let handle = codec::Handle::from(0x27_u64);
let mut style = DimStyle::new("ISO-25");
style.handle = handle;
style.dimtxt = 2.5;
@@ -844,7 +844,7 @@ mod tests {
// The entity's own overrides, shaped exactly as the file carries them:
// application "ACAD", naming itself "DSTYLE" in its first string value,
// then (variable code, value) pairs. Variable 140 = text height.
let mut rec = acadrust::xdata::ExtendedDataRecord::new("ACAD");
let mut rec = codec::xdata::ExtendedDataRecord::new("ACAD");
rec.add_value(XDataValue::String("DSTYLE".into()));
rec.add_value(XDataValue::ControlString("{".into()));
rec.add_value(XDataValue::Integer16(140));
@@ -869,7 +869,7 @@ mod tests {
/// Rows read downward and start at the left edge.
#[test]
fn rows_stack_downward_and_left_align() {
let doc = acadrust::CadDocument::new();
let doc = codec::CadDocument::new();
let mut tol = Tolerance::new();
tol.text = BENCH.to_string();
let (boxes, _) = tessellate_tolerance(&tol, &doc);
@@ -925,7 +925,7 @@ mod tests {
/// together inside correctly-sized boxes.
#[test]
fn cells_are_drawn_with_the_spacing_they_were_measured_with() {
let doc = acadrust::CadDocument::new();
let doc = codec::CadDocument::new();
let mut tol = Tolerance::new();
tol.text = "ABC".into();
@@ -1008,7 +1008,7 @@ mod tests {
fn compartments_are_measured_by_their_ink_not_the_trailing_pen_gap() {
// Cap height, so glyph units and world units line up.
let h = 9.0_f32;
let document = acadrust::CadDocument::new();
let document = codec::CadDocument::new();
let text_style = crate::entities::text_support::resolve_text_style("Standard", &document);
for src in ["{\\Fgdt;r}", "{\\Fgdt;n}tol{\\Fgdt;m}", "1{\\Fgdt;m}", "A"] {
let cell = parse_cell(src);
+3 -3
View File
@@ -1,4 +1,4 @@
use acadrust::{CadDocument, EntityType};
use codec::{CadDocument, EntityType};
use crate::command::EntityTransform;
use crate::scene::convert::acad_to_render::RenderEntity;
@@ -112,7 +112,7 @@ pub fn entity_type_name(et: &EntityType) -> &str {
match et {
EntityType::Point(_) => "Point",
EntityType::Line(line)
if acadrust::entities::CenterMarkAssociation::read(
if codec::entities::CenterMarkAssociation::read(
&line.common.extended_data,
)
.is_some() =>
@@ -120,7 +120,7 @@ pub fn entity_type_name(et: &EntityType) -> &str {
"CenterMark"
}
EntityType::Line(line)
if acadrust::entities::CenterLineAssociation::read(
if codec::entities::CenterLineAssociation::read(
&line.common.extended_data,
)
.is_some() =>
+17 -17
View File
@@ -7,7 +7,7 @@
// a PDF underlay. Rows that need the definition (name, page, path,
// width, height) are filled in by the Properties panel.
use acadrust::entities::{Underlay, UnderlayDisplayFlags};
use codec::entities::{Underlay, UnderlayDisplayFlags};
use crate::t;
use glam::DVec3;
@@ -20,7 +20,7 @@ use crate::scene::model::wire_model::SnapHint;
// ── Helpers ───────────────────────────────────────────────────────────────────
fn v3(v: &acadrust::types::Vector3) -> [f64; 3] {
fn v3(v: &codec::types::Vector3) -> [f64; 3] {
[v.x, v.y, v.z]
}
@@ -39,16 +39,16 @@ fn cross_wire(origin: [f64; 3], size: f64) -> Vec<[f64; 3]> {
/// The underlay's definition, when the handle resolves to one.
pub(crate) fn definition<'a>(
u: &Underlay,
document: &'a acadrust::CadDocument,
) -> Option<&'a acadrust::entities::UnderlayDefinition> {
document: &'a codec::CadDocument,
) -> Option<&'a codec::entities::UnderlayDefinition> {
match document.objects.get(&u.definition_handle) {
Some(acadrust::objects::ObjectType::UnderlayDefinition(d)) => Some(d),
Some(codec::objects::ObjectType::UnderlayDefinition(d)) => Some(d),
_ => None,
}
}
/// Page number of a definition ("1" when unset).
pub(crate) fn page_of(def: &acadrust::entities::UnderlayDefinition) -> &str {
pub(crate) fn page_of(def: &codec::entities::UnderlayDefinition) -> &str {
if def.page_name.trim().is_empty() {
"1"
} else {
@@ -58,9 +58,9 @@ pub(crate) fn page_of(def: &acadrust::entities::UnderlayDefinition) -> &str {
/// Size of the referenced page in underlay units (page inches), when the
/// definition resolves and its PDF page can be read.
pub(crate) fn page_size(u: &Underlay, document: &acadrust::CadDocument) -> Option<(f64, f64)> {
pub(crate) fn page_size(u: &Underlay, document: &codec::CadDocument) -> Option<(f64, f64)> {
let def = definition(u, document)?;
if !matches!(def.underlay_type, acadrust::entities::UnderlayType::Pdf) {
if !matches!(def.underlay_type, codec::entities::UnderlayType::Pdf) {
return None;
}
crate::scene::model::pdf_raster::page_size_inches(&def.file_path, page_of(def))
@@ -68,7 +68,7 @@ pub(crate) fn page_size(u: &Underlay, document: &acadrust::CadDocument) -> Optio
/// The name a definition shows: its own name, or "<file> - <page>" as the
/// reference names a PDF definition.
pub(crate) fn definition_display_name(def: &acadrust::entities::UnderlayDefinition) -> String {
pub(crate) fn definition_display_name(def: &codec::entities::UnderlayDefinition) -> String {
if !def.name.trim().is_empty() {
return def.name.clone();
}
@@ -114,7 +114,7 @@ pub(crate) fn is_clipped(u: &Underlay) -> bool {
}
/// Page frame in world space (CCW from the insertion).
fn page_quad(u: &Underlay, document: &acadrust::CadDocument) -> Option<[[f64; 3]; 4]> {
fn page_quad(u: &Underlay, document: &codec::CadDocument) -> Option<[[f64; 3]; 4]> {
let (w, h) = page_size(u, document)?;
Some([
local_to_world(u, [0.0, 0.0]),
@@ -126,7 +126,7 @@ fn page_quad(u: &Underlay, document: &acadrust::CadDocument) -> Option<[[f64; 3]
/// Local-space extent of what is shown: the clip polygon's box when clipped
/// to its inside, else the page.
fn shown_local_extent(u: &Underlay, document: &acadrust::CadDocument) -> Option<(f64, f64)> {
fn shown_local_extent(u: &Underlay, document: &codec::CadDocument) -> Option<(f64, f64)> {
if is_clipped(u) && !u.clip_inverted {
let clip = clip_polygon_local(u);
let (mut lo, mut hi) = ([f64::INFINITY; 2], [f64::NEG_INFINITY; 2]);
@@ -141,7 +141,7 @@ fn shown_local_extent(u: &Underlay, document: &acadrust::CadDocument) -> Option<
/// Width and height the Properties panel shows: the shown extent times the
/// scale (the clip's size once clipped, as the reference reports it).
pub(crate) fn shown_size(u: &Underlay, document: &acadrust::CadDocument) -> Option<(f64, f64)> {
pub(crate) fn shown_size(u: &Underlay, document: &codec::CadDocument) -> Option<(f64, f64)> {
shown_local_extent(u, document).map(|(w, h)| (w * u.x_scale.abs(), h * u.y_scale.abs()))
}
@@ -149,7 +149,7 @@ pub(crate) fn shown_size(u: &Underlay, document: &acadrust::CadDocument) -> Opti
/// inside, else the page frame. `None` when the page is unknown.
pub(crate) fn world_bounds(
u: &Underlay,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
) -> Option<([f64; 3], [f64; 3])> {
let outline: Vec<[f64; 3]> = if is_clipped(u) && !u.clip_inverted {
clip_polygon_local(u).into_iter().map(|p| local_to_world(u, p)).collect()
@@ -224,7 +224,7 @@ pub(crate) fn validate_property(field: &str, value: &str) -> Result<(), &'static
/// size itself is the page (or clip) size times the scale.
pub(crate) fn size_to_scale(
u: &Underlay,
document: &acadrust::CadDocument,
document: &codec::CadDocument,
field: &str,
value: &str,
) -> Option<String> {
@@ -241,7 +241,7 @@ pub(crate) fn size_to_scale(
// ── RenderConvertible ──────────────────────────────────────────────────────────
impl RenderConvertible for Underlay {
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
fn to_render(&self, document: &codec::CadDocument) -> Option<RenderEntity> {
let origin = v3(&self.insertion_point);
let insertion_snap = (
DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z),
@@ -493,7 +493,7 @@ impl Transformable for Underlay {
}
EntityTransform::Mirror { p1, p2, working_normal } => {
if !working_normal.normalize_or(DVec3::Z).abs_diff_eq(DVec3::Z, 1e-10) {
acadrust::Entity::apply_transform(
codec::Entity::apply_transform(
self,
&crate::scene::view::transform::reflection_about_working_line(
*p1,
@@ -549,7 +549,7 @@ impl Transformable for Underlay {
self.rotation += a;
}
EntityTransform::Affine(transform) => {
acadrust::Entity::apply_transform(self, transform);
codec::Entity::apply_transform(self, transform);
}
}
}
+5 -5
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{SectionSymbol, ViewBorder};
use codec::entities::{SectionSymbol, ViewBorder};
use crate::t;
use crate::command::EntityTransform;
@@ -6,7 +6,7 @@ use crate::entities::common::{edit_angle_prop, edit_prop, parse_f64, ro_prop, sq
use crate::entities::traits::{Grippable, PropertyEditable, Transformable};
use crate::scene::model::object::{GripApply, GripDef, PropSection};
fn handle_text(handle: acadrust::Handle) -> String {
fn handle_text(handle: codec::Handle) -> String {
if handle.is_null() {
"None".to_string()
} else {
@@ -14,11 +14,11 @@ fn handle_text(handle: acadrust::Handle) -> String {
}
}
fn vector_text(vector: &acadrust::types::Vector3) -> String {
fn vector_text(vector: &codec::types::Vector3) -> String {
format!("{:.6}, {:.6}, {:.6}", vector.x, vector.y, vector.z)
}
fn apply_entity_transform<T: acadrust::Entity>(entity: &mut T, transform: &EntityTransform) {
fn apply_entity_transform<T: codec::Entity>(entity: &mut T, transform: &EntityTransform) {
crate::scene::view::transform::apply_standard_entity_transform(
entity,
transform,
@@ -56,7 +56,7 @@ impl Grippable for SectionSymbol {
}
GripApply::Absolute(position) => {
point.point =
acadrust::types::Vector3::new(position.x, position.y, position.z);
codec::types::Vector3::new(position.x, position.y, position.z);
}
}
self.sync_display_fields();
+2 -2
View File
@@ -1,4 +1,4 @@
use acadrust::entities::{Viewport, ViewportRenderMode};
use codec::entities::{Viewport, ViewportRenderMode};
use crate::command::EntityTransform;
use crate::entities::common::{
@@ -180,7 +180,7 @@ fn properties(vp: &Viewport) -> Vec<PropSection> {
}
fn apply_geom_prop(vp: &mut Viewport, field: &str, value: &str) {
use acadrust::types::Vector3;
use codec::types::Vector3;
// Boolean / toggle fields handled first (value = "toggle" or "true"/"false").
match field {