class Linetype(DXFEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_LTYPETEMPLATE) DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'handle': DXFAttr(5), 'name': DXFAttr(2), 'description': DXFAttr(3), 'length': DXFAttr(40), 'items': DXFAttr(73), })) @classmethod def new(cls, handle: str, dxfattribs: dict = None, dxffactory: 'DXFFactoryType' = None) -> DXFEntity: if dxfattribs is not None: pattern = dxfattribs.pop('pattern', [0.0]) length = dxfattribs.pop('length', 0.) else: pattern = [0.0] length = 0. entity = super(Linetype, cls).new(handle, dxfattribs, dxffactory) entity._setup_pattern(pattern, length) return entity def _setup_pattern(self, pattern: Sequence[float], length: float) -> None: # length parameter is required for complex line types # pattern: [2.0, 1.25, -0.25, 0.25, -0.25] - 1. element is total pattern length # pattern elements: >0 line, <0 gap, =0 point self.tags.noclass.append(DXFTag(73, len(pattern) - 1)) self.tags.noclass.append(DXFTag(40, float(pattern[0]))) self.tags.noclass.extend((DXFTag(49, float(p)) for p in pattern[1:]))
class Circle(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_CIRCLE_TPL) DXFATTRIBS = make_attribs({ 'center': DXFAttr(10, xtype='Point2D/3D'), 'radius': DXFAttr(40), })
class Line(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_LINE_TPL) DXFATTRIBS = make_attribs({ 'start': DXFAttr(10, xtype='Point2D/3D'), 'end': DXFAttr(11, xtype='Point2D/3D'), })
class Layer(DXFEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_LAYERTEMPLATE) DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'handle': DXFAttr(5), 'name': DXFAttr(2), 'flags': DXFAttr(70), 'color': DXFAttr(62), # dxf color index, if < 0 layer is off 'linetype': DXFAttr(6), })) FROZEN = 0b00000001 THAW = 0b11111110 LOCK = 0b00000100 UNLOCK = 0b11111011 def post_new_hook(self) -> None: if not is_valid_layer_name(self.dxf.name): raise DXFInvalidLayerName("Invalid layer name '{}'".format( self.dxf.name)) def is_frozen(self) -> bool: return self.dxf.flags & Layer.FROZEN > 0 def freeze(self) -> None: self.dxf.flags = self.dxf.flags | Layer.FROZEN def thaw(self) -> None: self.dxf.flags = self.dxf.flags & Layer.THAW def is_locked(self) -> bool: return self.dxf.flags & Layer.LOCK > 0 def lock(self) -> None: self.dxf.flags = self.dxf.flags | Layer.LOCK def unlock(self) -> None: self.dxf.flags = self.dxf.flags & Layer.UNLOCK def is_off(self) -> bool: return self.dxf.color < 0 def is_on(self) -> bool: return not self.is_off() def on(self) -> None: self.dxf.color = abs(self.dxf.color) def off(self) -> None: self.dxf.color = -abs(self.dxf.color) def get_color(self) -> int: return abs(self.dxf.color) def set_color(self, color: int) -> None: color = abs(color) if self.is_on() else -abs(color) self.dxf.color = color
class SeqEnd(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(" 0\nSEQEND\n 5\n0\n") DXFATTRIBS = DXFAttributes( DefSubclass(None, { 'handle': DXFAttr(5), 'paperspace': DXFAttr(67, default=0), }))
def subclass(): return DefSubclass('AcDbTest', { 'test1': DXFAttr(1), 'test2': DXFAttr(2), 'test3': DXFAttr(1), # duplicate group code 'callback': DXFAttr(3, xtype=XType.callback), 'none_callback': DXFAttr(3), # duplicate group code })
class Arc(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_ARC_TPL) DXFATTRIBS = make_attribs({ 'center': DXFAttr(10, xtype='Point2D/3D'), 'radius': DXFAttr(40), 'start_angle': DXFAttr(50), 'end_angle': DXFAttr(51), })
class AppID(DXFEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_APPIDTEMPLATE) DXFATTRIBS = DXFAttributes( DefSubclass(None, { 'handle': DXFAttr(5), 'name': DXFAttr(2), 'flags': DXFAttr(70), }))
def subclass(): return DefSubclass( "AcDbTest", { "test1": DXFAttr(1), "test2": DXFAttr(2), "test3": DXFAttr(1), # duplicate group code "callback": DXFAttr(3, xtype=XType.callback), "none_callback": DXFAttr(3), # duplicate group code }, )
class RasterVariables(DXFEntity): TEMPLATE = ExtendedTags.from_text(_RASTER_VARIABLES_TPL) CLASS = ExtendedTags.from_text(_RASTER_VARIABLES_CLS) DXFATTRIBS = DXFAttributes( none_subclass, DefSubclass('AcDbRasterVariables', { 'version': DXFAttr(90, default=0), 'frame': DXFAttr(70, default=0), # 0 = no frame; 1= show frame 'quality': DXFAttr(71, default=1), # 0=draft; 1=high 'units': DXFAttr(72, default=3), # 0 = None; 1 = mm; 2 = cm 3 = m; 4 = km; 5 = in 6 = ft; 7 = yd; 8 = mi }), )
class Viewport(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_VPORT_TPL) DXFATTRIBS = make_attribs({ 'center': DXFAttr(10, xtype='Point2D/3D' ), # center point of entity in paper space coordinates) 'width': DXFAttr(40), # width in paper space units 'height': DXFAttr(41), # height in paper space units 'status': DXFAttr(68), 'id': DXFAttr(69), }) viewport_id = 2 # notes to id: # The id of the first viewport has to be 1, which is the definition of # paper space. For the following viewports it seems only important, that # the id is greater than 1. @contextmanager def edit_data(self): viewport_data = self.get_viewport_data() yield viewport_data self.set_viewport_data(viewport_data) def get_viewport_data(self): try: extended_dxf_data = self.tags.get_xdata('ACAD') except DXFValueError: DXFStructureError("Invalid viewport entity - missing data") else: return ViewportData.from_tags(extended_dxf_data) def set_viewport_data(self, viewport_data): dxftags = viewport_data.dxftags() pos = None for index, xdata in enumerate(self.tags.xdata): if xdata[0].value == 'ACAD' and xdata[1].value == 'MVIEW': pos = index if pos is None: self.tags.xdata.insert( 0, dxftags) # insert viewport data as first extended data else: self.tags.xdata[pos] = dxftags def get_next_viewport_id(self): current_id = Viewport.viewport_id Viewport.viewport_id += 1 return current_id
class PointAccessor(DXFEntity): DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'point': DXFAttr(10, xtype=XType.point3d), 'flat': DXFAttr(11, xtype=XType.point2d), 'xp': DXFAttr(12, xtype=XType.point3d), 'flex': DXFAttr(13, xtype=XType.any_point), 'flags': DXFAttr(70), 'counter': DXFAttr(-1, xtype=XType.callback, getter='get_counter', setter='set_counter'), 'just_AC1015': DXFAttr(71, default=777, dxfversion='AC1015'), })) def __init__(self, tags): super(PointAccessor, self).__init__(tags, drawing=DWG) self._counter = 0 def get_counter(self): return self._counter def set_counter(self, value): self._counter = value
class ImageDefReactor(DXFEntity): TEMPLATE = ExtendedTags.from_text(_IMAGE_DEF_REACTOR_TPL) CLASS = ExtendedTags.from_text(_IMAGE_DEF_REACTOR_CLS) DXFATTRIBS = DXFAttributes( none_subclass, DefSubclass( 'AcDbRasterImageDef', { 'image': DXFAttr(330), # handle to image }))
class Style(DXFEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_STYLETEMPLATE) DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'handle': DXFAttr(5), 'name': DXFAttr(2), 'flags': DXFAttr(70), 'height': DXFAttr(40), # fixed height, 0 if not fixed 'width': DXFAttr(41), # width factor 'oblique': DXFAttr(50), # oblique angle in degree, 0 = vertical 'generation_flags': DXFAttr(71), # 2 = backward, 4 = mirrored in Y 'last_height': DXFAttr(42), # last height used 'font': DXFAttr(3), # primary font file name 'bigfont': DXFAttr(4), # big font name, blank if none }))
def test_load_doublettes(): from ezdxf.lldxf.attributes import DefSubclass, DXFAttr from ezdxf.lldxf.tags import Tags, DXFTag subclass = DefSubclass('AcDbTest', { 'test1': DXFAttr(1), 'test2': DXFAttr(2), 'test3': DXFAttr(1), # same group code for different attribute }) class TestEntity(DXFEntity): DXFATTRIBS = DXFAttributes(subclass) data = Tags([ DXFTag(1, '1'), DXFTag(2, '2'), DXFTag(1, '3'), ]) ns = DXFNamespace(entity=TestEntity()) SubclassProcessor.load_tags_into_namespace(ns, data, subclass) assert ns.test1 == '1' assert ns.test2 == '2' assert ns.test3 == '3'
class DXFClass(DXFEntity): __slots__ = () DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'name': DXFAttr(1), 'cpp_class_name': DXFAttr(2), 'app_name': DXFAttr(3), 'flags': DXFAttr(90), 'instance_count': DXFAttr(91, dxfversion='AC1018'), 'was_a_proxy': DXFAttr(280), 'is_an_entity': DXFAttr(281), }), )
class Shape(GraphicEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_SHAPE_TPL) DXFATTRIBS = make_attribs({ 'insert': DXFAttr(10, xtype='Point2D/3D'), 'size': DXFAttr(40), 'name': DXFAttr(2), 'rotation': DXFAttr(50, default=0.0), 'xscale': DXFAttr(41, default=1.0), 'oblique': DXFAttr(51, default=0.0), })
class PointAccessor(DXFEntity): DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'point': DXFAttr(10, 'Point3D'), 'flat': DXFAttr(11, 'Point2D'), 'xp': DXFAttr(12, 'Point3D'), 'flex': DXFAttr(13, 'Point2D/3D'), 'flags': DXFAttr(70), 'just_AC1015': DXFAttr(71, default=777, dxfversion='AC1015'), })) def __init__(self, tags): super(PointAccessor, self).__init__(tags, drawing=DWG)
def test_return_default(): attr = DXFAttr( code=62, default=12, validator=lambda x: False, fixer=RETURN_DEFAULT, ) assert attr.fixer(7) == 12 attr2 = DXFAttr( code=63, default=13, validator=lambda x: False, fixer=RETURN_DEFAULT, ) assert attr2.fixer(7) == 13
def make_attribs(additional=None): dxfattribs = { 'handle': DXFAttr(5), 'layer': DXFAttr( 8, default='0' ), # layer name as string, mandatory according to the DXF Reference 'linetype': DXFAttr(6, default='BYLAYER' ), # linetype as string, special names BYLAYER/BYBLOCK 'color': DXFAttr(62, default=256), # dxf color index, 0 .. BYBLOCK, 256 .. BYLAYER 'thickness': DXFAttr(39, default=0), # thickness of 2D elements 'paperspace': DXFAttr(67, default=0), # 0=modelspace; 1=paperspace 'extrusion': DXFAttr(210, xtype='Point3D', default=(0.0, 0.0, 1.0)), # Z-axis of OCS (Object-Coordinate-System) } if additional is not None: dxfattribs.update(additional) return DXFAttributes(DefSubclass(None, dxfattribs))
class UCS(DXFEntity): __slots__ = () TEMPLATE = ExtendedTags.from_text(_UCSTEMPLATE) DXFATTRIBS = DXFAttributes( DefSubclass( None, { 'handle': DXFAttr(5), 'name': DXFAttr(2), 'flags': DXFAttr(70), 'origin': DXFAttr(10, xtype=XType.point3d), 'xaxis': DXFAttr(11, xtype=XType.point3d), 'yaxis': DXFAttr(12, xtype=XType.point3d), })) def ucs(self) -> UserCoordinateSystem: return UserCoordinateSystem( origin=self.get_dxf_attrib('origin', default=(0, 0, 0)), ux=self.get_dxf_attrib('xaxis', default=(1, 0, 0)), uy=self.get_dxf_attrib('yaxis', default=(0, 1, 0)), )
from ezdxf.math import Vector, Matrix44, NULLVEC, Z_AXIS from ezdxf.math.transformtools import ( transform_thickness_and_extrusion_without_ocs, ) from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace __all__ = ['Line'] acdb_line = DefSubclass( 'AcDbLine', { 'start': DXFAttr(10, xtype=XType.point3d, default=NULLVEC), 'end': DXFAttr(11, xtype=XType.point3d, default=NULLVEC), 'thickness': DXFAttr(39, default=0, optional=True), 'extrusion': DXFAttr( 210, xtype=XType.point3d, default=Z_AXIS, optional=True, validator=validator.is_not_null_vector, fixer=RETURN_DEFAULT, ), })
from ezdxf.tools import set_flag_state from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, Drawing __all__ = ['Viewport'] acdb_viewport = DefSubclass( 'AcDbViewport', { # Center point (in WCS) 'center': DXFAttr(10, xtype=XType.point3d, default=NULLVEC), # Width in paper space units: 'width': DXFAttr(40, default=1), # Height in paper space units: 'height': DXFAttr(41, default=1), # Viewport status field: # -1 = On, but is fully off screen, or is one of the viewports that is not # active because the $MAXACTVP count is currently being exceeded. # 0 = Off # <positive value> = On and active. The value indicates the order of # stacking for the viewports, where 1 is the active viewport, 2 is the next,
def fix_ratio(ratio: float) -> float: sign = -1 if ratio < 0 else +1 ratio = abs(ratio) if ratio < MIN_RATIO: return MIN_RATIO * sign elif ratio > MAX_RATIO: return MAX_RATIO * sign return ratio * sign acdb_ellipse = DefSubclass( 'AcDbEllipse', { 'center': DXFAttr(10, xtype=XType.point3d, default=NULLVEC), # Major axis vector from 'center': 'major_axis': DXFAttr( 11, xtype=XType.point3d, default=X_AXIS, validator=validator.is_not_null_vector, ), # The extrusion vector does not establish an OCS, it is just the normal # vector of the ellipse plane: 'extrusion': DXFAttr( 210,
from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, Matrix44 __all__ = ["Tolerance"] acdb_tolerance = DefSubclass( "AcDbFcf", { "dimstyle": DXFAttr( 3, default="Standard", validator=validator.is_valid_table_name, ), # Insertion point (in WCS): "insert": DXFAttr(10, xtype=XType.point3d, default=NULLVEC), # String representing the visual representation of the tolerance: "content": DXFAttr(1, default=""), "extrusion": DXFAttr( 210, xtype=XType.point3d, default=Z_AXIS, optional=True, validator=validator.is_not_null_vector,
RETURN_DEFAULT, ) from .dxfentity import base_class, SubclassProcessor from .dxfobj import DXFObject from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace __all__ = ['Sun'] acdb_sun = DefSubclass( 'AcDbSun', { 'version': DXFAttr(90, default=1), 'status': DXFAttr( 290, default=1, validator=validator.is_integer_bool, fixer=RETURN_DEFAULT, ), 'color': DXFAttr( 63, default=7, validator=validator.is_valid_aci_color, fixer=RETURN_DEFAULT, ), 'true_color':
from .factory import register_entity logger = logging.getLogger('ezdxf') if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace __all__ = ['Textstyle'] acdb_style = DefSubclass( 'AcDbTextStyleTableRecord', { 'name': DXFAttr( 2, default='Standard', validator=validator.is_valid_table_name, ), 'flags': DXFAttr(70, default=0), # Fixed height, 0 if not fixed 'height': DXFAttr( 40, default=0, validator=validator.is_greater_or_equal_zero, fixer=RETURN_DEFAULT, ), # Width factor: 'width':
from ezdxf.math.transformtools import OCSTransform from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity, elevation_to_z_axis from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace __all__ = ['Solid', 'Trace', 'Face3d'] acdb_trace = DefSubclass( 'AcDbTrace', { # 1. corner Solid WCS; Trace OCS 'vtx0': DXFAttr(10, xtype=XType.point3d, default=NULLVEC), # 2. corner Solid WCS; Trace OCS 'vtx1': DXFAttr(11, xtype=XType.point3d, default=NULLVEC), # 3. corner Solid WCS; Trace OCS 'vtx2': DXFAttr(12, xtype=XType.point3d, default=NULLVEC), # 4. corner Solid WCS; Trace OCS: # If only three corners are entered to define the SOLID, then the fourth # corner coordinate is the same as the third. 'vtx3': DXFAttr(13, xtype=XType.point3d, default=NULLVEC),
class Solid3d(Body): __slots__ = () TEMPLATE = ExtendedTags.from_text(_3DSOLID_TPL) DXFATTRIBS = DXFAttributes( none_subclass, entity_subclass, modeler_geometry_subclass, DefSubclass('AcDb3dSolid', {'history': DXFAttr(350, default=0)}))
5 0 330 0 100 AcDbEntity 8 0 100 AcDbModelerGeometry 70 1 """ modeler_geometry_subclass = DefSubclass('AcDbModelerGeometry', { 'version': DXFAttr(70, default=1), }) def convert_tags_to_text_lines(line_tags): """ Args: line_tags: tags with code 1 or 3, tag with code 3 is the tail of previous line with more than 255 chars. Returns: yield strings """ line_tags = iter(line_tags) try: line = next(line_tags).value # raises StopIteration except StopIteration: