use own code for checking if polygons intersect (as opposed to finding the intersection)
This commit is contained in:
parent
5254bcd018
commit
260bf5c767
@ -11,7 +11,7 @@ from numpy.typing import NDArray, ArrayLike
|
||||
from pyclipper import scale_to_clipper, scale_from_clipper, PyPolyNode
|
||||
|
||||
from .types import connectivity_t, layer_t, contour_t
|
||||
from .poly import poly_contains_points
|
||||
from .poly import poly_contains_points, intersects
|
||||
from .clipper import union_nonzero, union_evenodd, intersection_evenodd, difference_evenodd, hier2oriented
|
||||
from .tracker import NetsInfo, NetName
|
||||
from .utils import connectivity2layers
|
||||
@ -112,6 +112,7 @@ def trace_connectivity(
|
||||
nets_info = NetsInfo()
|
||||
|
||||
for ii, (top_layer, via_layer, bot_layer) in enumerate(connectivity):
|
||||
logger.info(f'{ii}, {top_layer}, {via_layer}, {bot_layer}')
|
||||
for metal_layer in (top_layer, bot_layer):
|
||||
if metal_layer in loaded_layers:
|
||||
continue
|
||||
@ -142,7 +143,7 @@ def trace_connectivity(
|
||||
))
|
||||
|
||||
# Figure out which nets are shorted by vias, then merge them
|
||||
merge_pairs = find_merge_pairs(nets_info.nets, top_layer, bot_layer, via_polys)
|
||||
merge_pairs = find_merge_pairs(nets_info.nets, top_layer, bot_layer, via_polys, clipper_scale_factor)
|
||||
for net_a, net_b in merge_pairs:
|
||||
nets_info.merge(net_a, net_b)
|
||||
|
||||
@ -286,6 +287,7 @@ def find_merge_pairs(
|
||||
top_layer: layer_t,
|
||||
bot_layer: layer_t,
|
||||
via_polys: Optional[Sequence[contour_t]],
|
||||
clipper_scale_factor: int,
|
||||
) -> Set[Tuple[NetName, NetName]]:
|
||||
"""
|
||||
Given a collection of (possibly anonymous) nets, figure out which pairs of
|
||||
@ -325,12 +327,23 @@ def find_merge_pairs(
|
||||
|
||||
if via_polys is not None:
|
||||
top_bot = intersection_evenodd(top_polys, bot_polys)
|
||||
overlap = intersection_evenodd(top_bot, via_polys)
|
||||
via_polys = difference_evenodd(via_polys, overlap) # reduce set of via polys for future nets
|
||||
overlap = check_any_intersection(scale_from_clipper(top_bot, clipper_scale_factor),
|
||||
scale_from_clipper(via_polys, clipper_scale_factor))
|
||||
# overlap = intersection_evenodd(top_bot, via_polys)
|
||||
# via_polys = difference_evenodd(via_polys, overlap) # reduce set of via polys for future nets
|
||||
else:
|
||||
overlap = intersection_evenodd(top_polys, bot_polys) # TODO verify there aren't any suspicious corner cases for this
|
||||
# overlap = intersection_evenodd(top_polys, bot_polys) # TODO verify there aren't any suspicious corner cases for this
|
||||
overlap = check_any_intersection(scale_from_clipper(top_polys, clipper_scale_factor), scale_from_clipper(bot_polys, clipper_scale_factor))
|
||||
|
||||
if overlap:
|
||||
merge_pairs.add(name_pair)
|
||||
|
||||
return merge_pairs
|
||||
|
||||
|
||||
def check_any_intersection(polys_a, polys_b) -> bool:
|
||||
for poly_a in polys_a:
|
||||
for poly_b in polys_b:
|
||||
if intersects(poly_a, poly_b):
|
||||
return True
|
||||
return False
|
||||
|
@ -65,3 +65,93 @@ def poly_contains_points(
|
||||
inside = nontrivial.copy()
|
||||
inside[nontrivial] = nontrivial_inside
|
||||
return inside
|
||||
|
||||
|
||||
def intersects(poly_a: ArrayLike, poly_b: ArrayLike) -> bool:
|
||||
"""
|
||||
Check if two polygons overlap and/or touch.
|
||||
|
||||
Args:
|
||||
poly_a: List of vertices, implicitly closed: `[[x0, y0], [x1, y1], ...]`
|
||||
poly_b: List of vertices, implicitly closed: `[[x0, y0], [x1, y1], ...]`
|
||||
|
||||
Returns:
|
||||
`True` if the polygons overlap and/or touch.
|
||||
"""
|
||||
poly_a = numpy.array(poly_a, copy=False)
|
||||
poly_b = numpy.array(poly_b, copy=False)
|
||||
|
||||
# Check bounding boxes
|
||||
min_a = poly_a.min(axis=0)
|
||||
min_b = poly_b.min(axis=0)
|
||||
max_a = poly_a.max(axis=0)
|
||||
max_b = poly_b.max(axis=0)
|
||||
|
||||
if ((min_a > max_b) | (min_b > max_a)).all():
|
||||
return False
|
||||
|
||||
#TODO: Check against sorted coords?
|
||||
|
||||
#Check if edges intersect
|
||||
if poly_edges_intersect(poly_a, poly_b):
|
||||
return True
|
||||
|
||||
# Check if either polygon contains the other
|
||||
if poly_contains_points(poly_b, poly_a).any():
|
||||
return True
|
||||
|
||||
if poly_contains_points(poly_a, poly_b).any():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def poly_edges_intersect(
|
||||
poly_a: NDArray[numpy.float64],
|
||||
poly_b: NDArray[numpy.float64],
|
||||
) -> NDArray[numpy.int_]:
|
||||
"""
|
||||
Check if the edges of two polygons intersect.
|
||||
|
||||
Args:
|
||||
poly_a: NDArray of vertices, implicitly closed: `[[x0, y0], [x1, y1], ...]`
|
||||
poly_b: NDArray of vertices, implicitly closed: `[[x0, y0], [x1, y1], ...]`
|
||||
|
||||
Returns:
|
||||
`True` if the polygons' edges intersect.
|
||||
"""
|
||||
a_next = numpy.roll(poly_a, -1, axis=0)
|
||||
b_next = numpy.roll(poly_b, -1, axis=0)
|
||||
|
||||
# Lists of initial/final coordinates for polygon segments
|
||||
xi1 = poly_a[:, 0, None]
|
||||
yi1 = poly_a[:, 1, None]
|
||||
xf1 = a_next[:, 0, None]
|
||||
yf1 = a_next[:, 1, None]
|
||||
|
||||
xi2 = poly_b[:, 0, None]
|
||||
yi2 = poly_b[:, 1, None]
|
||||
xf2 = b_next[:, 0, None]
|
||||
yf2 = b_next[:, 1, None]
|
||||
|
||||
# Perform calculation
|
||||
dxi = xi1 - xi2
|
||||
dyi = yi1 - yi2
|
||||
dx1 = xf1 - xi1
|
||||
dx2 = xf2 - xi2
|
||||
dy1 = yf1 - yi1
|
||||
dy2 = yf2 - yi2
|
||||
|
||||
numerator_a = dx2 * dyi - dy2 * dxi
|
||||
numerator_b = dx1 * dyi - dy1 * dxi
|
||||
denominator = dy2 * dx1 - dx2 * dy1
|
||||
|
||||
# Avoid warnings since we may multiply eg. NaN*False
|
||||
with numpy.errstate(invalid='ignore', divide='ignore'):
|
||||
u_a = numerator_a / denominator
|
||||
u_b = numerator_b / denominator
|
||||
|
||||
# Find the adjacency matrix
|
||||
adjacency = numpy.logical_and.reduce((u_a >= 0, u_a <= 1, u_b >= 0, u_b <= 1))
|
||||
|
||||
return adjacency.any()
|
||||
|
Loading…
Reference in New Issue
Block a user