snapshot 2019-04-20 13:34:52.427189

This commit is contained in:
Jan Petykiewicz 2019-04-20 13:34:52 -07:00
parent fa66e09f9b
commit bab12add10
5 changed files with 21 additions and 73 deletions

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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])

View File

@ -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,