123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- # 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
|