108 lines
3.7 KiB
Python
108 lines
3.7 KiB
Python
"""
|
|
Dynamic Dimensioning and Scaled Metrics Engine for PDF Exporter.
|
|
Centralizes all auto-scaling calculations for grid steps, legend ticks, arrows,
|
|
line widths, font sizes, and SA2 technical measure offsets.
|
|
"""
|
|
import math
|
|
import numpy as np
|
|
|
|
MM_TO_PT = 2.834645669291339
|
|
|
|
|
|
def compute_grid_steps(w_geom: float, h_geom: float) -> tuple[float, float]:
|
|
"""
|
|
Computes human-readable main_step (mm) and minor_step (mm) for grid overlay.
|
|
"""
|
|
L = max(w_geom, h_geom)
|
|
if L > 1e-6:
|
|
step_raw = L / 10.0
|
|
exponent = int(np.round(np.log10(step_raw)))
|
|
main_step = 10.0 ** exponent
|
|
else:
|
|
main_step = 10.0
|
|
minor_step = main_step / 10.0
|
|
return main_step, minor_step
|
|
|
|
|
|
def compute_effective_stroke_and_font(
|
|
line_width_mm: float,
|
|
font_size_mm: float,
|
|
minor_step_mm: float
|
|
) -> tuple[float, float]:
|
|
"""
|
|
Calculates line_width_pt and font_size_pt proportionally based on minor_step_mm.
|
|
Scales continuously from millimetric components up to large structural models.
|
|
"""
|
|
if line_width_mm <= 0:
|
|
line_width_pt = minor_step_mm * 0.05 * MM_TO_PT
|
|
else:
|
|
line_width_pt = line_width_mm * MM_TO_PT
|
|
|
|
if font_size_mm <= 0:
|
|
font_size_pt = minor_step_mm * MM_TO_PT
|
|
else:
|
|
font_size_pt = font_size_mm * MM_TO_PT
|
|
|
|
return line_width_pt, font_size_pt
|
|
|
|
|
|
class LegendSizing:
|
|
"""
|
|
Auto-scaling calculations for the Size Scale Legend (bottom-left grid scale bar).
|
|
"""
|
|
def __init__(self, main_step_mm: float, minor_step_mm: float, line_width_pt: float, font_size_pt: float):
|
|
self.main_step = main_step_mm
|
|
self.minor_step = minor_step_mm
|
|
self.line_width_pt = line_width_pt
|
|
self.font_size_pt = font_size_pt
|
|
|
|
# Tick heights in mm proportional to main grid step
|
|
self.major_tick_mm = main_step_mm * 0.30
|
|
self.minor_tick_mm = main_step_mm * 0.15
|
|
|
|
# Y-axis height in mm (extends comfortably past major tick height)
|
|
self.y_axis_height_mm = self.major_tick_mm * 1.5
|
|
|
|
# X-axis extension past last main step tick in mm
|
|
self.x_axis_extension_mm = minor_step_mm * 2.0
|
|
|
|
# Legend Arrowhead dimensions in PT (proportional to line width)
|
|
self.arrow_len_pt = max(0.5, line_width_pt * 4.0)
|
|
self.arrow_half_w_pt = self.arrow_len_pt * 0.35
|
|
|
|
|
|
class SA2Sizing:
|
|
"""
|
|
Auto-scaling calculations for SA2 technical measurement lines and feature callouts.
|
|
"""
|
|
def __init__(self, w_obj_mm: float, h_obj_mm: float, line_width_pt: float, font_size_pt: float):
|
|
self.w_obj = w_obj_mm
|
|
self.h_obj = h_obj_mm
|
|
self.line_width_pt = line_width_pt
|
|
self.font_size_pt = font_size_pt
|
|
|
|
self.obj_ref_size = min(w_obj_mm, h_obj_mm) if min(w_obj_mm, h_obj_mm) > 0 else max(w_obj_mm, h_obj_mm)
|
|
|
|
# Dimension line offset & extension line scaling (mm) proportional to object size
|
|
self.offset_mm = self.obj_ref_size * 0.10
|
|
self.ext_overhang_mm = self.offset_mm * 0.20
|
|
self.ext_gap_mm = self.offset_mm * 0.10
|
|
|
|
# Measure arrow dimensions (PT)
|
|
self.arrow_len_pt = max(0.5, line_width_pt * 4.0)
|
|
self.arrow_half_w_pt = self.arrow_len_pt * 0.35
|
|
|
|
def get_hole_callout_lengths(self, dia_mm: float) -> tuple[float, float]:
|
|
slant_mm = dia_mm * 0.30
|
|
leader_mm = dia_mm * 0.40
|
|
return slant_mm, leader_mm
|
|
|
|
def get_arc_callout_lengths(self, r_mm: float) -> tuple[float, float]:
|
|
slant_mm = r_mm * 0.30
|
|
leader_mm = r_mm * 0.40
|
|
return slant_mm, leader_mm
|
|
|
|
def get_chamfer_callout_lengths(self, c_val_mm: float) -> tuple[float, float]:
|
|
slant_mm = c_val_mm * 1.0
|
|
leader_mm = c_val_mm * 1.5
|
|
return slant_mm, leader_mm
|