[dxf] fix dxf repetition load
This commit is contained in:
parent
08421d6a54
commit
46a3559391
2 changed files with 82 additions and 5 deletions
|
|
@ -300,12 +300,57 @@ def _read_block(block: ezdxf.layouts.BlockLayout | ezdxf.layouts.Modelspace) ->
|
|||
)
|
||||
|
||||
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'],
|
||||
col_spacing = attr['column_spacing']
|
||||
row_spacing = attr['row_spacing']
|
||||
col_count = attr['column_count']
|
||||
row_count = attr['row_count']
|
||||
local_x = numpy.array((col_spacing, 0.0))
|
||||
local_y = numpy.array((0.0, row_spacing))
|
||||
inv_rot = rotation_matrix_2d(-rotation)
|
||||
|
||||
candidates = (
|
||||
(inv_rot @ local_x, inv_rot @ local_y, col_count, row_count),
|
||||
(inv_rot @ local_y, inv_rot @ local_x, row_count, col_count),
|
||||
)
|
||||
repetition = None
|
||||
for a_vector, b_vector, a_count, b_count in candidates:
|
||||
rotated_a = rotation_matrix_2d(rotation) @ a_vector
|
||||
rotated_b = rotation_matrix_2d(rotation) @ b_vector
|
||||
if (numpy.isclose(rotated_a[1], 0, atol=1e-8)
|
||||
and numpy.isclose(rotated_b[0], 0, atol=1e-8)
|
||||
and numpy.isclose(rotated_a[0], col_spacing, atol=1e-8)
|
||||
and numpy.isclose(rotated_b[1], row_spacing, atol=1e-8)
|
||||
and a_count == col_count
|
||||
and b_count == row_count):
|
||||
repetition = Grid(
|
||||
a_vector=a_vector,
|
||||
b_vector=b_vector,
|
||||
a_count=a_count,
|
||||
b_count=b_count,
|
||||
)
|
||||
break
|
||||
if (numpy.isclose(rotated_a[0], 0, atol=1e-8)
|
||||
and numpy.isclose(rotated_b[1], 0, atol=1e-8)
|
||||
and numpy.isclose(rotated_b[0], col_spacing, atol=1e-8)
|
||||
and numpy.isclose(rotated_a[1], row_spacing, atol=1e-8)
|
||||
and b_count == col_count
|
||||
and a_count == row_count):
|
||||
repetition = Grid(
|
||||
a_vector=a_vector,
|
||||
b_vector=b_vector,
|
||||
a_count=a_count,
|
||||
b_count=b_count,
|
||||
)
|
||||
break
|
||||
|
||||
if repetition is None:
|
||||
repetition = Grid(
|
||||
a_vector=inv_rot @ local_x,
|
||||
b_vector=inv_rot @ local_y,
|
||||
a_count=col_count,
|
||||
b_count=row_count,
|
||||
)
|
||||
args['repetition'] = repetition
|
||||
pat.ref(**args)
|
||||
else:
|
||||
logger.warning(f'Ignoring DXF element {element.dxftype()} (not implemented).')
|
||||
|
|
|
|||
|
|
@ -112,6 +112,38 @@ def test_dxf_manhattan_precision(tmp_path: Path):
|
|||
assert isinstance(ref.repetition, Grid), "Grid should be preserved for 90-degree rotation"
|
||||
|
||||
|
||||
def test_dxf_rotated_grid_roundtrip_preserves_basis_and_counts(tmp_path: Path):
|
||||
lib = Library()
|
||||
sub = Pattern()
|
||||
sub.polygon("1", vertices=[[0, 0], [1, 0], [1, 1]])
|
||||
lib["sub"] = sub
|
||||
|
||||
top = Pattern()
|
||||
top.ref(
|
||||
"sub",
|
||||
offset=(0, 0),
|
||||
rotation=numpy.pi / 2,
|
||||
repetition=Grid(a_vector=(10, 0), a_count=3, b_vector=(0, 20), b_count=2),
|
||||
)
|
||||
lib["top"] = top
|
||||
|
||||
dxf_file = tmp_path / "rotated_grid.dxf"
|
||||
dxf.writefile(lib, "top", dxf_file)
|
||||
|
||||
read_lib, _ = dxf.readfile(dxf_file)
|
||||
read_top = read_lib.get("Model") or read_lib.get("top") or list(read_lib.values())[0]
|
||||
|
||||
target_name = next(k for k in read_top.refs if k.upper() == "SUB")
|
||||
ref = read_top.refs[target_name][0]
|
||||
assert isinstance(ref.repetition, Grid)
|
||||
actual = ref.repetition.displacements
|
||||
expected = Grid(a_vector=(10, 0), a_count=3, b_vector=(0, 20), b_count=2).displacements
|
||||
assert_allclose(
|
||||
actual[numpy.lexsort((actual[:, 1], actual[:, 0]))],
|
||||
expected[numpy.lexsort((expected[:, 1], expected[:, 0]))],
|
||||
)
|
||||
|
||||
|
||||
def test_dxf_read_legacy_polyline() -> None:
|
||||
doc = ezdxf.new()
|
||||
msp = doc.modelspace()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue