lots of fixes to get test_rep running
This commit is contained in:
parent
92f7fce6ff
commit
b75c8de0c4
11 changed files with 197 additions and 145 deletions
|
|
@ -14,27 +14,29 @@ import pathlib
|
|||
import gzip
|
||||
|
||||
import numpy
|
||||
import ezdxf # type: ignore
|
||||
import ezdxf
|
||||
|
||||
from .. import Pattern, Ref, PatternError, Label, Shape
|
||||
from ..shapes import Polygon, Path
|
||||
from .. import Pattern, Ref, PatternError, Label
|
||||
from ..library import Library, WrapROLibrary
|
||||
from ..shapes import Shape, Polygon, Path
|
||||
from ..repetition import Grid
|
||||
from ..utils import rotation_matrix_2d, layer_t
|
||||
from .utils import is_gzipped
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
logger.warning('DXF support is experimental and only slightly tested!')
|
||||
logger.warning('DXF support is experimental!')
|
||||
|
||||
|
||||
DEFAULT_LAYER = 'DEFAULT'
|
||||
|
||||
|
||||
def write(
|
||||
library: Mapping[str, Pattern], # TODO could allow library=None for flat DXF
|
||||
top_name: str,
|
||||
library: Mapping[str, Pattern],
|
||||
stream: io.TextIOBase,
|
||||
stream: TextIO,
|
||||
*,
|
||||
dxf_version='AC1024',
|
||||
) -> None:
|
||||
|
|
@ -65,17 +67,23 @@ def write(
|
|||
array with rotated instances must be manhattan _after_ having a compensating rotation applied.
|
||||
|
||||
Args:
|
||||
top_name: Name of the top-level pattern to write.
|
||||
library: A {name: Pattern} mapping of patterns. Only `top_name` and patterns referenced
|
||||
by it are written.
|
||||
top_name: Name of the top-level pattern to write.
|
||||
stream: Stream object to write to.
|
||||
disambiguate_func: Function which takes a list of patterns and alters them
|
||||
to make their names valid and unique. Default is `disambiguate_pattern_names`.
|
||||
WARNING: No additional error checking is performed on the results.
|
||||
"""
|
||||
#TODO consider supporting DXF arcs?
|
||||
if not isinstance(library, Library):
|
||||
if isinstance(library, dict):
|
||||
library = WrapROLibrary(library)
|
||||
else:
|
||||
library = WrapROLibrary(dict(library))
|
||||
|
||||
pattern = library[top_name]
|
||||
subtree = library.subtree(top_name)
|
||||
|
||||
# Create library
|
||||
lib = ezdxf.new(dxf_version, setup=True)
|
||||
|
|
@ -85,8 +93,11 @@ def write(
|
|||
_mrefs_to_drefs(msp, pattern.refs)
|
||||
|
||||
# Now create a block for each referenced pattern, and add in any shapes
|
||||
for name, pat in library.items():
|
||||
for name, pat in subtree.items():
|
||||
assert pat is not None
|
||||
if name == top_name:
|
||||
continue
|
||||
|
||||
block = lib.blocks.new(name=name)
|
||||
|
||||
_shapes_to_elements(block, pat.shapes)
|
||||
|
|
@ -97,8 +108,8 @@ def write(
|
|||
|
||||
|
||||
def writefile(
|
||||
top_name: str,
|
||||
library: Mapping[str, Pattern],
|
||||
top_name: str,
|
||||
filename: Union[str, pathlib.Path],
|
||||
*args,
|
||||
**kwargs,
|
||||
|
|
@ -109,9 +120,9 @@ def writefile(
|
|||
Will automatically compress the file if it has a .gz suffix.
|
||||
|
||||
Args:
|
||||
top_name: Name of the top-level pattern to write.
|
||||
library: A {name: Pattern} mapping of patterns. Only `top_name` and patterns referenced
|
||||
by it are written.
|
||||
top_name: Name of the top-level pattern to write.
|
||||
filename: Filename to save to.
|
||||
*args: passed to `dxf.write`
|
||||
**kwargs: passed to `dxf.write`
|
||||
|
|
@ -181,19 +192,19 @@ def read(
|
|||
lib = ezdxf.read(stream)
|
||||
msp = lib.modelspace()
|
||||
|
||||
npat = _read_block(msp, clean_vertices)
|
||||
npat = _read_block(msp)
|
||||
patterns_dict = dict(
|
||||
[npat] + [_read_block(bb, clean_vertices) for bb in lib.blocks if bb.name != '*Model_Space']
|
||||
[npat] + [_read_block(bb) for bb in lib.blocks if bb.name != '*Model_Space']
|
||||
)
|
||||
|
||||
library_info = {
|
||||
'layers': [ll.dxfattribs() for ll in lib.layers]
|
||||
}
|
||||
library_info = dict(
|
||||
layers=[ll.dxfattribs() for ll in lib.layers],
|
||||
)
|
||||
|
||||
return patterns_dict, library_info
|
||||
|
||||
|
||||
def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
||||
def _read_block(block) -> Tuple[str, Pattern]:
|
||||
name = block.name
|
||||
pat = Pattern()
|
||||
for element in block:
|
||||
|
|
@ -225,18 +236,13 @@ def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
|||
else:
|
||||
shape = Path(layer=layer, width=width, vertices=points[:, :2])
|
||||
|
||||
if clean_vertices:
|
||||
try:
|
||||
shape.clean_vertices()
|
||||
except PatternError:
|
||||
continue
|
||||
|
||||
pat.shapes.append(shape)
|
||||
|
||||
elif eltype in ('TEXT',):
|
||||
args = {'offset': numpy.array(element.get_pos()[1])[:2],
|
||||
'layer': element.dxfattribs().get('layer', DEFAULT_LAYER),
|
||||
}
|
||||
args = dict(
|
||||
offset=numpy.array(element.get_pos()[1])[:2],
|
||||
layer=element.dxfattribs().get('layer', DEFAULT_LAYER),
|
||||
)
|
||||
string = element.dxfattribs().get('text', '')
|
||||
# height = element.dxfattribs().get('height', 0)
|
||||
# if height != 0:
|
||||
|
|
@ -257,20 +263,21 @@ def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
|||
|
||||
offset = numpy.array(attr.get('insert', (0, 0, 0)))[:2]
|
||||
|
||||
args = {
|
||||
'target': (attr.get('name', None),),
|
||||
'offset': offset,
|
||||
'scale': scale,
|
||||
'mirrored': mirrored,
|
||||
'rotation': rotation,
|
||||
'pattern': None,
|
||||
}
|
||||
args = dict(
|
||||
target=attr.get('name', None),
|
||||
offset=offset,
|
||||
scale=scale,
|
||||
mirrored=mirrored,
|
||||
rotation=rotation,
|
||||
)
|
||||
|
||||
if 'column_count' in attr:
|
||||
args['repetition'] = Grid(a_vector=(attr['column_spacing'], 0),
|
||||
b_vector=(0, attr['row_spacing']),
|
||||
a_count=attr['column_count'],
|
||||
b_count=attr['row_count'])
|
||||
args['repetition'] = Grid(
|
||||
a_vector=(attr['column_spacing'], 0),
|
||||
b_vector=(0, attr['row_spacing']),
|
||||
a_count=attr['column_count'],
|
||||
b_count=attr['row_count'],
|
||||
)
|
||||
pat.ref(**args)
|
||||
else:
|
||||
logger.warning(f'Ignoring DXF element {element.dxftype()} (not implemented).')
|
||||
|
|
@ -286,12 +293,12 @@ def _mrefs_to_drefs(
|
|||
continue
|
||||
encoded_name = ref.target
|
||||
|
||||
rotation = (ref.rotation * 180 / numpy.pi) % 360
|
||||
attribs = {
|
||||
'xscale': ref.scale * (-1 if ref.mirrored[1] else 1),
|
||||
'yscale': ref.scale * (-1 if ref.mirrored[0] else 1),
|
||||
'rotation': rotation,
|
||||
}
|
||||
rotation = numpy.rad2deg(ref.rotation) % 360
|
||||
attribs = dict(
|
||||
xscale=ref.scale * (-1 if ref.mirrored[1] else 1),
|
||||
yscale=ref.scale * (-1 if ref.mirrored[0] else 1),
|
||||
rotation=rotation,
|
||||
)
|
||||
|
||||
rep = ref.repetition
|
||||
if rep is None:
|
||||
|
|
@ -338,7 +345,7 @@ def _shapes_to_elements(
|
|||
' Please call library.wrap_repeated_shapes() before writing to file.'
|
||||
)
|
||||
|
||||
attribs = {'layer': _mlayer2dxf(shape.layer)}
|
||||
attribs = dict(layer=_mlayer2dxf(shape.layer))
|
||||
for polygon in shape.to_polygons():
|
||||
xy_open = polygon.vertices + polygon.offset
|
||||
xy_closed = numpy.vstack((xy_open, xy_open[0, :]))
|
||||
|
|
@ -350,7 +357,7 @@ def _labels_to_texts(
|
|||
labels: List[Label],
|
||||
) -> None:
|
||||
for label in labels:
|
||||
attribs = {'layer': _mlayer2dxf(label.layer)}
|
||||
attribs = dict(layer=_mlayer2dxf(label.layer))
|
||||
xy = label.offset
|
||||
block.add_text(label.string, dxfattribs=attribs).set_pos(xy, align='BOTTOM_LEFT')
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import string
|
|||
from pprint import pformat
|
||||
|
||||
import numpy
|
||||
from numpy.typing import NDArray, ArrayLike
|
||||
from numpy.typing import ArrayLike, NDArray
|
||||
import klamath
|
||||
from klamath import records
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ path_cap_map = {
|
|||
|
||||
|
||||
def rint_cast(val: ArrayLike) -> NDArray[numpy.int32]:
|
||||
return numpy.rint(val, dtype=numpy.int32, casting='unsafe')
|
||||
return numpy.rint(val).astype(numpy.int32)
|
||||
|
||||
|
||||
def write(
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ from ..utils import layer_t, normalize_mirror, annotations_t
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
logger.warning('OASIS support is experimental and mostly untested!')
|
||||
logger.warning('OASIS support is experimental!')
|
||||
|
||||
|
||||
path_cap_map = {
|
||||
|
|
@ -51,7 +51,7 @@ path_cap_map = {
|
|||
#TODO implement more shape types?
|
||||
|
||||
def rint_cast(val: ArrayLike) -> NDArray[numpy.int64]:
|
||||
return numpy.rint(val, dtype=numpy.int64, casting='unsafe')
|
||||
return numpy.rint(val).astype(numpy.int64)
|
||||
|
||||
|
||||
def build(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue