snapshot 2019-04-20 13:34:52.427189
This commit is contained in:
parent
fa66e09f9b
commit
bab12add10
@ -15,7 +15,7 @@ import logging
|
||||
|
||||
from .utils import mangle_name, make_dose_table
|
||||
from .. import Pattern, SubPattern, GridRepetition, PatternError, Label, Shape
|
||||
from ..shapes import Polygon
|
||||
from ..shapes import Polygon, Path
|
||||
from ..utils import rotation_matrix_2d, get_bit, set_bit, vector2, is_scalar
|
||||
from ..utils import remove_colinear_vertices
|
||||
|
||||
@ -272,76 +272,23 @@ def read(filename: str,
|
||||
pat.shapes.append(shape)
|
||||
|
||||
if isinstance(element, gdsii.elements.Path):
|
||||
if element.path_type == 0:
|
||||
#cap = Path.Cap.Flush
|
||||
extension = 0.0
|
||||
elif element.path_type in (1, 4):
|
||||
raise PatternError('Round-ended and custom paths (types 1 and 4) are not implemented yet')
|
||||
elif element.path_type == 2:
|
||||
extension = element.width / 2
|
||||
cap_map = {0: Path.Cap.Flush,
|
||||
1: Path.Cap.Circle,
|
||||
2: Path.Cap.Square,
|
||||
#3: custom?
|
||||
}
|
||||
if element.path_type in cap_map:
|
||||
cap = cap_map[element.path_type]
|
||||
else:
|
||||
raise PatternError('Unrecognized path type: {}'.format(element.path_type))
|
||||
|
||||
if element.width == 0:
|
||||
continue
|
||||
|
||||
v = remove_colinear_vertices(numpy.array(element.xy, dtype=float), closed_path=False)
|
||||
dv = numpy.diff(v, axis=0)
|
||||
dvdir = dv / numpy.sqrt((dv * dv).sum(axis=1))[:, None]
|
||||
perp = dvdir[:, ::-1] * [[1, -1]] * element.width / 2
|
||||
|
||||
# add extension
|
||||
v[0] -= dvdir[0] * extension
|
||||
v[-1] += dvdir[-1] * extension
|
||||
|
||||
# Find intersections of expanded sides
|
||||
As = numpy.stack((dv[:-1], -dv[1:]), axis=2)
|
||||
bs = v[1:-1] - v[:-2] + perp[1:] - perp[:-1]
|
||||
ds = v[1:-1] - v[:-2] - perp[1:] + perp[:-1]
|
||||
|
||||
rp = numpy.linalg.solve(As, bs)[:, 0, None]
|
||||
rn = numpy.linalg.solve(As, ds)[:, 0, None]
|
||||
|
||||
intersection_p = v[:-2] + rp * dv[:-1] + perp[:-1]
|
||||
intersection_n = v[:-2] + rn * dv[:-1] - perp[:-1]
|
||||
|
||||
towards_perp = (dv[1:] * perp[:-1]).sum(axis=1) > 0 # path bends towards previous perp?
|
||||
# straight = (dv[1:] * perp[:-1]).sum(axis=1) == 0 # path is straight
|
||||
acute = (dv[1:] * dv[:-1]).sum(axis=1) < 0 # angle is acute?
|
||||
|
||||
|
||||
o0 = [v[0] + perp[0]]
|
||||
o1 = [v[0] - perp[0]]
|
||||
for i in range(dv.shape[0] - 1):
|
||||
if towards_perp[i]:
|
||||
o0.append(intersection_p[i])
|
||||
if acute[i]:
|
||||
o1.append(intersection_n[i])
|
||||
else:
|
||||
# Opposite is >270
|
||||
pt0 = v[i + 1] - perp[i + 0] + dvdir[i + 0] * element.width / 2
|
||||
pt1 = v[i + 1] - perp[i + 1] - dvdir[i + 1] * element.width / 2
|
||||
o1 += [pt0, pt1]
|
||||
else:
|
||||
o1.append(intersection_n[i])
|
||||
if acute[i]:
|
||||
# > 270
|
||||
pt0 = v[i + 1] + perp[i + 0] + dvdir[i + 0] * element.width / 2
|
||||
pt1 = v[i + 1] + perp[i + 1] - dvdir[i + 1] * element.width / 2
|
||||
o0 += [pt0, pt1]
|
||||
else:
|
||||
o0.append(intersection_p[i])
|
||||
o0.append(v[-1] + perp[-1])
|
||||
o1.append(v[-1] - perp[-1])
|
||||
verts = numpy.vstack((o0, o1[::-1]))
|
||||
|
||||
if use_dtype_as_dose:
|
||||
shape = Polygon(vertices=verts,
|
||||
dose=element.data_type,
|
||||
layer=element.layer)
|
||||
shape = Path(vertices=element.xy,
|
||||
dose=element.data_type,
|
||||
layer=element.layer)
|
||||
else:
|
||||
shape = Polygon(vertices=verts,
|
||||
layer=(element.layer, element.data_type))
|
||||
shape = Path(vertices=element.xy,
|
||||
layer=(element.layer, element.data_type))
|
||||
if clean_vertices:
|
||||
try:
|
||||
shape.clean_vertices()
|
||||
|
@ -153,7 +153,7 @@ class Arc(Shape):
|
||||
self.width = width
|
||||
self.offset = offset
|
||||
self.rotation = rotation
|
||||
[self.mirror(a) for a in a, do in enumerate(mirrored) if do]
|
||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||
self.layer = layer
|
||||
self.dose = dose
|
||||
self.poly_num_points = poly_num_points
|
||||
|
@ -92,7 +92,7 @@ class Ellipse(Shape):
|
||||
self.radii = radii
|
||||
self.offset = offset
|
||||
self.rotation = rotation
|
||||
[self.mirror(a) for a in a, do in enumerate(mirrored) if do]
|
||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||
self.layer = layer
|
||||
self.dose = dose
|
||||
self.poly_num_points = poly_num_points
|
||||
|
@ -127,7 +127,7 @@ class Path(Shape):
|
||||
self.width = width
|
||||
self.cap = cap
|
||||
self.rotate(rotation)
|
||||
[self.mirror(a) for a in a, do in enumerate(mirrored) if do]
|
||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||
|
||||
@staticmethod
|
||||
def travel(travel_pairs: Tuple[Tuple[float, float]],
|
||||
@ -142,11 +142,12 @@ class Path(Shape):
|
||||
"""
|
||||
TODO
|
||||
|
||||
:param rotation: Rotation counterclockwise, in radians
|
||||
|
||||
:param offset: Offset, default (0, 0)
|
||||
:param rotation: Rotation counterclockwise, in radians
|
||||
:param layer: Layer, default 0
|
||||
:param dose: Dose, default 1.0
|
||||
:return: A Polygon object containing the requested square
|
||||
:return: The resulting Path object
|
||||
"""
|
||||
direction = numpy.array([1, 0])
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import List
|
||||
from typing import List, Tuple
|
||||
import copy
|
||||
import numpy
|
||||
from numpy import pi
|
||||
@ -82,7 +82,7 @@ class Polygon(Shape):
|
||||
self.vertices = vertices
|
||||
self.offset = offset
|
||||
self.rotate(rotation)
|
||||
[self.mirror(a) for a in a, do in enumerate(mirrored) if do]
|
||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||
|
||||
@staticmethod
|
||||
def square(side_length: float,
|
||||
|
Loading…
x
Reference in New Issue
Block a user