Compare commits

...

4 Commits

@ -47,5 +47,13 @@ pip3 install git+https://mpxd.net/code/jan/masque.git@release
* Better interface for polygon operations (e.g. with `pyclipper`)
- de-embedding
- boolean ops
* Construct polygons from bitmap using `skimage.find_contours`
* Deal with shape repetitions for dxf, svg
* Maybe lib.create(bname) -> (name, pat)
* Schematic:
- Simple cell:
+ Assumes no internal hierarchy, or only other simple hierarchy
+ Return pattern, refer to it by a well-known name
- Parametrized cell:
+ Take in `lib`
+ lib.create(), and return a string
+ Can have pcell hierarchy inside

@ -553,12 +553,10 @@ def load_library(
name = name_bytes.decode('ASCII')
def mkstruct(pos: int = pos, name: str = name) -> Pattern:
logger.error(f'mkstruct {name} @ {pos:x}')
stream.seek(pos)
pat = read_elements(stream, raw_mode=True)
if postprocess is not None:
pat = postprocess(lib, name, pat)
logger.error(f'mkstruct post {name} @ {pos:x}')
return pat
lib[name] = mkstruct

@ -286,12 +286,16 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
def get_bounds(
self,
library: Optional[Mapping[str, 'Pattern']] = None,
recurse: bool = True,
) -> Optional[NDArray[numpy.float64]]:
"""
Return a `numpy.ndarray` containing `[[x_min, y_min], [x_max, y_max]]`, corresponding to the
extent of the Pattern's contents in each dimension.
Returns `None` if the Pattern is empty.
Args:
TODO docs for get_bounds
Returns:
`[[x_min, y_min], [x_max, y_max]]` or `None`
"""
@ -311,12 +315,13 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
if self.refs and (library is None):
raise PatternError('Must provide a library to get_bounds() to resolve refs')
for entry in self.refs:
bounds = entry.get_bounds(library=library)
if bounds is None:
continue
min_bounds = numpy.minimum(min_bounds, bounds[0, :])
max_bounds = numpy.maximum(max_bounds, bounds[1, :])
if recurse:
for entry in self.refs:
bounds = entry.get_bounds(library=library)
if bounds is None:
continue
min_bounds = numpy.minimum(min_bounds, bounds[0, :])
max_bounds = numpy.maximum(max_bounds, bounds[1, :])
if (max_bounds < min_bounds).any():
return None
@ -326,10 +331,14 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
def get_bounds_nonempty(
self,
library: Optional[Mapping[str, 'Pattern']] = None,
recurse: bool = True,
) -> NDArray[numpy.float64]:
"""
Convenience wrapper for `get_bounds()` which asserts that the Pattern as non-None bounds.
Args:
TODO docs for get_bounds
Returns:
`[[x_min, y_min], [x_max, y_max]]`
"""

@ -56,7 +56,7 @@ def data_to_ports(
pattern: Pattern, # Pattern is good since we don't want to do library[name] to avoid infinite recursion.
# LazyLibrary protects against library[ref.target] causing a circular lookup.
# For others, maybe check for cycles up front? TODO
name: Optional[str] = None,
name: Optional[str] = None, # Note: name optional, but arg order different from read(postprocess=)
max_depth: int = 999_999,
skip_subcells: bool = True,
) -> Pattern:

Loading…
Cancel
Save