[pattern.visualize] add options for file output and port visualization

This commit is contained in:
jan 2026-03-07 10:22:54 -08:00
commit 46555dbd4d

View file

@ -1049,6 +1049,8 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
line_color: str = 'k', line_color: str = 'k',
fill_color: str = 'none', fill_color: str = 'none',
overdraw: bool = False, overdraw: bool = False,
filename: str | None = None,
ports: bool = False,
) -> None: ) -> None:
""" """
Draw a picture of the Pattern and wait for the user to inspect it Draw a picture of the Pattern and wait for the user to inspect it
@ -1063,6 +1065,8 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
line_color: Outlines are drawn with this color (passed to `matplotlib.collections.PolyCollection`) line_color: Outlines are drawn with this color (passed to `matplotlib.collections.PolyCollection`)
fill_color: Interiors are drawn with this color (passed to `matplotlib.collections.PolyCollection`) fill_color: Interiors are drawn with this color (passed to `matplotlib.collections.PolyCollection`)
overdraw: Whether to create a new figure or draw on a pre-existing one overdraw: Whether to create a new figure or draw on a pre-existing one
filename: If provided, save the figure to this file instead of showing it.
ports: If True, annotate the plot with arrows representing the ports
""" """
# TODO: add text labels to visualize() # TODO: add text labels to visualize()
try: try:
@ -1080,7 +1084,6 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
if not overdraw: if not overdraw:
figure = pyplot.figure() figure = pyplot.figure()
pyplot.axis('equal')
else: else:
figure = pyplot.gcf() figure = pyplot.gcf()
@ -1088,7 +1091,8 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
polygons = [] polygons = []
for shape in chain.from_iterable(self.shapes.values()): for shape in chain.from_iterable(self.shapes.values()):
polygons += [offset + s.offset + s.vertices for s in shape.to_polygons()] for ss in shape.to_polygons():
polygons.append(offset + ss.offset + ss.vertices)
mpl_poly_collection = matplotlib.collections.PolyCollection( mpl_poly_collection = matplotlib.collections.PolyCollection(
polygons, polygons,
@ -1096,7 +1100,25 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
edgecolors = line_color, edgecolors = line_color,
) )
axes.add_collection(mpl_poly_collection) axes.add_collection(mpl_poly_collection)
pyplot.axis('equal')
if ports:
for port_name, port in self.ports.items():
if port.rotation is not None:
p1 = offset + port.offset
angle = port.rotation
size = 1.0 # Arrow size based on bounds or fixed
dx = size * numpy.cos(angle)
dy = size * numpy.sin(angle)
p2 = p1 + numpy.array([dx, dy])
axes.annotate(
port_name,
xy = tuple(p1),
xytext = tuple(p2),
arrowprops = dict(arrowstyle="->", color='g', linewidth=1),
color = 'g',
fontsize = 8,
)
for target, refs in self.refs.items(): for target, refs in self.refs.items():
if target is None: if target is None:
@ -1112,12 +1134,19 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
overdraw = True, overdraw = True,
line_color = line_color, line_color = line_color,
fill_color = fill_color, fill_color = fill_color,
filename = filename,
) )
axes.autoscale_view()
axes.set_aspect('equal')
if not overdraw: if not overdraw:
pyplot.xlabel('x') axes.set_xlabel('x')
pyplot.ylabel('y') axes.set_ylabel('y')
pyplot.show() if filename:
figure.savefig(filename)
else:
figure.show()
# @overload # @overload
# def place( # def place(