dimension.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. # Created: 09.03.2016
  2. # Copyright (c) 2016-2018, Manfred Moitzi
  3. # License: MIT License
  4. from ezdxf.legacy import dimension
  5. from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType
  6. from ezdxf.lldxf.const import DXFInternalEzdxfError
  7. from ezdxf.lldxf.tags import Tags
  8. from .graphics import none_subclass, entity_subclass, ModernGraphicEntity, ExtendedTags
  9. dimension_subclass = DefSubclass('AcDbDimension', {
  10. 'geometry': DXFAttr(2), # name of pseudo-Block containing the current dimension entity geometry
  11. 'dimstyle': DXFAttr(3, default='STANDARD'), # dimension style name
  12. # The dimension style is stored in Drawing.sections.tables.dimstyles,
  13. # shortcut Drawings.dimstyles property
  14. 'defpoint': DXFAttr(10, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # definition point for all dimension types
  15. 'text_midpoint': DXFAttr(11, xtype=XType.any_point), # midpoint of dimension text
  16. 'dimtype': DXFAttr(70, default=0), # Dimension type:
  17. # Values 0–6 are integer values that represent the dimension type.
  18. # Values 32, 64, and 128 are bit values, which are added to the integer values
  19. # (value 32 is always set in R13 and later releases)
  20. # 0 = Rotated, horizontal, or vertical;
  21. # 1 = Aligned
  22. # 2 = Angular;
  23. # 3 = Diameter;
  24. # 4 = Radius
  25. # 5 = Angular 3 point;
  26. # 6 = Ordinate
  27. # 32 = Indicates that the block reference (group code 2) is referenced by this dimension only
  28. # 64 = Ordinate type. This is a bit value (bit 7) used only with integer
  29. # value 6. If set, ordinate is X-type; if not set, ordinate is Y-type
  30. # 128 = This is a bit value (bit 8) added to the other group 70 values if
  31. # the dimension text has been positioned at a user-defined location
  32. # rather than at the default location
  33. 'attachment_point': DXFAttr(71), # Attachment point:
  34. # 1 = Top left; 2 = Top center; 3 = Top right
  35. # 4 = Middle left; 5 = Middle center; 6 = Middle right
  36. # 7 = Bottom left; 8 = Bottom center; 9 = Bottom right
  37. 'line_spacing_style': DXFAttr(72, default=1), # Dimension text line-spacing style (optional):
  38. # 1 (or missing) = At least (taller characters will override)
  39. # 2 = Exact (taller characters will not override)
  40. 'line_spacing_factor': DXFAttr(41), # Dimension text-line spacing factor (optional):
  41. # Percentage of default (3-on-5) line spacing to be applied. Valid values
  42. # range from 0.25 to 4.00
  43. 'actual_measurement': DXFAttr(42), # Actual measurement (optional; read-only value)
  44. 'text': DXFAttr(1), # Dimension text explicitly entered by the user. Optional;
  45. # default is the measurement.
  46. # If null or “<>”, the dimension measurement is drawn as the text,
  47. # if “ “ (one blank space), the text is suppressed.
  48. # Anything else is drawn as the text.
  49. 'oblique_angle': DXFAttr(52, default=0), # Linear dimension types with an oblique angle have an optional group
  50. # code 52. When added to the rotation angle of the linear dimension (group code 50), it gives the angle of the
  51. # extension lines (DXF reference error: false subclass AcDbAlignedDimension)
  52. 'text_rotation': DXFAttr(53, default=0), # The optional group code 53 is the rotation angle of the dimension
  53. # text away from its default orientation (the direction of the dimension line) (optional)
  54. 'horizontal_direction': DXFAttr(51, default=0), # All dimension types have an optional 51 group code, which
  55. # indicates the horizontal direction for the dimension entity. The dimension entity determines the orientation of
  56. # dimension text and lines for horizontal, vertical, and rotated linear dimensions. This group value is the negative
  57. # of the angle between the OCS X axis and the UCS X axis. It is always in the XY plane of the OCS
  58. 'extrusion': DXFAttr(210, xtype=XType.point3d, default=(0.0, 0.0, 1.0)),
  59. })
  60. aligned_dimension_subclass = DefSubclass('AcDbAlignedDimension', {
  61. 'insert': DXFAttr(12, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Insertion point for clones of a
  62. # dimension—Baseline and Continue (in OCS)
  63. 'defpoint2': DXFAttr(13, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  64. 'defpoint3': DXFAttr(14, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  65. # The defpoint2 (13,23,33) specifies the start point of the first extension line and
  66. # the defpoint3 (14,24,34) specifies the start point of the second extension line.
  67. # Defpoint (10,20,30) specifies the dimension line location. The text_midpoint (11,21,31)
  68. # specifies the midpoint of the dimension text.
  69. 'angle': DXFAttr(50, default=0), # Angle of rotated, horizontal, or vertical dimensions
  70. })
  71. rotated_dimension_subclass = DefSubclass('AcDbRotatedDimension', {
  72. })
  73. radial_diametric_attribs = {
  74. 'defpoint4': DXFAttr(15, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for diameter, radius, and angular dimensions (in WCS)
  75. 'leader_length': DXFAttr(40), # Leader length for radius and diameter dimensions
  76. }
  77. radial_dimension_subclass = DefSubclass('AcDbRadialDimension', radial_diametric_attribs)
  78. diametric_dimension_subclass = DefSubclass('AcDbDiametricDimension', radial_diametric_attribs)
  79. angular_dimension_subclass = DefSubclass('AcDb3dPointAngularDimension', {
  80. 'defpoint2': DXFAttr(13, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  81. 'defpoint3': DXFAttr(14, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  82. 'defpoint4': DXFAttr(15, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for diameter, radius, and angular dimensions (in WCS)
  83. 'defpoint5': DXFAttr(16, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Point defining dimension arc for angular dimensions (in OCS)
  84. # The defpoint2 (13,23,33) and defpoint3 (14,24,34) specify the endpoints of the line used to determine the first
  85. # extension line. Defpoint (10,20,30) and defpoint4 (15,25,35) specify the endpoints of the line used to determine
  86. # the second extension line. Defpoint5 (16,26,36) specifies the location of the dimension line arc.
  87. # The text_midpoint (11,21,31) specifies the midpoint of the dimension text.
  88. # The point (15,25,35) specifies the vertex of the angle. The points (13,23,33)
  89. # and (14,24,34) specify the endpoints of the extension lines. The point
  90. # (10,20,30) specifies the location of the dimension line arc and the point
  91. # (11,21,31) specifies the midpoint of the dimension text.
  92. })
  93. ordinate_dimension_subclass = DefSubclass('AcDbOrdinateDimension', {
  94. 'defpoint2': DXFAttr(13, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  95. 'defpoint3': DXFAttr(14, xtype=XType.point3d, default=(0.0, 0.0, 0.0)), # Definition point for linear and angular dimensions (in WCS)
  96. # The defpoint1 (13,23,33) specifies the feature location and the defpoint2 (14,24,34) specifies the leader
  97. # endpoint. The text_midpoint (11,21,31) specifies the midpoint of the dimension text. Defpoint (10,20,30) is placed
  98. # at the origin of the UCS that is current when the dimension is created.
  99. })
  100. _DIMTXSTY = 'dimtxsty'
  101. _DIMENSION_TPL = """ 0
  102. DIMENSION
  103. 5
  104. 0
  105. 102
  106. {ACAD_REACTORS
  107. 330
  108. 0
  109. 102
  110. }
  111. 330
  112. DEAD
  113. 100
  114. AcDbEntity
  115. 8
  116. 0
  117. 100
  118. AcDbDimension
  119. 2
  120. *D0
  121. 10
  122. 0.0
  123. 20
  124. 0.0
  125. 30
  126. 0.0
  127. 11
  128. 0.0
  129. 21
  130. 0.0
  131. 31
  132. 0.0
  133. 70
  134. 32
  135. 71
  136. 5
  137. 42
  138. 0.0
  139. 3
  140. STANDARD
  141. """
  142. _ALIGNED_TPL = """100
  143. AcDbAlignedDimension
  144. 13
  145. 0.0
  146. 23
  147. 0.0
  148. 33
  149. 0.0
  150. 14
  151. 0.0
  152. 24
  153. 0.0
  154. 34
  155. 0.0
  156. """
  157. _ROTATED_TPL = """100
  158. AcDbRotatedDimension
  159. """
  160. _RADIAL_TPL = """100
  161. AcDbRadialDimension
  162. """
  163. _DIAMETRIC_TPL = """100
  164. AcDbDiametricDimension
  165. """
  166. _ANGULAR_TPL = """100
  167. AcDb3dPointAngularDimension
  168. """
  169. _ORDINATE_TPL = """100
  170. AcDbOrdinateDimension
  171. """
  172. class Dimension(dimension.Dimension, ModernGraphicEntity):
  173. __slots__ = ()
  174. BLOCK_EXCLUSIVE = 32
  175. TEMPLATE = ExtendedTags.from_text(_DIMENSION_TPL)
  176. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass)
  177. def post_new_hook(self) -> None:
  178. self.add_subclasses()
  179. def add_subclasses(self) -> None:
  180. def add_subclasses(templates) -> None:
  181. for template in templates:
  182. self.tags.subclasses.append(Tags.from_text(template))
  183. dim_type = self.dim_type
  184. if dim_type == self.LINEAR:
  185. add_subclasses([_ALIGNED_TPL, _ROTATED_TPL])
  186. elif dim_type == self.ALIGNED:
  187. add_subclasses([_ALIGNED_TPL])
  188. elif dim_type in (self.ANGULAR, self.ANGULAR_3P):
  189. add_subclasses([_ANGULAR_TPL])
  190. elif dim_type == self.RADIUS:
  191. add_subclasses([_RADIAL_TPL])
  192. elif dim_type == self.DIAMETER:
  193. add_subclasses([_DIAMETRIC_TPL])
  194. elif dim_type == self.ORDINATE:
  195. add_subclasses([_ORDINATE_TPL])
  196. def cast(self) -> 'Dimension': # create the REAL dimension entity
  197. DimClass = DimensionClasses[self.dim_type]
  198. return DimClass(self.tags, self.drawing)
  199. def set_acad_dstyle(self, data: dict) -> None:
  200. if self.drawing is None:
  201. raise DXFInternalEzdxfError('Dimension.drawing attribute not initialized.')
  202. # replace virtual 'dimtxsty' attribute by 'dimtxsty_handle'
  203. if _DIMTXSTY in data:
  204. dimtxsty = data.pop(_DIMTXSTY)
  205. txtstyle = self.drawing.styles.get(dimtxsty)
  206. data['dimtxsty_handle'] = txtstyle.dxf.handle
  207. super().set_acad_dstyle(data)
  208. class AlignedDimension(Dimension):
  209. __slots__ = ()
  210. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, aligned_dimension_subclass)
  211. class RotatedDimension(Dimension):
  212. __slots__ = ()
  213. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, aligned_dimension_subclass,
  214. rotated_dimension_subclass)
  215. class RadialDimension(Dimension):
  216. __slots__ = ()
  217. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, radial_dimension_subclass)
  218. class DiametricDimension(Dimension):
  219. __slots__ = ()
  220. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, diametric_dimension_subclass)
  221. class AngularDimension(Dimension):
  222. __slots__ = ()
  223. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, angular_dimension_subclass)
  224. class OrdinateDimension(Dimension):
  225. __slots__ = ()
  226. DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, dimension_subclass, ordinate_dimension_subclass)
  227. DimensionClasses = [
  228. RotatedDimension, # 0
  229. AlignedDimension, # 1
  230. AngularDimension, # 2
  231. DiametricDimension, # 3
  232. RadialDimension, # 4
  233. AngularDimension, # 5
  234. OrdinateDimension, # 6
  235. ]