Improve visualizations
|
|
@ -49,7 +49,7 @@ def main() -> None:
|
|||
print("Failed to route.")
|
||||
|
||||
# 5. Visualize
|
||||
fig, ax = plot_routing_results(results, [obstacle], bounds)
|
||||
fig, ax = plot_routing_results(results, [obstacle], bounds, netlist=netlist)
|
||||
fig.savefig("examples/simple_route.png")
|
||||
print("Saved plot to examples/simple_route.png")
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ def main() -> None:
|
|||
print(f" {nid}: valid={res.is_valid}, collisions={res.collisions}")
|
||||
|
||||
# 5. Visualize
|
||||
fig, ax = plot_routing_results(results, [], bounds)
|
||||
fig, ax = plot_routing_results(results, [], bounds, netlist=netlist)
|
||||
fig.savefig("examples/congestion.png")
|
||||
print("Saved plot to examples/congestion.png")
|
||||
|
||||
|
|
|
|||
|
|
@ -59,16 +59,18 @@ def main() -> None:
|
|||
print("Failed to route secondary net.")
|
||||
|
||||
# 5. Visualize
|
||||
# Combine results for plotting
|
||||
# Combine results and netlists for plotting
|
||||
all_results = {**results1, **results2}
|
||||
all_netlists = {**netlist_phase1, **netlist_phase2}
|
||||
|
||||
# Note: 'critical_net' is now in engine.static_obstacles internally,
|
||||
# but for visualization we plot it from the result object to see it clearly.
|
||||
# We pass an empty list for 'static_obstacles' to plot_routing_results
|
||||
# because we want to see the path colored, not grayed out as an obstacle.
|
||||
|
||||
fig, ax = plot_routing_results(all_results, [], bounds)
|
||||
fig, ax = plot_routing_results(all_results, [], bounds, netlist=all_netlists)
|
||||
fig.savefig("examples/locked.png")
|
||||
|
||||
print("Saved plot to examples/locked.png")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ def main() -> None:
|
|||
print(f"{nid}: {status}, collisions={res.collisions}")
|
||||
|
||||
# 6. Visualize
|
||||
fig, ax = plot_routing_results(results, [], bounds)
|
||||
fig, ax = plot_routing_results(results, [], bounds, netlist=netlist)
|
||||
fig.savefig("examples/sbends_radii.png")
|
||||
print("Saved plot to examples/sbends_radii.png")
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 28 KiB |
|
|
@ -3,12 +3,14 @@ from __future__ import annotations
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from matplotlib.axes import Axes
|
||||
from matplotlib.figure import Figure
|
||||
from shapely.geometry import Polygon
|
||||
|
||||
from inire.geometry.primitives import Port
|
||||
from inire.router.pathfinder import RoutingResult
|
||||
|
||||
|
||||
|
|
@ -16,6 +18,7 @@ def plot_routing_results(
|
|||
results: dict[str, RoutingResult],
|
||||
static_obstacles: list[Polygon],
|
||||
bounds: tuple[float, float, float, float],
|
||||
netlist: dict[str, tuple[Port, Port]] | None = None,
|
||||
) -> tuple[Figure, Axes]:
|
||||
"""Plot obstacles and routed paths using matplotlib."""
|
||||
fig, ax = plt.subplots(figsize=(10, 10))
|
||||
|
|
@ -34,7 +37,8 @@ def plot_routing_results(
|
|||
color = "red" # Highlight failing nets
|
||||
|
||||
label_added = False
|
||||
for comp in res.path:
|
||||
for j, comp in enumerate(res.path):
|
||||
# 1. Plot geometry
|
||||
for poly in comp.geometry:
|
||||
# Handle both Polygon and MultiPolygon (e.g. from SBend)
|
||||
geoms = [poly] if hasattr(poly, "exterior") else poly.geoms
|
||||
|
|
@ -43,6 +47,26 @@ def plot_routing_results(
|
|||
ax.fill(x, y, alpha=0.7, fc=color, ec="black", label=net_id if not label_added else "")
|
||||
label_added = True
|
||||
|
||||
# 2. Plot subtle port orientation arrow for internal ports
|
||||
# (Every segment's end_port except possibly the last one if it matches target)
|
||||
p = comp.end_port
|
||||
rad = np.radians(p.orientation)
|
||||
u = np.cos(rad)
|
||||
v = np.sin(rad)
|
||||
|
||||
# Internal ports get smaller, narrower, semi-transparent arrows
|
||||
ax.quiver(p.x, p.y, u, v, color="black", scale=40, width=0.003, alpha=0.3, pivot="tail", zorder=4)
|
||||
|
||||
# 3. Plot main arrows for netlist ports (if provided)
|
||||
if netlist and net_id in netlist:
|
||||
start_p, target_p = netlist[net_id]
|
||||
for p in [start_p, target_p]:
|
||||
rad = np.radians(p.orientation)
|
||||
u = np.cos(rad)
|
||||
v = np.sin(rad)
|
||||
# Netlist ports get prominent arrows
|
||||
ax.quiver(p.x, p.y, u, v, color="black", scale=25, width=0.005, pivot="tail", zorder=6)
|
||||
|
||||
ax.set_xlim(bounds[0], bounds[2])
|
||||
ax.set_ylim(bounds[1], bounds[3])
|
||||
ax.set_aspect("equal")
|
||||
|
|
@ -51,5 +75,5 @@ def plot_routing_results(
|
|||
handles, labels = ax.get_legend_handles_labels()
|
||||
if labels:
|
||||
ax.legend()
|
||||
plt.grid(True)
|
||||
ax.grid(alpha=0.6)
|
||||
return fig, ax
|
||||
|
|
|
|||