1#  Copyright (c) 2020, Manfred Moitzi
2#  License: MIT License
3from typing import List, Optional
4import ezdxf
5from ezdxf.math import Shape2d
6from ezdxf.render.forms import square
7from ezdxf.lldxf import const
8
9DX = 11
10SIZE = 10
11
12
13def add_hatch(msp, external: List[Shape2d] = None,
14              *,
15              outermost: List[Shape2d] = None,
16              default: List[Shape2d] = None,
17              hatch_style=const.HATCH_STYLE_NESTED,
18              offset=(0, 0),
19              ):
20    def add(path, flags: int, color: int, layer: str):
21        path.translate(offset)
22        hatch.paths.add_polyline_path(
23            path.vertices, flags=flags)
24        msp.add_lwpolyline(path.vertices, close=True, dxfattribs={
25            'color': color, 'layer': layer})
26
27    hatch = msp.add_hatch(2, dxfattribs={'layer': 'HATCH'})
28    hatch.dxf.hatch_style = hatch_style
29    if external:
30        for path in external:
31            add(path.copy(), const.BOUNDARY_PATH_EXTERNAL, 1, 'EXTERNAL-PATH')
32    if outermost:
33        for path in outermost:
34            add(path.copy(), const.BOUNDARY_PATH_OUTERMOST, 3, 'OUTERMOST-PATH')
35    if default:
36        for path in default:
37            add(path.copy(), const.BOUNDARY_PATH_DEFAULT, 5, 'DEFAULT-PATH')
38
39
40def add_hatch_boundaries_test(msp, offset):
41    x, y = offset
42    external = Shape2d(square(SIZE))
43    outermost = Shape2d(square(SIZE - 2))
44    outermost.translate((1, 1))
45    default0 = Shape2d(square(SIZE - 4))
46    default0.translate((2, 2))
47    default1 = Shape2d(square(SIZE - 6))
48    default1.translate((3, 3))
49    add_hatch(msp, external=None,
50              outermost=None,
51              default=[external, outermost, default0, default1],
52              hatch_style=const.HATCH_STYLE_NESTED,
53              offset=offset,
54              )
55    add_hatch(msp, external=[default0, default1],
56              outermost=[external, outermost],
57              hatch_style=const.HATCH_STYLE_OUTERMOST,
58              offset=(x + DX, y)
59              )
60    add_hatch(msp, external=[external, outermost, default0, default1],
61              hatch_style=const.HATCH_STYLE_IGNORE,
62              offset=(x + DX + DX, y)
63              )
64
65
66def add_hatch_boundaries_adjacent(msp, offset):
67    x, y = offset
68    external = Shape2d(square(SIZE))
69    outermost = Shape2d(square(SIZE - 2))
70    outermost.translate((1, 1))
71    default0 = Shape2d(square(2))
72    default0.translate((2, 2))
73    default1 = Shape2d(square(2))
74    default1.translate((6, 2))
75    add_hatch(msp, external=[external],
76              outermost=[outermost],
77              default=[default0, default1],
78              hatch_style=const.HATCH_STYLE_NESTED,
79              offset=offset,
80              )
81    add_hatch(msp, external=[external],
82              outermost=[outermost],
83              default=[default0, default1],
84              hatch_style=const.HATCH_STYLE_OUTERMOST,
85              offset=(x + DX, y)
86              )
87    add_hatch(msp, external=[external],
88              outermost=[outermost],
89              default=[default0, default1],
90              hatch_style=const.HATCH_STYLE_IGNORE,
91              offset=(x + DX + DX, y)
92              )
93
94
95def add_hatch_boundaries_overlapping(msp, offset):
96    x, y = offset
97    external = Shape2d(square(SIZE))
98    outermost = Shape2d(square(SIZE - 2))
99    outermost.translate((1, 1))
100    default0 = Shape2d(square(3))
101    default0.translate((2, 2))
102    default1 = Shape2d(square(3))
103    default1.translate((4, 3))
104    add_hatch(msp, external=[external],
105              outermost=[outermost],
106              default=[default0, default1],
107              hatch_style=const.HATCH_STYLE_NESTED,
108              offset=offset,
109              )
110    add_hatch(msp, external=[external],
111              outermost=[outermost],
112              default=[default0, default1],
113              hatch_style=const.HATCH_STYLE_OUTERMOST,
114              offset=(x + DX, y)
115              )
116    add_hatch(msp, external=[external],
117              outermost=[outermost],
118              default=[default0, default1],
119              hatch_style=const.HATCH_STYLE_IGNORE,
120              offset=(x + DX + DX, y)
121              )
122
123
124def add_hatch_boundaries_nested(msp, offset):
125    x, y = offset
126    external = Shape2d(square(SIZE))
127    outermost = Shape2d(square(SIZE - 2))
128    outermost.translate((1, 1))
129    default0 = Shape2d(square(SIZE - 4))
130    default0.translate((2, 2))
131    default1 = Shape2d(square(SIZE - 6))
132    default1.translate((3, 3))
133    add_hatch(msp, [external],
134              outermost=[outermost],
135              default=[default0, default1],
136              hatch_style=const.HATCH_STYLE_NESTED,
137              offset=offset,
138              )
139    add_hatch(msp, [external],
140              outermost=[outermost],
141              default=[default0, default1],
142              hatch_style=const.HATCH_STYLE_OUTERMOST,
143              offset=(x + DX, y)
144              )
145    add_hatch(msp, [external],
146              outermost=[outermost],
147              default=[default0, default1],
148              hatch_style=const.HATCH_STYLE_IGNORE,
149              offset=(x + DX + DX, y)
150              )
151
152
153if __name__ == '__main__':
154    doc = ezdxf.new()
155    add_hatch_boundaries_nested(doc.modelspace(), offset=(0, 0))
156    add_hatch_boundaries_adjacent(doc.modelspace(), offset=(0, 11))
157    add_hatch_boundaries_overlapping(doc.modelspace(), offset=(0, 22))
158    doc.set_modelspace_vport(40, (15, 20))
159    doc.saveas('hatch_boundaries.dxf')
160