# Created: 25.03.2011 # Copyright (c) 2011-2018, Manfred Moitzi # License: MIT License from typing import TYPE_CHECKING, Type from ezdxf.lldxf.const import DXFInternalEzdxfError, DXFValueError from ezdxf.lldxf.types import get_xcode_for from ezdxf.tools import take2 import logging from .graphics import GraphicEntity, ExtendedTags, make_attribs, DXFAttr, XType, DXFAttributes if TYPE_CHECKING: from ezdxf.eztypes import DimStyle logger = logging.getLogger('ezdxf') _DIMENSION_TPL = """0 DIMENSION 5 0 8 0 2 *BLOCKNAME 3 DIMSTYLE 10 0.0 20 0.0 30 0.0 11 0.0 21 0.0 31 0.0 70 0 1 13 0.0 23 0.0 33 0.0 14 0.0 24 0.0 34 0.0 40 1.0 50 0.0 """ class Dimension(GraphicEntity): __slots__ = () LINEAR = 0 ALIGNED = 1 ANGULAR = 2 DIAMETER = 3 RADIUS = 4 ANGULAR_3P = 5 ORDINATE = 6 ORDINATE_TYPE = 64 USER_LOCATION_OVERRIDE = 128 TEMPLATE = ExtendedTags.from_text(_DIMENSION_TPL) DXFATTRIBS = make_attribs({ 'geometry': DXFAttr(2), # name of pseudo-Block containing the current dimension entity geometry 'dimstyle': DXFAttr(3, default='STANDARD'), # dimension style name # The dimension style is stored in Drawing.sections.tables.dimstyles, # shortcut Drawings.dimstyles property 'defpoint': DXFAttr(10, xtype=XType.any_point), # WCS, definition point for all dimension types 'text_midpoint': DXFAttr(11, xtype=XType.any_point), # OCS, middle point of dimension text !!! projected onto # the dimension line, not below or above, -> LINEAR: both defpoint and text_midpoint are located at the dimline 'insert': DXFAttr(12, xtype=XType.point3d), # OCS, Insertion point for clones of a dimension — Baseline and Continue 'dimtype': DXFAttr(70, default=0), # Dimension type: # Values 0–6 are integer values that represent the dimension type. # Values 64 and 128 are bit values, which are added to the integer values # 0 = Rotated, horizontal, or vertical; # 1 = Aligned # 2 = Angular; # 3 = Diameter; # 4 = Radius # 5 = Angular 3 point; # 6 = Ordinate # 64 = Ordinate type. This is a bit value (bit 7) used only with integer # value 6. If set, ordinate is X-type; if not set, ordinate is Y-type # 128 = This is a bit value (bit 8) added to the other group 70 values if # the dimension text has been positioned at a user-defined location # rather than at the default location 'text': DXFAttr(1), # dimension text explicitly entered by the user. # If null or "<>", the dimension measurement is drawn as the text, # if " " [one blank space], the text is suppressed. # Anything else is drawn as the text. 'defpoint2': DXFAttr(13, xtype=XType.any_point), # WCS, definition point for linear and angular dimensions 'defpoint3': DXFAttr(14, xtype=XType.any_point), # WCS, definition point for linear and angular dimensions 'defpoint4': DXFAttr(15, xtype=XType.any_point), # WCS, definition point for diameter, radius, and angular dimensions 'defpoint5': DXFAttr(16, xtype=XType.any_point), # OCS, point defining dimension arc for angular dimensions 'leader_length': DXFAttr(40), # leader length for radius and diameter dimensions 'angle': DXFAttr(50), # angle of rotated, horizontal, or vertical linear dimensions 'horizontal_direction': DXFAttr(51), # In addition, all dimension types have an optional group # (code 51) that indicates the horizontal direction for the # Dimension entity. This determines the orientation of # dimension text and dimension lines for horizontal, # vertical, and rotated linear dimensions. The group value # is the negative of the Entity Coordinate Systems (ECS) # angle of the UCS X axis in effect when the Dimension was # drawn. The X axis of the UCS in effect when the Dimension # was drawn is always parallel to the XY plane for the # Dimension's ECS, and the angle between the UCS X axis and # the ECS X axis is a single 2D angle. The value in group 51 # is the angle from horizontal (the effective X axis) to the # ECS X axis. Entity Coordinate Systems (ECS) are described # later in this section. 'oblique_angle': DXFAttr(52), # Linear dimension types with an oblique angle have an # optional group (code 52).When added to the rotation angle # of the linear dimension (group code 50) this gives the # angle of the extension lines 'text_rotation': DXFAttr(53), # The optional group code 53 is the rotation angle of the # dimension text away from its default orientation (the direction # of the dimension line). }) @property def dim_type(self) -> int: return self.dxf.dimtype & 7 def dim_style(self) -> 'DimStyle': if self.drawing is None: raise DXFInternalEzdxfError('Dimension.drawing attribute not initialized.') dim_style_name = self.dxf.dimstyle # raises ValueError if not exists, but all used dim styles should exists! return self.drawing.dimstyles.get(dim_style_name) def cast(self) -> 'Dimension': # for modern dimension lines return self def dim_style_attributes(self)->'DXFAttributes': return self.dim_style().DXFATTRIBS def set_acad_dstyle(self, data: dict) -> None: tags = [] dim_style_attributes = self.dim_style_attributes() for key, value in data.items(): if key not in dim_style_attributes: # ignore unknown attributes, but log logging.debug('ignore unknown DIMSTYLE attribute: "{}"'.format(key)) continue dxf_attr = dim_style_attributes.get(key) if dxf_attr and dxf_attr.code > 0: # skip internal and virtual tags code = dxf_attr.code tags.append((1070, code)) if code == 5: # DimStyle 'dimblk' has group code 5 but is not a handle tags.append((1000, value)) else: tags.append((get_xcode_for(code), value)) if len(tags): self.set_xdata_list('ACAD', 'DSTYLE', tags) def get_acad_dstyle(self, dim_style: 'DimStyle') -> dict: try: data = self.get_xdata_list('ACAD', 'DSTYLE') except DXFValueError: return {} attribs = {} codes = dim_style.CODE_TO_DXF_ATTRIB for code_tag, value_tag in take2(data): group_code = code_tag.value value = value_tag.value if group_code in codes: attribs[codes[group_code]] = value return attribs