This commit is contained in:
Nicolas Predella 2026-07-29 18:40:40 +03:00
parent 6f21e407ac
commit 0037c977e2

View file

@ -507,6 +507,66 @@ def export_wireframe_to_pdf(
stream_cmds.extend(lines_str[start_idx:start_idx + 5000]) stream_cmds.extend(lines_str[start_idx:start_idx + 5000])
stream_cmds.append("S") stream_cmds.append("S")
# 6. Size Scale Legend (Bottom Left, aligned directly on the bottom main grid lines with exact wireframe thickness)
stream_cmds.append("/GS100 gs")
x_grid_start_mm = grid_min_x
x_grid_end_mm = min(grid_max_x, grid_min_x + 10.0 * main_step)
num_main_steps = int(np.round((x_grid_end_mm - x_grid_start_mm) / main_step))
p_start_pt = to_pdf_pt(np.array([[x_grid_start_mm, grid_min_y]]))
p_end_pt = to_pdf_pt(np.array([[x_grid_end_mm, grid_min_y]]))
x_start_pt = p_start_pt[0, 0]
x_end_pt = p_end_pt[0, 0]
y_bar_pt = p_start_pt[0, 1]
# Exact same stroke thickness as object wireframe lines
stream_cmds.append(f"{line_width_pt:.2f} w")
stream_cmds.append("1 j 1 J")
# Main horizontal legend line directly overlapping bottom grid line
stream_cmds.append(f"{x_start_pt:.2f} {y_bar_pt:.2f} m {x_end_pt:.2f} {y_bar_pt:.2f} l S")
# Ticks directly overlapping vertical main grid lines
tick_cmds = []
for k in range(num_main_steps + 1):
xk_mm = x_grid_start_mm + k * main_step
pk_pt = to_pdf_pt(np.array([[xk_mm, grid_min_y]]))
xk_pt = pk_pt[0, 0]
tick_h_pt = (5.0 if k in (0, 5, num_main_steps) else 3.0) * MM_TO_PT
tick_cmds.append(f"{xk_pt:.2f} {y_bar_pt:.2f} m {xk_pt:.2f} {y_bar_pt + tick_h_pt:.2f} l")
stream_cmds.extend(tick_cmds)
stream_cmds.append("S")
# Proportionate font size scaling with linework thickness
font_size_pt = max(8.0, line_width_pt * 4.0)
stream_cmds.append(f"{sr:.3f} {sg:.3f} {sb:.3f} rg")
stream_cmds.append("BT")
stream_cmds.append(f"/F1 {font_size_pt:.1f} Tf")
for k in range(num_main_steps + 1):
xk_mm = x_grid_start_mm + k * main_step
pk_pt = to_pdf_pt(np.array([[xk_mm, grid_min_y]]))
xk_pt = pk_pt[0, 0]
tick_h_pt = (5.0 if k in (0, 5, num_main_steps) else 3.0) * MM_TO_PT
val_mm = k * main_step
if main_step >= 1000.0:
val_num = val_mm / 1000.0
unit = " m" if k == num_main_steps else ""
tick_str = f"{val_num:g}{unit}"
else:
unit = " mm" if k == num_main_steps else ""
tick_str = f"{val_mm:g}{unit}"
x_text_pt = xk_pt - (len(tick_str) * font_size_pt * 0.28)
y_text_pt = y_bar_pt + tick_h_pt + (2.5 * MM_TO_PT)
stream_cmds.append(f"1 0 0 1 {x_text_pt:.2f} {y_text_pt:.2f} Tm")
stream_cmds.append(f"({tick_str}) Tj")
stream_cmds.append("ET")
stream_content = "\n".join(stream_cmds) + "\n" stream_content = "\n".join(stream_cmds) + "\n"
stream_bytes = stream_content.encode("utf-8") stream_bytes = stream_content.encode("utf-8")
@ -516,7 +576,7 @@ def export_wireframe_to_pdf(
page_header = ( page_header = (
f"3 0 obj\n" f"3 0 obj\n"
f"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 {page_w_pt:.2f} {page_h_pt:.2f}] " f"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 {page_w_pt:.2f} {page_h_pt:.2f}] "
f"/Resources << /ExtGState << /GS25 5 0 R /GS50 6 0 R /GS100 7 0 R >> >> " f"/Resources << /ExtGState << /GS25 5 0 R /GS50 6 0 R /GS100 7 0 R >> /Font << /F1 8 0 R >> >> "
f"/Contents 4 0 R >>\n" f"/Contents 4 0 R >>\n"
f"endobj\n" f"endobj\n"
) )
@ -527,6 +587,7 @@ def export_wireframe_to_pdf(
objects.append(b"5 0 obj\n<< /Type /ExtGState /CA 0.25 /ca 0.25 >>\nendobj\n") objects.append(b"5 0 obj\n<< /Type /ExtGState /CA 0.25 /ca 0.25 >>\nendobj\n")
objects.append(b"6 0 obj\n<< /Type /ExtGState /CA 0.5 /ca 0.5 >>\nendobj\n") objects.append(b"6 0 obj\n<< /Type /ExtGState /CA 0.5 /ca 0.5 >>\nendobj\n")
objects.append(b"7 0 obj\n<< /Type /ExtGState /CA 1.0 /ca 1.0 >>\nendobj\n") objects.append(b"7 0 obj\n<< /Type /ExtGState /CA 1.0 /ca 1.0 >>\nendobj\n")
objects.append(b"8 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n")
header = b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n" header = b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n"