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 <noreply@anthropic.com>
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

+3 -3
View File
@@ -1,8 +1,8 @@
// DIMALIGNED command — aligned dimension (measures true distance between two points).
use acadrust::entities::{Dimension, DimensionAligned};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use codec::entities::{Dimension, DimensionAligned};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use glam::DVec3;
use crate::command::{
+6 -6
View File
@@ -1,7 +1,7 @@
use acadrust::entities::{Dimension, DimensionAngular2Ln, DimensionAngular3Pt};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use cadkernel::geom2d::{
use codec::entities::{Dimension, DimensionAngular2Ln, DimensionAngular3Pt};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use kernel::geom2d::{
closest_point, line_line, Arc as KernelArc, BulgeArc, Curve as KernelCurve,
Line as KernelLine,
};
@@ -1172,13 +1172,13 @@ fn angular_preview_with_frame(
let second_end = vertex + DVec3::new(end.cos(), end.sin(), 0.0) * radius;
let mut points = vec![first, first_end, nan(), second, second_end, nan()];
points.extend(
cadkernel::geom2d::tessellate::arc(
kernel::geom2d::tessellate::arc(
[vertex.x, vertex.y],
radius,
start,
end,
vertex.z,
cadkernel::geom2d::tessellate::DEFAULT_SEGMENTS_PER_RADIAN,
kernel::geom2d::tessellate::DEFAULT_SEGMENTS_PER_RADIAN,
)
.into_iter()
.map(DVec3::from_array),
+1 -1
View File
@@ -1,4 +1,4 @@
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
+4 -4
View File
@@ -1,7 +1,7 @@
use acadrust::entities::{Dimension, DimensionArc};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use cadkernel::geom2d::tessellate::{arc, DEFAULT_SEGMENTS_PER_RADIAN};
use codec::entities::{Dimension, DimensionArc};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use kernel::geom2d::tessellate::{arc, DEFAULT_SEGMENTS_PER_RADIAN};
use glam::DVec3;
use crate::command::{
+5 -5
View File
@@ -4,8 +4,8 @@ use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::model::wire_model::WireModel;
use crate::t;
use acadrust::entities::Table;
use acadrust::EntityType;
use codec::entities::Table;
use codec::EntityType;
use glam::DVec3;
pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/data_link.svg"));
@@ -38,8 +38,8 @@ impl DataLinkPlaceCommand {
/// Place a table that references a data-link object already stored in the
/// drawing. Every populated cell is locked and points at the same link so
/// update and save/reopen keep one stable relationship.
pub fn existing(mut table: Table, link: acadrust::Handle) -> Self {
use acadrust::entities::table::CellStateFlags;
pub fn existing(mut table: Table, link: codec::Handle) -> Self {
use codec::entities::table::CellStateFlags;
let rows = table.row_count() as i32;
let columns = table.column_count() as i32;
for row in &mut table.rows {
@@ -156,7 +156,7 @@ impl CadCommand for DataLinkPlaceCommand {
fn on_point(&mut self, point: DVec3) -> CmdResult {
let point = self.plane.to_local(point);
self.table.insertion_point = acadrust::types::Vector3::new(point.x, point.y, point.z);
self.table.insertion_point = codec::types::Vector3::new(point.x, point.y, point.z);
CmdResult::CommitAndExit(
self.plane
.place_entity(EntityType::Table(self.table.clone())),
+1 -1
View File
@@ -7,7 +7,7 @@
// the rich MText editor for MText / MultiLeader. A Leader resolves to the
// entity it annotates.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{Dimension, DimensionDiameter};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use codec::entities::{Dimension, DimensionDiameter};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use glam::{DVec3, Vec3};
use crate::command::{
+5 -5
View File
@@ -1,16 +1,16 @@
use std::collections::HashMap;
use std::f64::consts::PI;
use acadrust::entities::{
use codec::entities::{
Dimension, DimensionAligned, DimensionAngular2Ln, DimensionAngular3Pt, DimensionBase,
DimensionLinear, DimensionOrdinate,
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::{
arc_span, intersect, nearest_of, Arc, Curve, Line, Tolerance, Transform, Vec2, XLine,
};
use cadkernel::space::Plane;
use kernel::space::Plane;
use glam::DVec3;
use crate::command::{
+5 -5
View File
@@ -1,14 +1,14 @@
use acadrust::entities::{
use codec::entities::{
Dimension, DimensionAngular2Ln, DimensionAngular3Pt, DimensionBase, DimensionLinear,
DimensionOrdinate,
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::{
arc_span, closest_point, intersect, nearest_of, Arc, Curve, Ray, Tolerance, Transform, Vec2,
XLine,
};
use cadkernel::space::Plane;
use kernel::space::Plane;
use glam::DVec3;
use crate::command::{
+1 -1
View File
@@ -1,6 +1,6 @@
// DIMBREAK — create automatic, object-driven or manual gaps in dimensions.
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
+1 -1
View File
@@ -1,6 +1,6 @@
// DIMEDIT — edit dimension text, rotation, extension-line obliquing or home position.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{
+4 -4
View File
@@ -1,7 +1,7 @@
// DIMJOGLINE — add or remove a jog on a linear/aligned dimension.
use acadrust::entities::Dimension;
use acadrust::{EntityType, Handle};
use codec::entities::Dimension;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
@@ -77,7 +77,7 @@ impl DimJogLineCommand {
} else {
[f64::NAN; 3]
};
cadkernel::space::default_dimension_jog_position(
kernel::space::default_dimension_jog_position(
[first.x, first.y, first.z],
[second.x, second.y, second.z],
[definition.x, definition.y, definition.z],
@@ -204,7 +204,7 @@ impl CadCommand for DimJogLineCommand {
),
_ => return None,
};
let points = cadkernel::space::dimension_jog_points(
let points = kernel::space::dimension_jog_points(
segment,
point.to_array(),
normal,
+5 -5
View File
@@ -5,7 +5,7 @@
// 2. Select the other dimensions to space (click each, Enter to finish)
// 3. Enter a non-negative spacing value, or choose Auto
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind, SelectionEntity};
@@ -107,8 +107,8 @@ impl CadCommand for DimSpaceCommand {
&& matches!(
selected.entity,
EntityType::Dimension(
acadrust::entities::Dimension::Linear(_)
| acadrust::entities::Dimension::Aligned(_)
codec::entities::Dimension::Linear(_)
| codec::entities::Dimension::Aligned(_)
)
)
&& !others.contains(&selected.handle)
@@ -127,8 +127,8 @@ impl CadCommand for DimSpaceCommand {
if !matches!(
self.picked_entity.take(),
Some(EntityType::Dimension(
acadrust::entities::Dimension::Linear(_)
| acadrust::entities::Dimension::Aligned(_)
codec::entities::Dimension::Linear(_)
| codec::entities::Dimension::Aligned(_)
))
) {
return CmdResult::ReportError(
+6 -6
View File
@@ -1,7 +1,7 @@
// DIMTEDIT — reposition, justify, home or rotate existing dimension text.
use acadrust::entities::{AttachmentPointType, Dimension};
use acadrust::{EntityType, Handle};
use codec::entities::{AttachmentPointType, Dimension};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
@@ -184,7 +184,7 @@ impl CadCommand for DimTeditCommand {
let EntityType::Dimension(dimension) = &mut entity else {
return CmdResult::Cancel;
};
let point = acadrust::types::Vector3::new(point.x, point.y, point.z);
let point = codec::types::Vector3::new(point.x, point.y, point.z);
let base = dimension.base_mut();
base.text_middle_point = point;
base.insertion_point = point;
@@ -274,8 +274,8 @@ fn dimension_line_endpoints(dimension: &Dimension) -> Option<(DVec3, DVec3)> {
fn apply_placement(dimension: &mut Dimension, placement: Placement) {
if matches!(placement, Placement::Home) {
let base = dimension.base_mut();
base.text_middle_point = acadrust::types::Vector3::ZERO;
base.insertion_point = acadrust::types::Vector3::ZERO;
base.text_middle_point = codec::types::Vector3::ZERO;
base.insertion_point = codec::types::Vector3::ZERO;
base.text_user_positioned = false;
base.attachment_point = AttachmentPointType::MiddleCenter;
return;
@@ -289,7 +289,7 @@ fn apply_placement(dimension: &mut Dimension, placement: Placement) {
Placement::Center => ((left + right) * 0.5, AttachmentPointType::MiddleCenter),
Placement::Home => unreachable!(),
};
let point = acadrust::types::Vector3::new(point.x, point.y, point.z);
let point = codec::types::Vector3::new(point.x, point.y, point.z);
let base = dimension.base_mut();
base.text_middle_point = point;
base.insertion_point = point;
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{Dimension, DimensionLargeRadial};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use codec::entities::{Dimension, DimensionLargeRadial};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use glam::{DVec3, Vec3};
use crate::command::{
+4 -4
View File
@@ -9,10 +9,10 @@
// The MText is a separate entity referenced by the leader's annotation_handle
// (DXF group 340); editing/erasing them stays in sync via that link.
use acadrust::entities::mtext::AttachmentPoint;
use acadrust::entities::{Leader, LeaderCreationType, LeaderPathType, MText};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::mtext::AttachmentPoint;
use codec::entities::{Leader, LeaderCreationType, LeaderPathType, MText};
use codec::types::Vector3;
use codec::EntityType;
use glam::{DVec3, Mat4, Vec3};
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind, WorkingPlane};
+6 -6
View File
@@ -1,7 +1,7 @@
use acadrust::entities::{Dimension, DimensionLinear};
use acadrust::types::Vector3;
use acadrust::EntityType;
use cadkernel::geom2d::{
use codec::entities::{Dimension, DimensionLinear};
use codec::types::Vector3;
use codec::EntityType;
use kernel::geom2d::{
closest_point, Circle as KernelCircle, Curve, Line as KernelLine,
};
@@ -87,7 +87,7 @@ pub struct LinearDimensionCommand {
axis_mode: AxisMode,
selecting_object: bool,
picked_entity: Option<EntityType>,
source_handle: Option<acadrust::Handle>,
source_handle: Option<codec::Handle>,
mtext_override: bool,
}
@@ -368,7 +368,7 @@ impl CadCommand for LinearDimensionCommand {
self.picked_entity = Some(entity);
}
fn on_entity_pick(&mut self, handle: acadrust::Handle, point: DVec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: codec::Handle, point: DVec3) -> CmdResult {
let Some(entity) = self.picked_entity.take() else {
return CmdResult::NeedPoint;
};
+33 -33
View File
@@ -1,8 +1,8 @@
// MLEADER: pick the arrow and elbow, then edit the text.
use acadrust::entities::{LeaderContentType, MultiLeader, MultiLeaderPathType};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::{LeaderContentType, MultiLeader, MultiLeaderPathType};
use codec::types::Vector3;
use codec::EntityType;
use glam::{DVec3, Mat4, Vec3};
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind, WorkingPlane};
@@ -24,7 +24,7 @@ pub fn tool() -> ToolDef {
pub struct MLeaderCommand {
verts: Vec<DVec3>,
plane: WorkingPlane,
style: Option<acadrust::objects::MultiLeaderStyle>,
style: Option<codec::objects::MultiLeaderStyle>,
display_scale: f64,
order: CreationOrder,
step: Step,
@@ -38,11 +38,11 @@ pub struct MLeaderCommand {
layer: String,
text: String,
picked_entity: Option<EntityType>,
selected_mtext: Option<acadrust::entities::MText>,
block_sources: Vec<(String, acadrust::Handle)>,
block_handle: Option<acadrust::Handle>,
selected_mtext: Option<codec::entities::MText>,
block_sources: Vec<(String, codec::Handle)>,
block_handle: Option<codec::Handle>,
layers: Vec<String>,
text_styles: Vec<(String, acadrust::Handle)>,
text_styles: Vec<(String, codec::Handle)>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -97,7 +97,7 @@ impl MLeaderCommand {
}
pub fn with_style(
style: acadrust::objects::MultiLeaderStyle,
style: codec::objects::MultiLeaderStyle,
annotation_multiplier: f64,
) -> Self {
let display_scale = if style.is_annotative {
@@ -134,9 +134,9 @@ impl MLeaderCommand {
pub fn with_drawing_resources(
mut self,
block_sources: Vec<(String, acadrust::Handle)>,
block_sources: Vec<(String, codec::Handle)>,
layers: Vec<String>,
text_styles: Vec<(String, acadrust::Handle)>,
text_styles: Vec<(String, codec::Handle)>,
) -> Self {
self.block_sources = block_sources;
self.layers = layers;
@@ -226,36 +226,36 @@ impl MLeaderCommand {
ml.context.background_fill_color = source.background_color;
ml.context.background_transparency = source.background_transparency;
ml.context.text_flow_direction = match source.drawing_direction {
acadrust::entities::mtext::DrawingDirection::LeftToRight => {
acadrust::entities::multileader::FlowDirectionType::Horizontal
codec::entities::mtext::DrawingDirection::LeftToRight => {
codec::entities::multileader::FlowDirectionType::Horizontal
}
acadrust::entities::mtext::DrawingDirection::TopToBottom => {
acadrust::entities::multileader::FlowDirectionType::Vertical
codec::entities::mtext::DrawingDirection::TopToBottom => {
codec::entities::multileader::FlowDirectionType::Vertical
}
acadrust::entities::mtext::DrawingDirection::ByStyle => {
acadrust::entities::multileader::FlowDirectionType::ByStyle
codec::entities::mtext::DrawingDirection::ByStyle => {
codec::entities::multileader::FlowDirectionType::ByStyle
}
};
let (attachment, alignment) = match source.attachment_point {
acadrust::entities::mtext::AttachmentPoint::TopCenter
| acadrust::entities::mtext::AttachmentPoint::MiddleCenter
| acadrust::entities::mtext::AttachmentPoint::BottomCenter => {
codec::entities::mtext::AttachmentPoint::TopCenter
| codec::entities::mtext::AttachmentPoint::MiddleCenter
| codec::entities::mtext::AttachmentPoint::BottomCenter => {
(
acadrust::entities::multileader::TextAttachmentPointType::Center,
acadrust::entities::TextAlignmentType::Center,
codec::entities::multileader::TextAttachmentPointType::Center,
codec::entities::TextAlignmentType::Center,
)
}
acadrust::entities::mtext::AttachmentPoint::TopRight
| acadrust::entities::mtext::AttachmentPoint::MiddleRight
| acadrust::entities::mtext::AttachmentPoint::BottomRight => {
codec::entities::mtext::AttachmentPoint::TopRight
| codec::entities::mtext::AttachmentPoint::MiddleRight
| codec::entities::mtext::AttachmentPoint::BottomRight => {
(
acadrust::entities::multileader::TextAttachmentPointType::Right,
acadrust::entities::TextAlignmentType::Right,
codec::entities::multileader::TextAttachmentPointType::Right,
codec::entities::TextAlignmentType::Right,
)
}
_ => (
acadrust::entities::multileader::TextAttachmentPointType::Left,
acadrust::entities::TextAlignmentType::Left,
codec::entities::multileader::TextAttachmentPointType::Left,
codec::entities::TextAlignmentType::Left,
),
};
ml.context.text_attachment_point = attachment;
@@ -625,7 +625,7 @@ impl CadCommand for MLeaderCommand {
self.picked_entity = Some(entity);
}
fn on_entity_pick(&mut self, _handle: acadrust::Handle, _point: DVec3) -> CmdResult {
fn on_entity_pick(&mut self, _handle: codec::Handle, _point: DVec3) -> CmdResult {
let Some(EntityType::MText(text)) = self.picked_entity.take() else {
return CmdResult::NeedPoint;
};
@@ -655,7 +655,7 @@ fn build_mleader(
verts: &[DVec3],
content_point: Option<DVec3>,
ucs: Mat4,
style: Option<&acadrust::objects::MultiLeaderStyle>,
style: Option<&codec::objects::MultiLeaderStyle>,
display_scale: f64,
) -> MultiLeader {
// First point is the arrow, last point is the elbow. Intermediate points
@@ -695,9 +695,9 @@ fn build_mleader(
let landing = ux * (sign as f32);
ml.context.text_attachment_point =
if to_right {
acadrust::entities::multileader::TextAttachmentPointType::Left
codec::entities::multileader::TextAttachmentPointType::Left
} else {
acadrust::entities::multileader::TextAttachmentPointType::Right
codec::entities::multileader::TextAttachmentPointType::Right
};
ml.context.text_rotation = (ux.y as f64).atan2(ux.x as f64);
+4 -4
View File
@@ -5,10 +5,10 @@
// MLEADERALIGN: select multileaders → pick base alignment direction
// MLEADERCOLLECT: select block-content multileaders → pick collection point
use acadrust::entities::{LeaderLine, MultiLeader};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{closest_point, Curve, Line};
use codec::entities::{LeaderLine, MultiLeader};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::{closest_point, Curve, Line};
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::mtext::AttachmentPoint;
use acadrust::types::Vector3;
use acadrust::MText;
use codec::entities::mtext::AttachmentPoint;
use codec::types::Vector3;
use codec::MText;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, DynField, InputKind, WorkingPlane};
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{Dimension, DimensionOrdinate};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::{Dimension, DimensionOrdinate};
use codec::types::Vector3;
use codec::EntityType;
use glam::{DVec3, Vec3};
use crate::command::{
+4 -4
View File
@@ -1,9 +1,9 @@
//! Quick dimension creation from a selected set of drawing entities.
use acadrust::entities::{Dimension, DimensionDiameter, DimensionLinear, DimensionOrdinate, DimensionRadius};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{characteristic_points, intersect, Curve, SnapKind, Tolerance};
use codec::entities::{Dimension, DimensionDiameter, DimensionLinear, DimensionOrdinate, DimensionRadius};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::{characteristic_points, intersect, Curve, SnapKind, Tolerance};
use glam::DVec3;
use crate::command::{
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{Dimension, DimensionRadius};
use acadrust::types::{Handle, Vector3};
use acadrust::EntityType;
use codec::entities::{Dimension, DimensionRadius};
use codec::types::{Handle, Vector3};
use codec::EntityType;
use crate::command::{
CadCommand, CmdOption, CmdResult, DimensionAssociationInput, DimensionPreview, InputKind,
+27 -27
View File
@@ -4,10 +4,10 @@
// data rows. The command remembers its previous settings and supports either a
// fixed insertion point or a two-corner sizing window.
use acadrust::entities::table::{CellStyle, CellStylePropertyFlags};
use acadrust::entities::TableBuilder;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::table::{CellStyle, CellStylePropertyFlags};
use codec::entities::TableBuilder;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use std::sync::{Mutex, OnceLock};
@@ -96,7 +96,7 @@ enum Step {
pub struct TableCommand {
step: Step,
style_handle: Option<acadrust::Handle>,
style_handle: Option<codec::Handle>,
suggested_column_width: f64,
suggested_row_height: f64,
preview_scale: f64,
@@ -107,7 +107,7 @@ pub struct TableCommand {
plane: WorkingPlane,
}
fn cell_style_from_row(style: &acadrust::objects::RowCellStyle) -> CellStyle {
fn cell_style_from_row(style: &codec::objects::RowCellStyle) -> CellStyle {
let mut result = CellStyle::new();
result.property_flags = CellStylePropertyFlags::DATA_TYPE
| CellStylePropertyFlags::DATA_FORMAT
@@ -130,7 +130,7 @@ fn cell_style_from_row(style: &acadrust::objects::RowCellStyle) -> CellStyle {
}
fn selected_row_style(
table_style: &acadrust::objects::TableStyle,
table_style: &codec::objects::TableStyle,
name: &str,
) -> CellStyle {
let style = if name.eq_ignore_ascii_case("Title") {
@@ -160,8 +160,8 @@ impl TableCommand {
}
pub fn with_style(
style_handle: acadrust::Handle,
style: &acadrust::objects::TableStyle,
style_handle: codec::Handle,
style: &codec::objects::TableStyle,
annotation_multiplier: f64,
) -> Self {
let text_height = style
@@ -192,7 +192,7 @@ impl TableCommand {
/// Table dialog. The dialog owns validation, so the command starts at the
/// point/window placement step instead of asking for the same values again.
pub fn configured(
style: Option<(acadrust::Handle, &acadrust::objects::TableStyle)>,
style: Option<(codec::Handle, &codec::objects::TableStyle)>,
annotation_multiplier: f64,
columns: usize,
data_rows: usize,
@@ -609,7 +609,7 @@ pub(crate) enum TableCellEditStart {
impl TableCellHit {
/// Flat cell index, matching the Properties palette ordering.
pub fn index(&self, table: &acadrust::entities::Table) -> usize {
pub fn index(&self, table: &codec::entities::Table) -> usize {
self.row * table.column_count() + self.column
}
}
@@ -620,8 +620,8 @@ impl TableCellHit {
/// object the table references, when the caller has the document at hand;
/// the table's embedded base style covers the common fallbacks.
pub(crate) fn table_cell_at(
table: &acadrust::entities::Table,
table_style: Option<&acadrust::objects::TableStyle>,
table: &codec::entities::Table,
table_style: Option<&codec::objects::TableStyle>,
click_world: DVec3,
) -> Option<TableCellHit> {
let horizontal = glam::DVec3::new(
@@ -671,8 +671,8 @@ pub(crate) fn table_cell_at(
}
/// True when the cell's content may not be edited (locked or read-only).
pub(crate) fn cell_locked(table: &acadrust::entities::Table, row: usize, column: usize) -> bool {
use acadrust::entities::table::CellStateFlags;
pub(crate) fn cell_locked(table: &codec::entities::Table, row: usize, column: usize) -> bool {
use codec::entities::table::CellStateFlags;
table.cell(row, column).is_some_and(|cell| {
cell.state
.intersects(CellStateFlags::CONTENT_LOCKED | CellStateFlags::CONTENT_READ_ONLY)
@@ -708,7 +708,7 @@ impl CadCommand for TableditCommand {
fn on_point(&mut self, point: DVec3) -> CmdResult {
CmdResult::EditTableCell {
handle: acadrust::Handle::NULL,
handle: codec::Handle::NULL,
point,
}
}
@@ -725,16 +725,16 @@ inventory::submit!(crate::command::CommandRegistration {
});
pub struct TableCellEditCommand {
handle: acadrust::Handle,
table: acadrust::entities::Table,
handle: codec::Handle,
table: codec::entities::Table,
row: usize,
column: usize,
}
impl TableCellEditCommand {
pub fn new(
handle: acadrust::Handle,
table: &acadrust::entities::Table,
handle: codec::Handle,
table: &codec::entities::Table,
row: usize,
column: usize,
) -> Self {
@@ -779,7 +779,7 @@ impl CadCommand for TableCellEditCommand {
}
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
use acadrust::entities::table::CellStateFlags;
use codec::entities::table::CellStateFlags;
let cell = self.table.cell_mut(self.row, self.column)?;
if cell
.state
@@ -815,9 +815,9 @@ mod tabledit_tests {
//! default orientation (horizontal +X, flow down).
use super::{table_cell_at, TableCellEditCommand, TableCellHit, TableditCommand};
use crate::command::{CadCommand, CmdResult};
use acadrust::entities::Table;
use acadrust::entities::table::CellStateFlags;
use acadrust::types::Vector3;
use codec::entities::Table;
use codec::entities::table::CellStateFlags;
use codec::types::Vector3;
use glam::DVec3;
fn table_2x2() -> Table {
@@ -892,7 +892,7 @@ mod tabledit_tests {
handle,
point,
} => {
assert_eq!(handle, acadrust::Handle::NULL);
assert_eq!(handle, codec::Handle::NULL);
assert_eq!(point, DVec3::new(1.0, 2.0, 0.0));
}
_ => panic!("expected EditTableCell"),
@@ -904,7 +904,7 @@ mod tabledit_tests {
#[test]
fn table_cell_edit_formats_newlines() {
let table = table_2x2();
let handle = acadrust::Handle::new(42);
let handle = codec::Handle::new(42);
let mut edit_cmd = TableCellEditCommand::new(handle, &table, 0, 0);
let result = edit_cmd
.on_text_input("Line1/nLine2\\nLine3\nLine4")
@@ -912,7 +912,7 @@ mod tabledit_tests {
match result {
CmdResult::ReplaceMany(repl, _) => {
assert_eq!(repl.len(), 1);
if let acadrust::EntityType::Table(t) = &repl[0].1[0] {
if let codec::EntityType::Table(t) = &repl[0].1[0] {
assert_eq!(t.cell_text(0, 0).unwrap(), "Line1\\PLine2\\PLine3\\PLine4");
} else {
panic!("expected Table entity");
+3 -3
View File
@@ -1,8 +1,8 @@
use acadrust::entities::{
use codec::entities::{
Text, TextHorizontalAlignment as HA, TextVerticalAlignment as VA,
};
use acadrust::tables::TextStyle;
use acadrust::types::Vector3;
use codec::tables::TextStyle;
use codec::types::Vector3;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, WorkingPlane};
+1 -1
View File
@@ -7,7 +7,7 @@
// and when closed, resumes the command loop.
// 4. In Single mode, editing an object exits the command immediately.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
+3 -3
View File
@@ -2,9 +2,9 @@
//
// The structured editor prepares the frame; this command places it.
use acadrust::entities::Tolerance;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::Tolerance;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
+1 -1
View File
@@ -15,7 +15,7 @@ pub const MENU_ITEMS: &[(&str, &str, IconKind)] = &[
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use codec::Handle;
use glam::{DVec3, Vec3};
use crate::t;
+3 -3
View File
@@ -1,9 +1,9 @@
// Arc creation commands.
use acadrust::types::Vector3;
use acadrust::{Arc as CadArc, EntityType};
use codec::types::Vector3;
use codec::{Arc as CadArc, EntityType};
use crate::t;
use cadkernel::geom2d::{self, Curve as KernelCurve};
use kernel::geom2d::{self, Curve as KernelCurve};
use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::modules::IconKind;
+3 -3
View File
@@ -6,9 +6,9 @@
// 3. Text: Enter default value (optional — press Enter for blank)
// 4. Point: Click insertion point
use acadrust::entities::AttributeDefinition;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::AttributeDefinition;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use crate::t;
+3 -3
View File
@@ -1,8 +1,8 @@
//! Associative centre-line construction from lines and linear polyline segments.
use acadrust::entities::{CenterLineAssociation, CenterLineSource};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::entities::{CenterLineAssociation, CenterLineSource};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
+4 -4
View File
@@ -1,8 +1,8 @@
// Circle creation commands.
use acadrust::types::Vector3;
use acadrust::{Circle, EntityType};
use cadkernel::geom2d::{
use codec::types::Vector3;
use codec::{Circle, EntityType};
use kernel::geom2d::{
fillets_between, Circle as KernelCircle, Curve as KernelCurve, Line as KernelLine,
Tolerance,
};
@@ -91,7 +91,7 @@ fn circumcircle(
plane: WorkingPlane,
) -> Option<(DVec3, f64)> {
let (a, b, c) = (plane.to_local(a), plane.to_local(b), plane.to_local(c));
let circle = cadkernel::geom2d::arc_through_points(
let circle = kernel::geom2d::arc_through_points(
[a.x, a.y],
[b.x, b.y],
[c.x, c.y],
+3 -3
View File
@@ -1,8 +1,8 @@
// Legacy centre cross and associative centre mark commands.
use acadrust::types::Vector3;
use acadrust::entities::{CenterMarkAssociation, CenterMarkSource};
use acadrust::{EntityType, Handle, Line};
use codec::types::Vector3;
use codec::entities::{CenterMarkAssociation, CenterMarkSource};
use codec::{EntityType, Handle, Line};
use glam::DVec3;
use crate::t;
+4 -4
View File
@@ -1,8 +1,8 @@
// DONUT creates a ring as a closed, constant-width LwPolyline.
use acadrust::entities::{LwPolyline, LwVertex};
use acadrust::EntityType;
use cadkernel::geom2d::{
use codec::entities::{LwPolyline, LwVertex};
use codec::EntityType;
use kernel::geom2d::{
Circle as KernelCircle, Curve as KernelCurve, Vec2 as KernelVec2,
};
use glam::DVec3;
@@ -254,7 +254,7 @@ fn donut_wire(
}
pub(crate) fn make_donut(cx: f64, cy: f64, elevation: f64, inner_r: f64, outer_r: f64) -> EntityType {
use acadrust::types::Vector2;
use codec::types::Vector2;
let r_avg = (inner_r + outer_r) / 2.0;
let width = outer_r - inner_r;
+2 -2
View File
@@ -5,8 +5,8 @@
// ELLIPSE_AXIS — Axis, End (axis endpoint 1 → endpoint 2 → minor distance)
// ELLIPSE_ARC — Ellipse Arc (shape as above, then start/end parametric angles)
use acadrust::types::Vector3;
use acadrust::{Ellipse, EntityType};
use codec::types::Vector3;
use codec::{Ellipse, EntityType};
use crate::t;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
+5 -5
View File
@@ -1,8 +1,8 @@
use acadrust::entities::{face3d::InvisibleEdgeFlags, Face3D};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::Tolerance;
use cadkernel::space::{curve::segments_overlap_collinearly, Vec3 as KernelVec3};
use codec::entities::{face3d::InvisibleEdgeFlags, Face3D};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::Tolerance;
use kernel::space::{curve::segments_overlap_collinearly, Vec3 as KernelVec3};
use glam::DVec3;
use std::collections::{HashMap, HashSet};
+26 -26
View File
@@ -4,8 +4,8 @@ use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::modules::IconKind;
use crate::scene::model::hatch_model::{HatchModel, HatchPattern, PatFamily};
use crate::scene::model::wire_model::WireModel;
use acadrust::Handle;
use cadkernel::geom2d::{
use codec::Handle;
use kernel::geom2d::{
bounded_faces, contains, ring_nesting_depths, signed_area, Circle, Curve, Line, Tolerance,
};
use glam::DVec3;
@@ -199,11 +199,11 @@ pub struct HatchCommand {
default_origin: [f64; 2],
associative: bool,
separate_hatches: bool,
island_style: acadrust::entities::HatchStyleType,
island_style: codec::entities::HatchStyleType,
inherited: Option<(
HatchModel,
acadrust::types::Color,
acadrust::types::Transparency,
codec::types::Color,
codec::types::Transparency,
)>,
plane: WorkingPlane,
}
@@ -215,8 +215,8 @@ impl HatchCommand {
selected_objects: Vec<Handle>,
inherited: Option<(
HatchModel,
acadrust::types::Color,
acadrust::types::Transparency,
codec::types::Color,
codec::types::Transparency,
)>,
plane: WorkingPlane,
) -> Self {
@@ -251,7 +251,7 @@ impl HatchCommand {
island_style: inherited
.as_ref()
.map(|(model, _, _)| model.style)
.unwrap_or(acadrust::entities::HatchStyleType::Normal),
.unwrap_or(codec::entities::HatchStyleType::Normal),
inherited,
plane,
};
@@ -293,9 +293,9 @@ impl HatchCommand {
fn island_style_label(&self) -> &'static str {
match self.island_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",
}
}
@@ -339,7 +339,7 @@ impl HatchCommand {
x_axis: self.plane.x.to_array(),
y_axis: self.plane.y.to_array(),
};
let exterior: Vec<bool> = cadkernel::geom2d::ring_nesting_depths(&rings)
let exterior: Vec<bool> = kernel::geom2d::ring_nesting_depths(&rings)
.into_iter()
.map(|depth| depth == 0)
.collect();
@@ -468,9 +468,9 @@ impl HatchCommand {
}
}
fn manual_boundary_path(&self) -> Option<acadrust::entities::BoundaryPath> {
use acadrust::entities::{BoundaryEdge, BoundaryPath, PolylineEdge};
use acadrust::types::Vector3;
fn manual_boundary_path(&self) -> Option<codec::entities::BoundaryPath> {
use codec::entities::{BoundaryEdge, BoundaryPath, PolylineEdge};
use codec::types::Vector3;
if self.manual_pts.len() < 3 {
return None;
}
@@ -496,7 +496,7 @@ impl HatchCommand {
}
fn arc_bulge(start: DVec3, middle: DVec3, end: DVec3) -> Option<f64> {
let curvature = DVec3::from_array(cadkernel::space::curve::curvature_through(
let curvature = DVec3::from_array(kernel::space::curve::curvature_through(
start.to_array(),
middle.to_array(),
end.to_array(),
@@ -885,14 +885,14 @@ impl CadCommand for HatchCommand {
}
"Y" | "ISLAND" => {
self.island_style = match self.island_style {
acadrust::entities::HatchStyleType::Normal => {
acadrust::entities::HatchStyleType::Outer
codec::entities::HatchStyleType::Normal => {
codec::entities::HatchStyleType::Outer
}
acadrust::entities::HatchStyleType::Outer => {
acadrust::entities::HatchStyleType::Ignore
codec::entities::HatchStyleType::Outer => {
codec::entities::HatchStyleType::Ignore
}
acadrust::entities::HatchStyleType::Ignore => {
acadrust::entities::HatchStyleType::Normal
codec::entities::HatchStyleType::Ignore => {
codec::entities::HatchStyleType::Normal
}
};
Some(CmdResult::NeedPoint)
@@ -956,7 +956,7 @@ impl GradientCommand {
fn make_hatch(&self, rings: Vec<Vec<[f64; 2]>>) -> HatchModel {
let (rel, origin, wcs) = pack_rings(&rings);
let exterior: Vec<bool> = cadkernel::geom2d::ring_nesting_depths(&rings)
let exterior: Vec<bool> = kernel::geom2d::ring_nesting_depths(&rings)
.into_iter()
.map(|depth| depth == 0)
.collect();
@@ -994,7 +994,7 @@ impl GradientCommand {
boundary_exterior: Some(std::sync::Arc::new(exterior)),
boundary_sources: Some(std::sync::Arc::new(boundary_sources)),
boundary_paths: Some(std::sync::Arc::new(boundary_paths)),
style: acadrust::entities::HatchStyleType::Normal,
style: codec::entities::HatchStyleType::Normal,
draw_depth: 0.0,
}
}
@@ -1297,7 +1297,7 @@ impl BoundaryCommand {
}
}
fn make_entities(&self) -> Vec<acadrust::EntityType> {
fn make_entities(&self) -> Vec<codec::EntityType> {
let sources = if self.restrict_sources {
&self.active_sources
} else {
@@ -1577,7 +1577,7 @@ inventory::submit!(crate::command::CommandRegistration { names: &["HATCH"] });
#[cfg(test)]
mod tests {
use super::*;
use acadrust::EntityType;
use codec::EntityType;
fn rect(x0: f64, y0: f64, x1: f64, y1: f64) -> Vec<[f64; 2]> {
vec![[x0, y0], [x1, y0], [x1, y1], [x0, y1]]
+39 -39
View File
@@ -8,7 +8,7 @@
// A <degrees> — change angle
// Press Enter to apply changes.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
@@ -30,20 +30,20 @@ pub struct HatcheditCommand {
disassociate: bool,
store_origin: bool,
current_origin: [f64; 2],
origin_plane: cadkernel::space::Plane,
origin_plane: kernel::space::Plane,
origin_bounds: Option<([f64;2],[f64;2])>,
origin_bounds_unavailable: bool,
style: Option<acadrust::entities::HatchStyleType>,
style: Option<codec::entities::HatchStyleType>,
annotative: Option<bool>,
annotative_current: bool,
style_current: acadrust::entities::HatchStyleType,
style_current: codec::entities::HatchStyleType,
input: Option<&'static str>,
source_appearance: Option<(acadrust::types::Color,String,acadrust::types::Transparency)>,
current_color: acadrust::types::Color,
current_transparency: acadrust::types::Transparency,
source_appearance: Option<(codec::types::Color,String,codec::types::Transparency)>,
current_color: codec::types::Color,
current_transparency: codec::types::Transparency,
boundary_region: bool,
association_sources: Option<(crate::command::WorkingPlane,rustc_hash::FxHashMap<Handle,crate::scene::BoundarySource>)>,
association_paths: Vec<acadrust::entities::BoundaryPath>,
association_paths: Vec<codec::entities::BoundaryPath>,
association_missed: bool,
}
@@ -57,15 +57,15 @@ impl HatcheditCommand {
origin_bounds: None,
origin_bounds_unavailable: false,
current_origin: [0.0, 0.0],
origin_plane: cadkernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
origin_plane: kernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
style: None,
annotative: None,
annotative_current: false,
style_current: acadrust::entities::HatchStyleType::Normal,
style_current: codec::entities::HatchStyleType::Normal,
input: None,
source_appearance: None,
current_color: acadrust::types::Color::ByLayer,
current_transparency: acadrust::types::Transparency::ByLayer,
current_color: codec::types::Color::ByLayer,
current_transparency: codec::types::Transparency::ByLayer,
boundary_region: false,
association_sources: None,
association_paths: Vec::new(),
@@ -93,15 +93,15 @@ impl HatcheditCommand {
origin_bounds: None,
origin_bounds_unavailable: false,
current_origin: [0.0, 0.0],
origin_plane: cadkernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
origin_plane: kernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
style: None,
annotative: None,
annotative_current: annotative,
style_current: acadrust::entities::HatchStyleType::Normal,
style_current: codec::entities::HatchStyleType::Normal,
input: None,
source_appearance: None,
current_color: acadrust::types::Color::ByLayer,
current_transparency: acadrust::types::Transparency::ByLayer,
current_color: codec::types::Color::ByLayer,
current_transparency: codec::types::Transparency::ByLayer,
boundary_region: false,
association_sources: None,
association_paths: Vec::new(),
@@ -133,15 +133,15 @@ impl HatcheditCommand {
command.input=Some("associate-point");command.association_sources=Some((plane,sources));command
}
fn add_association_rings(&mut self,rings:Vec<Vec<[f64;2]>>,sources:&rustc_hash::FxHashMap<Handle,crate::scene::BoundarySource>) {
let exterior=cadkernel::geom2d::ring_nesting_depths(&rings).into_iter().map(|depth|depth==0).collect::<Vec<_>>();
let exterior=kernel::geom2d::ring_nesting_depths(&rings).into_iter().map(|depth|depth==0).collect::<Vec<_>>();
let paths=crate::scene::exact_hatch_paths(&rings,&exterior,sources,1e-6);
self.association_missed=paths.is_empty()||paths.len()!=rings.len()||paths.iter().any(|path|path.boundary_handles.is_empty());
if !self.association_missed {
for path in paths {if !self.association_paths.contains(&path){self.association_paths.push(path);}}
}
}
pub fn with_appearance(mut self,entity:Option<&acadrust::EntityType>,current_color:acadrust::types::Color,current_transparency:acadrust::types::Transparency)->Self {
if let Some(acadrust::EntityType::Hatch(hatch)) = entity {
pub fn with_appearance(mut self,entity:Option<&codec::EntityType>,current_color:codec::types::Color,current_transparency:codec::types::Transparency)->Self {
if let Some(codec::EntityType::Hatch(hatch)) = entity {
self.style_current = hatch.style;
self.origin_plane = crate::entities::curve::ocs_plane(hatch.normal, hatch.elevation);
self.origin_bounds = hatch.paths.iter().flat_map(|path| &path.edges)
@@ -153,20 +153,20 @@ impl HatcheditCommand {
let mut anchors = Vec::new();
for curve in curves {
match curve {
cadkernel::geom2d::Curve::Ellipse(arc) => {
kernel::geom2d::Curve::Ellipse(arc) => {
if (arc.end_parameter - arc.start_parameter).abs() < std::f64::consts::TAU { return None; }
for angle in [0.0, std::f64::consts::FRAC_PI_2] {
anchors.push(cadkernel::geom2d::Curve::Line(cadkernel::geom2d::Line {
anchors.push(kernel::geom2d::Curve::Line(kernel::geom2d::Line {
start: arc.ellipse.point_at(angle),
end: arc.ellipse.point_at(angle + std::f64::consts::PI),
}));
}
}
cadkernel::geom2d::Curve::Nurbs(_) => return None,
kernel::geom2d::Curve::Nurbs(_) => return None,
other => anchors.push(other),
}
}
cadkernel::geom2d::analytic_curve_bounds(&anchors)
kernel::geom2d::analytic_curve_bounds(&anchors)
});
}
self.source_appearance=entity.map(|e|{let c=e.common();(c.color,c.layer.clone(),c.transparency)});
@@ -195,9 +195,9 @@ impl CadCommand for HatcheditCommand {
if let Some(input)=self.input {
if input == "style" {
let current = match self.style_current {
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",
};
return format!("Enter hatching style [Ignore/Outer/Normal] <{current}>:");
}
@@ -206,8 +206,8 @@ impl CadCommand for HatcheditCommand {
"color"=>return format!("New color [Truecolor/. (for use current)] <{color:?}>:"),
"layer"=>return format!("Specify layer or [. (for use current)] <{layer}>:"),
"transparency"=>return format!("Specify transparency (0-90) or ByLayer/ByBlock <{}>:",match transparency {
acadrust::types::Transparency::ByLayer=>"ByLayer".into(),
acadrust::types::Transparency::ByBlock=>"ByBlock".into(),
codec::types::Transparency::ByLayer=>"ByLayer".into(),
codec::types::Transparency::ByBlock=>"ByBlock".into(),
value=>format!("{:.0}",value.as_percent()*100.0),
}),
_=>{},
@@ -334,7 +334,7 @@ impl CadCommand for HatcheditCommand {
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
let keyword=text.trim().to_ascii_uppercase();
if let Some(input)=self.input {
use acadrust::types::{Color,Transparency};
use codec::types::{Color,Transparency};
let appearance=|color,layer,transparency|HatchEditOperation::Appearance{color,layer,transparency};
match input {
"origin" => match keyword.as_str() {
@@ -372,9 +372,9 @@ impl CadCommand for HatcheditCommand {
}
"style" => {
self.style = match keyword.as_str() {
"I" | "IGNORE" => Some(acadrust::entities::HatchStyleType::Ignore),
"O" | "OUTER" => Some(acadrust::entities::HatchStyleType::Outer),
"N" | "NORMAL" => Some(acadrust::entities::HatchStyleType::Normal),
"I" | "IGNORE" => Some(codec::entities::HatchStyleType::Ignore),
"O" | "OUTER" => Some(codec::entities::HatchStyleType::Outer),
"N" | "NORMAL" => Some(codec::entities::HatchStyleType::Normal),
_ => return Some(CmdResult::NeedPoint),
};
return self.apply_result(self.update_operation());
@@ -509,9 +509,9 @@ impl CadCommand for HatcheditCommand {
}
if let Some(rest) = text.strip_prefix('Y') {
self.style = match rest.trim() {
"NORMAL" | "N" => Some(acadrust::entities::HatchStyleType::Normal),
"OUTER" | "O" => Some(acadrust::entities::HatchStyleType::Outer),
"IGNORE" | "I" => Some(acadrust::entities::HatchStyleType::Ignore),
"NORMAL" | "N" => Some(codec::entities::HatchStyleType::Normal),
"OUTER" | "O" => Some(codec::entities::HatchStyleType::Outer),
"IGNORE" | "I" => Some(codec::entities::HatchStyleType::Ignore),
_ => self.style,
};
return Some(CmdResult::NeedPoint);
@@ -613,12 +613,12 @@ impl CadCommand for HatcheditCommand {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::hatch::{
use codec::entities::hatch::{
BoundaryEdge, BoundaryPath, EllipticArcEdge, LineEdge,
};
use acadrust::entities::{Hatch, HatchStyleType};
use acadrust::types::{Color, Transparency, Vector2};
use acadrust::EntityType;
use codec::entities::{Hatch, HatchStyleType};
use codec::types::{Color, Transparency, Vector2};
use codec::EntityType;
fn hatch_command() -> HatcheditCommand {
let mut hatch = Hatch::new();
+5 -5
View File
@@ -1,7 +1,7 @@
use acadrust::entities::{Helix, HelixConstraint, Spline};
use acadrust::types::Vector3;
use acadrust::EntityType;
use cadkernel::space::{HelixCurve, HelixDirection, Vec3};
use codec::entities::{Helix, HelixConstraint, Spline};
use codec::types::Vector3;
use codec::EntityType;
use kernel::space::{HelixCurve, HelixDirection, Vec3};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, DynField, WorkingPlane};
@@ -159,7 +159,7 @@ impl HelixCommand {
let points = self
.kernel_curve(height, axis)?
.nurbs()?
.tessellate_angle(cadkernel::tessellation::DEFAULT_ANGLE);
.tessellate_angle(kernel::tessellation::DEFAULT_ANGLE);
Some(WireModel::solid_f64(
"helix_preview".to_string(),
points,
+3 -3
View File
@@ -2,12 +2,12 @@
//
// Command: LINE — OpenCADStudio behaviour:
// 1. First click → stores start point, prompts for next point
// 2. Each further click → immediately commits an acadrust::Line entity
// 2. Each further click → immediately commits an codec::Line entity
// (start→end) to the document; end becomes the new start point
// 3. Enter / Escape → ends the command
use acadrust::types::Vector3;
use acadrust::{EntityType, Line};
use codec::types::Vector3;
use codec::{EntityType, Line};
use crate::t;
use crate::command::{CadCommand, CmdResult, TangentObject};
+3 -3
View File
@@ -1,6 +1,6 @@
use acadrust::entities::polygon_mesh::{PolygonMesh, PolygonMeshVertex};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::polygon_mesh::{PolygonMesh, PolygonMeshVertex};
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, DynField};
+4 -4
View File
@@ -1,9 +1,9 @@
// MLINE command — create a styled group of parallel lines.
use acadrust::entities::{MLine, MLineFlags, MLineJustification, MLineSegment, MLineVertex};
use acadrust::objects::MLineStyle;
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::entities::{MLine, MLineFlags, MLineJustification, MLineSegment, MLineVertex};
use codec::objects::MLineStyle;
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, WorkingPlane};
+2 -2
View File
@@ -3,8 +3,8 @@
// Command: POINT (PO)
// POINT commits one entity and exits. MULTIPOINT stays active.
use acadrust::types::Vector3;
use acadrust::{EntityType, Point as CadPoint};
use codec::types::Vector3;
use codec::{EntityType, Point as CadPoint};
use crate::t;
use crate::command::{CadCommand, CmdResult};
+3 -3
View File
@@ -1,8 +1,8 @@
// 3DPOLY creates open or closed non-planar paths.
use acadrust::entities::Polyline3D;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::Polyline3D;
use codec::types::Vector3;
use codec::EntityType;
use crate::t;
use crate::command::{CadCommand, CmdResult};
+3 -3
View File
@@ -13,9 +13,9 @@
// Bulge is stored per vertex (segment i→i+1); positive = CCW, negative = CW.
// Widths are stored per segment as (start, end).
use acadrust::entities::LwVertex;
use acadrust::types::Vector2;
use acadrust::{EntityType, Handle, LwPolyline};
use codec::entities::LwVertex;
use codec::types::Vector2;
use codec::{EntityType, Handle, LwPolyline};
use glam::{DVec2, DVec3, Vec2, Vec3};
use crate::t;
+5 -5
View File
@@ -10,9 +10,9 @@
// 3. User drags to pick width; height is computed from the image's aspect ratio.
// 4. Entity is committed.
use acadrust::entities::RasterImage;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::RasterImage;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use crate::t;
@@ -95,8 +95,8 @@ impl ImageCommand {
world_width,
world_height,
);
img.flags = acadrust::entities::ImageDisplayFlags::SHOW_IMAGE
| acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
img.flags = codec::entities::ImageDisplayFlags::SHOW_IMAGE
| codec::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
self.plane.place_entity(EntityType::RasterImage(img))
}
ImageSource::Embedded(image) => {
+8 -8
View File
@@ -5,9 +5,9 @@
// XLINE — infinite construction line: same two-click pattern, yields XLine.
use crate::t;
use acadrust::entities::{Ray as RayEnt, XLine as XLineEnt};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::{Ray as RayEnt, XLine as XLineEnt};
use codec::types::Vector3;
use codec::EntityType;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::scene::model::wire_model::WireModel;
@@ -168,7 +168,7 @@ impl XLineCommand {
let base = self.base?;
let first = self.reference?.1;
let last = (pt - base).try_normalize()?;
let direction = cadkernel::space::curve::angle_bisector(
let direction = kernel::space::curve::angle_bisector(
first.to_array(), last.to_array(), self.plane.z.to_array())?;
(base, DVec3::from_array(direction))
}
@@ -290,7 +290,7 @@ impl CadCommand for XLineCommand {
(delta.x.hypot(delta.y) > 1e-10).then(|| delta.y.atan2(delta.x).to_degrees())
}
XLineMode::OffsetDistance => {
let distance = cadkernel::space::Vec3::from(cursor.to_array()).distance(origin.to_array().into());
let distance = kernel::space::Vec3::from(cursor.to_array()).distance(origin.to_array().into());
(distance.is_finite() && distance > 0.0).then_some(distance)
}
_ => None,
@@ -302,7 +302,7 @@ impl CadCommand for XLineCommand {
}
fn inject_before_entity_pick(&self) -> bool { true }
fn inject_picked_entity(&mut self, entity: EntityType) { self.picked = Some(entity); }
fn on_entity_pick(&mut self, _handle: acadrust::Handle, _pt: DVec3) -> CmdResult {
fn on_entity_pick(&mut self, _handle: codec::Handle, _pt: DVec3) -> CmdResult {
let xyz = |v: Vector3| DVec3::new(v.x, v.y, v.z);
let reference = match self.picked.take() {
Some(EntityType::Line(line)) => Some((xyz(line.start), xyz(line.end) - xyz(line.start))),
@@ -524,13 +524,13 @@ mod tests {
assert!(matches!(command.on_point(DVec3::Y * 2.0), CmdResult::NeedPoint));
assert!(command.needs_entity_pick());
let line = acadrust::entities::Line::from_points(
let line = codec::entities::Line::from_points(
Vector3::new(0.0, 0.0, 0.0),
Vector3::new(1.0, 0.0, 0.0),
);
command.inject_picked_entity(EntityType::Line(line));
assert!(matches!(
command.on_entity_pick(acadrust::Handle::new(1), DVec3::ZERO),
command.on_entity_pick(codec::Handle::new(1), DVec3::ZERO),
CmdResult::NeedPoint
));
let CmdResult::CommitEntity(EntityType::XLine(entity)) =
+4 -4
View File
@@ -2,10 +2,10 @@
use std::sync::atomic::{AtomicU64, AtomicU8, Ordering};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{distance_to, Curve, Polyline, PolylineVertex, Vec2};
use cadkernel::space::{PlanarCurve, Plane, Vec3};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use kernel::geom2d::{distance_to, Curve, Polyline, PolylineVertex, Vec2};
use kernel::space::{PlanarCurve, Plane, Vec3};
use glam::DVec3;
use rustc_hash::FxHashMap;
+4 -4
View File
@@ -10,10 +10,10 @@
// POLY_C — Circumscribed about circle (edges tangent to circle)
// POLY_E — Edge (pick two endpoints of one edge)
use acadrust::entities::LwVertex;
use acadrust::types::Vector2;
use acadrust::{EntityType, LwPolyline};
use cadkernel::geom2d::{
use codec::entities::LwVertex;
use codec::types::Vector2;
use codec::{EntityType, LwPolyline};
use kernel::geom2d::{
arc_span, fillet_between_rays, Curve as KernelCurve, Frame as KernelFrame,
Polyline as KernelPolyline, PolylineVertex as KernelVertex, Ray as KernelRay,
Transform as KernelTransform, Vec2 as KernelVec2,
+4 -4
View File
@@ -1,9 +1,9 @@
// Freehand sketch tool.
use acadrust::entities::{Line, LwPolyline, LwVertex, Spline};
use acadrust::types::{Vector2, Vector3};
use acadrust::EntityType;
use cadkernel::geom2d::NurbsCurve;
use codec::entities::{Line, LwPolyline, LwVertex, Spline};
use codec::types::{Vector2, Vector3};
use codec::EntityType;
use kernel::geom2d::NurbsCurve;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, WorkingPlane};
+3 -3
View File
@@ -6,9 +6,9 @@
// starts the next connected shape. Enter after the third point commits a
// triangle.
use acadrust::entities::Solid;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::Solid;
use codec::types::Vector3;
use codec::EntityType;
use crate::t;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
+4 -4
View File
@@ -4,8 +4,8 @@
// Click to add fit points. Enter (≥2 pts) → commits EntityType::Spline.
use crate::t;
use acadrust::types::Vector3;
use acadrust::{CadDocument, EntityType, Handle, Spline};
use codec::types::Vector3;
use codec::{CadDocument, EntityType, Handle, Spline};
use std::collections::HashMap;
use crate::command::{CadCommand, CmdResult};
@@ -90,7 +90,7 @@ impl SplineCommand {
}
fn control_spline(points: &[[f64; 3]], degree: usize, closed: bool) -> Option<Spline> {
let curve = cadkernel::space::NurbsCurve3::from_control_polygon(degree, points, closed)?;
let curve = kernel::space::NurbsCurve3::from_control_polygon(degree, points, closed)?;
let mut spline = Spline {
degree: curve.degree() as i32,
control_points: curve.control_points().iter().map(|p| Vector3::new(p[0], p[1], p[2])).collect(),
@@ -453,7 +453,7 @@ mod tests {
#[test]
fn closed_fitted_polyline_conversion_preserves_a_periodic_spline() {
use acadrust::entities::{
use codec::entities::{
Polyline2D, PolylineFlags, SmoothSurfaceType, Vertex2D, VertexFlags,
};
+3 -3
View File
@@ -11,9 +11,9 @@
// so the planar point-pick path is used (every vertex shares the polyline
// elevation, taken from the first point's Z).
use acadrust::entities::{LwPolyline, LwVertex};
use acadrust::types::{Vector2, Vector3};
use acadrust::EntityType;
use codec::entities::{LwPolyline, LwVertex};
use codec::types::{Vector2, Vector3};
use codec::EntityType;
use crate::t;
use crate::command::{CadCommand, CmdResult, WorkingPlane};
+10 -10
View File
@@ -1,10 +1,10 @@
// WIPEOUT command — draw a polygonal mask or derive one from a closed polyline.
use acadrust::entities::{Wipeout, WipeoutClipType};
use acadrust::types::{Vector2, Vector3};
use acadrust::{CadDocument, EntityType, Handle};
use cadkernel::geom2d::{polygon_frame, Tolerance};
use cadkernel::space::Plane;
use codec::entities::{Wipeout, WipeoutClipType};
use codec::types::{Vector2, Vector3};
use codec::{CadDocument, EntityType, Handle};
use kernel::geom2d::{polygon_frame, Tolerance};
use kernel::space::Plane;
use glam::DVec3;
use crate::t;
@@ -184,8 +184,8 @@ impl CadCommand for WipeoutCommand {
if let Some(first) = self.points.first() {
let first = self.plane.to_local(*first);
let point = self.plane.to_local(point);
let distance = cadkernel::geom2d::Vec2::new(point.x, point.y)
.distance(cadkernel::geom2d::Vec2::new(first.x, first.y));
let distance = kernel::geom2d::Vec2::new(point.x, point.y)
.distance(kernel::geom2d::Vec2::new(first.x, first.y));
if self.points.len() >= 3
&& distance <= Tolerance::default().linear()
{
@@ -445,8 +445,8 @@ fn make_poly_wipeout(points: &[[f64; 2]], plane: Plane) -> Option<EntityType> {
fn explicitly_closed(points: &[[f64; 2]]) -> bool {
points.len() >= 4
&& cadkernel::geom2d::Vec2::from(points[0])
.distance(cadkernel::geom2d::Vec2::from(*points.last().unwrap()))
&& kernel::geom2d::Vec2::from(points[0])
.distance(kernel::geom2d::Vec2::from(*points.last().unwrap()))
<= Tolerance::default().linear()
}
@@ -501,7 +501,7 @@ inventory::submit!(crate::command::CommandRegistration { names: &["WIPEOUT"] });
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::LwPolyline;
use codec::entities::LwPolyline;
#[test]
fn command_undo_never_removes_the_first_point() {
+1 -1
View File
@@ -13,7 +13,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+1 -1
View File
@@ -13,7 +13,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+2 -2
View File
@@ -1,5 +1,5 @@
use cadkernel::space::polygon;
use acadrust::{EntityType, Handle};
use kernel::space::polygon;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{
+7 -7
View File
@@ -1,9 +1,9 @@
// DIVIDE and MEASURE place points or block references along a curve.
use acadrust::entities::{Insert, Point as PointEnt};
use acadrust::types::Vector3;
use acadrust::{Entity, EntityType, Handle};
use cadkernel::space::PlanarCurve;
use codec::entities::{Insert, Point as PointEnt};
use codec::types::Vector3;
use codec::{Entity, EntityType, Handle};
use kernel::space::PlanarCurve;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, CurveMarker, WorkingPlane};
@@ -198,7 +198,7 @@ impl<const MEASURE: bool> CadCommand for CurveMarkerCommand<MEASURE> {
return None;
}
let origin = self.value_origin?;
let distance = cadkernel::space::Vec3::from(cursor.to_array())
let distance = kernel::space::Vec3::from(cursor.to_array())
.distance(origin.to_array().into());
(distance.is_finite() && distance > 0.0).then_some(distance)
}
@@ -308,7 +308,7 @@ fn make_marker(
enum MeasuredCurve {
Planar(PlanarCurve),
Spatial(cadkernel::space::ArcLengthCurve3),
Spatial(kernel::space::ArcLengthCurve3),
}
impl MeasuredCurve {
@@ -359,7 +359,7 @@ inventory::submit!(crate::command::CommandRegistration { names: &["MEASURE"] });
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::{Circle, Line};
use codec::entities::{Circle, Line};
fn point(entity: &EntityType) -> DVec3 {
let EntityType::Point(point) = entity else { panic!("expected point") };
+1 -1
View File
@@ -14,7 +14,7 @@
// All arithmetic is kept in f64 (picked points stay full precision; downcasting
// to f32 loses several hundredths of a unit at survey-scale coordinates).
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::t;
+4 -4
View File
@@ -11,7 +11,7 @@
use std::collections::BTreeMap;
use std::path::Path;
use acadrust::tables::Layer;
use codec::tables::Layer;
use crate::scene::Scene;
@@ -179,7 +179,7 @@ pub fn translate(
// Whatever reference the target drawing held it through does not
// come with it.
layer.flags.xref_dependent = false;
layer.xref_block_record_handle = acadrust::Handle::NULL;
layer.xref_block_record_handle = codec::Handle::NULL;
let _ = scene.document.layers.add(layer);
}
let moved = merge_layer(scene, &mapping.from, &mapping.to, options.force_bylayer);
@@ -214,12 +214,12 @@ pub fn merge_layer(scene: &mut Scene, from: &str, to: &str, force_bylayer: bool)
let common = entity.common_mut();
common.layer = to.to_string();
if force_bylayer {
common.color = acadrust::Color::ByLayer;
common.color = codec::Color::ByLayer;
common.color_name = None;
common.color_book_handle = None;
common.linetype = String::new();
common.linetype_handle = None;
common.line_weight = acadrust::LineWeight::ByLayer;
common.line_weight = codec::LineWeight::ByLayer;
}
moved += 1;
}
+1 -1
View File
@@ -15,7 +15,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
+7 -7
View File
@@ -10,7 +10,7 @@
// With 2 pairs: translate + rotate (+ optional uniform scale to fit)
// With 3 pairs: rigid 3D placement without scaling
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
@@ -127,7 +127,7 @@ impl CadCommand for AlignCommand {
}
AlignState::Src2 => {
let pair = [self.src1.unwrap().to_array(), pt.to_array()];
if cadkernel::space::align_point_pairs(&pair, &pair, false).is_none() {
if kernel::space::align_point_pairs(&pair, &pair, false).is_none() {
return CmdResult::NeedPoint;
}
self.src2 = Some(pt);
@@ -136,7 +136,7 @@ impl CadCommand for AlignCommand {
}
AlignState::Dst2 => {
let pair = [self.dst1.unwrap().to_array(), pt.to_array()];
if cadkernel::space::align_point_pairs(&pair, &pair, false).is_none() {
if kernel::space::align_point_pairs(&pair, &pair, false).is_none() {
return CmdResult::NeedPoint;
}
self.dst2 = Some(pt);
@@ -145,7 +145,7 @@ impl CadCommand for AlignCommand {
}
AlignState::Src3 => {
let frame = [self.src1.unwrap().to_array(), self.src2.unwrap().to_array(), pt.to_array()];
if cadkernel::space::align_point_pairs(&frame, &frame, false).is_none() {
if kernel::space::align_point_pairs(&frame, &frame, false).is_none() {
return CmdResult::NeedPoint;
}
self.src3 = Some(pt);
@@ -295,10 +295,10 @@ impl AlignCommand {
source.push(s3.to_array());
target.push(d3.to_array());
}
let Some(matrix) = cadkernel::space::align_point_pairs(&source, &target, with_scale)
let Some(matrix) = kernel::space::align_point_pairs(&source, &target, with_scale)
else { return CmdResult::NeedPoint; };
CmdResult::TransformSelected(self.handles.clone(), EntityTransform::Affine(
acadrust::types::Transform::from_matrix(acadrust::types::Matrix4 { m: matrix }),
codec::types::Transform::from_matrix(codec::types::Matrix4 { m: matrix }),
))
}
}
@@ -340,7 +340,7 @@ mod tests {
};
assert_eq!(handles, vec![handle]);
for (from, expected) in source.into_iter().zip(target) {
let actual = transform.apply(acadrust::types::Vector3::new(from.x, from.y, from.z));
let actual = transform.apply(codec::types::Vector3::new(from.x, from.y, from.z));
let actual = DVec3::new(actual.x, actual.y, actual.z);
assert!(actual.abs_diff_eq(expected, 1.0e-12));
}
+2 -2
View File
@@ -13,7 +13,7 @@
// Polar array: copies rotated around a center point by a total angle.
// 1. Center point → 2. Item count (text) → 3. Total angle in degrees (text)
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
@@ -456,7 +456,7 @@ impl CadCommand for ArrayPolarCommand {
// 2. Enter item count (total, including the original at the path start)
// → Returns BatchCopy with Translate transforms derived from path samples.
use acadrust::EntityType;
use codec::EntityType;
use crate::entities::curve::entity_curve;
use std::f64::consts::PI as FPI;
use std::f64::consts::TAU as FTAU;
+3 -3
View File
@@ -15,7 +15,7 @@ use crate::scene::model::wire_model::WireModel;
pub struct AtteditCommand {
/// The picked block reference, once the user clicks one.
picked: Option<acadrust::Handle>,
picked: Option<codec::Handle>,
}
impl AtteditCommand {
@@ -37,7 +37,7 @@ impl CadCommand for AtteditCommand {
self.picked.is_none()
}
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: DVec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: codec::Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -57,7 +57,7 @@ impl CadCommand for AtteditCommand {
vec![]
}
fn attedit_pending_handle(&self) -> Option<acadrust::Handle> {
fn attedit_pending_handle(&self) -> Option<codec::Handle> {
self.picked
}
}
+7 -7
View File
@@ -5,13 +5,13 @@
//! first and second derivatives reproduce the source curves' tangent and
//! geometric curvature (G2).
use acadrust::entities::{EntityCommon, Spline};
use cadkernel::space::curve as space_curve;
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::entities::{EntityCommon, Spline};
use kernel::space::curve as space_curve;
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::t;
use cadkernel::space::NurbsCurve3;
use kernel::space::NurbsCurve3;
use crate::command::{CadCommand, CmdOption, CmdResult};
use crate::entities::common::BulgeArc;
@@ -447,7 +447,7 @@ fn polyline_endpoint(points: &[DVec3], click: DVec3) -> Option<EndpointFrame> {
}
}
fn arc_endpoint(arc: &acadrust::entities::Arc, click: DVec3) -> Option<EndpointFrame> {
fn arc_endpoint(arc: &codec::entities::Arc, click: DVec3) -> Option<EndpointFrame> {
if arc.radius <= EPS {
return None;
}
@@ -479,7 +479,7 @@ fn arc_endpoint(arc: &acadrust::entities::Arc, click: DVec3) -> Option<EndpointF
})
}
fn lw_point(poly: &acadrust::entities::LwPolyline, index: usize) -> DVec3 {
fn lw_point(poly: &codec::entities::LwPolyline, index: usize) -> DVec3 {
let normal = to_dvec(poly.normal).normalize_or_zero();
let p = poly.vertices[index].location;
ocs_to_dvec(p.x, p.y, poly.elevation, normal)
+3 -3
View File
@@ -15,7 +15,7 @@
// block record in place, so there is no copy-back and no transform — the space
// render filter (`current_layout_block_handle`) already draws only the block.
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -66,7 +66,7 @@ pub struct BlockEditSession {
/// Rebasing the origin moves them with the definition; Discard restores
/// their exact on-entry state.
pub reference_attributes:
Vec<(Handle, Vec<acadrust::entities::AttributeEntity>)>,
Vec<(Handle, Vec<codec::entities::AttributeEntity>)>,
/// Camera state of the space that was active when BEDIT began, restored
/// on Save/Discard so the view returns exactly where it was (#425).
pub return_camera: crate::scene::view::camera::Camera,
@@ -75,7 +75,7 @@ pub struct BlockEditSession {
pub editor_camera: crate::scene::view::camera::Camera,
/// Transient UCS being manipulated in this block tab. On commit its full
/// frame is baked into the definition and this returns to `None`.
pub editor_ucs: Option<acadrust::tables::Ucs>,
pub editor_ucs: Option<codec::tables::Ucs>,
}
// ── BEDIT pick command ─────────────────────────────────────────────────────
+13 -13
View File
@@ -8,11 +8,11 @@
// BREAK @ (at-sign as second point) → Break at a single point (splits without gap).
use crate::modules::draw::modify::spline_ops::{spline_cut, spline_nearest_t, spline_range};
use acadrust::entities::{
use codec::entities::{
Arc as ArcEnt, Ellipse as EllipseEnt, Line as LineEnt, LwPolyline, Spline as SplineEnt,
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::t;
@@ -88,12 +88,12 @@ fn break_line(line: &LineEnt, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
result
}
fn picked_spans(curve: &cadkernel::space::PlanarCurve, p1: DVec3, p2: DVec3) -> Option<Vec<[f64; 2]>> {
fn picked_spans(curve: &kernel::space::PlanarCurve, p1: DVec3, p2: DVec3) -> Option<Vec<[f64; 2]>> {
let first = curve.plane.project(p1.to_array())?;
let second = curve.plane.project(p2.to_array())?;
let a = cadkernel::geom2d::closest_point(&curve.curve, first).t;
let b = cadkernel::geom2d::closest_point(&curve.curve, second).t;
cadkernel::geom2d::break_spans(&curve.curve, a, b, cadkernel::geom2d::Tolerance::new(1e-9))
let a = kernel::geom2d::closest_point(&curve.curve, first).t;
let b = kernel::geom2d::closest_point(&curve.curve, second).t;
kernel::geom2d::break_spans(&curve.curve, a, b, kernel::geom2d::Tolerance::new(1e-9))
}
fn break_arc(arc: &ArcEnt, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
@@ -101,7 +101,7 @@ fn break_arc(arc: &ArcEnt, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
let Some(spans) = picked_spans(&curve, p1, p2) else {
return vec![EntityType::Arc(arc.clone())];
};
let cadkernel::geom2d::Curve::Arc(geometry) = &curve.curve else { unreachable!() };
let kernel::geom2d::Curve::Arc(geometry) = &curve.curve else { unreachable!() };
spans.into_iter().map(|[from, to]| {
let mut result = arc.clone();
result.common.handle = Handle::NULL;
@@ -111,7 +111,7 @@ fn break_arc(arc: &ArcEnt, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
}).collect()
}
fn break_circle(circle: &acadrust::entities::Circle, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
fn break_circle(circle: &codec::entities::Circle, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
let curve = crate::entities::curve::circle_curve(circle);
let Some(spans) = picked_spans(&curve, p1, p2) else {
return vec![EntityType::Circle(circle.clone())];
@@ -133,7 +133,7 @@ fn break_lwpolyline(p: &LwPolyline, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
let unchanged = || vec![EntityType::LwPolyline(p.clone())];
let Some(curve) = crate::entities::curve::lwpolyline_curve(p) else { return unchanged(); };
let Some(spans) = picked_spans(&curve, p1, p2) else { return unchanged(); };
let cadkernel::geom2d::Curve::Polyline(geometry) = &curve.curve else { unreachable!() };
let kernel::geom2d::Curve::Polyline(geometry) = &curve.curve else { unreachable!() };
let mut result = Vec::with_capacity(spans.len());
for [from, to] in spans {
let Some(range) = geometry.ranged(from, to) else { return unchanged(); };
@@ -172,7 +172,7 @@ fn break_ellipse(ell: &EllipseEnt, p1: DVec3, p2: DVec3) -> Vec<EntityType> {
let Some(spans) = picked_spans(&curve, p1, p2) else {
return vec![EntityType::Ellipse(ell.clone())];
};
let cadkernel::geom2d::Curve::Ellipse(geometry) = &curve.curve else { unreachable!() };
let kernel::geom2d::Curve::Ellipse(geometry) = &curve.curve else { unreachable!() };
spans.into_iter().map(|[from, to]| {
let mut result = ell.clone();
result.common.handle = Handle::NULL;
@@ -387,8 +387,8 @@ inventory::submit!(crate::command::CommandRegistration { names: &["BREAK"] });
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::LwVertex;
use acadrust::types::Vector2;
use codec::entities::LwVertex;
use codec::types::Vector2;
#[test]
fn first_option_replaces_the_selection_point_and_at_reuses_it() {
+1 -1
View File
@@ -5,7 +5,7 @@
// Step 1: pick base point
// Step 2+: each click makes another copy at (click - base); Enter to finish.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
+1 -1
View File
@@ -5,7 +5,7 @@
//! as TRIM, to nearby boundary entities. Keeping this compact command-local
//! index avoids cloning/scanning the complete drawing on every mouse move.
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use rustc_hash::{FxHashMap, FxHashSet};
use crate::scene::convert::tess::entity_world_aabb_f64;
+44 -44
View File
@@ -8,7 +8,7 @@
// Polyline2D → Lines + Arcs
// Polyline3D → Lines
// Polyline → Lines
// Insert → constituent entities (via acadrust explode_from_document)
// Insert → constituent entities (via opencadcodec explode_from_document)
// MLine → Lines (spine + offset lines per miter direction)
// Dimension → Lines (extension + dimension + arrows) + Text
//
@@ -16,15 +16,15 @@
use super::geom::normalize_angle as norm_angle;
use acadrust::entities::EntityCommon;
use acadrust::entities::{
use codec::entities::EntityCommon;
use codec::entities::{
Arc as ArcEnt, Block, BlockEnd, Circle as CircleEnt, Dimension, Line as LineEnt, LwPolyline,
MLine,
};
use acadrust::entities::{Polyline, Polyline2D};
use acadrust::tables::BlockRecord;
use acadrust::types::Vector3;
use acadrust::{CadDocument, EntityType, Handle};
use codec::entities::{Polyline, Polyline2D};
use codec::tables::BlockRecord;
use codec::types::Vector3;
use codec::{CadDocument, EntityType, Handle};
use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::entities::curve::lwpolyline_world_xy;
@@ -64,7 +64,7 @@ pub fn explode_polyline_segments(entity: &EntityType) -> Vec<EntityType> {
pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec<EntityType> {
match entity {
EntityType::Line(line) => {
let Some(association) = acadrust::entities::CenterMarkAssociation::read(
let Some(association) = codec::entities::CenterMarkAssociation::read(
&line.common.extended_data,
) else {
return vec![];
@@ -74,7 +74,7 @@ pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec<Entity
.map(|segment| {
let mut common = line.common.clone();
common.handle = Handle::NULL;
acadrust::entities::CenterMarkAssociation::remove(&mut common.extended_data);
codec::entities::CenterMarkAssociation::remove(&mut common.extended_data);
EntityType::Line(LineEnt {
common,
start: Vector3::new(segment[0].x, segment[0].y, segment[0].z),
@@ -141,7 +141,7 @@ fn explode_polyline(p: &Polyline) -> Vec<EntityType> {
result
}
fn explode_polyline3d(p: &acadrust::entities::Polyline3D) -> Vec<EntityType> {
fn explode_polyline3d(p: &codec::entities::Polyline3D) -> Vec<EntityType> {
let n = p.vertices.len();
if n < 2 {
return vec![];
@@ -309,7 +309,7 @@ fn bulge_to_arc(
) -> Option<EntityType> {
let ba = crate::entities::common::BulgeArc::from_bulge(p0, p1, bulge)?;
// acadrust Arc is always CCW from start_angle to end_angle. Negative
// opencadcodec Arc is always CCW from start_angle to end_angle. Negative
// bulge means the polyline goes p0→p1 the CW way around the centre,
// which is the same circular arc traversed p1→p0 the CCW way — so
// swap endpoints when bulge < 0.
@@ -340,15 +340,15 @@ fn explode_mline(ml: &MLine) -> Vec<EntityType> {
if n < 2 {
return vec![];
}
let closed = ml.flags.contains(acadrust::entities::MLineFlags::CLOSED);
let closed = ml.flags.contains(codec::entities::MLineFlags::CLOSED);
let scale = ml.scale_factor;
let n_segs = if closed { n } else { n - 1 };
let mut result = Vec::new();
// Helper: build a Line from two Vector3 positions.
let make_line = |common: &acadrust::entities::EntityCommon,
s: &acadrust::types::Vector3,
e: &acadrust::types::Vector3|
let make_line = |common: &codec::entities::EntityCommon,
s: &codec::types::Vector3,
e: &codec::types::Vector3|
-> EntityType {
let mut c = common.clone();
c.handle = Handle::NULL;
@@ -395,7 +395,7 @@ fn explode_mline(ml: &MLine) -> Vec<EntityType> {
/// Convert a Dimension entity into Lines (geometry) + Text (label).
/// A NULL-handle line segment for a baked dimension block.
fn dim_seg(a: Vector3, b: Vector3, common: &acadrust::entities::EntityCommon) -> EntityType {
fn dim_seg(a: Vector3, b: Vector3, common: &codec::entities::EntityCommon) -> EntityType {
let mut c = common.clone();
c.handle = Handle::NULL;
EntityType::Line(LineEnt {
@@ -408,8 +408,8 @@ fn dim_seg(a: Vector3, b: Vector3, common: &acadrust::entities::EntityCommon) ->
fn dim_geom_entities(
geometry: &crate::scene::convert::tessellate::DimGeom,
ext_common: &acadrust::entities::EntityCommon,
dim_common: &acadrust::entities::EntityCommon,
ext_common: &codec::entities::EntityCommon,
dim_common: &codec::entities::EntityCommon,
) -> Vec<EntityType> {
let mut entities = Vec::new();
let point = |value: [f32; 3]| {
@@ -426,7 +426,7 @@ fn dim_geom_entities(
}
}
for triangle in geometry.arrow_fill.chunks_exact(3) {
let mut solid = acadrust::entities::Solid::triangle(
let mut solid = codec::entities::Solid::triangle(
point(triangle[0]),
point(triangle[1]),
point(triangle[2]),
@@ -448,7 +448,7 @@ fn dim_terminator(
dx: f64,
dy: f64,
arrow: &crate::scene::convert::tessellate::ArrowKind,
common: &acadrust::entities::EntityCommon,
common: &codec::entities::EntityCommon,
) -> Vec<EntityType> {
use crate::scene::convert::tessellate::ArrowKind as A;
let (dx, dy) = norm2(dx, dy, 1.0, 0.0);
@@ -459,7 +459,7 @@ fn dim_terminator(
};
let mut out: Vec<EntityType> = Vec::new();
let tri = |a: Vector3, b: Vector3, c: Vector3, out: &mut Vec<EntityType>| {
let mut s = acadrust::entities::Solid::triangle(a, b, c);
let mut s = codec::entities::Solid::triangle(a, b, c);
s.common = common.clone();
s.common.handle = Handle::NULL;
out.push(EntityType::Solid(s));
@@ -565,7 +565,7 @@ fn terminator_circle(
center: Vector3,
r: f64,
filled: bool,
common: &acadrust::entities::EntityCommon,
common: &codec::entities::EntityCommon,
out: &mut Vec<EntityType>,
) {
const N: usize = 16;
@@ -580,7 +580,7 @@ fn terminator_circle(
}
if filled {
for i in 0..N {
let mut s = acadrust::entities::Solid::triangle(center, ring[i], ring[i + 1]);
let mut s = codec::entities::Solid::triangle(center, ring[i], ring[i + 1]);
s.common = common.clone();
s.common.handle = Handle::NULL;
out.push(EntityType::Solid(s));
@@ -593,7 +593,7 @@ fn dim_center_mark(
center: Vector3,
dimcen: f64,
radius: f64,
common: &acadrust::entities::EntityCommon,
common: &codec::entities::EntityCommon,
) -> Vec<EntityType> {
let mag = dimcen.abs();
if mag < 1e-9 {
@@ -624,7 +624,7 @@ fn dim_arc_segs(
radius: f64,
a1: f64,
a2: f64,
common: &acadrust::entities::EntityCommon,
common: &codec::entities::EntityCommon,
) -> Vec<EntityType> {
use std::f64::consts::PI;
let mut sweep = a2 - a1;
@@ -644,7 +644,7 @@ fn dim_arc_segs_with_sweep(
radius: f64,
start: f64,
sweep: f64,
common: &acadrust::entities::EntityCommon,
common: &codec::entities::EntityCommon,
) -> Vec<EntityType> {
use std::f64::consts::PI;
let steps = 12usize.max((sweep.abs() / (PI / 36.0)).ceil() as usize);
@@ -759,25 +759,25 @@ fn dim_metrics(dim: &Dimension, doc: &CadDocument) -> DimMetrics {
/// A DIMCLR* of 0 (ByBlock) or 256 (ByLayer) keeps the dimension's own colour
/// so the block inherits it; a specific ACI overrides. DIMLW* < 0 (ByBlock /
/// ByLayer) keeps the dimension's lineweight.
fn dim_common(base: &acadrust::entities::EntityCommon, clr: i16, lw: i16) -> acadrust::entities::EntityCommon {
fn dim_common(base: &codec::entities::EntityCommon, clr: i16, lw: i16) -> codec::entities::EntityCommon {
let mut c = base.clone();
c.handle = Handle::NULL;
if clr != 0 && clr != 256 {
c.color = acadrust::types::Color::from_index(clr);
c.color = codec::types::Color::from_index(clr);
c.color_name = None;
c.color_book_handle = None;
}
if lw >= 0 {
c.line_weight = acadrust::types::LineWeight::from_value(lw);
c.line_weight = codec::types::LineWeight::from_value(lw);
}
c
}
fn with_dim_linetype(
mut common: acadrust::entities::EntityCommon,
mut common: codec::entities::EntityCommon,
doc: &CadDocument,
handle: Handle,
) -> acadrust::entities::EntityCommon {
) -> codec::entities::EntityCommon {
common.linetype = doc
.line_types
.iter()
@@ -800,8 +800,8 @@ fn angular_block_segs(
p2: Vector3,
arc_loc: Vector3,
met: &DimMetrics,
ext_c: &acadrust::entities::EntityCommon,
dim_c: &acadrust::entities::EntityCommon,
ext_c: &codec::entities::EntityCommon,
dim_c: &codec::entities::EntityCommon,
explicit_sweep: Option<(f64, f64)>,
) -> Vec<EntityType> {
use std::f64::consts::PI;
@@ -853,7 +853,7 @@ fn angular_block_segs(
/// The text anchor for a radial leader: the saved text middle point when set,
/// else the midpoint of `a` and `b` — mirroring the live `dimension_text_position`.
fn dim_text_anchor(
base: &acadrust::entities::dimension::DimensionBase,
base: &codec::entities::dimension::DimensionBase,
a: Vector3,
b: Vector3,
) -> Vector3 {
@@ -1495,15 +1495,15 @@ impl CadCommand for ExplodeCommand {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::DimensionLinear;
use codec::entities::DimensionLinear;
#[test]
fn minsert_too_large_to_materialize_is_left_intact() {
let mut doc = CadDocument::new();
let mut block = acadrust::tables::BlockRecord::new("B1");
let mut block = codec::tables::BlockRecord::new("B1");
block.handle = doc.allocate_handle();
doc.block_records.add(block).unwrap();
let mut insert = acadrust::entities::Insert::new("B1", Vector3::new(0.0, 0.0, 0.0));
let mut insert = codec::entities::Insert::new("B1", Vector3::new(0.0, 0.0, 0.0));
insert.row_count = u16::MAX;
insert.column_count = u16::MAX;
assert!(explode_entity(&EntityType::Insert(insert), &doc).is_empty());
@@ -1512,12 +1512,12 @@ mod tests {
#[test]
fn unexplodable_block_is_not_exploded() {
let mut doc = CadDocument::new();
let mut block = acadrust::tables::BlockRecord::new("NO_EXPLODE");
let mut block = codec::tables::BlockRecord::new("NO_EXPLODE");
block.handle = doc.allocate_handle();
block.explodable = false;
doc.block_records.add(block).unwrap();
let insert = acadrust::entities::Insert::new("NO_EXPLODE", Vector3::new(0.0, 0.0, 0.0));
let insert = codec::entities::Insert::new("NO_EXPLODE", Vector3::new(0.0, 0.0, 0.0));
assert!(explode_entity(&EntityType::Insert(insert), &doc).is_empty());
}
@@ -1772,7 +1772,7 @@ mod tests {
// two extension lines plus many arc chords.
#[test]
fn angular_dim_bakes_an_arc() {
use acadrust::entities::DimensionAngular3Pt;
use codec::entities::DimensionAngular3Pt;
let mut doc = CadDocument::new();
let mut d = DimensionAngular3Pt::new(
Vector3::new(0.0, 0.0, 0.0),
@@ -1799,7 +1799,7 @@ mod tests {
// Diameter endpoints stay equidistant from the circle center.
#[test]
fn diameter_dim_bakes_through_center() {
use acadrust::entities::DimensionDiameter;
use codec::entities::DimensionDiameter;
let mut doc = CadDocument::new();
let center = Vector3::new(3.0, 4.0, 0.0);
let edge = Vector3::new(8.0, 4.0, 0.0); // radius 5 along +x
@@ -1864,8 +1864,8 @@ mod tests {
// must carry the source thickness instead of resetting to 0 (#916).
#[test]
fn explode_keeps_lwpolyline_thickness() {
use acadrust::entities::LwVertex;
use acadrust::types::Vector2;
use codec::entities::LwVertex;
use codec::types::Vector2;
let mut pl = LwPolyline::new();
// One straight span + one bulged span, so the result holds a Line and
@@ -1900,7 +1900,7 @@ mod tests {
#[test]
fn explode_keeps_polyline2d_extrusion() {
use acadrust::entities::Vertex2D;
use codec::entities::Vertex2D;
let mut pl = Polyline2D::new();
pl.vertices = vec![
+10 -10
View File
@@ -9,19 +9,19 @@
// Pick two lines (line-only; arcs are not chamferable).
// Finds intersection, backs off dist1 along line 1 and dist2 along line 2.
use acadrust::entities::{Arc as ArcEnt, Line as LineEnt, LwPolyline};
use codec::entities::{Arc as ArcEnt, Line as LineEnt, LwPolyline};
// Shared plane geometry, from cadkernel via the local adapters.
// Shared plane geometry, from opencadkernel via the local adapters.
use super::geom;
use super::geom::{arc_points as arc_pts, line_line as ll, normalize_angle as norm_angle};
use cadkernel::geom2d::{
use kernel::geom2d::{
circle_circle_points as circle_circle_pts, fillet_between_rays, fillets_between, line_circle,
Arc as KernelArc, Curve as KernelCurve, Fillet as KernelFillet,
Line as KernelLine, Tolerance,
};
use acadrust::entities::EntityCommon;
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::entities::EntityCommon;
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::t;
@@ -1552,7 +1552,7 @@ impl CadCommand for FilletCommand {
self.undo_last()
}
fn on_document_undone(&mut self, document: &acadrust::CadDocument) {
fn on_document_undone(&mut self, document: &codec::CadDocument) {
self.all_entities = document
.entities()
.map(crate::entities::curve::entity_with_lwpolyline_world_xy)
@@ -2147,7 +2147,7 @@ impl CadCommand for ChamferCommand {
self.undo_last()
}
fn on_document_undone(&mut self, document: &acadrust::CadDocument) {
fn on_document_undone(&mut self, document: &codec::CadDocument) {
self.all_entities = document
.entities()
.map(crate::entities::curve::entity_with_lwpolyline_world_xy)
@@ -2377,7 +2377,7 @@ mod tests {
/// by an infinite factor: the center becomes (inf, NaN).
fn overflowed_arc(sweep_sign: f64) -> ArcEnt {
let mut arc = ArcEnt::new();
arc.center = acadrust::types::Vector3::new(f64::INFINITY, f64::NAN, 0.0);
arc.center = codec::types::Vector3::new(f64::INFINITY, f64::NAN, 0.0);
arc.radius = f64::INFINITY;
arc.start_angle = 0.0;
arc.end_angle = sweep_sign * std::f64::consts::PI;
@@ -2410,7 +2410,7 @@ mod tests {
assert!(matches!(command.on_text_input("U"), Some(CmdResult::UndoDocument)));
assert_eq!(keywords(&command), ["P", "R"]);
// The host hands the restored document back; the cache follows it.
let mut doc = acadrust::CadDocument::new();
let mut doc = codec::CadDocument::new();
let _ = doc.add_entity(line(0.0, 0.0, 20.0, 0.0, 7));
command.on_document_undone(&doc);
assert_eq!(command.all_entities.len(), 1);
+3 -3
View File
@@ -1,4 +1,4 @@
//! Adapters between the editing commands and `cadkernel`'s plane geometry.
//! Adapters between the editing commands and `opencadkernel`'s plane geometry.
//!
//! The kernel takes points as `[f64; 2]` and hands tessellation back as
//! `[f64; 3]`. The commands here grew up passing loose `x, y` scalars and
@@ -11,11 +11,11 @@
//! resident render path splits the `f64` into a high/low pair instead. Only a
//! caller knows which of the two it is.
use cadkernel::geom2d::{self, Ellipse};
use kernel::geom2d::{self, Ellipse};
/// Re-exported unchanged: these already speak in plain `f64`, so there is no
/// call-shape difference for this module to absorb.
pub use cadkernel::geom2d::{arc_parameter, lerp, normalize_angle};
pub use kernel::geom2d::{arc_parameter, lerp, normalize_angle};
/// Preview geometry keeps the density the commands have always used.
const SEGMENTS_PER_RADIAN: f64 = geom2d::DEFAULT_SEGMENTS_PER_RADIAN;
+28 -28
View File
@@ -9,8 +9,8 @@
//
// Workflow: select objects then press Enter to join.
use acadrust::types::{Vector2, Vector3};
use acadrust::{EntityType, Handle};
use codec::types::{Vector2, Vector3};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -48,7 +48,7 @@ impl CadCommand for JoinCommand {
fn on_text_input(&mut self,text:&str) -> Option<CmdResult> {
if matches!(text.trim().to_ascii_uppercase().as_str(),"L"|"CLOSE") {
if let Some((handle,EntityType::Arc(arc)))=&self.source {
let mut circle=acadrust::entities::Circle::new();
let mut circle=codec::entities::Circle::new();
circle.common=arc.common.clone();circle.common.handle=Handle::NULL;
circle.center=arc.center.clone();circle.normal=arc.normal.clone();circle.radius=arc.radius;circle.thickness=arc.thickness;
return Some(CmdResult::ReplaceMany(vec![(*handle,vec![EntityType::Circle(circle)])],Vec::new()));
@@ -95,23 +95,23 @@ pub fn join_to_source(source: &EntityType, candidates: &[(Handle, &EntityType)])
let next = match (&result, *candidate) {
(EntityType::Line(a), EntityType::Line(b)) => {
let point = |p: &Vector3| [p.x,p.y,p.z];
cadkernel::space::source_join::join_collinear_lines([point(&a.start),point(&a.end)],[point(&b.start),point(&b.end)],JOIN_EPS).map(|span| {
kernel::space::source_join::join_collinear_lines([point(&a.start),point(&a.end)],[point(&b.start),point(&b.end)],JOIN_EPS).map(|span| {
let mut line = a.clone(); line.start = Vector3::new(span[0][0],span[0][1],span[0][2]); line.end = Vector3::new(span[1][0],span[1][1],span[1][2]); EntityType::Line(line)
})
}
(EntityType::Arc(a), EntityType::Arc(b)) => {
let data = |a: &acadrust::entities::Arc| ([a.center.x,a.center.y,a.center.z],[a.normal.x,a.normal.y,a.normal.z],a.radius,[a.start_angle,a.end_angle]);
cadkernel::space::source_join::join_cocircular_arcs(data(a),data(b),JOIN_EPS).map(|span| {
let data = |a: &codec::entities::Arc| ([a.center.x,a.center.y,a.center.z],[a.normal.x,a.normal.y,a.normal.z],a.radius,[a.start_angle,a.end_angle]);
kernel::space::source_join::join_cocircular_arcs(data(a),data(b),JOIN_EPS).map(|span| {
if span[1]-span[0] >= std::f64::consts::TAU {
let mut circle = acadrust::entities::Circle::new(); circle.common = a.common.clone(); circle.center = a.center.clone(); circle.normal = a.normal.clone(); circle.radius = a.radius; circle.thickness = a.thickness; EntityType::Circle(circle)
let mut circle = codec::entities::Circle::new(); circle.common = a.common.clone(); circle.center = a.center.clone(); circle.normal = a.normal.clone(); circle.radius = a.radius; circle.thickness = a.thickness; EntityType::Circle(circle)
} else { let mut arc = a.clone(); arc.start_angle = span[0]; arc.end_angle = span[1].rem_euclid(std::f64::consts::TAU); EntityType::Arc(arc) }
})
}
(EntityType::Spline(source), candidate) => {
let curve = |s:&acadrust::entities::Spline| {
let curve = |s:&codec::entities::Spline| {
if s.flags.closed || s.flags.periodic {return None;}
if s.control_points.is_empty() && s.fit_points.len() >= 2 {
use cadkernel::space::{NurbsCurve3, Parameterization};
use kernel::space::{NurbsCurve3, Parameterization};
let points: Vec<_> = s.fit_points.iter().map(|point| [point.x,point.y,point.z]).collect();
let parameterization = match s.knot_parameterization {
1 => Parameterization::Centripetal, 2 => Parameterization::Uniform, _ => Parameterization::Chord,
@@ -122,22 +122,22 @@ pub fn join_to_source(source: &EntityType, candidates: &[(Handle, &EntityType)])
.compact_knots(s.control_tolerance.max(1e-9));
}
let weights=if s.weights.is_empty(){vec![1.0;s.control_points.len()]}else{s.weights.clone()};
cadkernel::space::NurbsCurve3::new_strict(s.degree as usize,s.control_points.iter().map(|p|[p.x,p.y,p.z]).collect(),s.knots.clone(),weights)
kernel::space::NurbsCurve3::new_strict(s.degree as usize,s.control_points.iter().map(|p|[p.x,p.y,p.z]).collect(),s.knots.clone(),weights)
};
curve(source).and_then(|a| {
let b=match candidate {
EntityType::Spline(s)=>curve(s),
EntityType::Line(line)=>cadkernel::space::source_join::line_as_nurbs([[line.start.x,line.start.y,line.start.z],[line.end.x,line.end.y,line.end.z]],a.degree()),
EntityType::Line(line)=>kernel::space::source_join::line_as_nurbs([[line.start.x,line.start.y,line.start.z],[line.end.x,line.end.y,line.end.z]],a.degree()),
_=>None,
}?;
let joined=cadkernel::space::source_join::join_nurbs_curves(&a,&b,JOIN_EPS)?;
let joined=kernel::space::source_join::join_nurbs_curves(&a,&b,JOIN_EPS)?;
let mut spline=source.clone();
spline.degree=joined.degree() as i32;
spline.control_points=joined.control_points().iter().map(|p|Vector3::new(p[0],p[1],p[2])).collect();
spline.knots=joined.knots().to_vec();spline.weights=joined.weights().to_vec();
spline.fit_points.clear();spline.flags.rational=joined.is_rational();
spline.dwg_flags1 &= !1;spline.dxf_flags &= !(32 | 1024);
spline.flags.planar=cadkernel::space::are_coplanar(joined.control_points(),&[]);
spline.flags.planar=kernel::space::are_coplanar(joined.control_points(),&[]);
spline.begin_tangent=Vector3::new(0.0,0.0,0.0);spline.end_tangent=Vector3::new(0.0,0.0,0.0);
Some(EntityType::Spline(spline))
})
@@ -261,7 +261,7 @@ fn segs_of(e: &EntityType) -> Option<Vec<Seg>> {
if normal.x.abs() > 1e-12 || normal.y.abs() > 1e-12 {
return None;
}
let cadkernel::geom2d::Curve::Polyline(curve) =
let kernel::geom2d::Curve::Polyline(curve) =
crate::entities::curve::entity_curve_xy(&EntityType::Polyline2D(p.clone()))?
else {
return None;
@@ -327,7 +327,7 @@ pub fn join_entities(entities: &[(Handle, &EntityType)]) -> Option<(Vec<Handle>,
// An open run of collinear straight segments collapses back to one Line.
if !closed && !has_arc && chain.iter().all(|segment| segment.widths == Some((0.0,0.0))) && !matches!(entities[0].1, EntityType::LwPolyline(_) | EntityType::Polyline2D(_)) && is_collinear(&verts) {
let mut line = acadrust::entities::Line::new();
let mut line = codec::entities::Line::new();
line.common = common;
line.common.handle = Handle::NULL;
line.start = v3(verts.first().unwrap().0);
@@ -342,10 +342,10 @@ pub fn join_entities(entities: &[(Handle, &EntityType)]) -> Option<(Vec<Handle>,
return None;
}
let flipped = thickness != 0.0 && normal.z < 0.0;
let lw_verts: Vec<acadrust::entities::LwVertex> = verts
let lw_verts: Vec<codec::entities::LwVertex> = verts
.iter().enumerate()
.map(|(index,(p, bulge))| {
let mut v = acadrust::entities::LwVertex::new(Vector2::new(
let mut v = codec::entities::LwVertex::new(Vector2::new(
if flipped { -p.x } else { p.x },
p.y,
));
@@ -356,7 +356,7 @@ pub fn join_entities(entities: &[(Handle, &EntityType)]) -> Option<(Vec<Handle>,
v
})
.collect();
let mut pl = acadrust::entities::LwPolyline::new();
let mut pl = codec::entities::LwPolyline::new();
pl.common = common;
pl.common.handle = Handle::NULL;
pl.vertices = lw_verts;
@@ -372,8 +372,8 @@ pub fn join_entities(entities: &[(Handle, &EntityType)]) -> Option<(Vec<Handle>,
let output = crate::entities::curve::ocs_plane(source.normal.clone(),source.elevation);
polyline.vertices = pl.vertices.iter().map(|vertex| {
let point = output.project(input.point_at([vertex.location.x,vertex.location.y]))?;
let mut result = acadrust::entities::polyline::Vertex2D::new(Vector3::new(point[0],point[1],source.elevation));
result.bulge = if cadkernel::space::Vec3::from(input.normal()?).dot(cadkernel::space::Vec3::from(output.normal()?)) < 0.0 {-vertex.bulge} else {vertex.bulge}; result.start_width = vertex.start_width; result.end_width = vertex.end_width;
let mut result = codec::entities::polyline::Vertex2D::new(Vector3::new(point[0],point[1],source.elevation));
result.bulge = if kernel::space::Vec3::from(input.normal()?).dot(kernel::space::Vec3::from(output.normal()?)) < 0.0 {-vertex.bulge} else {vertex.bulge}; result.start_width = vertex.start_width; result.end_width = vertex.end_width;
Some(result)
}).collect::<Option<Vec<_>>>()?;
polyline.start_width = 0.0; polyline.end_width = 0.0;
@@ -397,12 +397,12 @@ pub fn join_entities(entities: &[(Handle, &EntityType)]) -> Option<(Vec<Handle>,
if thickness != 0.0 {
return None;
}
let mut pl = acadrust::entities::Polyline3D::new();
let mut pl = codec::entities::Polyline3D::new();
pl.common = common;
pl.common.handle = Handle::NULL;
pl.vertices = verts
.iter()
.map(|(p, _)| acadrust::entities::Vertex3DPolyline::new(v3(*p)))
.map(|(p, _)| codec::entities::Vertex3DPolyline::new(v3(*p)))
.collect();
if closed {
pl.close();
@@ -460,8 +460,8 @@ fn stitch(mut segs: Vec<Seg>) -> Option<(Vec<Seg>, bool)> {
#[cfg(test)]
mod join_tests {
use super::*;
use acadrust::entities::{Line as LineEnt, LwVertex};
use acadrust::Handle;
use codec::entities::{Line as LineEnt, LwVertex};
use codec::Handle;
fn line(x0: f64, y0: f64, x1: f64, y1: f64, thickness: f64) -> EntityType {
let mut l = LineEnt::new();
@@ -472,7 +472,7 @@ mod join_tests {
}
fn lw_2pts(p0: (f64, f64), p1: (f64, f64), thickness: f64) -> EntityType {
let mut pl = acadrust::entities::LwPolyline::new();
let mut pl = codec::entities::LwPolyline::new();
pl.vertices = vec![
LwVertex::new(Vector2::new(p0.0, p0.1)),
LwVertex::new(Vector2::new(p1.0, p1.1)),
@@ -554,7 +554,7 @@ mod join_tests {
fn source_join_elevates_splines_and_clears_fit_representation() {
let source_handle = Handle::new(21);
let candidate_handle = Handle::new(22);
let mut source = acadrust::entities::Spline::new();
let mut source = codec::entities::Spline::new();
source.common.handle = source_handle;
source.degree = 1;
source.control_points = vec![
@@ -565,7 +565,7 @@ mod join_tests {
source.fit_points = vec![Vector3::new(0.0, 0.0, 0.0)];
source.dwg_flags1 = 1;
source.dxf_flags = 32 | 1024;
let mut candidate = acadrust::entities::Spline::new();
let mut candidate = codec::entities::Spline::new();
candidate.degree = 3;
candidate.control_points = vec![
Vector3::new(1.0, 0.0, 0.0),
@@ -595,7 +595,7 @@ mod join_tests {
#[test]
fn arc_source_accepts_the_typed_close_option() {
let handle = Handle::new(31);
let mut arc = acadrust::entities::Arc::new();
let mut arc = codec::entities::Arc::new();
arc.common.handle = handle;
arc.center = Vector3::new(2.0, 3.0, 4.0);
arc.radius = 5.0;
+12 -12
View File
@@ -8,12 +8,12 @@
// The entity is modified at whichever end is closest to the pick point.
use crate::modules::draw::modify::spline_ops::{spline_cut, spline_to_nurbs};
use acadrust::entities::{
use codec::entities::{
Spline as SplineEnt,
};
use cadkernel::geom2d::Curve;
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use kernel::geom2d::Curve;
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::{DVec3, Vec3};
use crate::t;
@@ -249,7 +249,7 @@ pub fn lengthen_entity(entity: &EntityType, pick_pt: Vec3, mode: &LenMode) -> Op
}
fn lengthen_entity_precise(entity: &EntityType, pick: DVec3, mode: &LenMode) -> Option<EntityType> {
use cadkernel::space::lengthen::{LengthChange, lengthen_line, lengthen_arc};
use kernel::space::lengthen::{LengthChange, lengthen_line, lengthen_arc};
let change = match mode {
LenMode::Delta(value) => LengthChange::Delta(*value),
LenMode::Total(value) => LengthChange::Total(*value),
@@ -279,7 +279,7 @@ fn lengthen_entity_precise(entity: &EntityType, pick: DVec3, mode: &LenMode) ->
}
EntityType::Ellipse(ellipse) => {
let curve = crate::entities::curve::ellipse_curve(ellipse)?;
let (start, end) = cadkernel::space::lengthen::lengthen_ellipse(&curve, pick.to_array(), change)?;
let (start, end) = kernel::space::lengthen::lengthen_ellipse(&curve, pick.to_array(), change)?;
let mut result = ellipse.clone();
result.start_parameter = start;
result.end_parameter = end;
@@ -288,7 +288,7 @@ fn lengthen_entity_precise(entity: &EntityType, pick: DVec3, mode: &LenMode) ->
EntityType::Spline(s) => lengthen_spline(s, pick.as_vec3(), mode),
EntityType::LwPolyline(polyline) => {
let curve = crate::entities::curve::lwpolyline_curve(polyline)?;
let vertices = cadkernel::space::lengthen::lengthen_polyline(&curve, pick.to_array(), change)?;
let vertices = kernel::space::lengthen::lengthen_polyline(&curve, pick.to_array(), change)?;
let mut result = polyline.clone();
result.vertices = vertices.into_iter().map(|vertex| {
let mut value = polyline.vertices[vertex.source].clone();
@@ -365,7 +365,7 @@ mod tests {
use super::*;
fn spatial_line() -> EntityType {
EntityType::Line(acadrust::entities::Line::from_points(
EntityType::Line(codec::entities::Line::from_points(
Vector3::new(0.0, 0.0, 0.0),
Vector3::new(0.0, 0.0, 4.0),
))
@@ -422,7 +422,7 @@ mod tests {
#[test]
fn circular_arc_accepts_total_angle_in_radians() {
let arc = acadrust::entities::Arc::from_center_radius_angles(
let arc = codec::entities::Arc::from_center_radius_angles(
Vector3::ZERO,
2.0,
0.0,
@@ -447,13 +447,13 @@ mod tests {
#[test]
fn polyline_lengthening_preserves_plane_and_interpolates_widths() {
let mut polyline = acadrust::entities::LwPolyline::new();
let mut polyline = codec::entities::LwPolyline::new();
polyline.normal = Vector3::new(0.0, 1.0, 0.0);
polyline.elevation = 5.0;
let mut start = acadrust::entities::LwVertex::from_coords(0.0, 0.0);
let mut start = codec::entities::LwVertex::from_coords(0.0, 0.0);
start.start_width = 2.0;
start.end_width = 4.0;
polyline.vertices = vec![start, acadrust::entities::LwVertex::from_coords(10.0, 0.0)];
polyline.vertices = vec![start, codec::entities::LwVertex::from_coords(10.0, 0.0)];
let entity = EntityType::LwPolyline(polyline.clone());
let pick = DVec3::from_array(crate::entities::curve::lwpolyline_curve(&polyline)
.unwrap().point_at(1.0));
+1 -1
View File
@@ -8,7 +8,7 @@
// No → keep the original, add a mirrored copy
// Yes → flip the original in place (no copy kept)
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+18 -18
View File
@@ -1,8 +1,8 @@
use acadrust::entities::MLine;
use acadrust::objects::MLineStyle;
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::{Curve, Line};
use cadkernel::space::{PlanarCurve, Plane, Vec3 as KernelVec3};
use codec::entities::MLine;
use codec::objects::MLineStyle;
use codec::{EntityType, Handle};
use kernel::geom2d::{Curve, Line};
use kernel::space::{PlanarCurve, Plane, Vec3 as KernelVec3};
use glam::DVec3;
use rustc_hash::FxHashMap as HashMap;
@@ -95,7 +95,7 @@ impl MlineEditCommand {
}
let insert = segment + 1;
let mut vertex = mline.vertices[segment].clone();
vertex.position = acadrust::types::Vector3::new(
vertex.position = codec::types::Vector3::new(
projected.x,
projected.y,
projected.z,
@@ -710,7 +710,7 @@ fn snapshot_segment_data(
mline: &MLine,
segment: usize,
normal: DVec3,
) -> Option<Vec<(acadrust::entities::MLineSegment, f64)>> {
) -> Option<Vec<(codec::entities::MLineSegment, f64)>> {
(0..mline.style_element_count)
.map(|element| {
let endpoints = element_segment(mline, segment, element)?;
@@ -726,7 +726,7 @@ fn restore_shifted_segment_data(
mline: &mut MLine,
segment: usize,
normal: DVec3,
source: Vec<(acadrust::entities::MLineSegment, f64)>,
source: Vec<(codec::entities::MLineSegment, f64)>,
moved_start: bool,
) {
for (element, (source, source_length)) in source.into_iter().enumerate() {
@@ -1057,7 +1057,7 @@ fn move_closest_end(
};
let peripheral = peripheral_segment
.and_then(|segment| snapshot_segment_data(mline, segment, normal).map(|data| (segment, data)));
mline.vertices[index].position = acadrust::types::Vector3::new(
mline.vertices[index].position = codec::types::Vector3::new(
intersection.x,
intersection.y,
intersection.z,
@@ -1096,11 +1096,11 @@ fn segment_intersection(
second: (DVec3, DVec3),
normal: DVec3,
) -> Option<(DVec3, f64, f64, f64)> {
let axis = (cadkernel::space::Vec3::from(first.1.to_array())
- cadkernel::space::Vec3::from(first.0.to_array()))
let axis = (kernel::space::Vec3::from(first.1.to_array())
- kernel::space::Vec3::from(first.0.to_array()))
.normalize()?
.to_array();
let plane = cadkernel::space::Plane::orthonormal(
let plane = kernel::space::Plane::orthonormal(
first.0.to_array(),
axis,
normal.to_array(),
@@ -1111,15 +1111,15 @@ fn segment_intersection(
second.0.to_array(),
second.1.to_array(),
];
let tolerance = cadkernel::space::coplanarity_tolerance(&points);
let tolerance = kernel::space::coplanarity_tolerance(&points);
if !plane.contains(points[2], tolerance) || !plane.contains(points[3], tolerance) {
return None;
}
let p = cadkernel::geom2d::Vec2::from(plane.project(points[0])?);
let q = cadkernel::geom2d::Vec2::from(plane.project(points[2])?);
let r = cadkernel::geom2d::Vec2::from(plane.project(points[1])?) - p;
let s = cadkernel::geom2d::Vec2::from(plane.project(points[3])?) - q;
let (t, u) = cadkernel::geom2d::intersect::line_line(
let p = kernel::geom2d::Vec2::from(plane.project(points[0])?);
let q = kernel::geom2d::Vec2::from(plane.project(points[2])?);
let r = kernel::geom2d::Vec2::from(plane.project(points[1])?) - p;
let s = kernel::geom2d::Vec2::from(plane.project(points[3])?) - q;
let (t, u) = kernel::geom2d::intersect::line_line(
p.to_array(),
r.to_array(),
q.to_array(),
+7 -7
View File
@@ -1,6 +1,6 @@
use acadrust::{CadDocument, EntityType, Handle};
use codec::{CadDocument, EntityType, Handle};
use glam::DVec3;
use acadrust::nested_copy::{NestedCopyMode, NestedCopySymbolNames};
use codec::nested_copy::{NestedCopyMode, NestedCopySymbolNames};
use std::collections::{HashMap, HashSet};
use crate::command::{CadCommand, CmdOption, CmdResult, EntityTransform};
use crate::entities::traits::EntityTypeOps;
@@ -101,13 +101,13 @@ impl CadCommand for NcopyCommand {
let nearest = entities.iter().enumerate().filter_map(|(index, entity)| {
let distance = if let Some(curve) = crate::entities::curve::entity_curve(entity) {
let projected = curve.plane.project([point.x, point.y, point.z])?;
cadkernel::geom2d::closest_point(&curve.curve, projected).distance
kernel::geom2d::closest_point(&curve.curve, projected).distance
.hypot(curve.plane.distance_to(point.to_array())?)
} else {
let path = self.hit_paths.get(&handle)?.get(index)?;
let point = cadkernel::space::Vec3::from(point.to_array());
let point = kernel::space::Vec3::from(point.to_array());
if path.len() == 1 {
point.distance(cadkernel::space::Vec3::from(path[0]))
point.distance(kernel::space::Vec3::from(path[0]))
} else {
path.windows(2).filter(|segment| segment.iter().flatten().all(|v| v.is_finite()))
.map(|segment| point.distance_to_segment(segment[0].into(), segment[1].into()))
@@ -197,8 +197,8 @@ impl CadCommand for NcopyCommand {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::Line;
use acadrust::types::Vector3;
use codec::entities::Line;
use codec::types::Vector3;
#[test]
fn placement_moves_only_geometry_and_keeps_source_style() {
+11 -11
View File
@@ -12,16 +12,16 @@
use crate::entities::curve::{entity_curve, lwpolyline_world_xy};
use crate::modules::draw::modify::spline_ops::spline_sample_xy;
use acadrust::entities::LwVertex;
use acadrust::entities::{
use codec::entities::LwVertex;
use codec::entities::{
Arc as ArcEnt, Circle as CircleEnt, Ellipse as EllipseEnt, Line as LineEnt, LwPolyline,
Spline as SplineEnt, XLine as XLineEnt,
};
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
// Polyline offsetting, and the angle normalisation that goes with it, come
// from the kernel; only the entity conversion stays here.
use cadkernel::geom2d::nurbs::clamped_uniform_knots;
use cadkernel::geom2d::{
use kernel::geom2d::nurbs::clamped_uniform_knots;
use kernel::geom2d::{
offset_polyline, Polyline as KernelPolyline, PolylineVertex as KernelVertex,
};
use glam::{DVec3, Vec3};
@@ -269,7 +269,7 @@ fn offset_spline(spl: &SplineEnt, dist: f64, side_pt: Vec3) -> Option<EntityType
})?;
// Offset each sample point along the local normal.
let offset_pts: Vec<acadrust::types::Vector3> = pts
let offset_pts: Vec<codec::types::Vector3> = pts
.iter()
.enumerate()
.map(|(i, p)| {
@@ -290,14 +290,14 @@ fn offset_spline(spl: &SplineEnt, dist: f64, side_pt: Vec3) -> Option<EntityType
let nx = -dy / len; // left perpendicular
let ny = dx / len;
let z = spl.control_points.first().map(|v| v.z).unwrap_or(0.0);
acadrust::types::Vector3::new(p[0] + sign * nx * dist, p[1] + sign * ny * dist, z)
codec::types::Vector3::new(p[0] + sign * nx * dist, p[1] + sign * ny * dist, z)
})
.collect();
let _ = ts_knot;
// Build a new spline from the offset control points (treat sample pts as fit pts → ctrl pts).
let degree = spl.degree.max(1) as usize;
let new_ctrl: Vec<acadrust::types::Vector3> = offset_pts;
let new_ctrl: Vec<codec::types::Vector3> = offset_pts;
let n_ctrl = new_ctrl.len();
let mut new_spl = spl.clone();
new_spl.common.handle = Handle::NULL;
@@ -364,7 +364,7 @@ fn perp_distance(entity: &EntityType, pt: Vec3) -> f64 {
// ── Wire preview points ─────────────────────────────────────────────────────
/// Preview density, matching the figure the drawn wires use.
const PREVIEW_SEGMENTS_PER_RADIAN: f64 = cadkernel::geom2d::DEFAULT_SEGMENTS_PER_RADIAN;
const PREVIEW_SEGMENTS_PER_RADIAN: f64 = kernel::geom2d::DEFAULT_SEGMENTS_PER_RADIAN;
/// Preview points for an entity, from its own curve.
///
@@ -989,7 +989,7 @@ inventory::submit!(crate::command::CommandRegistration { names: &["OFFSET"] });
#[cfg(test)]
mod offset_tests {
use super::*;
use acadrust::types::Vector2;
use codec::types::Vector2;
fn rect(corners: &[[f64; 2]]) -> LwPolyline {
LwPolyline {
@@ -1049,7 +1049,7 @@ mod option_tests {
use super::*;
fn line(x1: f64, y1: f64, x2: f64, y2: f64, handle: u64) -> EntityType {
let mut line = acadrust::entities::Line::from_coords(x1, y1, 0.0, x2, y2, 0.0);
let mut line = codec::entities::Line::from_coords(x1, y1, 0.0, x2, y2, 0.0);
line.common.handle = Handle::new(handle);
EntityType::Line(line)
}
+5 -5
View File
@@ -1,4 +1,4 @@
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult};
@@ -104,7 +104,7 @@ impl CadCommand for OverkillCommand {
pub fn normalized(entity:&EntityType, ignore:u16) -> EntityType {
let mut e=entity.clone();
let common=e.common_mut();
let default=acadrust::entities::EntityCommon::new();
let default=codec::entities::EntityCommon::new();
common.handle=Handle::NULL;
if ignore&1!=0 {common.color=default.color;common.color_name=None;common.color_book_handle=None;}
if ignore&2!=0 {common.layer.clear();}
@@ -125,7 +125,7 @@ pub fn optimize(entity:&mut EntityType, tolerance:f64) {
// Width changes and bulged spans carry geometry that must be retained.
if p.vertices.iter().any(|v|v.bulge!=0.0||v.start_width!=0.0||v.end_width!=0.0) {return;}
let points:Vec<_>=p.vertices.iter().map(|v|[v.location.x,v.location.y,p.elevation]).collect();
let indices=cadkernel::space::simplify_linear_chain(&points,tolerance);
let indices=kernel::space::simplify_linear_chain(&points,tolerance);
if indices.len()>=if p.is_closed{3}else{2} {
p.vertices=indices.into_iter().map(|i|p.vertices[i].clone()).collect();
}
@@ -135,8 +135,8 @@ pub fn optimize(entity:&mut EntityType, tolerance:f64) {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::{Line, LwPolyline};
use acadrust::types::{Color, Vector2};
use codec::entities::{Line, LwPolyline};
use codec::types::{Color, Vector2};
#[test]
fn normalization_ignores_only_the_requested_properties() {
+46 -46
View File
@@ -1,10 +1,10 @@
// PEDIT edits polylines and polygon meshes.
use acadrust::entities::LwVertex;
use acadrust::types::{Vector2, Vector3};
use acadrust::{EntityType, Handle};
use cadkernel::geom2d::nurbs::clamped_uniform_knots;
use cadkernel::geom2d::NurbsCurve;
use codec::entities::LwVertex;
use codec::types::{Vector2, Vector3};
use codec::{EntityType, Handle};
use kernel::geom2d::nurbs::clamped_uniform_knots;
use kernel::geom2d::NurbsCurve;
use glam::DVec3;
use rustc_hash::FxHashMap as HashMap;
@@ -12,7 +12,7 @@ use crate::command::{CadCommand, CmdResult};
use crate::t;
const TAU: f64 = std::f64::consts::TAU;
pub use cadkernel::space::endpoint_join::JoinType;
pub use kernel::space::endpoint_join::JoinType;
static JOIN_TYPE: std::sync::Mutex<JoinType> = std::sync::Mutex::new(JoinType::Extend);
static JOIN_FUZZ: std::sync::Mutex<f64> = std::sync::Mutex::new(0.0);
@@ -70,7 +70,7 @@ pub struct PeditCommand {
vertex_tangents: HashMap<usize, f64>,
pending_tangents: Option<HashMap<usize, f64>>,
tangent_history: Vec<HashMap<usize, f64>>,
mesh_smooth_type: acadrust::entities::polygon_mesh::SurfaceSmoothType,
mesh_smooth_type: codec::entities::polygon_mesh::SurfaceSmoothType,
mesh_smooth_density: (i16, i16),
mesh_vertex_default: isize,
pending_mesh_closed: Option<(bool, bool)>,
@@ -84,7 +84,7 @@ impl PeditCommand {
surface_u_density: i16,
surface_v_density: i16,
) -> Self {
use acadrust::entities::polygon_mesh::SurfaceSmoothType;
use codec::entities::polygon_mesh::SurfaceSmoothType;
let mesh_smooth_type = match surface_type {
5 => SurfaceSmoothType::Quadratic,
@@ -622,7 +622,7 @@ impl CadCommand for PeditCommand {
handle,
op: PeditOp::SetMeshSmooth {
smooth:
acadrust::entities::polygon_mesh::SurfaceSmoothType::NoSmooth,
codec::entities::polygon_mesh::SurfaceSmoothType::NoSmooth,
m_density: self.mesh_smooth_density.0,
n_density: self.mesh_smooth_density.1,
},
@@ -741,7 +741,7 @@ impl CadCommand for PeditCommand {
_ => return CmdResult::NeedPoint,
};
let Some(local) = crate::entities::curve::ocs_plane(normal, elevation).project([point.x, point.y, point.z]) else { return CmdResult::NeedPoint; };
let delta = cadkernel::geom2d::Vec2::new(local[0] - location[0], local[1] - location[1]);
let delta = kernel::geom2d::Vec2::new(local[0] - location[0], local[1] - location[1]);
if !delta.length_squared().is_finite() || delta.length_squared() <= 1e-24 { return CmdResult::NeedPoint; }
self.vertex_tangents.insert(index, delta.angle().rem_euclid(TAU));
self.mode = Mode::PolyVertex(index);
@@ -838,7 +838,7 @@ pub enum PeditOp {
SetMeshClosedM(bool),
SetMeshClosedN(bool),
SetMeshSmooth {
smooth: acadrust::entities::polygon_mesh::SurfaceSmoothType,
smooth: codec::entities::polygon_mesh::SurfaceSmoothType,
m_density: i16,
n_density: i16,
},
@@ -878,9 +878,9 @@ pub fn edit_vertex_range(entity: &EntityType, first: usize, last: usize, split:
}
match entity {
EntityType::LwPolyline(polyline) => edit!(polyline, polyline.is_closed, LwPolyline,
|value: &mut acadrust::entities::LwPolyline| { value.is_closed = false; }),
|value: &mut codec::entities::LwPolyline| { value.is_closed = false; }),
EntityType::Polyline2D(polyline) => edit!(polyline, polyline.flags.is_closed(), Polyline2D,
|value: &mut acadrust::entities::Polyline2D| { value.flags.set_closed(false); }),
|value: &mut codec::entities::Polyline2D| { value.flags.set_closed(false); }),
_ => None,
}
}
@@ -929,7 +929,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
if *index >= polyline.vertices.len() { return false; }
let location = Vector3::new(local[0], local[1], polyline.elevation);
if *insert {
polyline.vertices.insert(index + 1, acadrust::entities::polyline::Vertex2D::new(location));
polyline.vertices.insert(index + 1, codec::entities::polyline::Vertex2D::new(location));
} else { polyline.vertices[*index].location = location; }
true
}
@@ -948,10 +948,10 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
true
}
EntityType::Polyline2D(polyline) => {
let flag = acadrust::entities::polyline::PolylineFlags::LINETYPE_CONTINUOUS;
let flag = codec::entities::polyline::PolylineFlags::LINETYPE_CONTINUOUS;
let bits = polyline.flags.bits();
if (bits & flag.bits() != 0) == *enabled { return false; }
polyline.flags = acadrust::entities::polyline::PolylineFlags::from_bits(
polyline.flags = codec::entities::polyline::PolylineFlags::from_bits(
if *enabled { bits | flag.bits() } else { bits & !flag.bits() }
);
true
@@ -1014,7 +1014,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
return false;
}
mesh.flags.set(
acadrust::entities::polygon_mesh::PolygonMeshFlags::CLOSED_M,
codec::entities::polygon_mesh::PolygonMeshFlags::CLOSED_M,
*closed,
);
true
@@ -1027,7 +1027,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
return false;
}
mesh.flags.set(
acadrust::entities::polygon_mesh::PolygonMeshFlags::CLOSED_N,
codec::entities::polygon_mesh::PolygonMeshFlags::CLOSED_N,
*closed,
);
true
@@ -1043,7 +1043,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
let mut changed = mesh.smooth_type != *smooth;
mesh.smooth_type = *smooth;
if mesh.smooth_type
!= acadrust::entities::polygon_mesh::SurfaceSmoothType::NoSmooth
!= codec::entities::polygon_mesh::SurfaceSmoothType::NoSmooth
{
let m_density = (*m_density).clamp(2, 200);
let n_density = (*n_density).clamp(2, 200);
@@ -1074,7 +1074,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
{
return false;
}
vertex.location = acadrust::types::Vector3::new(point.x, point.y, point.z);
vertex.location = codec::types::Vector3::new(point.x, point.y, point.z);
true
}
_ => false,
@@ -1087,7 +1087,7 @@ pub fn apply_pedit(entity: &mut EntityType, op: &PeditOp) -> bool {
/// A Line or Arc as an equivalent 2-vertex LwPolyline (common carried over,
/// handle NULL for the replace flow). `None` for anything else.
pub fn convert_to_polyline(entity: &EntityType) -> Option<EntityType> {
let mut pl = acadrust::LwPolyline::new();
let mut pl = codec::LwPolyline::new();
match entity {
EntityType::Line(l) => {
let normal = DVec3::new(l.normal.x, l.normal.y, l.normal.z).try_normalize()?;
@@ -1098,7 +1098,7 @@ pub fn convert_to_polyline(entity: &EntityType) -> Option<EntityType> {
normal.x, normal.y, normal.z,
));
let plane = crate::entities::curve::ocs_plane(normal.clone(), elevation);
let tolerance = cadkernel::space::coplanarity_tolerance(&[start, end]);
let tolerance = kernel::space::coplanarity_tolerance(&[start, end]);
if !plane.contains(end, tolerance) {
return None;
}
@@ -1154,10 +1154,10 @@ mod convert_tests {
// onto the new entity instead of resetting to 0 (#916).
#[test]
fn convert_keeps_line_thickness() {
let mut l = acadrust::entities::Line::new();
l.start = acadrust::types::Vector3::new(2.0, 3.0, 4.0);
l.end = acadrust::types::Vector3::new(2.0, 5.0, 6.0);
l.normal = acadrust::types::Vector3::new(1.0, 0.0, 0.0);
let mut l = codec::entities::Line::new();
l.start = codec::types::Vector3::new(2.0, 3.0, 4.0);
l.end = codec::types::Vector3::new(2.0, 5.0, 6.0);
l.normal = codec::types::Vector3::new(1.0, 0.0, 0.0);
l.thickness = 3.5;
let Some(EntityType::LwPolyline(pl)) = convert_to_polyline(&EntityType::Line(l)) else {
panic!("line must convert");
@@ -1167,15 +1167,15 @@ mod convert_tests {
"converted polyline must keep source thickness, got {}",
pl.thickness
);
assert_eq!(pl.normal, acadrust::types::Vector3::new(1.0, 0.0, 0.0));
assert_eq!(pl.normal, codec::types::Vector3::new(1.0, 0.0, 0.0));
assert!((pl.elevation - 2.0).abs() < 1e-12);
}
#[test]
fn convert_keeps_arc_thickness() {
let mut a = acadrust::entities::Arc::new();
a.center = acadrust::types::Vector3::new(0.0, 0.0, 4.0);
a.normal = acadrust::types::Vector3::new(0.0, 1.0, 0.0);
let mut a = codec::entities::Arc::new();
a.center = codec::types::Vector3::new(0.0, 0.0, 4.0);
a.normal = codec::types::Vector3::new(0.0, 1.0, 0.0);
a.radius = 5.0;
a.start_angle = 0.0;
a.end_angle = std::f64::consts::FRAC_PI_2;
@@ -1188,7 +1188,7 @@ mod convert_tests {
"converted polyline must keep negative thickness, got {}",
pl.thickness
);
assert_eq!(pl.normal, acadrust::types::Vector3::new(0.0, 1.0, 0.0));
assert_eq!(pl.normal, codec::types::Vector3::new(0.0, 1.0, 0.0));
assert!((pl.elevation - 4.0).abs() < 1e-12);
}
}
@@ -1196,7 +1196,7 @@ mod convert_tests {
// ── Curve fitting ─────────────────────────────────────────────────────────
fn fit_entity(entity: &EntityType, overrides: &[(usize, f64)]) -> Option<EntityType> {
use acadrust::entities::{Polyline2D, PolylineFlags, Vertex2D, VertexFlags};
use codec::entities::{Polyline2D, PolylineFlags, Vertex2D, VertexFlags};
let mut polyline = match entity {
EntityType::Polyline2D(p) => p.clone(),
EntityType::LwPolyline(p) => {
@@ -1231,7 +1231,7 @@ fn fit_entity(entity: &EntityType, overrides: &[(usize, f64)]) -> Option<EntityT
}
let points: Vec<_> = originals.iter().map(|v| [v.location.x, v.location.y]).collect();
let directions: Vec<_> = originals.iter().map(|v| (v.flags.bits() & 2 != 0).then(|| [v.curve_tangent.cos(), v.curve_tangent.sin()])).collect();
let fitted = cadkernel::geom2d::fit_arc_chain(&points, polyline.flags.is_closed(), &directions)?;
let fitted = kernel::geom2d::fit_arc_chain(&points, polyline.flags.is_closed(), &directions)?;
let mut vertices = Vec::with_capacity(fitted.len());
for (i, fitted_vertex) in fitted.iter().enumerate() {
let original = &originals[fitted_vertex.source];
@@ -1251,7 +1251,7 @@ fn fit_entity(entity: &EntityType, overrides: &[(usize, f64)]) -> Option<EntityT
Some(EntityType::Polyline2D(polyline))
}
fn defining_vertices(polyline: &acadrust::entities::Polyline2D) -> Vec<acadrust::entities::Vertex2D> {
fn defining_vertices(polyline: &codec::entities::Polyline2D) -> Vec<codec::entities::Vertex2D> {
polyline.vertices.iter().enumerate().filter(|(_, vertex)| vertex.flags.bits() & 1 == 0).map(|(index, vertex)| {
let mut original = vertex.clone();
if let Some(knee) = polyline.vertices[index + 1..].iter().take_while(|next| next.flags.bits() & 1 != 0).last() {
@@ -1265,7 +1265,7 @@ fn decurve_entity(entity: &EntityType) -> Option<EntityType> {
let mut result = match entity {
EntityType::LwPolyline(p) => p.clone(),
EntityType::Polyline2D(p) => {
let mut result = acadrust::LwPolyline::new();
let mut result = codec::LwPolyline::new();
result.common = p.common.clone(); result.normal = p.normal;
result.elevation = p.elevation; result.thickness = p.thickness;
result.is_closed = p.flags.is_closed(); result.plinegen = p.flags.bits() & 128 != 0;
@@ -1299,7 +1299,7 @@ fn decurve_entity(entity: &EntityType) -> Option<EntityType> {
/// out, with the open case clamped by repeating end points and then the two
/// ends pinned back afterwards to undo the drift that leaves — all of which
/// a clamped knot vector expresses directly and exactly.
fn spline_smooth(p: &mut acadrust::LwPolyline) -> bool {
fn spline_smooth(p: &mut codec::LwPolyline) -> bool {
const DEGREE: usize = 3;
const PER_SPAN: usize = 8;
@@ -1350,10 +1350,10 @@ fn spline_smooth(p: &mut acadrust::LwPolyline) -> bool {
#[cfg(test)]
mod editing_tests {
use super::*;
use acadrust::entities::{Polyline2D, Vertex2D};
use codec::entities::{Polyline2D, Vertex2D};
fn lightweight(handle: u64, points: &[[f64; 2]]) -> EntityType {
let mut polyline = acadrust::LwPolyline::new();
let mut polyline = codec::LwPolyline::new();
polyline.common.handle = Handle::new(handle);
polyline.vertices = points
.iter()
@@ -1488,9 +1488,9 @@ mod editing_tests {
#[test]
fn multiple_decline_and_fuzz_join_keep_the_command_active() {
*JOIN_TYPE.lock().unwrap_or_else(|error| error.into_inner()) = JoinType::Extend;
let mut line = acadrust::entities::Line::new();
let mut line = codec::entities::Line::new();
line.common.handle = Handle::new(11);
let mut arc = acadrust::entities::Arc::new();
let mut arc = codec::entities::Arc::new();
arc.common.handle = Handle::new(12);
let mut declined = command(
vec![EntityType::Line(line), EntityType::Arc(arc)],
@@ -1663,14 +1663,14 @@ pub fn join_selection_extend(source: &EntityType, candidates: &[(Handle, &Entity
let b_ends = [true,false].into_iter().filter_map(|start| endpoint(candidate,start).map(|points|(start,points))).collect::<Vec<_>>();
let a_points = a_ends.iter().map(|(_,points)|*points).collect::<Vec<_>>();
let b_points = b_ends.iter().map(|(_,points)|*points).collect::<Vec<_>>();
if let Some((a_index,b_index,joint)) = cadkernel::space::endpoint_join::closest_line_end_join(&a_points,&b_points,fuzz,connector_distance.unwrap_or(0.0),kind) {
if let Some((a_index,b_index,joint)) = kernel::space::endpoint_join::closest_line_end_join(&a_points,&b_points,fuzz,connector_distance.unwrap_or(0.0),kind) {
let (a_start,a_points) = a_ends[a_index]; let (b_start,b_points) = b_ends[b_index];
let mut a = result.clone(); let mut b = (*candidate).clone();
let joined_pair = if let Some(point) = joint {
if move_endpoint(&mut a,a_start,point).is_none() || move_endpoint(&mut b,b_start,point).is_none() {continue;}
super::join::join_to_source(&a,&[(*handle,&b)])
} else {
let mut line = acadrust::entities::Line::new();
let mut line = codec::entities::Line::new();
line.start = Vector3::new(a_points[1][0],a_points[1][1],a_points[1][2]);
line.end = Vector3::new(b_points[1][0],b_points[1][1],b_points[1][2]);
match &a {
@@ -1710,7 +1710,7 @@ pub fn selection_connector_distance(entities: &[(Handle, EntityType)], fuzz: f64
};
if !z.is_finite() { return None; }
let plane = crate::entities::curve::ocs_plane(*normal, z);
let normal = cadkernel::space::Vec3::from(plane.normal()?);
let normal = kernel::space::Vec3::from(plane.normal()?);
let points = vertices.into_iter().map(|point| plane.point_at(point)).collect::<Vec<_>>();
curves.push((normal, points));
}
@@ -1719,10 +1719,10 @@ pub fn selection_connector_distance(entities: &[(Handle, EntityType)], fuzz: f64
return None;
}
let world = curves.iter().flat_map(|(_, points)| points.iter().copied()).collect::<Vec<_>>();
let tolerance = cadkernel::space::coplanarity_tolerance(&world);
let tolerance = kernel::space::coplanarity_tolerance(&world);
let shared = crate::entities::curve::ocs_plane(Vector3::new(normal.x, normal.y, normal.z),
cadkernel::space::Vec3::from(world[0]).dot(*normal));
kernel::space::Vec3::from(world[0]).dot(*normal));
if world.iter().any(|point| !shared.contains(*point, tolerance)) { return None; }
let points = world.into_iter().map(|point| shared.project(point)).collect::<Option<Vec<_>>>()?;
cadkernel::space::endpoint_join::planar_connector_distance(&points, fuzz)
kernel::space::endpoint_join::planar_connector_distance(&points, fuzz)
}
+3 -3
View File
@@ -13,7 +13,7 @@
// with an error message — full matrix inversion for those cases would
// require per-entity matrix transforms not yet in EntityTransform.
use acadrust::{EntityType, Handle};
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::t;
@@ -53,9 +53,9 @@ pub struct RefEditSession {
// ── INSERT placement, as full affine transforms ───────────────────
/// Block-local → world (the INSERT's `get_transform`). Handles OCS,
/// rotation and non-uniform / mirrored scale in one matrix.
pub forward: acadrust::types::Transform,
pub forward: codec::types::Transform,
/// World → block-local, applied on SAVE to bring edits back.
pub inverse: acadrust::types::Transform,
pub inverse: codec::types::Transform,
/// Handle watermark captured before the temp copies were created: every
/// entity allocated at or above it during the session (drawn, pasted,
/// offset, …) belongs to the working set, so Save folds it into the block
+8 -8
View File
@@ -21,8 +21,8 @@
// `CmdResult::NeedPoint` and keeps prompting so nothing is corrupted.
use crate::t;
use acadrust::entities::Spline;
use acadrust::{EntityType, Handle};
use codec::entities::Spline;
use codec::{EntityType, Handle};
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -104,7 +104,7 @@ impl ReverseCommand {
/// starting at original vertex `(n-1-i-1).rem_euclid(n)`. The widths follow the
/// Widths are segment-relative. Reversing a segment swaps its start and end
/// widths in addition to moving them to the corresponding reversed segment.
fn reverse_lwpolyline(pl: &acadrust::LwPolyline) -> acadrust::LwPolyline {
fn reverse_lwpolyline(pl: &codec::LwPolyline) -> codec::LwPolyline {
let mut out = pl.clone();
let n = pl.vertices.len();
if n < 2 {
@@ -141,7 +141,7 @@ fn reverse_lwpolyline(pl: &acadrust::LwPolyline) -> acadrust::LwPolyline {
}
/// Reverse a heavy 2D polyline with the same segment semantics as LWPolyline.
fn reverse_polyline2d(pl: &acadrust::entities::Polyline2D) -> acadrust::entities::Polyline2D {
fn reverse_polyline2d(pl: &codec::entities::Polyline2D) -> codec::entities::Polyline2D {
let mut out = pl.clone();
let n = pl.vertices.len();
if n < 2 {
@@ -152,7 +152,7 @@ fn reverse_polyline2d(pl: &acadrust::entities::Polyline2D) -> acadrust::entities
out.start_width = pl.end_width;
out.end_width = pl.start_width;
for vertex in &mut out.vertices {
let tangent_flag = acadrust::entities::VertexFlags::CURVE_FIT_TANGENT.bits();
let tangent_flag = codec::entities::VertexFlags::CURVE_FIT_TANGENT.bits();
if vertex.flags.bits() & tangent_flag != 0 {
vertex.curve_tangent =
(vertex.curve_tangent + std::f64::consts::PI).rem_euclid(std::f64::consts::TAU);
@@ -190,8 +190,8 @@ pub(super) fn reverse_spline(sp: &Spline) -> Spline {
out.knots = curve.reversed().knots().to_vec();
}
out.begin_tangent =
acadrust::types::Vector3::new(-sp.end_tangent.x, -sp.end_tangent.y, -sp.end_tangent.z);
out.end_tangent = acadrust::types::Vector3::new(
codec::types::Vector3::new(-sp.end_tangent.x, -sp.end_tangent.y, -sp.end_tangent.z);
out.end_tangent = codec::types::Vector3::new(
-sp.begin_tangent.x,
-sp.begin_tangent.y,
-sp.begin_tangent.z,
@@ -252,7 +252,7 @@ inventory::submit!(crate::command::CommandRegistration {
#[cfg(test)]
mod tests {
use super::*;
use acadrust::types::Vector3;
use codec::types::Vector3;
#[test]
fn spline_reversal_preserves_knot_spacing_weights_and_tangents() {
+2 -2
View File
@@ -9,8 +9,8 @@
// two points. The new absolute angle is then typed or picked from the center;
// the applied rotation is new-angle - reference-angle.
use acadrust::Handle;
use cadkernel::geom2d::{self, Curve as KernelCurve};
use codec::Handle;
use kernel::geom2d::{self, Curve as KernelCurve};
use glam::DVec3;
use crate::t;
+1 -1
View File
@@ -12,7 +12,7 @@
// measured between two points; the new length may be typed or measured
// from the scale base.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+10 -10
View File
@@ -1,4 +1,4 @@
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult};
@@ -6,10 +6,10 @@ static MODE: std::sync::atomic::AtomicU8 = std::sync::atomic::AtomicU8::new(255)
pub fn mode() -> u8 { MODE.load(std::sync::atomic::Ordering::Relaxed) }
pub fn set_mode(value: u8) { MODE.store(value, std::sync::atomic::Ordering::Relaxed); }
pub fn apply_mask(common: &mut acadrust::entities::EntityCommon, mask: u8, change_byblock: bool) -> bool {
pub fn apply_mask(common: &mut codec::entities::EntityCommon, mask: u8, change_byblock: bool) -> bool {
let before = common.clone();
if mask & 1 != 0 && (change_byblock || common.color != acadrust::types::Color::ByBlock) {
common.color = acadrust::types::Color::ByLayer;
if mask & 1 != 0 && (change_byblock || common.color != codec::types::Color::ByBlock) {
common.color = codec::types::Color::ByLayer;
common.color_name = None;
common.color_book_handle = None;
}
@@ -17,8 +17,8 @@ pub fn apply_mask(common: &mut acadrust::entities::EntityCommon, mask: u8, chang
common.linetype = "ByLayer".to_string();
common.linetype_handle = None;
}
if mask & 4 != 0 && (change_byblock || common.line_weight != acadrust::types::LineWeight::ByBlock) {
common.line_weight = acadrust::types::LineWeight::ByLayer;
if mask & 4 != 0 && (change_byblock || common.line_weight != codec::types::LineWeight::ByBlock) {
common.line_weight = codec::types::LineWeight::ByLayer;
}
if mask & 8 != 0 && (change_byblock || common.material_flags != 1) {
common.material_flags = 0;
@@ -28,8 +28,8 @@ pub fn apply_mask(common: &mut acadrust::entities::EntityCommon, mask: u8, chang
common.plotstyle_flags = 0;
common.plotstyle_handle = None;
}
if mask & 128 != 0 && (change_byblock || common.transparency != acadrust::types::Transparency::BY_BLOCK) {
common.transparency = acadrust::types::Transparency::BY_LAYER;
if mask & 128 != 0 && (change_byblock || common.transparency != codec::types::Transparency::BY_BLOCK) {
common.transparency = codec::types::Transparency::BY_LAYER;
}
*common != before
}
@@ -155,8 +155,8 @@ inventory::submit!(crate::command::CommandRegistration { names: &["SETBYLAYERMOD
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::EntityCommon;
use acadrust::types::{Color, Transparency};
use codec::entities::EntityCommon;
use codec::types::{Color, Transparency};
#[test]
fn mask_changes_only_requested_properties() {
+8 -8
View File
@@ -1,6 +1,6 @@
// Shared B-spline utilities for modify commands (TRIM, BREAK, OFFSET, LENGTHEN).
//
// The evaluation lives in cadkernel; this file converts a drawing's SPLINE
// The evaluation lives in opencadkernel; this file converts a drawing's SPLINE
// entity to and from it and keeps the knot-domain call shapes the commands
// were written against.
//
@@ -9,11 +9,11 @@
// piece of a NURBS circle into a piece of a parabola — a change that looks
// fine until it is measured.
use acadrust::entities::Spline;
use acadrust::types::Vector3;
use acadrust::Handle;
use cadkernel::geom2d::{NurbsCurve, Parameterization};
use cadkernel::space::Plane;
use codec::entities::Spline;
use codec::types::Vector3;
use codec::Handle;
use kernel::geom2d::{NurbsCurve, Parameterization};
use kernel::space::Plane;
/// The drawing plane a spline sits on.
///
@@ -30,7 +30,7 @@ fn elevation(spl: &Spline) -> f64 {
// ── Conversion ─────────────────────────────────────────────────────────────
/// Convert an acadrust `Spline` to a kernel `NurbsCurve`, weights included.
/// Convert an opencadcodec `Spline` to a kernel `NurbsCurve`, weights included.
///
/// A SPLINE is stored one of two ways and both turn up: a control polygon the
/// curve approaches, or fit points it must pass through with optional end
@@ -114,7 +114,7 @@ fn spline_to_nurbs_with(
)
}
/// Rebuild an acadrust `Spline` from a kernel curve.
/// Rebuild an opencadcodec `Spline` from a kernel curve.
///
/// The `template` supplies entity common data and the Z elevation; splines
/// here are planar, so the kernel's 2D points are lifted back onto it.
+34 -34
View File
@@ -9,8 +9,8 @@
//
// Control-point dragging is already supported via the grip editing system.
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
@@ -53,16 +53,16 @@ enum Step {
pub struct SplineditCommand {
step: Step,
handle: acadrust::Handle,
spline: Option<acadrust::entities::Spline>,
pending: Option<acadrust::entities::Spline>,
history: Vec<(acadrust::Handle, acadrust::entities::Spline)>,
handle: codec::Handle,
spline: Option<codec::entities::Spline>,
pending: Option<codec::entities::Spline>,
history: Vec<(codec::Handle, codec::entities::Spline)>,
pick_context: Option<crate::command::PointPickContext>,
join_candidates: Vec<crate::command::SelectionEntity>,
delete_source: bool,
}
fn clear_fit_method(spline: &mut acadrust::entities::Spline) {
fn clear_fit_method(spline: &mut codec::entities::Spline) {
spline.fit_points.clear();
spline.begin_tangent = Vector3::ZERO;
spline.end_tangent = Vector3::ZERO;
@@ -80,7 +80,7 @@ fn weights_are_rational(weights: &[f64]) -> bool {
impl SplineditCommand {
pub fn new() -> Self {
Self { step: Step::SelectSpline, handle: acadrust::Handle::NULL, spline: None, pending: None, history: Vec::new(), pick_context: None, join_candidates: Vec::new(), delete_source: true }
Self { step: Step::SelectSpline, handle: codec::Handle::NULL, spline: None, pending: None, history: Vec::new(), pick_context: None, join_candidates: Vec::new(), delete_source: true }
}
pub fn with_delete_source(mut self, delete: bool) -> Self { self.delete_source = delete; self }
@@ -97,19 +97,19 @@ impl SplineditCommand {
if points.len() < 2 { return None; }
let entity = if let Some(planar) = crate::entities::curve::entity_curve(&EntityType::Spline(source.clone())) {
let normal = planar.plane.normal()?;
let elevation = cadkernel::space::Vec3::from(points[0]).dot(cadkernel::space::Vec3::from(normal));
let elevation = kernel::space::Vec3::from(points[0]).dot(kernel::space::Vec3::from(normal));
let normal = Vector3::new(normal[0], normal[1], normal[2]);
let plane = crate::entities::curve::ocs_plane(normal.clone(), elevation);
let mut polyline = acadrust::LwPolyline::new();
let mut polyline = codec::LwPolyline::new();
polyline.common = source.common.clone();
polyline.elevation = elevation; polyline.normal = normal; polyline.is_closed = self.closed();
polyline.vertices = points.iter().map(|point| {
let uv = plane.project(*point)?;
Some(acadrust::entities::LwVertex::new(acadrust::types::Vector2::new(uv[0], uv[1])))
Some(codec::entities::LwVertex::new(codec::types::Vector2::new(uv[0], uv[1])))
}).collect::<Option<Vec<_>>>()?;
EntityType::LwPolyline(polyline)
} else {
let mut polyline = acadrust::entities::Polyline3D::from_points(points.iter().map(|p| Vector3::new(p[0],p[1],p[2])).collect());
let mut polyline = codec::entities::Polyline3D::from_points(points.iter().map(|p| Vector3::new(p[0],p[1],p[2])).collect());
polyline.common = source.common.clone(); polyline.flags.closed = self.closed();
EntityType::Polyline3D(polyline)
};
@@ -117,7 +117,7 @@ impl SplineditCommand {
});
let Some(mut entity) = result else { return CmdResult::ReportError(crate::t!("Spline cannot be converted within the requested precision.").into_owned()); };
if self.delete_source { CmdResult::ReplaceMany(vec![(self.handle,vec![entity])], Vec::new()) }
else { entity.common_mut().handle = acadrust::Handle::NULL; CmdResult::ReplaceMany(Vec::new(), vec![entity]) }
else { entity.common_mut().handle = codec::Handle::NULL; CmdResult::ReplaceMany(Vec::new(), vec![entity]) }
}
fn picked_vertex(&self, point: DVec3) -> Option<usize> { self.picked_from_points(point, &self.spline.as_ref()?.control_points) }
@@ -132,7 +132,7 @@ impl SplineditCommand {
self.rebuild_fit(result)
}
fn rebuild_fit(&mut self, mut result: acadrust::entities::Spline) -> CmdResult {
fn rebuild_fit(&mut self, mut result: codec::entities::Spline) -> CmdResult {
let Some(source) = self.spline.as_ref() else { return CmdResult::NeedPoint; };
if source.fit_tolerance != 0.0 || source.weights.windows(2).any(|w| w[0] != w[1]) {
return CmdResult::ReportError(crate::t!("Editing weighted or tolerance-fitted interpolation data is not supported.").into_owned());
@@ -201,7 +201,7 @@ impl SplineditCommand {
self.spline.as_ref().is_some_and(|spline| spline.flags.closed || spline.flags.periodic)
}
fn replace(&mut self, spline: acadrust::entities::Spline) -> CmdResult {
fn replace(&mut self, spline: codec::entities::Spline) -> CmdResult {
self.pending = Some(spline.clone());
CmdResult::ReplaceManyContinue(vec![(self.handle, vec![EntityType::Spline(spline)])])
}
@@ -224,7 +224,7 @@ impl SplineditCommand {
CmdResult::ReplaceManyContinue(replacements)
}
fn refined(&self, point: Option<DVec3>, degree: Option<usize>) -> Option<acadrust::entities::Spline> {
fn refined(&self, point: Option<DVec3>, degree: Option<usize>) -> Option<codec::entities::Spline> {
let source = self.spline.as_ref()?;
if let Some(degree) = degree {
let current = usize::try_from(source.degree).ok()?;
@@ -244,10 +244,10 @@ impl SplineditCommand {
return Some(result);
}
let planar = crate::entities::curve::entity_curve(&EntityType::Spline(source.clone()))?;
let cadkernel::geom2d::Curve::Nurbs(mut curve) = planar.curve else { return None; };
let kernel::geom2d::Curve::Nurbs(mut curve) = planar.curve else { return None; };
if let Some(point) = point {
let projected = planar.plane.project([point.x, point.y, point.z])?;
let nearest = cadkernel::geom2d::closest_point(&cadkernel::geom2d::Curve::Nurbs(curve.clone()), projected);
let nearest = kernel::geom2d::closest_point(&kernel::geom2d::Curve::Nurbs(curve.clone()), projected);
let (start, end) = curve.domain();
let parameter = start + nearest.t * (end - start);
if parameter <= start || parameter >= end { return None; }
@@ -321,7 +321,7 @@ impl CadCommand for SplineditCommand {
fn inject_selection_entities(&mut self, entities: Vec<crate::command::SelectionEntity>) {
if matches!(self.step, Step::Join) { self.join_candidates = entities; }
}
fn on_selection_complete(&mut self, handles: Vec<acadrust::Handle>) -> CmdResult {
fn on_selection_complete(&mut self, handles: Vec<codec::Handle>) -> CmdResult {
self.join_candidates.retain(|item| handles.contains(&item.handle) && item.handle != self.handle);
CmdResult::NeedPoint
}
@@ -330,13 +330,13 @@ impl CadCommand for SplineditCommand {
fn inject_picked_entity(&mut self, entity: EntityType) {
self.spline = match entity { EntityType::Spline(spline) => Some(spline), _ => None };
}
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: DVec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: codec::Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() || self.spline.is_none() { return CmdResult::NeedPoint; }
self.handle = handle;
self.step = Step::Options;
CmdResult::NeedPoint
}
fn on_entity_replaced(&mut self, old: acadrust::Handle, new: &[acadrust::Handle]) {
fn on_entity_replaced(&mut self, old: codec::Handle, new: &[codec::Handle]) {
if old == self.handle {
if let (Some(&handle), Some(replacement)) = (new.first(), self.pending.take()) {
if let Some(previous) = self.spline.replace(replacement) { self.history.push((old, previous)); }
@@ -514,7 +514,7 @@ impl CadCommand for SplineditCommand {
let controls = source.control_points.iter().map(|point| [point.x, point.y, point.z]).collect();
let weights = if source.weights.is_empty() { vec![1.0; source.control_points.len()] }
else { source.weights.clone() };
let curve = cadkernel::space::NurbsCurve3::new_strict(source.degree as usize, controls,
let curve = kernel::space::NurbsCurve3::new_strict(source.degree as usize, controls,
source.knots.clone(), weights).map(|curve| curve.with_periodicity(source.flags.periodic || source.flags.closed));
let Some(curve) = curve.and_then(|curve| curve.without_control_vertex(index)) else { return CmdResult::NeedPoint; };
let mut spline = source.clone();
@@ -576,14 +576,14 @@ impl CadCommand for SplineditCommand {
}
/// Apply a spline operation (CLOSE/OPEN/REVERSE) to a spline entity.
/// Called from `cmd_result.rs` when the ReplaceEntity sentinel is detected.
pub fn apply_spline_op(doc: &mut acadrust::CadDocument, handle: acadrust::Handle, op: &str) {
pub fn apply_spline_op(doc: &mut codec::CadDocument, handle: codec::Handle, op: &str) {
let Some(EntityType::Spline(spline)) = doc.get_entity_mut(handle) else {
return;
};
apply_to_spline(spline, op);
}
fn apply_to_spline(spline: &mut acadrust::entities::Spline, op: &str) {
fn apply_to_spline(spline: &mut codec::entities::Spline, op: &str) {
let result = match op {
"__SPLINEDIT_CLOSE__" => change_closure(spline, true),
"__SPLINEDIT_OPEN__" => change_closure(spline, false),
@@ -593,8 +593,8 @@ fn apply_to_spline(spline: &mut acadrust::entities::Spline, op: &str) {
if let Some(result) = result { *spline = result; }
}
fn change_closure(source: &acadrust::entities::Spline, closed: bool) -> Option<acadrust::entities::Spline> {
use cadkernel::space::{NurbsCurve3, Parameterization};
fn change_closure(source: &codec::entities::Spline, closed: bool) -> Option<codec::entities::Spline> {
use kernel::space::{NurbsCurve3, Parameterization};
if (source.flags.closed || source.flags.periodic) == closed { return None; }
let fit_method = !source.fit_points.is_empty() || source.dwg_flags1 & 1 != 0 || source.dxf_flags & 32 != 0;
let parameterization = match source.knot_parameterization {
@@ -654,8 +654,8 @@ fn change_closure(source: &acadrust::entities::Spline, closed: bool) -> Option<a
#[cfg(test)]
mod tests {
use super::*;
use acadrust::entities::Spline;
use acadrust::Handle;
use codec::entities::Spline;
use codec::Handle;
use iced::Rectangle;
fn control_spline(points: &[[f64; 3]], degree: usize) -> Spline {
@@ -665,7 +665,7 @@ mod tests {
.iter()
.map(|point| Vector3::new(point[0], point[1], point[2]))
.collect();
spline.knots = cadkernel::space::clamped_uniform_knots(degree, points.len());
spline.knots = kernel::space::clamped_uniform_knots(degree, points.len());
spline
}
@@ -785,7 +785,7 @@ mod tests {
#[test]
fn a_closed_weighted_control_curve_can_be_opened() {
let curve = cadkernel::space::NurbsCurve3::from_weighted_control_polygon(
let curve = kernel::space::NurbsCurve3::from_weighted_control_polygon(
2,
&[
[0.0, 0.0, 0.0],
@@ -806,7 +806,7 @@ mod tests {
let opened = change_closure(&spline, false).expect("closed control curve opens");
assert!(!opened.flags.closed);
assert!(!opened.flags.periodic);
assert!(cadkernel::space::NurbsCurve3::new_strict(
assert!(kernel::space::NurbsCurve3::new_strict(
opened.degree as usize,
opened
.control_points
@@ -888,7 +888,7 @@ mod tests {
#[test]
fn closed_conversion_closes_once_and_invalid_precision_retries() {
let curve = cadkernel::space::NurbsCurve3::from_control_polygon(
let curve = kernel::space::NurbsCurve3::from_control_polygon(
2,
&[
[0.0, 0.0, 0.0],
@@ -964,13 +964,13 @@ mod tests {
// ── Autocomplete registry ─────────────────────────────────
inventory::submit!(crate::command::CommandRegistration { names: &["SPLINEDIT"] }); // SplineditCommand
fn spatial_spline(source: &acadrust::entities::Spline) -> Option<cadkernel::space::NurbsCurve3> {
fn spatial_spline(source: &codec::entities::Spline) -> Option<kernel::space::NurbsCurve3> {
let curve = if crate::entities::spline::uses_fit_method(source) {
crate::entities::spline::fit_nurbs3(source)?
} else {
let current = usize::try_from(source.degree).ok()?;
let weights = if source.weights.is_empty() { vec![1.0; source.control_points.len()] } else { source.weights.clone() };
cadkernel::space::NurbsCurve3::new_strict(current,
kernel::space::NurbsCurve3::new_strict(current,
source.control_points.iter().map(|point| [point.x, point.y, point.z]).collect(),
source.knots.clone(), weights)?
};
+1 -1
View File
@@ -15,7 +15,7 @@
// Insert : move the whole entity if its insertion point is inside.
// All others : move the whole entity if any point is inside.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+2 -2
View File
@@ -5,13 +5,13 @@
// Step 1: Wait for an angle (numerical input), Enter (Most Readable), or pick first point.
// Step 2: If first point picked, pick second point to define angle vector.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
use crate::command::{CadCommand, CmdResult, DynField};
use crate::scene::model::wire_model::WireModel;
use acadrust::EntityType;
use codec::EntityType;
// ── Command implementation ─────────────────────────────────────────────────
+1 -1
View File
@@ -6,7 +6,7 @@
// Step 2: pick destination → translates all selected entities by (dest - base);
// Enter uses the base point as the displacement (commercial solutions).
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
+14 -14
View File
@@ -10,7 +10,7 @@
use std::f64::consts::TAU;
// The plane geometry these commands run on lives in cadkernel; `geom` adapts
// The plane geometry these commands run on lives in opencadkernel; `geom` adapts
// its call shapes to the loose scalars and f32 render vertices used here.
use super::geom;
use super::geom::{
@@ -20,15 +20,15 @@ use super::geom::{
use crate::modules::draw::fence::{crossing_box_preview, FencePick};
use acadrust::entities::{
use codec::entities::{
Arc as ArcEnt, Circle as CircleEnt, Ellipse as EllipseEnt, Line as LineEnt, LwPolyline,
LwVertex, Ray as RayEnt, Spline as SplineEnt, XLine as XLineEnt,
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use codec::types::Vector3;
use codec::{EntityType, Handle};
use glam::DVec3;
use cadkernel::geom2d::nurbs::clamped_uniform_knots;
use cadkernel::geom2d::{
use kernel::geom2d::nurbs::clamped_uniform_knots;
use kernel::geom2d::{
intersect as kernel_intersect, trim_spans as kernel_trim_spans, Arc as KernelArc,
BulgeArc, Circle as KernelCircle, Curve, Extent as KernelExtent,
Ellipse as KernelEllipse, EllipseArc as KernelEllipseArc, Line as KernelLine,
@@ -77,7 +77,7 @@ const TRIM_EXTENT: f64 = 1_000_000.0;
/// Sampling density for the plan-view point lists the fence and preview
/// passes walk. The renderer's own figure, so a preview cut lands where the
/// drawn geometry is rather than a chord away from it.
const SAMPLE_SEGMENTS_PER_RADIAN: f64 = cadkernel::geom2d::DEFAULT_SEGMENTS_PER_RADIAN;
const SAMPLE_SEGMENTS_PER_RADIAN: f64 = kernel::geom2d::DEFAULT_SEGMENTS_PER_RADIAN;
/// If a trim interval endpoint is beyond this threshold it is treated as "infinite".
#[derive(Clone)]
@@ -694,11 +694,11 @@ fn extend_spline(spl: &SplineEnt, t_click: f64, geos: &[Geo]) -> Option<EntityTy
if extend_end {
new_spl
.control_points
.push(acadrust::types::Vector3::new(hit_x, hit_y, z));
.push(codec::types::Vector3::new(hit_x, hit_y, z));
} else {
new_spl
.control_points
.insert(0, acadrust::types::Vector3::new(hit_x, hit_y, z));
.insert(0, codec::types::Vector3::new(hit_x, hit_y, z));
}
// Rebuild knots (uniform) for the extended control polygon.
let degree = new_spl.degree as usize;
@@ -2548,7 +2548,7 @@ impl CadCommand for TrimCommand {
}
}
fn on_entity_replaced(&mut self, _old: Handle, new_handles: &[acadrust::Handle]) {
fn on_entity_replaced(&mut self, _old: Handle, new_handles: &[codec::Handle]) {
// Batch gestures stage several NULL-handle replacement groups before
// the document assigns real handles. The host applies them in the same
// order, so fill the first remaining placeholders on each callback.
@@ -3227,7 +3227,7 @@ impl CadCommand for ExtendCommand {
}
}
fn on_entity_replaced(&mut self, _old: Handle, new_handles: &[acadrust::Handle]) {
fn on_entity_replaced(&mut self, _old: Handle, new_handles: &[codec::Handle]) {
// The last new_handles.len() entries are the pieces appended with NULL
// handles in on_entity_pick — assign their real document handles.
let start = self.all_entities.len().saturating_sub(new_handles.len());
@@ -3816,7 +3816,7 @@ mod tests {
/// two empty ends as equal and sliced the empty sample from index 1.
#[test]
fn sampling_skips_segments_with_no_plan_shape() {
use acadrust::entities::{Polyline3D, Vertex3DPolyline};
use codec::entities::{Polyline3D, Vertex3DPolyline};
let mut pl = Polyline3D::new();
pl.vertices = vec![
@@ -3842,7 +3842,7 @@ mod tests {
/// must keep dropping the duplicated seam vertex between two of them.
#[test]
fn sampling_still_joins_segments_at_their_seam() {
use acadrust::entities::{Polyline3D, Vertex3DPolyline};
use codec::entities::{Polyline3D, Vertex3DPolyline};
let mut pl = Polyline3D::new();
pl.vertices = vec![
@@ -3862,7 +3862,7 @@ mod tests {
#[test]
fn preview_sampling_skips_edge_on_polyline2d_arc_segments() {
use acadrust::entities::{Polyline2D, Vertex2D};
use codec::entities::{Polyline2D, Vertex2D};
let mut pl = Polyline2D::new();
let mut start = Vertex2D::new(Vector3::new(0.0, 0.0, 0.0));
+1 -1
View File
@@ -13,7 +13,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
+1 -1
View File
@@ -8,7 +8,7 @@
// Single-object commands (e.g. LAYMCUR) use `instant()` instead: the first
// completed selection action fires straight away, no Enter required.
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::t;
+1 -1
View File
@@ -145,7 +145,7 @@ pub fn conversion_factor(from: i16, to: i16) -> Option<f64> {
/// Paper space is deliberately left out. Its geometry is measured on the sheet,
/// in sheet units, and means the same thing however the model is labelled —
/// scaling it would resize the drawing frame along with the building.
pub fn model_space_handles(scene: &crate::scene::Scene) -> Vec<acadrust::Handle> {
pub fn model_space_handles(scene: &crate::scene::Scene) -> Vec<codec::Handle> {
let Some(model) = scene.document.block_records.get("*Model_Space") else {
return Vec::new();
};
+9 -9
View File
@@ -1,5 +1,5 @@
use crate::t;
use acadrust::Handle;
use codec::Handle;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -205,15 +205,15 @@ mod tests {
use super::*;
use crate::scene::{CreateBlockOptions, Scene};
use crate::ui::window::block_definition::BlockObjectMode;
use acadrust::entities::Line;
use acadrust::types::{Transform, Vector3};
use codec::entities::Line;
use codec::types::{Transform, Vector3};
fn make_test_scene() -> (Scene, Handle) {
let mut scene = Scene::new();
let mut line = Line::new();
line.start = Vector3::new(0.0, 0.0, 0.0);
line.end = Vector3::new(10.0, 10.0, 0.0);
let h = scene.add_entity(acadrust::EntityType::Line(line));
let h = scene.add_entity(codec::EntityType::Line(line));
(scene, h)
}
@@ -279,7 +279,7 @@ mod tests {
// Insert entity exists in drawing
let insert_entity = scene.document.get_entity(insert_h);
assert!(insert_entity.is_some());
if let Some(acadrust::EntityType::Insert(ins)) = insert_entity {
if let Some(codec::EntityType::Insert(ins)) = insert_entity {
assert_eq!(ins.block_name, "BLK_CONVERT");
} else {
panic!("Expected Insert entity");
@@ -352,7 +352,7 @@ mod tests {
let mut line2 = Line::new();
line2.start = Vector3::new(5.0, 5.0, 0.0);
line2.end = Vector3::new(15.0, 15.0, 0.0);
scene.add_entity(acadrust::EntityType::Line(line2))
scene.add_entity(codec::EntityType::Line(line2))
};
let options2 = CreateBlockOptions {
@@ -560,7 +560,7 @@ mod tests {
// In Convert mode, the insert entity must be placed at the picked base point
let insert_entity = scene.document.get_entity(insert_h).unwrap();
if let acadrust::EntityType::Insert(ins) = insert_entity {
if let codec::EntityType::Insert(ins) = insert_entity {
assert_eq!(ins.block_name, "ON_SCREEN_BASE_TEST");
assert!((ins.insert_point.x - 10.0).abs() < 1e-6);
assert!((ins.insert_point.y - 10.0).abs() < 1e-6);
@@ -580,10 +580,10 @@ mod tests {
.document
.entities()
.find(|e| {
e.common().owner_handle == br.handle && matches!(e, acadrust::EntityType::Line(_))
e.common().owner_handle == br.handle && matches!(e, codec::EntityType::Line(_))
})
.unwrap();
if let acadrust::EntityType::Line(l) = block_line {
if let codec::EntityType::Line(l) = block_line {
assert!((l.start.x - (-10.0)).abs() < 1e-6);
assert!((l.start.y - (-10.0)).abs() < 1e-6);
assert!((l.end.x - 0.0).abs() < 1e-6);
+5 -5
View File
@@ -1,6 +1,6 @@
use acadrust::entities::{AttributeDefinition, AttributeEntity, Entity, Insert};
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::{AttributeDefinition, AttributeEntity, Entity, Insert};
use codec::types::Vector3;
use codec::EntityType;
use glam::{DVec3, Vec3};
use crate::t;
@@ -341,7 +341,7 @@ impl CadCommand for InsertBlockCommand {
fn attreq_set_attdefs(
&mut self,
attdefs: Vec<AttributeDefinition>,
) -> Option<acadrust::EntityType> {
) -> Option<codec::EntityType> {
self.step = Step::FillAttr {
attdefs,
idx: 0,
@@ -350,7 +350,7 @@ impl CadCommand for InsertBlockCommand {
self.advance_automatic_attributes()
}
fn attreq_take_insert(&mut self) -> Option<acadrust::EntityType> {
fn attreq_take_insert(&mut self) -> Option<codec::EntityType> {
self.pending_insert
.take()
.map(|ins| EntityType::Insert(ins))
+3 -3
View File
@@ -6,9 +6,9 @@
//! entity is a single [`Insert`] with its array fields set, which the renderer
//! replicates over `row_count × column_count` using the row/column spacing.
use acadrust::entities::Insert;
use acadrust::types::Vector3;
use acadrust::EntityType;
use codec::entities::Insert;
use codec::types::Vector3;
use codec::EntityType;
use glam::DVec3;
use crate::t;
+5 -5
View File
@@ -13,10 +13,10 @@
use std::sync::Mutex;
use acadrust::entities::{Underlay, UnderlayDisplayFlags};
use acadrust::objects::{Dictionary, ObjectType, UnderlayDefinition};
use acadrust::types::{Handle, Vector3};
use acadrust::{CadDocument, EntityType};
use codec::entities::{Underlay, UnderlayDisplayFlags};
use codec::objects::{Dictionary, ObjectType, UnderlayDefinition};
use codec::types::{Handle, Vector3};
use codec::{CadDocument, EntityType};
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind, WorkingPlane};
@@ -493,7 +493,7 @@ fn same_path(a: &str, b: &str) -> bool {
pub fn ensure_pdf_definition(document: &mut CadDocument, path: &str, page: &str) -> Handle {
let existing = document.objects.iter().find_map(|(handle, object)| match object {
ObjectType::UnderlayDefinition(def)
if matches!(def.underlay_type, acadrust::entities::UnderlayType::Pdf)
if matches!(def.underlay_type, codec::entities::UnderlayType::Pdf)
&& same_path(&def.file_path, path)
&& crate::entities::underlay::page_of(def) == page =>
{
+3 -3
View File
@@ -11,9 +11,9 @@
// The boundary is stored in underlay units; the clip-inside bit follows the
// Invert choice.
use acadrust::entities::{Underlay, UnderlayDisplayFlags, UnderlayType};
use acadrust::types::{Handle, Vector2};
use acadrust::EntityType;
use codec::entities::{Underlay, UnderlayDisplayFlags, UnderlayType};
use codec::types::{Handle, Vector2};
use codec::EntityType;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
+4 -4
View File
@@ -14,12 +14,12 @@
// (other fills solid hatches), text runs MTEXT in a "PDF <font>" style and
// raster images PNG files referenced by IMAGE objects.
use acadrust::entities::{
use codec::entities::{
AttachmentPoint, BoundaryEdge, BoundaryPath, Circle, Hatch, LwPolyline, MText, PolylineEdge,
Solid, Spline, Underlay, UnderlayType,
};
use acadrust::types::{Color, Handle, LineWeight, Vector2, Vector3};
use acadrust::EntityType;
use codec::types::{Color, Handle, LineWeight, Vector2, Vector3};
use codec::EntityType;
use glam::DVec3;
use crate::command::{CadCommand, CmdOption, CmdResult, InputKind};
@@ -746,7 +746,7 @@ pub fn convert(
color
}
};
let fill_transparency = acadrust::types::Transparency::from_alpha_value(0x0200_007F);
let fill_transparency = codec::types::Transparency::from_alpha_value(0x0200_007F);
let mut strokes: Vec<Stroke> = Vec::new();
let mut curves: Vec<EntityType> = Vec::new();
Loaded 100 of 430 files, more files were not shown because too many files have changed in this diff. Show more