forked from 1b-agent/opencadstudio-upstream
fix(scene): viewport auto-fit fallback + f64-precision projection
Three changes to make paper-space viewports render correctly on UTM-scale drawings whose viewports were saved with default view_target=(0, 0, 0) and a view_center pointing at empty WCS: 1. **Auto-fit fallback.** When the saved view's WCS rect doesn't overlap the IQR-bounded content cluster (`world_offset ± local_extent_max`), override `view_center` with `world_offset` and recompute `view_height` to fit the cluster into the paper viewport. Matches AutoCAD's silent auto-fit-on-open for stale / uninitialized viewports; without it those viewports rendered blank. 2. **f64 projection inner loop.** The previous f32 path computed `(wire_offset_rel - target_offset_rel).dot(view_right) - view_center` by subtracting values at ~5e6 magnitude (f32 ULP ~0.5 m) to land on a small paper offset. The cancellation produced centimetre-scale jitter on paper output even when the model was clean. Reconstruct the wire WCS coord, subtract the display center, and dot-project in f64; cast to f32 only at the final paper position where magnitudes are bounded by the viewport rect. 3. **examples/inspect_viewports.rs** — diagnostic that dumps every viewport's saved view fields (view_target, view_center, view_height vs paper height, custom_scale, status flags) plus drawing-level insertion_units and model-space extents. Used to verify that acadrust's DWG reader reads view_height correctly; the `view_height == vp.height` patterns observed on real files turn out to be genuine "default 1:1" file content rather than a reader bug (a round-trip test through DwgWriter / DwgReader survives all per-viewport values). Also: switch the `acadrust` patch from `HakanSeven12/acadrust@feat/ expose-blockrecord-is-loaded` (a stale branch with the abandoned is_loaded experiment) to `hakanaktt/acadrust@main`. Upstream main now carries the layout paper-dimensions and mirrored-arc fixes that this branch used to add — plus PR #20's DXF reading fixes that the old branch was missing. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
68fe77c133
commit
de37ee04bf
4 files changed
+247
-27
No files matched your search
@@ -0,0 +1,126 @@
|
||||
// Dumps every paper-space viewport's view fields from a DWG/DXF.
|
||||
// cargo run --release --example inspect_viewports -- <path>
|
||||
use acadrust::entities::EntityType;
|
||||
use acadrust::io::dwg::DwgReader;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let path = std::env::args().nth(1).expect("usage: inspect_viewports <file>");
|
||||
let doc = DwgReader::from_file(&path)?.read()?;
|
||||
println!("file: {}", path);
|
||||
println!("total entities: {}", doc.entities().count());
|
||||
let unit_name = match doc.header.insertion_units {
|
||||
0 => "Unitless",
|
||||
1 => "Inches",
|
||||
2 => "Feet",
|
||||
3 => "Miles",
|
||||
4 => "Millimeters",
|
||||
5 => "Centimeters",
|
||||
6 => "Meters",
|
||||
7 => "Kilometers",
|
||||
_ => "Other",
|
||||
};
|
||||
println!(
|
||||
"header.insertion_units = {} ({})",
|
||||
doc.header.insertion_units, unit_name
|
||||
);
|
||||
println!(
|
||||
"header.model_space_extents min=({:.3}, {:.3}, {:.3}) max=({:.3}, {:.3}, {:.3})",
|
||||
doc.header.model_space_extents_min.x,
|
||||
doc.header.model_space_extents_min.y,
|
||||
doc.header.model_space_extents_min.z,
|
||||
doc.header.model_space_extents_max.x,
|
||||
doc.header.model_space_extents_max.y,
|
||||
doc.header.model_space_extents_max.z,
|
||||
);
|
||||
println!();
|
||||
|
||||
let viewports: Vec<_> = doc
|
||||
.entities()
|
||||
.filter_map(|e| {
|
||||
if let EntityType::Viewport(v) = e {
|
||||
Some(v.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
println!("viewports: {}\n", viewports.len());
|
||||
|
||||
for (i, vp) in viewports.iter().enumerate() {
|
||||
let scale_from_view_height = if vp.view_height.abs() > 1e-9 {
|
||||
vp.height / vp.view_height
|
||||
} else {
|
||||
f64::NAN
|
||||
};
|
||||
println!(
|
||||
"[{}] id={} handle={:?}",
|
||||
i, vp.id, vp.common.handle
|
||||
);
|
||||
println!(
|
||||
" paper center=({:.3}, {:.3}) size={:.3} × {:.3}",
|
||||
vp.center.x, vp.center.y, vp.width, vp.height
|
||||
);
|
||||
println!(
|
||||
" view_target=({:.3}, {:.3}, {:.3})",
|
||||
vp.view_target.x, vp.view_target.y, vp.view_target.z
|
||||
);
|
||||
println!(
|
||||
" view_direction=({:.3}, {:.3}, {:.3})",
|
||||
vp.view_direction.x, vp.view_direction.y, vp.view_direction.z
|
||||
);
|
||||
println!(
|
||||
" view_center=({:.3}, {:.3})",
|
||||
vp.view_center.x, vp.view_center.y
|
||||
);
|
||||
println!(
|
||||
" view_height={:.6} == vp.height? {} ⇒ height/view_height = {:.6}",
|
||||
vp.view_height,
|
||||
(vp.view_height - vp.height).abs() < 1e-6,
|
||||
scale_from_view_height
|
||||
);
|
||||
println!(
|
||||
" custom_scale={:.6} twist={:.4} lens={:.2}",
|
||||
vp.custom_scale, vp.twist_angle, vp.lens_length
|
||||
);
|
||||
println!(
|
||||
" status: on={}, locked={}, perspective={}",
|
||||
vp.status.is_on, vp.status.locked, vp.status.perspective
|
||||
);
|
||||
println!();
|
||||
}
|
||||
|
||||
// Summary stats
|
||||
let n_with_view_eq_height = viewports
|
||||
.iter()
|
||||
.filter(|v| (v.view_height - v.height).abs() < 1e-6)
|
||||
.count();
|
||||
let n_with_target_zero = viewports
|
||||
.iter()
|
||||
.filter(|v| {
|
||||
v.view_target.x.abs() < 1e-9
|
||||
&& v.view_target.y.abs() < 1e-9
|
||||
&& v.view_target.z.abs() < 1e-9
|
||||
})
|
||||
.count();
|
||||
let unique_view_heights: std::collections::BTreeSet<u64> = viewports
|
||||
.iter()
|
||||
.map(|v| v.view_height.to_bits())
|
||||
.collect();
|
||||
|
||||
println!("─────── summary ───────");
|
||||
println!(
|
||||
" view_height == vp.height : {}/{}",
|
||||
n_with_view_eq_height,
|
||||
viewports.len()
|
||||
);
|
||||
println!(
|
||||
" view_target == (0, 0, 0) : {}/{}",
|
||||
n_with_target_zero,
|
||||
viewports.len()
|
||||
);
|
||||
println!(
|
||||
" unique view_height values : {}",
|
||||
unique_view_heights.len()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user