add fast approximate manhattanization function
This commit is contained in:
parent
fca3d8fda1
commit
e2b05d7c86
@ -188,6 +188,90 @@ class Shape(metaclass=ABCMeta):
|
|||||||
self.translate(+pivot)
|
self.translate(+pivot)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def manhattanize_fast(self, grid_x: numpy.ndarray, grid_y: numpy.ndarray) -> List['Polygon']:
|
||||||
|
from . import Polygon
|
||||||
|
|
||||||
|
grid_x = numpy.unique(grid_x)
|
||||||
|
grid_y = numpy.unique(grid_y)
|
||||||
|
|
||||||
|
polygon_contours = []
|
||||||
|
for polygon in self.to_polygons():
|
||||||
|
mins, maxs = polygon.get_bounds()
|
||||||
|
|
||||||
|
vertex_lists = []
|
||||||
|
p_verts = polygon.vertices + polygon.offset
|
||||||
|
for v, v_next in zip(p_verts, numpy.roll(p_verts, -1, axis=0)):
|
||||||
|
dv = v_next - v
|
||||||
|
|
||||||
|
if abs(dv[0]) < 1e-20:
|
||||||
|
xs = numpy.array([v[0], v[0]]) # TODO maybe pick between v[0] and v_next[0]?
|
||||||
|
ys = numpy.array([v[1], v_next[1]])
|
||||||
|
xi = numpy.digitize(xs, grid_x).clip(1, len(grid_x) - 1)
|
||||||
|
yi = numpy.digitize(ys, grid_y).clip(1, len(grid_y) - 1)
|
||||||
|
err_x = (xs - grid_x[xi]) / (grid_x[xi] - grid_x[xi - 1])
|
||||||
|
err_y = (ys - grid_y[yi]) / (grid_y[yi] - grid_y[yi - 1])
|
||||||
|
xi[err_y < 0.5] -= 1
|
||||||
|
yi[err_y < 0.5] -= 1
|
||||||
|
|
||||||
|
segment = numpy.column_stack((grid_x[xi], grid_y[yi]))
|
||||||
|
vertex_lists.append(segment)
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = dv[1]/dv[0]
|
||||||
|
def get_grid_inds(xes):
|
||||||
|
ys = m * (xes - v[0]) + v[1]
|
||||||
|
|
||||||
|
# (inds - 1) is the index of the y-grid line below the edge's intersection with the x-grid
|
||||||
|
inds = numpy.digitize(ys, grid_y).clip(1, len(grid_y) - 1)
|
||||||
|
|
||||||
|
# err is what fraction of the cell upwards we have to go to reach our y
|
||||||
|
# (can be negative at bottom edge due to clip above)
|
||||||
|
err = (ys - grid_y[inds - 1]) / (grid_y[inds] - grid_y[inds - 1])
|
||||||
|
|
||||||
|
# now set inds to the index of the nearest y-grid line
|
||||||
|
inds[err < 0.5] -= 1
|
||||||
|
#if dv[0] >= 0:
|
||||||
|
# inds[err <= 0.5] -= 1
|
||||||
|
#else:
|
||||||
|
# inds[err < 0.5] -= 1
|
||||||
|
return inds
|
||||||
|
|
||||||
|
gxi_range = numpy.digitize([v[0], v_next[0]], grid_x)
|
||||||
|
gxi_min = numpy.min(gxi_range - 1).clip(0, len(grid_x))
|
||||||
|
gxi_max = numpy.max(gxi_range).clip(0, len(grid_x))
|
||||||
|
|
||||||
|
xs = grid_x[gxi_min:gxi_max]
|
||||||
|
inds = get_grid_inds(xs)
|
||||||
|
|
||||||
|
# Find intersections for midpoints
|
||||||
|
xs2 = (xs[:-1] + xs[1:]) / 2
|
||||||
|
inds2 = get_grid_inds(xs2)
|
||||||
|
|
||||||
|
xinds = numpy.round(numpy.arange(gxi_min, gxi_max - 0.99, 1/3)).astype(int)
|
||||||
|
|
||||||
|
# interleave the results
|
||||||
|
yinds = xinds.copy()
|
||||||
|
yinds[0::3] = inds
|
||||||
|
yinds[1::3] = inds2
|
||||||
|
yinds[2::3] = inds2
|
||||||
|
|
||||||
|
vlist = numpy.column_stack((grid_x[xinds], grid_y[yinds]))
|
||||||
|
if dv[0] < 0:
|
||||||
|
vlist = vlist[::-1]
|
||||||
|
|
||||||
|
vertex_lists.append(vlist)
|
||||||
|
polygon_contours.append(numpy.vstack(vertex_lists))
|
||||||
|
|
||||||
|
manhattan_polygons = []
|
||||||
|
for contour in polygon_contours:
|
||||||
|
manhattan_polygons.append(Polygon(
|
||||||
|
vertices=contour,
|
||||||
|
layer=self.layer,
|
||||||
|
dose=self.dose))
|
||||||
|
|
||||||
|
return manhattan_polygons
|
||||||
|
|
||||||
|
|
||||||
def manhattanize(self, grid_x: numpy.ndarray, grid_y: numpy.ndarray) -> List['Polygon']:
|
def manhattanize(self, grid_x: numpy.ndarray, grid_y: numpy.ndarray) -> List['Polygon']:
|
||||||
"""
|
"""
|
||||||
Returns a list of polygons with grid-aligned ("Manhattan") edges approximating the shape.
|
Returns a list of polygons with grid-aligned ("Manhattan") edges approximating the shape.
|
||||||
@ -233,6 +317,7 @@ class Shape(metaclass=ABCMeta):
|
|||||||
|
|
||||||
polygon_contours = []
|
polygon_contours = []
|
||||||
for polygon in self.to_polygons():
|
for polygon in self.to_polygons():
|
||||||
|
# Get rid of unused gridlines (anything not within 2 lines of the polygon bounds)
|
||||||
mins, maxs = polygon.get_bounds()
|
mins, maxs = polygon.get_bounds()
|
||||||
keep_x = numpy.logical_and(grid_x > mins[0], grid_x < maxs[0])
|
keep_x = numpy.logical_and(grid_x > mins[0], grid_x < maxs[0])
|
||||||
keep_y = numpy.logical_and(grid_y > mins[1], grid_y < maxs[1])
|
keep_y = numpy.logical_and(grid_y > mins[1], grid_y < maxs[1])
|
||||||
|
Loading…
Reference in New Issue
Block a user