forked from 1b-agent/opencadstudio-upstream
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:
1 parent
9c08e8a3ed
commit
8d287decd8
7 files changed
+77
-79
No files matched your search
@@ -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),
|
||||
|
||||
Reference in new issue
Block a user