forked from 1b-agent/opencadstudio-upstream
Merge pull request #1854 from gianlucafiore/fix/layout-paper-units-independent-of-model
fix(plot): keep paper layout dimensions independent of model units
This commit is contained in:
1 file changed
+65
-4
+65
-4
@@ -5057,15 +5057,26 @@ impl OpenCADStudio {
|
|||||||
crate::io::paper_catalog::PaperUnits::Inches => PlotPaperUnits::Inches,
|
crate::io::paper_catalog::PaperUnits::Inches => PlotPaperUnits::Inches,
|
||||||
crate::io::paper_catalog::PaperUnits::Millimeters => PlotPaperUnits::Millimeters,
|
crate::io::paper_catalog::PaperUnits::Millimeters => PlotPaperUnits::Millimeters,
|
||||||
};
|
};
|
||||||
if d.fit_to_paper && !layout_area {
|
if layout_area {
|
||||||
|
// Paper layouts use physical paper-space coordinates, independently
|
||||||
|
// of INSUNITS and the model's scale family. One unit in a metric
|
||||||
|
// paper layout is 1 mm; on an inch plotter, 1 inch is 25.4 such
|
||||||
|
// units. Using dialog_plot_scale_ratio() here incorrectly brings
|
||||||
|
// the model unit conversion (1000 for metres) into the paper
|
||||||
|
// sheet: A3 then appears as 0.420 x 0.297 instead of 420 x 297.
|
||||||
|
let page_unit_mm = plot_paper_unit_mm(ps.paper_units);
|
||||||
|
ps.scale_type = ScaledType::OneToOne;
|
||||||
|
ps.flags.use_standard_scale = false;
|
||||||
|
ps.scale_numerator = 1.0;
|
||||||
|
ps.scale_denominator = page_unit_mm;
|
||||||
|
ps.standard_scale_factor =
|
||||||
|
stored_scale_factor(1.0 / page_unit_mm, ps.paper_units);
|
||||||
|
} else if d.fit_to_paper {
|
||||||
ps.set_scale_to_fit();
|
ps.set_scale_to_fit();
|
||||||
// The commercial application marks fitted plots with the
|
// The commercial application marks fitted plots with the
|
||||||
// "standard scale" bit and leaves the ratio it computed.
|
// "standard scale" bit and leaves the ratio it computed.
|
||||||
ps.flags.use_standard_scale = true;
|
ps.flags.use_standard_scale = true;
|
||||||
} else {
|
} else {
|
||||||
// A layout plot goes through the same path as the other areas:
|
|
||||||
// the dialog holds it at 1:1, which the unit conversion turns
|
|
||||||
// into whatever keeps the paper space's unit intact.
|
|
||||||
let ((numerator, denominator), standard) = self.dialog_plot_scale_ratio();
|
let ((numerator, denominator), standard) = self.dialog_plot_scale_ratio();
|
||||||
// The commercial application leaves the "standard scale" bit
|
// The commercial application leaves the "standard scale" bit
|
||||||
// clear even for a standard code and keeps the ratio in the
|
// clear even for a standard code and keeps the ratio in the
|
||||||
@@ -7754,6 +7765,56 @@ mod plot_paper_tests {
|
|||||||
assert_eq!(app.plot_dialog.scale, "1:100");
|
assert_eq!(app.plot_dialog.scale, "1:100");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn metre_model_a3_layout_uses_millimetre_paper_space() {
|
||||||
|
use codec::objects::{PlotPaperUnits, PlotType, ScaledType};
|
||||||
|
|
||||||
|
let mut app = app_with_printer_named_sheet();
|
||||||
|
let i = app.active_tab;
|
||||||
|
app.tabs[i].scene.document.header.insertion_units = 6; // Metres.
|
||||||
|
let _ = app.on_plot_dialog_open();
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::Paper("ISO_A3_(297.00_x_420.00_MM)".into()));
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::Orientation("Landscape".into()));
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::Area("Layout".into()));
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::SetCurrent);
|
||||||
|
|
||||||
|
let ps = layout_settings(&app);
|
||||||
|
assert_eq!(ps.plot_type, PlotType::Layout);
|
||||||
|
assert_eq!(ps.paper_units, PlotPaperUnits::Millimeters);
|
||||||
|
assert_eq!(ps.scale_type, ScaledType::OneToOne);
|
||||||
|
assert_eq!((ps.scale_numerator, ps.scale_denominator), (1.0, 1.0));
|
||||||
|
assert!((app.tabs[i].scene.paper_space_unit_factor() - 1.0).abs() < 1e-12);
|
||||||
|
|
||||||
|
let ((x0, y0), (x1, y1)) = app.tabs[i].scene.paper_limits().unwrap();
|
||||||
|
assert!(((x1 - x0) - 420.0).abs() < 1e-9);
|
||||||
|
assert!(((y1 - y0) - 297.0).abs() < 1e-9);
|
||||||
|
assert_eq!(app.tabs[i].scene.document.header.insertion_units, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn metre_model_inch_page_still_uses_millimetre_paper_space() {
|
||||||
|
use codec::objects::{PlotPaperUnits, PlotType};
|
||||||
|
|
||||||
|
let mut app = app_with_printer_named_sheet();
|
||||||
|
let i = app.active_tab;
|
||||||
|
app.tabs[i].scene.document.header.insertion_units = 6; // Metres.
|
||||||
|
let _ = app.on_plot_dialog_open();
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::PaperUnits("Inches".into()));
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::Area("Layout".into()));
|
||||||
|
let _ = app.on_plot_dlg(PlotDlgMsg::SetCurrent);
|
||||||
|
|
||||||
|
let ps = layout_settings(&app);
|
||||||
|
assert_eq!(ps.plot_type, PlotType::Layout);
|
||||||
|
assert_eq!(ps.paper_units, PlotPaperUnits::Inches);
|
||||||
|
assert!((ps.scale_numerator - 1.0).abs() < 1e-12);
|
||||||
|
assert!((ps.scale_denominator - 25.4).abs() < 1e-12);
|
||||||
|
assert!((app.tabs[i].scene.paper_space_unit_factor() - 1.0).abs() < 1e-12);
|
||||||
|
let ((x0, y0), (x1, y1)) = app.tabs[i].scene.paper_limits().unwrap();
|
||||||
|
assert!(((x1 - x0) - 297.0).abs() < 1e-9);
|
||||||
|
assert!(((y1 - y0) - 210.0).abs() < 1e-9);
|
||||||
|
assert_eq!(app.tabs[i].scene.document.header.insertion_units, 6);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn an_inch_layout_keeps_its_unit_and_converts_the_scale() {
|
fn an_inch_layout_keeps_its_unit_and_converts_the_scale() {
|
||||||
use codec::objects::{PlotPaperUnits, ScaledType};
|
use codec::objects::{PlotPaperUnits, ScaledType};
|
||||||
|
|||||||
Reference in new issue
Block a user