sampling-mesh-monitor/uut_meshes_density/plot_length_delay.py

136 lines
5.8 KiB
Python

#!/usr/bin/env python3
import math
import pathlib
from collections import defaultdict
import matplotlib.cm
import gerbonara
from gerbonara.utils import MM, Tag
import click
@click.command()
@click.option('-o', '--overlay', multiple=True, type=click.Path(path_type=pathlib.Path, exists=True, dir_okay=False))
@click.option('-a', '--anchor', multiple=True)
@click.option('-i', '--interval', type=float, default=5)
@click.option('--text/--no-text', default=True)
@click.argument('in_gerber', type=click.Path(path_type=pathlib.Path, exists=True, dir_okay=False))
@click.argument('out_svg', type=click.Path(path_type=pathlib.Path, dir_okay=False))
def cli(in_gerber, overlay, anchor, interval, out_svg, text):
grb = gerbonara.rs274x.GerberFile.open(in_gerber)
anchor = [y for x in anchor for y in x.split(',')]
line_map = defaultdict(lambda: [])
anchor_pos = []
for obj in grb.objects:
if isinstance(obj, gerbonara.graphic_objects.Flash):
if (part_info := obj.attrs.get('.P')):
component, number, *function = part_info
for elem in anchor:
if f'{component}.{number}' == elem:
x, y = MM(obj.x, obj.unit), MM(obj.y, obj.unit)
anchor_pos.append((elem, (round(x * 100), round(y * 100))))
elif isinstance(obj, gerbonara.graphic_objects.Line):
x1, y1 = MM(obj.x1, obj.unit), MM(obj.y1, obj.unit)
x2, y2 = MM(obj.x2, obj.unit), MM(obj.y2, obj.unit)
key1 = (round(x1 * 100), round(y1 * 100))
key2 = (round(x2 * 100), round(y2 * 100))
line_map[key1].append((key2, obj))
line_map[key2].append((key1, obj))
tags = []
lines = []
for anchor_name, start_pos in anchor_pos:
stack, visited = [(0, 0, start_pos)], [start_pos]
current_polyline = None
lines.append([])
while stack:
#print(stack)
distance, last_tag, pos = stack.pop()
visited.append(pos)
x1, y1 = pos
x1, y1 = x1/100, y1/100
if len(line_map.get(pos, [])) < 2 and pos != start_pos:
print(f'Anchor {anchor_name}: start at {start_pos}, end at {pos}, total distance {distance:.2f}mm')
for far, obj in line_map.get(pos, []):
if far not in visited:
x2, y2 = far
x2, y2 = x2/100, y2/100
length = math.dist((x1, y1), (x2, y2))
ang = math.degrees(math.atan2(y2-y1, x2-x1))
if abs(ang) > 90:
ang += 180
if last_tag + length > interval:
xform = {'transform': f'rotate({ang:.3f}) scale(1 -1)'} #'transform': 'scale(1, -1)', 'transform_origin': 'center'}
#if abs(x2 - x1) < abs(y2 - y1):
# xform = {'transform': 'rotate(-90)', 'transform_origin': 'center'}
# produce tag in the middle
def do_text(**kw):
tags.append(Tag('g',
[Tag('text',
[Tag('tspan',
[f'{distance + length/2:.2f}'],
dominant_baseline='middle')],
x='0',
y='0',
text_anchor='middle',
**xform,
**kw,
style=f'font: 0.2px bold sans-serif; fill: black')
],
transform=f'translate({(x1+x2)/2:.3f} {(y1+y2)/2:.3f})'))
if text:
do_text(stroke='white', stroke_width='0.02mm')
do_text()
if current_polyline:
lines[-1].append(current_polyline.to_svg())
current_polyline = gerbonara.cam.Polyline(*obj.to_primitives())
stack.insert(0, (distance + length, length/2, far))
else:
if current_polyline is None:
current_polyline = gerbonara.cam.Polyline(*obj.to_primitives())
elif not current_polyline.append(*obj.to_primitives()):
if current_polyline:
lines[-1].append(current_polyline.to_svg())
current_polyline = gerbonara.cam.Polyline(*obj.to_primitives())
stack.insert(0, (distance + length, last_tag + length, far))
if current_polyline:
lines[-1].append(current_polyline.to_svg())
for i, path in enumerate(lines[-1]):
f = i/(len(lines[-1])-1)
n = 10
f = abs((((n*f)*2) % 2) - 1)
r, g, b, _a = matplotlib.cm.viridis(f)
path.attrs['stroke'] = f'#{round(r*255):02x}{round(g*255):02x}{round(b*255):02x}'
grb.objects = [obj for obj in grb.objects if not isinstance(obj, gerbonara.graphic_objects.Line)]
svg = grb.to_svg(margin=3)
svg.children[0].children += sum(lines, start=[])
svg.children[0].children += tags
for fn in overlay:
grb = gerbonara.rs274x.GerberFile.open(fn)
for tag in grb.svg_objects(fg='red'):
if tag.name == 'path' and float(tag.attrs.get('stroke_width', 1000)) < 0.2:
tag.attrs['stroke_width'] = '0.2'
svg.children.append(tag)
out_svg.write_text(str(svg))
if __name__ == '__main__':
cli()