Example #1
0
        ),
        # Oblique angle in degrees:
        "oblique":
        DXFAttr(51, default=0, optional=True),
        "extrusion":
        DXFAttr(
            210,
            xtype=XType.point3d,
            default=Z_AXIS,
            optional=True,
            validator=validator.is_not_null_vector,
            fixer=RETURN_DEFAULT,
        ),
    },
)
acdb_shape_group_codes = group_code_mapping(acdb_shape)
merged_shape_group_codes = merge_group_code_mappings(
    acdb_entity_group_codes,
    acdb_shape_group_codes  # type: ignore
)


@register_entity
class Shape(DXFGraphic):
    """DXF SHAPE entity"""

    DXFTYPE = "SHAPE"
    DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_shape)

    def load_dxf_attribs(self,
                         processor: SubclassProcessor = None
Example #2
0
def test_duplicate_group_codes():
    m = group_code_mapping(acdb_dublicates)
    assert m[1] == ['n1', 'n2', 'n3']
    assert m[2] == ['n4', 'n5']
    assert m[3] == 'n6'
Example #3
0
def test_if_callbacks_are_marked():
    m = group_code_mapping(acdb_unique)
    assert m[5] == '*n5', 'callbacks have to marked with a leading "*"'
Example #4
0
def test_unique_group_codes():
    m = group_code_mapping(acdb_unique)
    assert len(m) == 5
    assert set(type(v) for v in m.values()) == {str}
Example #5
0
def test_ignored_group_codes():
    # These group codes are ignored from logging as unprocessed tags, which
    # would happen if they are just left out:
    m = group_code_mapping(acdb_unique, ignore=(1, 2))
    assert m[1] == '*IGNORE'
    assert m[2] == '*IGNORE'
Example #6
0
            validator=validator.is_one_of({0, 5, 6, 8}),
            fixer=RETURN_DEFAULT,
        ),
        '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,
        ),
    })
acdb_polyline_group_codes = group_code_mapping(acdb_polyline, ignore=(66, ))

# Notes to SEQEND:
# todo: A loaded entity should have a valid SEQEND, a POLYLINE without vertices
#  makes no sense - has to be tested
#
# A virtual POLYLINE does not need a SEQEND, because it can not be exported,
# therefore the SEQEND entity should not be created in the
# DXFEntity.post_new_hook() method.
#
# A bounded POLYLINE needs a SEQEND to valid at export, therefore the
# LinkedEntities.post_bind_hook() method creates a new SEQEND after binding
# the entity to a document if needed.


@factory.register_entity
Example #7
0
    'ambient_light_color_2': DXFAttr(421, dxfversion='AC1021'),

    # as True Color:
    'ambient_light_color_3': DXFAttr(431, dxfversion='AC1021'),

    'sun_handle': DXFAttr(361, dxfversion='AC1021'),
    'ref_vp_object_1': DXFAttr(335, dxfversion='AC1021'),
    # unknown meaning, don't ask mozman
    'ref_vp_object_2': DXFAttr(343, dxfversion='AC1021'),
    # unknown meaning, don't ask mozman
    'ref_vp_object_3': DXFAttr(344, dxfversion='AC1021'),
    # unknown meaning, don't ask mozman
    'ref_vp_object_4': DXFAttr(91, dxfversion='AC1021'),
    # unknown meaning, don't ask mozman
})
acdb_viewport_group_codes = group_code_mapping(acdb_viewport)
# Note:
# The ZOOM XP factor is calculated with the following formula:
# group_41 / group_45 (or pspace_height / mspace_height).

FROZEN_LAYER_GROUP_CODE = 331


@register_entity
class Viewport(DXFGraphic):
    """ DXF VIEWPORT entity """
    DXFTYPE = 'VIEWPORT'
    DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_viewport)
    viewport_id = 2

    # Notes to vieport_id:
Example #8
0
            281,
            default=0,
            dxfversion=DXF2007,
            validator=validator.is_integer_bool,
            fixer=RETURN_DEFAULT,
        ),
        # see ezdxf/units.py
        'units':
        DXFAttr(70,
                default=0,
                dxfversion=DXF2007,
                validator=validator.is_in_integer_range(0, 25),
                fixer=RETURN_DEFAULT),
        # 310: Binary data for bitmap preview (optional) - removed (ignored) by ezdxf
    })
acdb_blockrec_group_codes = group_code_mapping(acdb_blockrec)

# optional XDATA for all DXF versions
# 1000: "ACAD"
# 1001: "DesignCenter Data" (optional)
# 1002: "{"
# 1070: Autodesk Design Center version number
# 1070: Insert units: like 'units'
# 1002: "}"


@register_entity
class BlockRecord(DXFEntity):
    """ DXF BLOCK_RECORD table entity

    BLOCK_RECORD is the hard owner of all entities in BLOCK definitions, this
Example #9
0
        DXFAttr(
            98,
            default=0,
            validator=validator.is_greater_or_equal_zero,
            fixer=RETURN_DEFAULT,
        ),
        # MPolygon: offset vector in OCS ???
        "offset_vector":
        DXFAttr(11, xtype=XType.point2d, default=(0, 0)),
        # MPolygon: number of degenerate boundary paths (loops), where a
        # degenerate boundary path is a border that is ignored by the hatch:
        "degenerated_loops":
        DXFAttr(99, default=0),
    },
)
acdb_mpolygon_group_code = group_code_mapping(acdb_mpolygon)


@register_entity
class MPolygon(DXFPolygon):
    """DXF MPOLYGON entity

    The MPOLYGON is not a core DXF entity, and requires a CLASS definition.

    """

    DXFTYPE = "MPOLYGON"
    DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_mpolygon)
    MIN_DXF_VERSION_FOR_EXPORT = const.DXF2000
    LOAD_GROUP_CODES = acdb_mpolygon_group_code
Example #10
0
            73,
            default=0,
            dxfversion=DXF2007,
            validator=validator.is_integer_bool,
            fixer=RETURN_DEFAULT,
        ),
        'background_handle':
        DXFAttr(332, optional=True, dxfversion=DXF2007),
        'live_selection_handle':
        DXFAttr(334, optional=True, dxfversion=DXF2007),
        'visual_style_handle':
        DXFAttr(348, optional=True, dxfversion=DXF2007),
        'sun_handle':
        DXFAttr(361, optional=True, dxfversion=DXF2010),
    })
acdb_view_group_codes = group_code_mapping(acdb_view)


@register_entity
class View(DXFEntity):
    """ DXF VIEW entity """
    DXFTYPE = 'VIEW'
    DXFATTRIBS = DXFAttributes(base_class, acdb_symbol_table_record, acdb_view)

    def load_dxf_attribs(self,
                         processor: SubclassProcessor = None
                         ) -> 'DXFNamespace':
        dxf = super().load_dxf_attribs(processor)
        if processor:
            processor.fast_load_dxfattribs(dxf,
                                           acdb_view_group_codes,
Example #11
0
        # PlotStyleName type enum (AcDb::PlotStyleNameType). Stored and moved around
        # as a 16-bit integer. Custom non-entity
        'plotstyle_enum':
        DXFAttr(380, dxfversion=DXF2007, default=1, optional=True),

        # Handle value of the PlotStyleName object, basically a hard pointer, but
        # has a different range to make backward compatibility easier to deal with.
        'plotstyle_handle':
        DXFAttr(390, dxfversion=DXF2007, optional=True),

        # 92 or 160?: Number of bytes in the proxy entity graphics represented in
        # the subsequent 310 groups, which are binary chunk records (optional)
        # 310: Proxy entity graphics data (multiple lines; 256 characters max. per
        # line) (optional), compiled by TagCompiler() to a DXFBinaryTag() objects
    })
acdb_entity_group_codes = group_code_mapping(acdb_entity)


def elevation_to_z_axis(dxf: 'DXFNamespace', names: Iterable[str]):
    # The elevation group code (38) is only used for DXF R11 and prior and
    # ignored for DXF R2000 and later.
    # DXF R12 and later store the entity elevation in the z-axis of the
    # vertices, but AutoCAD supports elevation for R12 if no z-axis is present.
    # DXF types with legacy elevation support:
    # SOLID, TRACE, TEXT, CIRCLE, ARC, TEXT, ATTRIB, ATTDEF, INSERT, SHAPE

    # The elevation is only used for DXF R12 if no z-axis is stored in the DXF
    # file. This is a problem because ezdxf loads the vertices always as 3D
    # vertex including a z-axis even if no z-axis is present in DXF file.
    if dxf.hasattr('elevation'):
        elevation = dxf.elevation
Example #12
0
        "generation_flags":
        DXFAttr(71, default=0),
        # Last height used:
        "last_height":
        DXFAttr(42, default=2.5),
        # Primary font file name:
        # ATTENTION: The font file name can be an empty string and the font family
        # may be stored in XDATA! See also posts at the (unrelated) issue #380.
        "font":
        DXFAttr(3, default="txt"),
        # Big font name, blank if none
        "bigfont":
        DXFAttr(4, default=""),
    },
)
acdb_style_group_codes = group_code_mapping(acdb_style)

# XDATA: This is not a reliable source for font data!
# 1001 <ctrl> ACAD
# 1000 <str> Arial  ; font-family sometimes an empty string!
# 1071 <int> 34  ; flags
# ----
# "Arial" "normal" flags = 34               = 0b00:00000000:00000000:00100010
# "Arial" "italic" flags = 16777250         = 0b01:00000000:00000000:00100010
# "Arial" "bold" flags = 33554466           = 0b10:00000000:00000000:00100010
# "Arial" "bold+italic" flags = 50331682    = 0b11:00000000:00000000:00100010


@register_entity
class Textstyle(DXFEntity):
    """DXF STYLE entity"""
Example #13
0
            validator=validator.is_not_null_vector,
            fixer=RETURN_DEFAULT,
        ),
        # Ratio has to be in the range from 1e-6 to 1, but could be negative:
        'ratio':
        DXFAttr(
            40, default=MAX_RATIO, validator=is_valid_ratio, fixer=fix_ratio),
        # Start of ellipse, this value is 0.0 for a full ellipse:
        'start_param':
        DXFAttr(41, default=0),

        # End of ellipse, this value is 2*pi for a full ellipse:
        'end_param':
        DXFAttr(42, default=math.tau),
    })
acdb_ellipse_group_code = group_code_mapping(acdb_ellipse)
HALF_PI = math.pi / 2.0


@register_entity
class Ellipse(DXFGraphic):
    """ DXF ELLIPSE entity """
    DXFTYPE = 'ELLIPSE'
    DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_ellipse)
    MIN_DXF_VERSION_FOR_EXPORT = DXF2000

    def load_dxf_attribs(self,
                         processor: SubclassProcessor = None
                         ) -> 'DXFNamespace':
        dxf = super().load_dxf_attribs(processor)
        if processor:
Example #14
0
        'gen_proc_val_bool': DXFAttr(291),
        'gen_proc_val_int': DXFAttr(271),
        'gen_proc_val_real': DXFAttr(469),
        'gen_proc_val_text': DXFAttr(301),
        'gen_proc_table_end': DXFAttr(292),
        'gen_proc_val_color_index': DXFAttr(62),
        'gen_proc_val_color_rgb': DXFAttr(420),
        'gen_proc_val_color_name': DXFAttr(430),
        'map_utile': DXFAttr(270),  # multiple usage of group code 270
        'translucence': DXFAttr(148),
        'self_illumination': DXFAttr(90),
        'reflectivity': DXFAttr(468),
        'illumination_model': DXFAttr(93),
        'channel_flags': DXFAttr(94, default=63),
    })
acdb_material_group_codes = group_code_mapping(acdb_material)


@register_entity
class Material(DXFObject):
    DXFTYPE = 'MATERIAL'
    DEFAULT_ATTRIBS = {
        'diffuse_color_method': 1,
        'diffuse_color_value': -1023410177,
    }
    DXFATTRIBS = DXFAttributes(base_class, acdb_material)

    def __init__(self):
        super().__init__()
        self.diffuse_mapper_matrix: Optional[Matrix44] = None  # code 43
        self.specular_mapper_matrix: Optional[Matrix44] = None  # code 47