@linkiez/dxf-renew 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.github/instructions/code-patterns.instructions.md +1 -1
  2. package/.github/instructions/exdxf.instruction.md +161 -0
  3. package/.github/instructions/tdd.instructions.md +271 -0
  4. package/.yarn/install-state.gz +0 -0
  5. package/CHANGELOG.md +23 -0
  6. package/CONTRIBUTING.md +16 -14
  7. package/PLAN.md +34 -84
  8. package/README.md +43 -8
  9. package/dist/dxf.js +1388 -376
  10. package/docs/DIMENSION_SUMMARY.md +11 -5
  11. package/docs/DXF_VERSION_SUPPORT.md +45 -0
  12. package/docs/ENTITY_SVG_ROADMAP.md +96 -0
  13. package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
  14. package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
  15. package/docs/README.md +22 -0
  16. package/docs/SVG_RENDERING_INTEGRATION_TESTS.md +119 -0
  17. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +1 -1
  18. package/lib/Helper.cjs +2 -2
  19. package/lib/Helper.cjs.map +2 -2
  20. package/lib/Helper.js +2 -2
  21. package/lib/Helper.js.map +2 -2
  22. package/lib/denormalise.cjs +131 -91
  23. package/lib/denormalise.cjs.map +2 -2
  24. package/lib/denormalise.js +131 -91
  25. package/lib/denormalise.js.map +2 -2
  26. package/lib/dimensionToSVG.cjs +318 -53
  27. package/lib/dimensionToSVG.cjs.map +3 -3
  28. package/lib/dimensionToSVG.js +316 -52
  29. package/lib/dimensionToSVG.js.map +2 -2
  30. package/lib/handlers/entities.cjs +90 -26
  31. package/lib/handlers/entities.cjs.map +3 -3
  32. package/lib/handlers/entities.js +90 -26
  33. package/lib/handlers/entities.js.map +3 -3
  34. package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
  35. package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
  36. package/lib/handlers/entity/dgnUnderlay.js +71 -0
  37. package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
  38. package/lib/handlers/entity/dimension.cjs +24 -0
  39. package/lib/handlers/entity/dimension.cjs.map +2 -2
  40. package/lib/handlers/entity/dimension.js +24 -0
  41. package/lib/handlers/entity/dimension.js.map +2 -2
  42. package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
  43. package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
  44. package/lib/handlers/entity/dwfUnderlay.js +71 -0
  45. package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
  46. package/lib/handlers/entity/image.cjs +123 -0
  47. package/lib/handlers/entity/image.cjs.map +7 -0
  48. package/lib/handlers/entity/image.js +88 -0
  49. package/lib/handlers/entity/image.js.map +7 -0
  50. package/lib/handlers/entity/leader.cjs +148 -0
  51. package/lib/handlers/entity/leader.cjs.map +7 -0
  52. package/lib/handlers/entity/leader.js +113 -0
  53. package/lib/handlers/entity/leader.js.map +7 -0
  54. package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
  55. package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
  56. package/lib/handlers/entity/pdfUnderlay.js +71 -0
  57. package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
  58. package/lib/handlers/entity/tolerance.cjs +90 -0
  59. package/lib/handlers/entity/tolerance.cjs.map +7 -0
  60. package/lib/handlers/entity/tolerance.js +55 -0
  61. package/lib/handlers/entity/tolerance.js.map +7 -0
  62. package/lib/handlers/objects.cjs +257 -136
  63. package/lib/handlers/objects.cjs.map +2 -2
  64. package/lib/handlers/objects.js +257 -136
  65. package/lib/handlers/objects.js.map +2 -2
  66. package/lib/toSVG.cjs +71 -8
  67. package/lib/toSVG.cjs.map +3 -3
  68. package/lib/toSVG.js +72 -9
  69. package/lib/toSVG.js.map +2 -2
  70. package/lib/types/dimension-entity.cjs.map +1 -1
  71. package/lib/types/entity.cjs.map +1 -1
  72. package/lib/types/image-entity.cjs +17 -0
  73. package/lib/types/image-entity.cjs.map +7 -0
  74. package/lib/types/image-entity.js +1 -0
  75. package/lib/types/image-entity.js.map +7 -0
  76. package/lib/types/index.cjs +8 -0
  77. package/lib/types/index.cjs.map +2 -2
  78. package/lib/types/index.js +4 -0
  79. package/lib/types/index.js.map +2 -2
  80. package/lib/types/leader-entity.cjs +17 -0
  81. package/lib/types/leader-entity.cjs.map +7 -0
  82. package/lib/types/leader-entity.js +1 -0
  83. package/lib/types/leader-entity.js.map +7 -0
  84. package/lib/types/options.cjs.map +1 -1
  85. package/lib/types/tables.cjs.map +1 -1
  86. package/lib/types/tolerance-entity.cjs +17 -0
  87. package/lib/types/tolerance-entity.cjs.map +7 -0
  88. package/lib/types/tolerance-entity.js +1 -0
  89. package/lib/types/tolerance-entity.js.map +7 -0
  90. package/lib/types/underlay-entity.cjs +17 -0
  91. package/lib/types/underlay-entity.cjs.map +7 -0
  92. package/lib/types/underlay-entity.js +1 -0
  93. package/lib/types/underlay-entity.js.map +7 -0
  94. package/lib/util/escapeXmlText.cjs +27 -0
  95. package/lib/util/escapeXmlText.cjs.map +7 -0
  96. package/lib/util/escapeXmlText.js +7 -0
  97. package/lib/util/escapeXmlText.js.map +7 -0
  98. package/package.json +6 -1
  99. package/playwright.config.cjs +20 -0
  100. package/src/Helper.ts +3 -3
  101. package/src/denormalise.ts +182 -116
  102. package/src/dimensionToSVG.ts +466 -54
  103. package/src/handlers/entities.ts +109 -34
  104. package/src/handlers/entity/dgnUnderlay.ts +94 -0
  105. package/src/handlers/entity/dimension.ts +27 -1
  106. package/src/handlers/entity/dwfUnderlay.ts +94 -0
  107. package/src/handlers/entity/image.ts +118 -0
  108. package/src/handlers/entity/leader.ts +153 -0
  109. package/src/handlers/entity/pdfUnderlay.ts +94 -0
  110. package/src/handlers/entity/tolerance.ts +75 -0
  111. package/src/handlers/objects.ts +323 -139
  112. package/src/toSVG.ts +98 -7
  113. package/src/types/dimension-entity.ts +11 -0
  114. package/src/types/entity.ts +10 -0
  115. package/src/types/image-entity.ts +35 -0
  116. package/src/types/index.ts +4 -0
  117. package/src/types/leader-entity.ts +40 -0
  118. package/src/types/options.ts +41 -0
  119. package/src/types/tables.ts +84 -0
  120. package/src/types/tolerance-entity.ts +20 -0
  121. package/src/types/underlay-entity.ts +35 -0
  122. package/src/util/escapeXmlText.ts +10 -0
  123. package/tools/browser_test_server.cjs +87 -0
  124. package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
  125. package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
  126. package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
  127. package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
  128. package/tools/ezdxf_validate_fixtures.py +165 -0
  129. package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
  130. package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
  131. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
@@ -0,0 +1,246 @@
1
+ """Generate per-type DIMENSION fixtures.
2
+
3
+ This script generates one DXF fixture per DXF DIMENSION type used by our renderer.
4
+
5
+ Usage:
6
+ ./.venv-ezdxf/bin/python tools/ezdxf_generate_dimensions_all_types.py
7
+
8
+ Output:
9
+ test/resources/dimension-type-0-linear.dxf
10
+ test/resources/dimension-type-1-aligned.dxf
11
+ test/resources/dimension-type-2-angular-2l.dxf
12
+ test/resources/dimension-type-3-diameter.dxf
13
+ test/resources/dimension-type-4-radius.dxf
14
+ test/resources/dimension-type-5-angular-3p.dxf
15
+ test/resources/dimension-type-6-ordinate-x.dxf
16
+ test/resources/dimension-type-6-ordinate-y.dxf
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from pathlib import Path
22
+
23
+ import ezdxf
24
+
25
+
26
+ def _out_path(name: str) -> Path:
27
+ repo_root = Path(__file__).resolve().parents[1]
28
+ return repo_root / "test" / "resources" / name
29
+
30
+
31
+ def _new_doc() -> ezdxf.EzDxf:
32
+ doc = ezdxf.new("R2010")
33
+ doc.header["$INSUNITS"] = 4 # millimeters
34
+ return doc
35
+
36
+
37
+ def generate_type_0_linear() -> None:
38
+ out_path = _out_path("dimension-type-0-linear.dxf")
39
+ doc = _new_doc()
40
+ msp = doc.modelspace()
41
+
42
+ # Reference geometry
43
+ p1 = (10.0, 10.0)
44
+ p2 = (110.0, 10.0)
45
+ msp.add_line(p1, p2)
46
+
47
+ dim = msp.add_linear_dim(
48
+ base=(10.0, 35.0),
49
+ p1=p1,
50
+ p2=p2,
51
+ angle=0,
52
+ text="<>",
53
+ dimstyle="EZDXF",
54
+ )
55
+ dim.update({"dimdec": 2})
56
+ dim.render()
57
+
58
+ doc.saveas(out_path)
59
+ print(f"Wrote {out_path}")
60
+
61
+
62
+ def generate_type_1_aligned() -> None:
63
+ out_path = _out_path("dimension-type-1-aligned.dxf")
64
+ doc = _new_doc()
65
+ msp = doc.modelspace()
66
+
67
+ # Reference geometry along a slope
68
+ p1 = (10.0, 10.0)
69
+ p2 = (90.0, 50.0)
70
+ msp.add_line(p1, p2)
71
+
72
+ # distance is the offset from the measured line
73
+ dim = msp.add_aligned_dim(
74
+ p1=p1,
75
+ p2=p2,
76
+ distance=20.0,
77
+ text="<>",
78
+ dimstyle="EZDXF",
79
+ )
80
+ dim.update({"dimdec": 2})
81
+ dim.render()
82
+
83
+ doc.saveas(out_path)
84
+ print(f"Wrote {out_path}")
85
+
86
+
87
+ def generate_type_2_angular_2l() -> None:
88
+ out_path = _out_path("dimension-type-2-angular-2l.dxf")
89
+ doc = _new_doc()
90
+ msp = doc.modelspace()
91
+
92
+ # Two lines meeting at the origin (vertex)
93
+ center = (0.0, 0.0)
94
+ p1 = (100.0, 0.0)
95
+ p2 = (0.0, 80.0)
96
+ msp.add_line(center, p1)
97
+ msp.add_line(center, p2)
98
+
99
+ # line1 and line2 each defined by (start, end)
100
+ dim = msp.add_angular_dim_2l(
101
+ base=(50.0, 50.0),
102
+ line1=(center, p1),
103
+ line2=(center, p2),
104
+ text="<>",
105
+ dimstyle="EZ_CURVED",
106
+ )
107
+ dim.update({"dimdec": 2})
108
+ dim.render()
109
+
110
+ doc.saveas(out_path)
111
+ print(f"Wrote {out_path}")
112
+
113
+
114
+ def generate_type_3_diameter() -> None:
115
+ out_path = _out_path("dimension-type-3-diameter.dxf")
116
+ doc = _new_doc()
117
+ msp = doc.modelspace()
118
+
119
+ center = (60.0, 40.0)
120
+ radius = 25.0
121
+ msp.add_circle(center, radius)
122
+
123
+ dim = msp.add_diameter_dim(
124
+ center=center,
125
+ radius=radius,
126
+ location=(center[0] + 40.0, center[1] + 30.0),
127
+ text="<>",
128
+ dimstyle="EZ_RADIUS",
129
+ )
130
+ dim.update({"dimdec": 2})
131
+ dim.render()
132
+
133
+ doc.saveas(out_path)
134
+ print(f"Wrote {out_path}")
135
+
136
+
137
+ def generate_type_4_radius() -> None:
138
+ out_path = _out_path("dimension-type-4-radius.dxf")
139
+ doc = _new_doc()
140
+ msp = doc.modelspace()
141
+
142
+ center = (60.0, 40.0)
143
+ radius = 30.0
144
+ msp.add_circle(center, radius)
145
+
146
+ dim = msp.add_radius_dim(
147
+ center=center,
148
+ radius=radius,
149
+ location=(center[0] + 45.0, center[1] + 20.0),
150
+ text="<>",
151
+ dimstyle="EZ_RADIUS",
152
+ )
153
+ dim.update({"dimdec": 2})
154
+ dim.render()
155
+
156
+ doc.saveas(out_path)
157
+ print(f"Wrote {out_path}")
158
+
159
+
160
+ def generate_type_5_angular_3p() -> None:
161
+ # Keep this aligned with tools/ezdxf_generate_dimensions_angular_3p.py
162
+ out_path = _out_path("dimension-type-5-angular-3p.dxf")
163
+ doc = _new_doc()
164
+ msp = doc.modelspace()
165
+
166
+ center = (0.0, 0.0)
167
+ p1 = (100.0, 0.0)
168
+ p2 = (0.0, 120.0)
169
+ msp.add_line(center, p1)
170
+ msp.add_line(center, p2)
171
+
172
+ dim = msp.add_angular_dim_3p(
173
+ base=(80.0, 80.0),
174
+ center=center,
175
+ p1=p1,
176
+ p2=p2,
177
+ text="<>",
178
+ dimstyle="EZ_CURVED",
179
+ )
180
+ dim.update({"dimdec": 2})
181
+ dim.render()
182
+
183
+ doc.saveas(out_path)
184
+ print(f"Wrote {out_path}")
185
+
186
+
187
+ def generate_type_6_ordinate_x() -> None:
188
+ out_path = _out_path("dimension-type-6-ordinate-x.dxf")
189
+ doc = _new_doc()
190
+ msp = doc.modelspace()
191
+
192
+ feature = (70.0, 30.0)
193
+ msp.add_point(feature)
194
+
195
+ # offset is from the feature location to the leader end (where the text sits).
196
+ dim = msp.add_ordinate_x_dim(
197
+ feature_location=feature,
198
+ offset=(30.0, 25.0),
199
+ origin=(0.0, 0.0),
200
+ rotation=0.0,
201
+ text="<>",
202
+ dimstyle="EZDXF",
203
+ )
204
+ dim.update({"dimdec": 2})
205
+ dim.render()
206
+
207
+ doc.saveas(out_path)
208
+ print(f"Wrote {out_path}")
209
+
210
+
211
+ def generate_type_6_ordinate_y() -> None:
212
+ out_path = _out_path("dimension-type-6-ordinate-y.dxf")
213
+ doc = _new_doc()
214
+ msp = doc.modelspace()
215
+
216
+ feature = (40.0, 90.0)
217
+ msp.add_point(feature)
218
+
219
+ dim = msp.add_ordinate_y_dim(
220
+ feature_location=feature,
221
+ offset=(25.0, 30.0),
222
+ origin=(0.0, 0.0),
223
+ rotation=0.0,
224
+ text="<>",
225
+ dimstyle="EZDXF",
226
+ )
227
+ dim.update({"dimdec": 2})
228
+ dim.render()
229
+
230
+ doc.saveas(out_path)
231
+ print(f"Wrote {out_path}")
232
+
233
+
234
+ def main() -> None:
235
+ generate_type_0_linear()
236
+ generate_type_1_aligned()
237
+ generate_type_2_angular_2l()
238
+ generate_type_3_diameter()
239
+ generate_type_4_radius()
240
+ generate_type_5_angular_3p()
241
+ generate_type_6_ordinate_x()
242
+ generate_type_6_ordinate_y()
243
+
244
+
245
+ if __name__ == "__main__":
246
+ main()
@@ -0,0 +1,59 @@
1
+ """Generate an angular 3-point DIMENSION fixture DXF.
2
+
3
+ This fixture is meant to exercise DIMENSION type 5 (Angular 3-point).
4
+
5
+ Usage:
6
+ ./.venv-ezdxf/bin/python tools/ezdxf_generate_dimensions_angular_3p.py
7
+
8
+ Output:
9
+ test/resources/dimensions-angular-3p.dxf
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from pathlib import Path
15
+
16
+ import ezdxf
17
+
18
+
19
+ def main() -> None:
20
+ repo_root = Path(__file__).resolve().parents[1]
21
+ out_path = repo_root / "test" / "resources" / "dimensions-angular-3p.dxf"
22
+
23
+ doc = ezdxf.new("R2010")
24
+ doc.header["$INSUNITS"] = 4 # millimeters
25
+ msp = doc.modelspace()
26
+
27
+ # Geometry: two rays forming an angle at "center".
28
+ center = (0.0, 0.0)
29
+ p1 = (100.0, 0.0)
30
+ p2 = (0.0, 120.0)
31
+
32
+ # Draw legs for visual reference.
33
+ msp.add_line(center, p1)
34
+ msp.add_line(center, p2)
35
+
36
+ # Place the dimension arc at a larger radius.
37
+ base = (80.0, 80.0)
38
+
39
+ # ezdxf renders DIMENSION via an anonymous block; our renderer uses the DIMENSION
40
+ # entity definition points.
41
+ dim = msp.add_angular_dim_3p(
42
+ base=base,
43
+ center=center,
44
+ p1=p1,
45
+ p2=p2,
46
+ text="<>",
47
+ dimstyle="EZDXF",
48
+ )
49
+
50
+ # Ensure deterministic text formatting.
51
+ dim.update({"dimdec": 2})
52
+ dim.render()
53
+
54
+ doc.saveas(out_path)
55
+ print(f"Wrote {out_path}")
56
+
57
+
58
+ if __name__ == "__main__":
59
+ main()
@@ -0,0 +1,87 @@
1
+ """Generate a large-scale DIMENSION fixture DXF.
2
+
3
+ This fixture is meant to exercise viewport-based DIMENSION autoScale.
4
+ It intentionally uses a very large modelspace extent so that autoScale
5
+ has a noticeable effect in rendering.
6
+
7
+ Usage:
8
+ ./.venv-ezdxf/bin/python tools/ezdxf_generate_dimensions_large_scale.py
9
+
10
+ Output:
11
+ test/resources/dimensions-large-scale.dxf
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+
18
+ import ezdxf
19
+
20
+
21
+ def main() -> None:
22
+ repo_root = Path(__file__).resolve().parents[1]
23
+ out_path = repo_root / "test" / "resources" / "dimensions-large-scale.dxf"
24
+
25
+ doc = ezdxf.new("R2010")
26
+ doc.header["$INSUNITS"] = 4 # millimeters
27
+ msp = doc.modelspace()
28
+
29
+ # Large geometry: very large extents so viewport-based autoScale has a
30
+ # noticeable effect.
31
+ base_x = 0.0
32
+ base_y = 0.0
33
+
34
+ length = 80000.0
35
+ p1 = (base_x + 10000.0, base_y + 20000.0)
36
+ p2 = (base_x + 10000.0 + length, base_y + 20000.0)
37
+
38
+ # Draw a rectangle below the dimension line to resemble the existing fixture.
39
+ rect_min = (base_x + 10000.0, base_y + 0.0)
40
+ rect_max = (base_x + 10000.0 + length, base_y + 10000.0)
41
+ msp.add_lwpolyline(
42
+ [
43
+ rect_min,
44
+ (rect_max[0], rect_min[1]),
45
+ rect_max,
46
+ (rect_min[0], rect_max[1]),
47
+ rect_min,
48
+ ],
49
+ dxfattribs={"closed": True},
50
+ )
51
+
52
+ # Linear dimension above the rectangle.
53
+ # ezdxf renders DIMENSION via an anonymous block; our parser reads DIMENSION entity
54
+ # and uses its definition points.
55
+ dim = msp.add_linear_dim(
56
+ base=(base_x + 10000.0, base_y + 25000.0),
57
+ p1=p1,
58
+ p2=p2,
59
+ angle=0,
60
+ dimstyle="EZDXF",
61
+ )
62
+
63
+ # Force a predictable text format.
64
+ # ezdxf 1.4.x: add_linear_dim returns DimStyleOverride; use update().
65
+ dim.update({"dimdec": 2})
66
+ dim.render()
67
+
68
+ # Radial dimension for a large circle.
69
+ center = (base_x + 50000.0, base_y + 80000.0)
70
+ radius = 86020.0
71
+ msp.add_circle(center, radius)
72
+
73
+ rdim = msp.add_radius_dim(
74
+ center=center,
75
+ radius=radius,
76
+ location=(center[0] - 60000.0, center[1] + 10000.0),
77
+ dimstyle="EZDXF",
78
+ )
79
+ rdim.update({"dimdec": 2})
80
+ rdim.render()
81
+
82
+ doc.saveas(out_path)
83
+ print(f"Wrote {out_path}")
84
+
85
+
86
+ if __name__ == "__main__":
87
+ main()
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env python3
2
+ """Regenerate a small set of DXF fixtures using ezdxf.
3
+
4
+ These fixtures were previously handcrafted/minimal and ezdxf could not read them.
5
+ Regenerating them via ezdxf makes them valid DXF fixtures and unblocks
6
+ `yarn validate:fixtures`.
7
+
8
+ This script overwrites files in test/resources.
9
+
10
+ Usage:
11
+ ./.venv-ezdxf/bin/python tools/ezdxf_regenerate_problem_fixtures.py
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+
18
+ import ezdxf
19
+ from ezdxf.lldxf.tags import Tags
20
+
21
+
22
+ PROJECT_ROOT = Path(__file__).resolve().parents[1]
23
+ RESOURCES_DIR = PROJECT_ROOT / "test" / "resources"
24
+
25
+
26
+ def _write(doc: ezdxf.document.Drawing, filename: str) -> None:
27
+ target = RESOURCES_DIR / filename
28
+ target.parent.mkdir(parents=True, exist_ok=True)
29
+ doc.saveas(target)
30
+
31
+
32
+ def regenerate_leader_basic() -> None:
33
+ doc = ezdxf.new("R2010")
34
+ msp = doc.modelspace()
35
+
36
+ # A simple leader with 3 vertices.
37
+ msp.add_leader(vertices=[(0, 0), (100, 0), (100, 50)], dimstyle="EZDXF")
38
+
39
+ _write(doc, "leader-basic.dxf")
40
+
41
+
42
+ def regenerate_tolerance_basic() -> None:
43
+ doc = ezdxf.new("R2010")
44
+ msp = doc.modelspace()
45
+
46
+ tol = msp.new_entity(
47
+ "TOLERANCE",
48
+ {
49
+ "layer": "0",
50
+ "dimstyle": "Standard",
51
+ "insert": (10.0, 20.0, 0.0),
52
+ "content": "%%v%%v",
53
+ "x_axis_vector": (1.0, 0.0, 0.0),
54
+ "extrusion": (0.0, 0.0, 1.0),
55
+ },
56
+ )
57
+ # Silence unused variable warning in some linters.
58
+ _ = tol
59
+
60
+ _write(doc, "tolerance-basic.dxf")
61
+
62
+
63
+ def regenerate_underlay_basic() -> None:
64
+ doc = ezdxf.new("R2010")
65
+ msp = doc.modelspace()
66
+
67
+ underlay_def = doc.objects.add_underlay_def(
68
+ filename="file.pdf",
69
+ fmt="pdf",
70
+ name="U1",
71
+ )
72
+
73
+ msp.add_underlay(
74
+ underlay_def=underlay_def,
75
+ insert=(10.0, 20.0, 0.0),
76
+ scale=(1.0, 1.0, 1.0),
77
+ rotation=0.0,
78
+ )
79
+
80
+ _write(doc, "underlay-basic.dxf")
81
+
82
+
83
+ def regenerate_imagedef_basic() -> None:
84
+ doc = ezdxf.new("R2010")
85
+
86
+ # A standalone IMAGEDEF is still a valid fixture.
87
+ doc.objects.add_image_def(filename="my.png", size_in_pixel=(640, 480), name="I1")
88
+
89
+ _write(doc, "imagedef-basic.dxf")
90
+
91
+
92
+ def regenerate_image_basic() -> None:
93
+ doc = ezdxf.new("R2010")
94
+ msp = doc.modelspace()
95
+
96
+ image_def = doc.objects.add_image_def(filename="my.png", size_in_pixel=(640, 480), name="I1")
97
+
98
+ # Place a 640x480 image at (1, 2) in drawing units.
99
+ msp.add_image(
100
+ image_def=image_def,
101
+ insert=(1.0, 2.0, 0.0),
102
+ size_in_units=(640.0, 480.0),
103
+ rotation=0.0,
104
+ )
105
+
106
+ _write(doc, "image-basic.dxf")
107
+
108
+
109
+ def regenerate_xrecord_basic() -> None:
110
+ doc = ezdxf.new("R2010")
111
+
112
+ # Register under root dictionary.
113
+ xr = doc.rootdict.add_xrecord("TEST")
114
+ xr.tags = Tags([(1, "HELLO"), (40, 3.14)])
115
+
116
+ _write(doc, "xrecord-basic.dxf")
117
+
118
+
119
+ def regenerate_block_basepoint_text_mtext_dimension() -> None:
120
+ doc = ezdxf.new("R2010")
121
+
122
+ blk = doc.blocks.new(name="B1", base_point=(5.0, 6.0, 0.0))
123
+
124
+ blk.add_text("Hello", dxfattribs={"height": 1.0}).set_placement((6.0, 8.0, 0.0))
125
+ blk.add_mtext("World", dxfattribs={"char_height": 1.0}).set_location((7.0, 9.0, 0.0))
126
+
127
+ dim = blk.add_linear_dim(
128
+ base=(8.0, 10.0, 0.0),
129
+ p1=(8.0, 10.0, 0.0),
130
+ p2=(12.0, 10.0, 0.0),
131
+ location=(8.0, 10.0, 0.0),
132
+ dimstyle="EZDXF",
133
+ )
134
+ dim.render()
135
+
136
+ msp = doc.modelspace()
137
+ msp.add_blockref("B1", insert=(100.0, 200.0, 0.0))
138
+
139
+ _write(doc, "block-basepoint-text-mtext-dimension.dxf")
140
+
141
+
142
+ def main() -> int:
143
+ missing = [
144
+ name
145
+ for name in [
146
+ "leader-basic.dxf",
147
+ "tolerance-basic.dxf",
148
+ "underlay-basic.dxf",
149
+ "image-basic.dxf",
150
+ "imagedef-basic.dxf",
151
+ "xrecord-basic.dxf",
152
+ "block-basepoint-text-mtext-dimension.dxf",
153
+ ]
154
+ if not (RESOURCES_DIR / name).exists()
155
+ ]
156
+
157
+ # We still regenerate even if files are missing: this script is authoritative.
158
+ regenerate_leader_basic()
159
+ regenerate_tolerance_basic()
160
+ regenerate_underlay_basic()
161
+ regenerate_imagedef_basic()
162
+ regenerate_image_basic()
163
+ regenerate_xrecord_basic()
164
+ regenerate_block_basepoint_text_mtext_dimension()
165
+
166
+ if missing:
167
+ print("Generated missing fixtures:")
168
+ for name in missing:
169
+ print(f"- {name}")
170
+
171
+ print("Regenerated fixtures:")
172
+ print("- leader-basic.dxf")
173
+ print("- tolerance-basic.dxf")
174
+ print("- underlay-basic.dxf")
175
+ print("- imagedef-basic.dxf")
176
+ print("- image-basic.dxf")
177
+ print("- xrecord-basic.dxf")
178
+ print("- block-basepoint-text-mtext-dimension.dxf")
179
+
180
+ return 0
181
+
182
+
183
+ if __name__ == "__main__":
184
+ raise SystemExit(main())