1# Copyright (c) 2019-2020 Manfred Moitzi
2# License: MIT License
3from typing import TYPE_CHECKING
4from ezdxf.lldxf import validator
5from ezdxf.lldxf.attributes import (
6    DXFAttr, DXFAttributes, DefSubclass, XType, RETURN_DEFAULT,
7    group_code_mapping
8)
9from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER
10from ezdxf.math import Vec3, Matrix44, NULLVEC, Z_AXIS
11from ezdxf.math.transformtools import (
12    transform_thickness_and_extrusion_without_ocs,
13)
14from .dxfentity import base_class, SubclassProcessor
15from .dxfgfx import DXFGraphic, acdb_entity
16from .factory import register_entity
17
18if TYPE_CHECKING:
19    from ezdxf.eztypes import TagWriter, DXFNamespace
20
21__all__ = ['Line']
22
23acdb_line = DefSubclass('AcDbLine', {
24    'start': DXFAttr(10, xtype=XType.point3d, default=NULLVEC),
25    'end': DXFAttr(11, xtype=XType.point3d, default=NULLVEC),
26    'thickness': DXFAttr(39, default=0, optional=True),
27    'extrusion': DXFAttr(
28        210, xtype=XType.point3d, default=Z_AXIS, optional=True,
29        validator=validator.is_not_null_vector,
30        fixer=RETURN_DEFAULT,
31    ),
32})
33
34acdb_line_group_codes = group_code_mapping(acdb_line)
35
36
37@register_entity
38class Line(DXFGraphic):
39    """ The LINE entity represents a 3D line from `start` to `end` """
40    DXFTYPE = 'LINE'
41    DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_line)
42
43    def load_dxf_attribs(
44            self, processor: SubclassProcessor = None) -> 'DXFNamespace':
45        """ Adds subclass processing for 'AcDbLine', requires previous base
46        class and 'AcDbEntity' processing by parent class. (internal API)
47
48        """
49        dxf = super().load_dxf_attribs(processor)
50        if processor:
51            processor.fast_load_dxfattribs(
52                dxf, acdb_line_group_codes, subclass=2, recover=True)
53        return dxf
54
55    def export_entity(self, tagwriter: 'TagWriter') -> None:
56        """ Export entity specific data as DXF tags. (internal API) """
57        super().export_entity(tagwriter)
58        if tagwriter.dxfversion > DXF12:
59            tagwriter.write_tag2(SUBCLASS_MARKER, acdb_line.name)
60        self.dxf.export_dxf_attribs(tagwriter, [
61            'start', 'end', 'thickness', 'extrusion',
62        ])
63
64    def transform(self, m: Matrix44) -> 'Line':
65        """ Transform the LINE entity by transformation matrix `m` inplace.
66        """
67        start, end = m.transform_vertices([self.dxf.start, self.dxf.end])
68        self.dxf.start = start
69        self.dxf.end = end
70        transform_thickness_and_extrusion_without_ocs(self, m)
71        return self
72
73    def translate(self, dx: float, dy: float, dz: float) -> 'Line':
74        """ Optimized LINE translation about `dx` in x-axis, `dy` in y-axis and
75        `dz` in z-axis.
76
77        """
78        vec = Vec3(dx, dy, dz)
79        self.dxf.start = vec + self.dxf.start
80        self.dxf.end = vec + self.dxf.end
81        return self
82