move clean_vertices functionality out into a common function

This commit is contained in:
Jan Petykiewicz 2020-09-26 17:32:12 -07:00
parent 0e4b6828df
commit 84f811e9d1
3 changed files with 31 additions and 24 deletions

View File

@ -28,7 +28,7 @@ import gdsii.library
import gdsii.structure import gdsii.structure
import gdsii.elements import gdsii.elements
from .utils import mangle_name, make_dose_table, dose2dtype, dtype2dose from .utils import mangle_name, make_dose_table, dose2dtype, dtype2dose, clean_pattern_vertices
from .. import Pattern, SubPattern, PatternError, Label, Shape from .. import Pattern, SubPattern, PatternError, Label, Shape
from ..shapes import Polygon, Path from ..shapes import Polygon, Path
from ..repetition import Grid from ..repetition import Grid
@ -250,20 +250,10 @@ def read(stream: io.BufferedIOBase,
# Switch based on element type: # Switch based on element type:
if isinstance(element, gdsii.elements.Boundary): if isinstance(element, gdsii.elements.Boundary):
poly = _boundary_to_polygon(element, raw_mode) poly = _boundary_to_polygon(element, raw_mode)
if clean_vertices:
try:
poly.clean_vertices()
except PatternError:
continue
pat.shapes.append(poly) pat.shapes.append(poly)
if isinstance(element, gdsii.elements.Path): if isinstance(element, gdsii.elements.Path):
path = _gpath_to_mpath(element, raw_mode) path = _gpath_to_mpath(element, raw_mode)
if clean_vertices:
try:
path.clean_vertices()
except PatternError as err:
continue
pat.shapes.append(path) pat.shapes.append(path)
elif isinstance(element, gdsii.elements.Text): elif isinstance(element, gdsii.elements.Text):
@ -276,6 +266,8 @@ def read(stream: io.BufferedIOBase,
isinstance(element, gdsii.elements.ARef)): isinstance(element, gdsii.elements.ARef)):
pat.subpatterns.append(_ref_to_subpat(element)) pat.subpatterns.append(_ref_to_subpat(element))
if clean_vertices:
clean_pattern_vertices(pat)
patterns.append(pat) patterns.append(pat)
# Create a dict of {pattern.name: pattern, ...}, then fix up all subpattern.pattern entries # Create a dict of {pattern.name: pattern, ...}, then fix up all subpattern.pattern entries

View File

@ -27,7 +27,7 @@ import fatamorgana
import fatamorgana.records as fatrec import fatamorgana.records as fatrec
from fatamorgana.basic import PathExtensionScheme, AString, NString, PropStringReference from fatamorgana.basic import PathExtensionScheme, AString, NString, PropStringReference
from .utils import mangle_name, make_dose_table from .utils import mangle_name, make_dose_table, clean_pattern_vertices
from .. import Pattern, SubPattern, PatternError, Label, Shape from .. import Pattern, SubPattern, PatternError, Label, Shape
from ..shapes import Polygon, Path, Circle from ..shapes import Polygon, Path, Circle
from ..repetition import Grid, Arbitrary, Repetition from ..repetition import Grid, Arbitrary, Repetition
@ -289,12 +289,6 @@ def read(stream: io.BufferedIOBase,
annotations=annotations, annotations=annotations,
repetition=repetition) repetition=repetition)
if clean_vertices:
try:
poly.clean_vertices()
except PatternError:
continue
pat.shapes.append(poly) pat.shapes.append(poly)
elif isinstance(element, fatrec.Path): elif isinstance(element, fatrec.Path):
@ -321,12 +315,6 @@ def read(stream: io.BufferedIOBase,
cap=cap, cap=cap,
**path_args) **path_args)
if clean_vertices:
try:
path.clean_vertices()
except PatternError as err:
continue
pat.shapes.append(path) pat.shapes.append(path)
elif isinstance(element, fatrec.Rectangle): elif isinstance(element, fatrec.Rectangle):
@ -455,6 +443,8 @@ def read(stream: io.BufferedIOBase,
for placement in cell.placements: for placement in cell.placements:
pat.subpatterns.append(_placement_to_subpat(placement, lib)) pat.subpatterns.append(_placement_to_subpat(placement, lib))
if clean_vertices:
clean_pattern_vertices(pat)
patterns.append(pat) patterns.append(pat)
# Create a dict of {pattern.name: pattern, ...}, then fix up all subpattern.pattern entries # Create a dict of {pattern.name: pattern, ...}, then fix up all subpattern.pattern entries

View File

@ -6,6 +6,7 @@ import re
import copy import copy
from .. import Pattern, PatternError from .. import Pattern, PatternError
from ..shapes import Polygon, Path
def mangle_name(pattern: Pattern, dose_multiplier: float=1.0) -> str: def mangle_name(pattern: Pattern, dose_multiplier: float=1.0) -> str:
@ -25,6 +26,30 @@ def mangle_name(pattern: Pattern, dose_multiplier: float=1.0) -> str:
return sanitized_name return sanitized_name
def clean_pattern_vertices(pat: Pattern) -> Pattern:
"""
Given a pattern, remove any redundant vertices in its polygons and paths.
The cleaning process completely removes any polygons with zero area or <3 vertices.
Args:
pat: Pattern to clean
Returns:
pat
"""
remove_inds = []
for ii, shape in enumerate(pat.shapes):
if not isinstance(shape, (Polygon, Path)):
continue
try:
shape.clean_vertices()
except PatternError:
remove_inds.append(ii)
for ii in sorted(remove_inds, reverse=True):
del pat.shapes[ii]
return pat
def make_dose_table(patterns: List[Pattern], dose_multiplier: float=1.0) -> Set[Tuple[int, float]]: def make_dose_table(patterns: List[Pattern], dose_multiplier: float=1.0) -> Set[Tuple[int, float]]:
""" """
Create a set containing `(id(pat), written_dose)` for each pattern (including subpatterns) Create a set containing `(id(pat), written_dose)` for each pattern (including subpatterns)