1# Copyright (c) 2018-2021 Manfred Moitzi 2# License: MIT License 3import pytest 4import ezdxf 5from ezdxf.entities.dimension import Dimension 6 7 8@pytest.fixture(scope='module') 9def dxf2000(): 10 return ezdxf.new('R2000', setup='all') 11 12 13@pytest.fixture(scope='module') 14def dxf2007(): 15 return ezdxf.new('R2007', setup='all') 16 17 18def test_dimstyle_standard_exist(dxf2000): 19 assert 'EZDXF' in dxf2000.dimstyles 20 21 22def test_rotated_dimline(dxf2000): 23 msp = dxf2000.modelspace() 24 dxfattribs = { 25 'dimtype': Dimension.LINEAR 26 } 27 dimline = msp.new_entity('DIMENSION', dxfattribs) 28 assert dimline.dimtype == Dimension.LINEAR 29 assert dimline.dxf.defpoint == (0, 0, 0) 30 assert dimline.dxf.insert == (0, 0, 0) 31 assert dimline.dxf.defpoint2 == (0, 0, 0) 32 assert dimline.dxf.defpoint3 == (0, 0, 0) 33 assert dimline.dxf.angle == 0. 34 assert dimline.dxf.oblique_angle == 0. 35 36 37def test_aligned_dimline(dxf2000): 38 msp = dxf2000.modelspace() 39 dxfattribs = { 40 'dimtype': Dimension.ALIGNED 41 } 42 dimline = msp.new_entity('DIMENSION', dxfattribs) 43 assert dimline.dimtype == Dimension.ALIGNED 44 assert dimline.dxf.defpoint == (0, 0, 0) 45 assert dimline.dxf.insert == (0, 0, 0) 46 assert dimline.dxf.defpoint2 == (0, 0, 0) 47 assert dimline.dxf.defpoint3 == (0, 0, 0) 48 assert dimline.dxf.angle == 0. 49 assert dimline.dxf.oblique_angle == 0. 50 51 52def test_angular_dimline(dxf2000): 53 msp = dxf2000.modelspace() 54 dxfattribs = { 55 'dimtype': Dimension.ANGULAR 56 } 57 dimline = msp.new_entity('DIMENSION', dxfattribs) 58 assert dimline.dimtype == Dimension.ANGULAR 59 assert dimline.dxf.defpoint == (0, 0, 0) 60 assert dimline.dxf.defpoint2 == (0, 0, 0) 61 assert dimline.dxf.defpoint3 == (0, 0, 0) 62 assert dimline.dxf.defpoint4 == (0, 0, 0) 63 assert dimline.dxf.defpoint5 == (0, 0, 0) 64 65 66def test_angular_3p_dimline(dxf2000): 67 msp = dxf2000.modelspace() 68 dxfattribs = { 69 'dimtype': Dimension.ANGULAR_3P 70 } 71 dimline = msp.new_entity('DIMENSION', dxfattribs) 72 assert dimline.dimtype == Dimension.ANGULAR_3P 73 74 75def test_radius_dimline(dxf2000): 76 msp = dxf2000.modelspace() 77 dxfattribs = { 78 'dimtype': Dimension.RADIUS 79 } 80 dimline = msp.new_entity('DIMENSION', dxfattribs) 81 assert dimline.dimtype == Dimension.RADIUS 82 assert dimline.dxf.defpoint == (0, 0, 0) 83 assert dimline.dxf.defpoint4 == (0, 0, 0) 84 assert dimline.is_supported_dxf_attrib('leader_length') 85 86 87def test_diameter_dimline(dxf2000): 88 msp = dxf2000.modelspace() 89 dxfattribs = { 90 'dimtype': Dimension.DIAMETER 91 } 92 dimline = msp.new_entity('DIMENSION', dxfattribs) 93 assert dimline.dimtype == Dimension.DIAMETER 94 assert dimline.dxf.defpoint == (0, 0, 0) 95 assert dimline.dxf.defpoint4 == (0, 0, 0) 96 assert dimline.is_supported_dxf_attrib('leader_length') 97 98 99def test_ordinate_dimline(dxf2000): 100 msp = dxf2000.modelspace() 101 dxfattribs = { 102 'dimtype': Dimension.ORDINATE 103 } 104 dimline = msp.new_entity('DIMENSION', dxfattribs) 105 assert dimline.dimtype == Dimension.ORDINATE 106 assert dimline.dxf.defpoint == (0, 0, 0) 107 assert dimline.dxf.defpoint2 == (0, 0, 0) 108 assert dimline.dxf.defpoint3 == (0, 0, 0) 109 110 111def add_linear_dimension(doc): 112 msp = doc.modelspace() 113 override = msp.add_linear_dim( 114 base=(3, 2, 0), 115 p1=(0, 0, 0), 116 p2=(3, 0, 0), 117 118 ) 119 override.render() 120 return override.dimension 121 122 123def test_add_horizontal_dimline(dxf2000): 124 dimline = add_linear_dimension(dxf2000) 125 assert dimline.dxf.dimstyle == 'EZDXF' 126 block_name = dimline.dxf.geometry 127 assert block_name.startswith('*D') 128 129 block = dimline.get_geometry_block() 130 assert len(list(block.query('MTEXT'))) == 1 131 assert len(list(block.query('INSERT'))) == 2 132 assert len( 133 list(block.query('LINE'))) == 3 # dimension line + 2 extension lines 134 assert len(list(block.query('POINT'))) == 3 # def points 135 136 137def test_virtual_entities_and_explode(dxf2000): 138 dimline = add_linear_dimension(dxf2000) 139 140 parts = list(dimline.virtual_entities()) 141 assert len(parts) == 9 142 geometry = dimline.dxf.geometry 143 parts = dimline.explode() 144 assert len(list(parts.query('MTEXT'))) == 1 145 assert len(list(parts.query('INSERT'))) == 2 146 assert len( 147 list(parts.query('LINE'))) == 3 # dimension line + 2 extension lines 148 assert len(list(parts.query('POINT'))) == 3 # def points 149 assert dimline.is_alive is False 150 assert geometry in dxf2000.blocks, 'Do not destroy anonymous block, may be used by block references.' 151 152 153def test_transformation_of_associated_anonymous_geometry_block(dxf2000): 154 dimline = add_linear_dimension(dxf2000) 155 dx, dy = 1, 1 156 block = dimline.get_geometry_block() 157 original_points = [e.dxf.location for e in block if e.dxftype() == 'POINT'] 158 dimline.translate(dx, dy, 0) 159 transformed_points = [e.dxf.location for e in block if 160 e.dxftype() == 'POINT'] 161 for o, t in zip(original_points, transformed_points): 162 assert t.isclose(o + (dx, dy)) 163 164 165def test_copy_dimension_with_geometry_block(dxf2000): 166 dimline = add_linear_dimension(dxf2000) 167 vcopy = dimline.copy() 168 assert vcopy.virtual_block_content is not None 169 assert vcopy.dxf.hasattr('geometry') is False 170 block = dimline.get_geometry_block() 171 assert len(vcopy.virtual_block_content) == len(block) 172 for copy, original in zip(vcopy.virtual_block_content, block): 173 assert copy.is_virtual is True 174 assert original.is_virtual is False 175 assert copy.dxftype() == original.dxftype() 176 177 178def test_destroy_virtual_dimension_copy(dxf2000): 179 dimline = add_linear_dimension(dxf2000) 180 dimline.destroy() 181 assert hasattr(dimline, 'virtual_block_content') is False 182 183 184def test_transform_virtual_geometry_block(dxf2000): 185 original = add_linear_dimension(dxf2000) 186 187 original_points = [e.dxf.location for e in original.virtual_entities() 188 if e.dxftype() == 'POINT'] 189 vcopy = original.copy() 190 dx, dy = 1, 1 191 vcopy.translate(dx, dy, 0) 192 transformed_points = [e.dxf.location for e in vcopy.virtual_entities() if 193 e.dxftype() == 'POINT'] 194 assert len(transformed_points) == len(original_points) 195 for o, t in zip(original_points, transformed_points): 196 assert t.isclose(o + (dx, dy)) 197 198 199def test_add_virtual_dimension_copy_to_layout(dxf2000): 200 dimline = add_linear_dimension(dxf2000) 201 vcopy = dimline.copy() 202 msp = dxf2000.modelspace() 203 content = vcopy.virtual_block_content 204 msp.add_entity(vcopy) 205 assert vcopy.is_virtual is False 206 assert vcopy.virtual_block_content is None 207 assert all(not e.is_virtual for e in content), \ 208 "all entities should be non virtual" 209 db = dxf2000.entitydb 210 assert all(e.dxf.handle in db for e in content), \ 211 "all entities should be stored in the entity database" 212 assert all(e.doc is dxf2000 for e in content), \ 213 "all entities should be bound to the document" 214 215 216def test_dimstyle_override(dxf2000): 217 msp = dxf2000.modelspace() 218 dimstyle = msp.add_linear_dim( 219 base=(3, 2, 0), 220 p1=(0, 0, 0), 221 p2=(3, 0, 0), 222 dxfattribs={ 223 'dimstyle': 'EZDXF', 224 } 225 ) 226 dimline = dimstyle.dimension 227 assert dimline.dxf.dimstyle == 'EZDXF' 228 if 'TEST' not in dxf2000.styles: # text style must exists 229 dxf2000.styles.new('TEST') 230 231 preset = { 232 'dimtxsty': 'TEST', 233 'dimexe': 0.777, 234 } 235 dimstyle.update(preset) 236 assert dimstyle['dimtxsty'] == 'TEST' 237 assert dimstyle['dimexe'] == 0.777 238 239 assert dimstyle['invalid'] is None 240 dimstyle.update({'invalid': 7}) 241 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 242 # unknown attributes are ignored 243 dstyle_orig = dimstyle.get_dstyle_dict() 244 assert len(dstyle_orig) == 0 245 246 dimstyle.commit() 247 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 248 dstyle = dimstyle.get_dstyle_dict() 249 250 assert dstyle['dimexe'] == 0.777 251 252 # handle attributes not available, just stored transparent in XDATA 253 assert 'dimtxsty_handle' not in dstyle 254 255 assert dstyle['dimtxsty'] == 'TEST' 256 257 258def test_linetype_override_R2000(dxf2000): 259 msp = dxf2000.modelspace() 260 preset = { 261 'dimltype': 'DOT', 262 'dimltex1': 'DOT2', 263 'dimltex2': 'DOTX2', 264 } 265 dimstyle = msp.add_linear_dim( 266 base=(3, 2, 0), 267 p1=(0, 0, 0), 268 p2=(3, 0, 0), 269 dimstyle='EZDXF', 270 override=preset, 271 ) 272 assert dimstyle['dimltype'] == 'DOT' 273 assert dimstyle['dimltex1'] == 'DOT2' 274 assert dimstyle['dimltex2'] == 'DOTX2' 275 276 dimstyle.commit() 277 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 278 dstyle = dimstyle.get_dstyle_dict() 279 280 # handle attributes not available, just stored transparent in XDATA 281 assert 'dimltype_handle' not in dstyle 282 assert 'dimltex1_handle' not in dstyle 283 assert 'dimltex2_handle' not in dstyle 284 285 # line type not supported by DXF R2000 286 assert 'dimltype' not in dstyle 287 assert 'dimltex1' not in dstyle 288 assert 'dimltex2' not in dstyle 289 290 291def test_linetype_override_R2007(dxf2007): 292 msp = dxf2007.modelspace() 293 preset = { 294 'dimltype': 'DOT', 295 'dimltex1': 'DOT2', 296 'dimltex2': 'DOTX2', 297 } 298 dimstyle = msp.add_linear_dim( 299 base=(3, 2, 0), 300 p1=(0, 0, 0), 301 p2=(3, 0, 0), 302 dimstyle='EZDXF', 303 override=preset, 304 ) 305 assert dimstyle['dimltype'] == 'DOT' 306 assert dimstyle['dimltex1'] == 'DOT2' 307 assert dimstyle['dimltex2'] == 'DOTX2' 308 309 dimstyle.commit() 310 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 311 dstyle = dimstyle.get_dstyle_dict() 312 313 # handle attributes not available, just stored transparent in XDATA 314 assert 'dimltype_handle' not in dstyle 315 assert 'dimltex1_handle' not in dstyle 316 assert 'dimltex2_handle' not in dstyle 317 318 assert dstyle['dimltype'] == 'DOT' 319 assert dstyle['dimltex1'] == 'DOT2' 320 assert dstyle['dimltex2'] == 'DOTX2' 321 322 323def test_dimstyle_override_arrows(dxf2000): 324 msp = dxf2000.modelspace() 325 arrows = ezdxf.ARROWS 326 blocks = dxf2000.blocks 327 328 arrows.create_block(blocks, arrows.dot_blank) 329 arrows.create_block(blocks, arrows.box) 330 arrows.create_block(blocks, arrows.closed) 331 arrows.create_block(blocks, arrows.closed_filled) 332 333 preset = { 334 'dimblk': arrows.dot_blank, 335 'dimblk1': arrows.box, 336 'dimblk2': arrows.closed, 337 'dimldrblk': arrows.closed_filled, # virtual attribute 338 } 339 dimstyle = msp.add_linear_dim( 340 base=(3, 2, 0), 341 p1=(0, 0, 0), 342 p2=(3, 0, 0), 343 dimstyle='EZDXF', 344 override=preset, 345 ) 346 # still as block names stored 347 assert dimstyle['dimblk'] == arrows.dot_blank 348 assert dimstyle['dimblk1'] == arrows.box 349 assert dimstyle['dimblk2'] == arrows.closed 350 assert dimstyle['dimldrblk'] == arrows.closed_filled 351 352 dstyle_orig = dimstyle.get_dstyle_dict() 353 assert len(dstyle_orig) == 0 354 355 dimstyle.commit() 356 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 357 dstyle = dimstyle.get_dstyle_dict() 358 359 # handle attributes not available, just stored transparent in XDATA 360 assert 'dimblk_handle' not in dstyle 361 assert 'dimblk1_handle' not in dstyle 362 assert 'dimblk2_handle' not in dstyle 363 assert 'dimldrblk_handle' not in dstyle 364 365 assert dstyle['dimblk'] == arrows.dot_blank 366 assert dstyle['dimblk1'] == arrows.box 367 assert dstyle['dimblk2'] == arrows.closed 368 assert dstyle['dimldrblk'] == '' # special handle for closed filled 369 370 dimstyle.set_arrows(blk=arrows.closed, blk1=arrows.dot_blank, 371 blk2=arrows.box, ldrblk=arrows.dot_small) 372 assert dimstyle['dimblk'] == arrows.closed 373 assert dimstyle['dimblk1'] == arrows.dot_blank 374 assert dimstyle['dimblk2'] == arrows.box 375 assert dimstyle['dimldrblk'] == arrows.dot_small 376 377 dimstyle.commit() 378 # ezdxf 0.10 and later uses internally only resource names not handles for dim style attributes 379 dstyle = dimstyle.get_dstyle_dict() 380 assert dstyle['dimblk'] == arrows.closed 381 assert dstyle['dimblk1'] == arrows.dot_blank 382 assert dstyle['dimblk2'] == arrows.box 383 # create acad arrows on demand 384 assert dstyle['dimldrblk'] == arrows.dot_small 385