-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport_documentation.sh
More file actions
executable file
·137 lines (119 loc) · 5.74 KB
/
Copy pathexport_documentation.sh
File metadata and controls
executable file
·137 lines (119 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/bin/bash
# Build a full per-board documentation PDF: hierarchical schematic +
# composite PCB layer view (color) + 3D top / bottom / isometric renders.
# Output is written to <repo>/schematics_pdf/<board>.pdf, replacing the
# schematic-only PDF that export_schematics.sh would produce there.
set -euo pipefail
for tool in kicad-cli rsvg-convert pdfunite img2pdf; do
if ! command -v "$tool" &>/dev/null; then
echo "Missing dependency: $tool" >&2
echo " Ubuntu: sudo apt install kicad librsvg2-bin poppler-utils" >&2
echo " pip install -r requirements.txt # for img2pdf" >&2
exit 1
fi
done
ROOT="$(cd "$(dirname "$0")" && pwd)"
OUT="$ROOT/schematics_pdf"
mkdir -p "$OUT"
# Layer set used for the 2D color view. Mirrors what the PCB editor shows
# with all default layers visible. Inner copper (In1/In2) is included for
# 4-layer boards; KiCad silently ignores the inner layers on 2-layer boards.
PCB_LAYERS="F.Cu,In1.Cu,In2.Cu,B.Cu,F.Silkscreen,B.Silkscreen,F.Mask,B.Mask,F.Paste,B.Paste,F.Courtyard,B.Courtyard,Edge.Cuts,User.Comments,User.Drawings"
# Per-element opacity applied to the PCB SVG so stacked layers blend instead
# of fully obscuring each other.
PCB_ALPHA="0.5"
# Margin (mm) between the scaled board and each edge of the page.
PCB_MARGIN_MM="10"
RENDER_W=2400
RENDER_H=1800
build_one() {
local pro="$1"
local dir name pcb sch
dir="$(dirname "$pro")"
name="$(basename "$pro" .kicad_pro)"
sch="$dir/$name.kicad_sch"
pcb="$dir/$name.kicad_pcb"
if [[ ! -f "$sch" ]]; then
echo "skip ($name): no schematic" >&2
return
fi
echo "=== $name ==="
local tmp; tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' RETURN
# Match every page (PCB layer view + 3D renders) to the root schematic's
# paper size so pdfunite produces a uniform document.
local paper
paper=$(grep -m1 -oE '\(paper "[^"]+"' "$sch" | grep -oE '"[^"]+"' | tr -d '"')
paper="${paper:-A4}"
echo " - schematic ($paper)"
kicad-cli sch export pdf -o "$tmp/01-schematic.pdf" "$sch" >/dev/null
if [[ -f "$pcb" ]]; then
echo " - 2D layer view"
# page-size-mode 2 crops the SVG page to the board outline so we can
# then center the board on a full schematic-sized page below.
kicad-cli pcb export svg --mode-single --page-size-mode 2 \
--exclude-drawing-sheet --layers "$PCB_LAYERS" \
-o "$tmp/pcb.svg" "$pcb" >/dev/null
# Force every element to PCB_ALPHA so stacked layers blend.
sed -i -E "s/(fill-opacity|stroke-opacity):[0-9]+(\.[0-9]+)?/\1:$PCB_ALPHA/g" "$tmp/pcb.svg"
# Match the schematic paper, choosing orientation by board aspect.
local svg_w svg_h page_w page_h scale new_w new_h left top
svg_w=$(grep -oE 'width="[0-9.]+mm"' "$tmp/pcb.svg" | head -1 | grep -oE '[0-9.]+')
svg_h=$(grep -oE 'height="[0-9.]+mm"' "$tmp/pcb.svg" | head -1 | grep -oE '[0-9.]+')
case "$paper" in
A3) page_w=420; page_h=297 ;;
A4) page_w=297; page_h=210 ;;
*) page_w=297; page_h=210 ;;
esac
# Flip to portrait if the board is taller than wide.
if awk -v w="$svg_w" -v h="$svg_h" 'BEGIN{exit !(h>w)}'; then
local tmpv=$page_w; page_w=$page_h; page_h=$tmpv
fi
# Scale uniformly so the longest board axis sits PCB_MARGIN_MM from
# both edges of the corresponding page axis, while still fitting on
# the short axis.
read -r scale new_w new_h left top < <(awk \
-v sw="$svg_w" -v sh="$svg_h" \
-v pw="$page_w" -v ph="$page_h" -v m="$PCB_MARGIN_MM" '
BEGIN {
sl = sw>sh?sw:sh; ss = sw>sh?sh:sw;
pl = pw>ph?pw:ph; ps = pw>ph?ph:pw;
a = (pl-2*m)/sl; b = (ps-2*m)/ss;
s = a<b?a:b;
nw = sw*s; nh = sh*s;
printf "%.6f %.4f %.4f %.4f %.4f\n", s, nw, nh, (pw-nw)/2, (ph-nh)/2
}')
rsvg-convert -f pdf \
--page-width "${page_w}mm" --page-height "${page_h}mm" \
--width "${new_w}mm" --height "${new_h}mm" \
--left "${left}mm" --top "${top}mm" \
-o "$tmp/02-pcb.pdf" "$tmp/pcb.svg"
echo " - 3D render: top"
kicad-cli pcb render --side top --quality high \
-w "$RENDER_W" -h "$RENDER_H" --background opaque \
-o "$tmp/top.png" "$pcb" >/dev/null
img2pdf --pagesize "$paper" --auto-orient --border "${PCB_MARGIN_MM}mm" "$tmp/top.png" -o "$tmp/03-top.pdf" >/dev/null
echo " - 3D render: bottom"
kicad-cli pcb render --side bottom --quality high \
-w "$RENDER_W" -h "$RENDER_H" --background opaque \
-o "$tmp/bottom.png" "$pcb" >/dev/null
img2pdf --pagesize "$paper" --auto-orient --border "${PCB_MARGIN_MM}mm" "$tmp/bottom.png" -o "$tmp/04-bottom.pdf" >/dev/null
echo " - 3D render: isometric"
# KiCad CLI argparser rejects negative-leading values; 315° == -45°.
kicad-cli pcb render --side top --quality high \
-w "$RENDER_W" -h "$RENDER_H" --background opaque \
--rotate '315,0,45' \
-o "$tmp/iso.png" "$pcb" >/dev/null
img2pdf --pagesize "$paper" --auto-orient --border "${PCB_MARGIN_MM}mm" "$tmp/iso.png" -o "$tmp/05-iso.pdf" >/dev/null
else
echo " - no .kicad_pcb, schematic only"
fi
# Filter the harmless poppler "recursive dicts" warning that some
# rsvg-convert output triggers.
pdfunite "$tmp"/*.pdf "$OUT/$name.pdf" 2> >(grep -v 'recursive dicts' >&2)
echo " -> $OUT/$name.pdf"
}
find "$ROOT" -name '*.kicad_pro' -not -path '*/.claude/*' -not -path "$OUT/*" -not -path '*/Base Project/*' -print0 |
while IFS= read -r -d '' pro; do
build_one "$pro"
done