Add support for gds paths

This commit is contained in:
Jan Petykiewicz 2019-04-20 15:25:19 -07:00
commit 783c0c0844
3 changed files with 414 additions and 22 deletions

View file

@ -15,8 +15,9 @@ 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
__author__ = 'Jan Petykiewicz'
@ -25,6 +26,13 @@ __author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
path_cap_map = {0: Path.Cap.Flush,
1: Path.Cap.Circle,
2: Path.Cap.Square,
#3: custom?
}
def write(patterns: Pattern or List[Pattern],
filename: str,
meters_per_unit: float,
@ -81,12 +89,8 @@ def write(patterns: Pattern or List[Pattern],
structure = gdsii.structure.Structure(name=pat.name)
lib.append(structure)
# Add a Boundary element for each shape
structure += _shapes_to_boundaries(pat.shapes)
structure += _shapes_to_elements(pat.shapes)
structure += _labels_to_texts(pat.labels)
# Add an SREF / AREF for each subpattern entry
structure += _subpatterns_to_refs(pat.subpatterns)
with open(filename, mode='wb') as stream:
@ -255,13 +259,17 @@ def read(filename: str,
for element in structure:
# Switch based on element type:
if isinstance(element, gdsii.elements.Boundary):
args = {'vertices': element.xy[:-1],
}
if use_dtype_as_dose:
shape = Polygon(vertices=element.xy[:-1],
dose=element.data_type,
layer=element.layer)
args['dose'] = element.data_type
args['layer'] = element.layer
else:
shape = Polygon(vertices=element.xy[:-1],
layer=(element.layer, element.data_type))
args['layer'] = (element.layer, element.data_type)
shape = Polygon(**args)
if clean_vertices:
try:
shape.clean_vertices()
@ -270,6 +278,33 @@ def read(filename: str,
pat.shapes.append(shape)
if isinstance(element, gdsii.elements.Path):
if element.path_type in path_cap_map:
cap = path_cap_map[element.path_type]
else:
raise PatternError('Unrecognized path type: {}'.format(element.path_type))
args = {'vertices': element.xy,
'width': element.width,
'cap': cap,
}
if use_dtype_as_dose:
args['dose'] = element.data_type
args['layer'] = element.layer
else:
args['layer'] = (element.layer, element.data_type)
shape = Path(**args)
if clean_vertices:
try:
shape.clean_vertices()
except PatternError as err:
continue
pat.shapes.append(shape)
elif isinstance(element, gdsii.elements.Text):
label = Label(offset=element.xy,
layer=(element.layer, element.text_type),
@ -425,19 +460,31 @@ def _subpatterns_to_refs(subpatterns: List[SubPattern or GridRepetition]
return refs
def _shapes_to_boundaries(shapes: List[Shape]
) -> List[gdsii.elements.Boundary]:
# Add a Boundary element for each shape
boundaries = []
def _shapes_to_elements(shapes: List[Shape],
polygonize_paths: bool = False
) -> List[gdsii.elements.Boundary]:
elements = []
# Add a Boundary element for each shape, and Path elements if necessary
for shape in shapes:
layer, data_type = _mlayer2gds(shape.layer)
for polygon in shape.to_polygons():
xy_open = numpy.round(polygon.vertices + polygon.offset).astype(int)
xy_closed = numpy.vstack((xy_open, xy_open[0, :]))
boundaries.append(gdsii.elements.Boundary(layer=layer,
data_type=data_type,
xy=xy_closed))
return boundaries
if isinstance(shape, Path) and not polygonize_paths:
xy = numpy.round(shape.vertices + shape.offset).astype(int)
width = numpy.round(shape.width).astype(int)
path_type = next(k for k, v in path_cap_map.items() if v == shape.cap) #reverse lookup
path = gdsii.elements.Path(layer=layer,
data_type=data_type,
xy=xy)
path.path_type = path_type
path.width = width
elements.append(path)
else:
for polygon in shape.to_polygons():
xy_open = numpy.round(polygon.vertices + polygon.offset).astype(int)
xy_closed = numpy.vstack((xy_open, xy_open[0, :]))
elements.append(gdsii.elements.Boundary(layer=layer,
data_type=data_type,
xy=xy_closed))
return elements
def _labels_to_texts(labels: List[Label]) -> List[gdsii.elements.Text]: