fix(explode): use codec block explosion for attributes and arrays

Delegate INSERT and MINSERT explosion to the document-aware codec implementation, removing duplicate attribute and base-point handling. Update workspace, kernel and graph pins together and cover rotated arrays with a nonzero base.
This commit is contained in:
Karim Jerbi committed 2026-10-13 11:10:11 +01:00
1 parent 9c08e8a3ed
commit 8d287decd8
7 files changed
+77 -79

No files matched your search

+7 -64
View File
@@ -23,8 +23,8 @@ use codec::entities::{
};
use codec::entities::{Polyline, Polyline2D};
use codec::tables::BlockRecord;
use codec::types::{Transform, Vector3};
use codec::{CadDocument, Entity, EntityType, Handle};
use codec::types::Vector3;
use codec::{CadDocument, EntityType, Handle};
use crate::command::{CadCommand, CmdResult, WorkingPlane};
use crate::entities::curve::lwpolyline_world_xy;
@@ -98,68 +98,11 @@ pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec<Entity
{
vec![]
}
EntityType::Insert(ins) => {
let explodable = document
.block_records
.get(&ins.block_name)
.map_or(true, |br| br.explodable);
if !explodable {
vec![]
} else {
// The codec applies only `Insert::get_transform`, which does
// not know the block's base point, so shift the definition's
// contents by -base first: get_transform(P - base) is exactly
// world = insert_point + Rot*Scale*(P - base), the placement
// the render path uses. MINSERT cells and nested references
// get the same treatment because the shift happens on the
// contents, not on the insert.
let base = crate::scene::render_graph::block_base_point(document, &ins.block_name);
let to_block = Transform::from_translation(Vector3::new(-base.x, -base.y, -base.z));
let mut attdefs: Vec<EntityType> = Vec::new();
let entities: Vec<EntityType> = document
.entities_in_block(&ins.block_name)
.map(|entity| {
let mut shifted = entity.clone();
Entity::apply_transform(shifted.as_entity_mut(), &to_block);
if let EntityType::AttributeDefinition(_) = &shifted {
attdefs.push(shifted.clone());
}
shifted
})
.collect();
let mut pieces: Vec<EntityType> = ins
.explode(&entities)
.into_iter()
.map(normalize_insert_entity)
.collect();
// Exploding an INSERT drops attribute values (ATTRIBs)
// and the attribute definitions (ATTDEF tags) reappear as ATTDEF entities.
// The codec's `ins.explode` skips `AttributeDefinition` entities, so we
// transform and append them here.
if !attdefs.is_empty() {
let insert_xform = ins.get_transform();
for ad_ent in &attdefs {
let mut exploded_ad = ad_ent.clone();
Entity::apply_transform(exploded_ad.as_entity_mut(), &insert_xform);
// Resolve common properties (layer "0", ByBlock color / line weight)
let common = exploded_ad.common_mut();
if common.layer == "0" {
common.layer = ins.common.layer.clone();
}
if common.color == codec::types::Color::ByBlock {
common.color = ins.common.color;
}
if common.line_weight == codec::types::LineWeight::ByBlock {
common.line_weight = ins.common.line_weight;
}
pieces.push(exploded_ad);
}
}
pieces
}
}
EntityType::Insert(ins) => ins
.explode_from_document(document)
.into_iter()
.map(normalize_insert_entity)
.collect(),
EntityType::MLine(ml) => explode_mline(ml),
EntityType::Dimension(dim) => explode_dimension(dim, document),
EntityType::MText(t) => crate::entities::mtext::explode_mtext(t, document),