mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-24 10:56:51 -06:00
Write a layout's paper-space viewport (id 1) ahead of its other viewports (#1782)
DWG stores no viewport ids; readers number a layout's viewports in order. A drawing whose draw order (SORTENTS) put the paper-space viewport behind a model viewport came back from DWG with that model viewport as the sheet. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
9d9e4c3b0d
commit
7db656fdc7
@@ -1629,6 +1629,15 @@ fn paper_views(d: &Drawing) -> HashMap<Handle, usize> {
|
||||
out
|
||||
}
|
||||
|
||||
/// A layout's entities with its paper-space viewport (id 1) first. DWG stores no viewport ids and
|
||||
/// readers number a layout's viewports in order, so the sheet must lead even when the draw order
|
||||
/// (SORTENTS) put it behind a model viewport; otherwise that viewport becomes the sheet.
|
||||
fn sheet_first(l: &Layout) -> Vec<&Entity> {
|
||||
let sheet = |e: &&Entity| matches!(&e.kind, EntityKind::Viewport(v) if v.id == 1);
|
||||
let all = || l.entities.iter().map(|e| e.as_ref());
|
||||
all().filter(sheet).chain(all().filter(|e| !sheet(e))).collect()
|
||||
}
|
||||
|
||||
/// The paper-space viewport (id 1) of the layout whose first viewport is `e`, if it needs one
|
||||
/// ([`paper_views`]): the whole sheet, viewed 1:1. Marked with CADCraft xdata so that our reader
|
||||
/// leaves it implicit again.
|
||||
@@ -2340,7 +2349,7 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
if i == 0 {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut std::iter::empty(), true);
|
||||
} else {
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut l.entities.iter().map(|e| e.as_ref()), true);
|
||||
block(&mut w, n, "", h, Vec3::ZERO, 0, &mut sheet_first(l).into_iter(), true);
|
||||
}
|
||||
}
|
||||
for (n, h, b) in &user_blocks {
|
||||
@@ -2371,7 +2380,7 @@ fn tags_for(d: &Drawing, version: Version, target: Version) -> Vec<Tag> {
|
||||
entity(&mut w, d, e, &ms_br, false, &cx);
|
||||
}
|
||||
if let Some((_, h, l)) = ps_brs.first() {
|
||||
for e in l.entities.iter() {
|
||||
for e in sheet_first(l) {
|
||||
entity(&mut w, d, e, h, true, &cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,3 +138,24 @@ fn viewport_ids_survive_dwg_and_the_paper_viewport_stays_implicit() {
|
||||
assert!(!text.contains("PAPERVIEW"));
|
||||
assert_eq!(viewport_ids(&cadcraft_io::read_dxf(text.as_bytes()).unwrap().layouts[0]), [1, 2]);
|
||||
}
|
||||
|
||||
/// The paper-space viewport (id 1) of a drawing from another program can come after a model
|
||||
/// viewport in the layout, e.g. when the draw order (SORTENTS) put it behind. DWG numbers in
|
||||
/// order, so the writer puts it first: otherwise the model viewport became the sheet on reopen.
|
||||
#[test]
|
||||
fn a_paper_viewport_behind_a_model_viewport_stays_id_1_through_dwg() {
|
||||
let mut d = Drawing::new_metric();
|
||||
let names: Vec<String> = d.layouts.iter().map(|l| l.name.clone()).collect();
|
||||
for name in &names {
|
||||
let space = Space::Paper(name.clone());
|
||||
let model = d.add(&space, Common::default(), viewport(2)).unwrap();
|
||||
let sheet = d.add(&space, Common::default(), viewport(1)).unwrap();
|
||||
let back = through_dwg(&d);
|
||||
let l = back.layouts.iter().find(|l| &l.name == name).unwrap();
|
||||
let id = |h: Handle| match &l.entities.get(h).map(|e| &e.kind) {
|
||||
Some(EntityKind::Viewport(v)) => Some(v.id),
|
||||
_ => None,
|
||||
};
|
||||
assert_eq!((id(model), id(sheet)), (Some(2), Some(1)), "layout {name}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user