fix: align white paper fill with entity borders
- paper_entity_extents() computes the bounding box of actual DXF entities so the white fill always matches the drawn title-block / frame borders, regardless of whether Layout min/max_limits match entity positions - Falls back to paper_limits() (→ A4 297×210) when layout has no entities - Removed paper_boundary_wire: the white fill now acts as the visual paper edge so the near-white wire (invisible on white) was redundant - LayoutCreate sets limits to A4 landscape immediately after add_layout() to override acadrust's imperial default (12×9) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0a291c877b
commit
f63858876d
3 changed files with 50 additions and 37 deletions
|
|
@ -2268,6 +2268,18 @@ impl H7CAD {
|
|||
self.push_undo_snapshot(i, "LAYOUT");
|
||||
match self.tabs[i].scene.document.add_layout(&new_name) {
|
||||
Ok(_) => {
|
||||
// Override the acadrust default limits (12×9 imperial) with A4 landscape.
|
||||
for obj in self.tabs[i].scene.document.objects.values_mut() {
|
||||
if let acadrust::objects::ObjectType::Layout(l) = obj {
|
||||
if l.name == new_name {
|
||||
l.min_limits = (0.0, 0.0);
|
||||
l.max_limits = (297.0, 210.0);
|
||||
l.min_extents = (0.0, 0.0, 0.0);
|
||||
l.max_extents = (297.0, 210.0, 0.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.tabs[i].scene.current_layout = new_name.clone();
|
||||
self.tabs[i].scene.deselect_all();
|
||||
self.tabs[i].scene.fit_all();
|
||||
|
|
|
|||
|
|
@ -348,10 +348,6 @@ impl Scene {
|
|||
let layout_block = self.current_layout_block_handle();
|
||||
let mut wires: Vec<WireModel> = self.wires_for_block(layout_block);
|
||||
if self.current_layout != "Model" {
|
||||
// Draw the paper boundary rectangle first (rendered beneath everything else).
|
||||
if let Some(((x0, y0), (x1, y1))) = self.paper_limits() {
|
||||
wires.insert(0, paper_boundary_wire(x0 as f32, y0 as f32, x1 as f32, y1 as f32));
|
||||
}
|
||||
wires.extend(self.viewport_content_wires(layout_block, None, None));
|
||||
}
|
||||
wires
|
||||
|
|
@ -2247,11 +2243,40 @@ impl Scene {
|
|||
|
||||
pub(super) fn paper_sheet_wires(&self) -> Vec<WireModel> {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let mut wires = self.wires_for_block(layout_block);
|
||||
if let Some(((x0, y0), (x1, y1))) = self.paper_limits() {
|
||||
wires.insert(0, paper_boundary_wire(x0 as f32, y0 as f32, x1 as f32, y1 as f32));
|
||||
self.wires_for_block(layout_block)
|
||||
}
|
||||
|
||||
/// Bounding box (min_x, min_y), (max_x, max_y) of all DXF entities in the
|
||||
/// current paper layout, in paper-space coordinates. Used by the 2-D canvas
|
||||
/// to position the white paper fill so it aligns with the drawn entity borders.
|
||||
/// Falls back to `paper_limits()` when the layout has no entities.
|
||||
pub fn paper_entity_extents(&self) -> Option<((f32, f32), (f32, f32))> {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let wires = self.wires_for_block(layout_block);
|
||||
|
||||
let mut min_x = f32::MAX;
|
||||
let mut min_y = f32::MAX;
|
||||
let mut max_x = f32::MIN;
|
||||
let mut max_y = f32::MIN;
|
||||
|
||||
for wire in &wires {
|
||||
for &[x, y, _] in &wire.points {
|
||||
if x.is_finite() && y.is_finite() {
|
||||
min_x = min_x.min(x);
|
||||
min_y = min_y.min(y);
|
||||
max_x = max_x.max(x);
|
||||
max_y = max_y.max(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if min_x == f32::MAX {
|
||||
// No entities — fall back to layout limits.
|
||||
self.paper_limits()
|
||||
.map(|((x0, y0), (x1, y1))| ((x0 as f32, y0 as f32), (x1 as f32, y1 as f32)))
|
||||
} else {
|
||||
Some(((min_x, min_y), (max_x, max_y)))
|
||||
}
|
||||
wires
|
||||
}
|
||||
|
||||
/// Build a Camera oriented and scaled to match a paper-space Viewport entity.
|
||||
|
|
@ -2463,28 +2488,3 @@ fn clip_polyline_to_rect(
|
|||
result
|
||||
}
|
||||
|
||||
/// A thin white rectangle wire that represents the printable-area boundary
|
||||
/// of the active paper layout. Rendered beneath all other paper-space
|
||||
/// geometry so it acts as a visual "page" backdrop.
|
||||
fn paper_boundary_wire(x0: f32, y0: f32, x1: f32, y1: f32) -> WireModel {
|
||||
WireModel {
|
||||
name: "__paper_boundary__".to_string(),
|
||||
points: vec![
|
||||
[x0, y0, 0.0],
|
||||
[x1, y0, 0.0],
|
||||
[x1, y1, 0.0],
|
||||
[x0, y1, 0.0],
|
||||
[x0, y0, 0.0],
|
||||
],
|
||||
// Near-white so it stands out against the dark paper-space background.
|
||||
color: [0.95, 0.95, 0.95, 1.0],
|
||||
selected: false,
|
||||
pattern_length: 0.0,
|
||||
pattern: [0.0; 8],
|
||||
line_weight_px: 1.5,
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,10 +68,11 @@ impl<'a> canvas::Program<Message> for PaperCanvas<'a> {
|
|||
const DESK: Color = Color { r: 0.22, g: 0.24, b: 0.28, a: 1.0 };
|
||||
frame.fill_rectangle(Point::ORIGIN, bounds.size(), DESK);
|
||||
|
||||
// ── White paper area ──────────────────────────────────────────────────
|
||||
if let Some(((px0, py0), (px1, py1))) = self.scene.paper_limits() {
|
||||
let tl = to_px(px0 as f32, py1 as f32);
|
||||
let br = to_px(px1 as f32, py0 as f32);
|
||||
// ── White paper area — use entity extents so the fill aligns with the
|
||||
// drawn DXF entity borders (title block frame, viewport border, etc.).
|
||||
if let Some(((px0, py0), (px1, py1))) = self.scene.paper_entity_extents() {
|
||||
let tl = to_px(px0, py1);
|
||||
let br = to_px(px1, py0);
|
||||
let pw = br.x - tl.x;
|
||||
let ph = br.y - tl.y;
|
||||
if pw > 0.0 && ph > 0.0 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue