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 pyclipper import scale_to_clipper, scale_from_clipper, PyPolyNode
|
||||||
|
|
||||||
from .types import connectivity_t, layer_t, contour_t
|
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 .clipper import union_nonzero, union_evenodd, intersection_evenodd, difference_evenodd, hier2oriented
|
||||||
from .tracker import NetsInfo, NetName
|
from .tracker import NetsInfo, NetName
|
||||||
from .utils import connectivity2layers
|
from .utils import connectivity2layers
|
||||||
@ -112,6 +112,7 @@ def trace_connectivity(
|
|||||||
nets_info = NetsInfo()
|
nets_info = NetsInfo()
|
||||||
|
|
||||||
for ii, (top_layer, via_layer, bot_layer) in enumerate(connectivity):
|
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):
|
for metal_layer in (top_layer, bot_layer):
|
||||||
if metal_layer in loaded_layers:
|
if metal_layer in loaded_layers:
|
||||||
continue
|
continue
|
||||||
@ -142,7 +143,7 @@ def trace_connectivity(
|
|||||||
))
|
))
|
||||||
|
|
||||||
# Figure out which nets are shorted by vias, then merge them
|
# 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:
|
for net_a, net_b in merge_pairs:
|
||||||
nets_info.merge(net_a, net_b)
|
nets_info.merge(net_a, net_b)
|
||||||
|
|
||||||
@ -286,6 +287,7 @@ def find_merge_pairs(
|
|||||||
top_layer: layer_t,
|
top_layer: layer_t,
|
||||||
bot_layer: layer_t,
|
bot_layer: layer_t,
|
||||||
via_polys: Optional[Sequence[contour_t]],
|
via_polys: Optional[Sequence[contour_t]],
|
||||||
|
clipper_scale_factor: int,
|
||||||
) -> Set[Tuple[NetName, NetName]]:
|
) -> Set[Tuple[NetName, NetName]]:
|
||||||
"""
|
"""
|
||||||
Given a collection of (possibly anonymous) nets, figure out which pairs of
|
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:
|
if via_polys is not None:
|
||||||
top_bot = intersection_evenodd(top_polys, bot_polys)
|
top_bot = intersection_evenodd(top_polys, bot_polys)
|
||||||
overlap = intersection_evenodd(top_bot, via_polys)
|
overlap = check_any_intersection(scale_from_clipper(top_bot, clipper_scale_factor),
|
||||||
via_polys = difference_evenodd(via_polys, overlap) # reduce set of via polys for future nets
|
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:
|
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:
|
if overlap:
|
||||||
merge_pairs.add(name_pair)
|
merge_pairs.add(name_pair)
|
||||||
|
|
||||||
return merge_pairs
|
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.copy()
|
||||||
inside[nontrivial] = nontrivial_inside
|
inside[nontrivial] = nontrivial_inside
|
||||||
return 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