1#  Copyright (c) 2021, Manfred Moitzi
2#  License: MIT License
3
4import pytest
5import ezdxf
6from ezdxf.disassemble import recursive_decompose
7
8
9@pytest.fixture(scope='module')
10def doc():
11    d = ezdxf.new()
12    l0 = d.blocks.new('L0')
13    build_level_0(l0)
14    l1 = d.blocks.new('L1')
15    build_nesting_level_1(l1)
16    return d
17
18
19def build_level_0(l0):
20    # Block of 4 lines in 4 different colors
21    l0.add_line((1, -1), (1, 1), dxfattribs={'color': 1})
22    l0.add_line((1, 1), (-1, 1), dxfattribs={'color': 2})
23    l0.add_line((-1, 1), (-1, -1), dxfattribs={'color': 3})
24    l0.add_line((-1, -1), (1, -1), dxfattribs={'color': 4})
25
26
27def scale(sx, sy, sz):
28    return {
29        'xscale': sx,
30        'yscale': sy,
31        'zscale': sz,
32    }
33
34
35def build_nesting_level_1(l1, name='L0'):
36    l1.add_blockref(name, (0, 0), dxfattribs=scale(1, 1, 1))
37    l1.add_blockref(name, (3, 0), dxfattribs=scale(-1, 1, 1))
38    l1.add_blockref(name, (6, 0), dxfattribs=scale(1, -1, 1))
39    l1.add_blockref(name, (9, 0), dxfattribs=scale(-1, -1, 1))
40    l1.add_blockref(name, (0, 3), dxfattribs=scale(1, 1, -1))
41    l1.add_blockref(name, (3, 3), dxfattribs=scale(-1, 1, -1))
42    l1.add_blockref(name, (6, 3), dxfattribs=scale(1, -1, -1))
43    l1.add_blockref(name, (9, 3), dxfattribs=scale(-1, -1, -1))
44
45
46def count(doc, block_names) -> int:
47    count = 1
48    for name in block_names:
49        block = doc.blocks.get(name)
50        count *= len(block)
51    return count
52
53
54def test_decompose_block_level_0(doc):
55    l0 = doc.blocks.get('L0')
56    result = list(recursive_decompose(l0))
57    assert len(result) == count(doc, ['L0'])
58
59
60REFLECTIONS = [(1, 1, 1), (-1, 1, 1), (1, -1, 1), (1, 1, -1)]
61NAMES = ["normal", "reflect-x", "reflect-y", "reflect-z", ]
62
63
64@pytest.mark.parametrize("sx,sy,sz", REFLECTIONS, ids=NAMES)
65def test_decompose_block_reference_level_0(doc, sx, sy, sz):
66    msp = doc.modelspace()
67    msp.delete_all_entities()
68    msp.add_blockref('L0', (0, 0), dxfattribs=scale(sx, sy, sz))
69    result = list(recursive_decompose(msp))
70    assert len(result) == count(doc, ['L0'])
71
72
73def test_decompose_block_level_1(doc):
74    l1 = doc.blocks.get('L1')
75    types = [e.dxftype() for e in recursive_decompose(l1)]
76    assert len(types) == count(doc, ['L0', 'L1'])
77    assert set(types) == {'LINE'}, "expected only LINES"
78
79
80@pytest.mark.parametrize("sx,sy,sz", REFLECTIONS, ids=NAMES)
81def test_decompose_block_reference_level_1(doc, sx, sy, sz):
82    msp = doc.modelspace()
83    msp.delete_all_entities()
84    msp.add_blockref('L1', (0, 0), dxfattribs=scale(sx, sy, sz))
85    types = [e.dxftype() for e in recursive_decompose(msp)]
86    assert len(types) == count(doc, ['L0', 'L1'])
87    assert set(types) == {'LINE'}, "expected only LINES"
88
89
90def test_decompose_minsert_level_1(doc):
91    nrows = 2
92    ncols = 2
93    expected_count = count(doc, ['L0', 'L1']) * nrows * ncols
94
95    msp = doc.modelspace()
96    msp.delete_all_entities()
97    msp.add_blockref('L1', (0, 0), dxfattribs={
98        'row_count': nrows,
99        'row_spacing': 5,
100        'column_count': ncols,
101        'column_spacing': 5,
102    })
103    types = [e.dxftype() for e in recursive_decompose(msp)]
104    assert len(types) == expected_count
105    assert set(types) == {'LINE'}, "expected only LINES"
106
107
108if __name__ == '__main__':
109    pytest.main([__file__])
110