Ejemplo n.º 1
0
def tag_processor(tags: ExtendedTags) -> ExtendedTags:
    spline_tags = tags.get_subclass('AcDbSpline')
    control_points = ControlPoints.from_tags(spline_tags)
    fit_points = FitPoints.from_tags(spline_tags)
    knots = KnotTags.from_tags(spline_tags)
    weights = WeightTags.from_tags(spline_tags)
    spline_tags.remove_tags(codes=REMOVE_CODES)
    spline_tags.extend((knots, weights, control_points, fit_points))
    return tags
Ejemplo n.º 2
0
def test_xrecord_with_group_code_102():
    tags = ExtendedTags(Tags.from_text(XRECORD_WITH_GROUP_CODE_102))
    assert tags.dxftype() == 'XRECORD'
    assert len(tags.appdata) == 1
    assert tags.noclass[2] == (102, 0)  # 0 == index in appdata list
    assert tags.appdata[0][0] == (102, '{ACAD_REACTORS')

    xrecord = tags.get_subclass('AcDbXrecord')
    assert xrecord[2] == (102, 'ACAD_ROUNDTRIP_PRE2007_TABLESTYLE')
    assert len(list(tags)) * 2 + 1 == len(XRECORD_WITH_GROUP_CODE_102.split('\n'))  # +1 == appending '\n'
Ejemplo n.º 3
0
def test_group_code_1000_outside_XDATA():
    tags = ExtendedTags(Tags.from_text(BLOCKBASEPOINTPARAMETER_CVIL_3D_2018))
    assert tags.dxftype() == 'BLOCKBASEPOINTPARAMETER'
    assert len(tags.subclasses) == 6
    block_base_point_parameter = tags.get_subclass('AcDbBlockBasepointParameter')
    assert len(block_base_point_parameter) == 3
    assert block_base_point_parameter[0] == (100, 'AcDbBlockBasepointParameter')
    assert block_base_point_parameter[1] == (1011, (0., 0., 0.))
    assert block_base_point_parameter[2] == (1012, (0., 0., 0.))

    block_element = tags.get_subclass('AcDbBlockElement')
    assert block_element[4] == (1071, 0)

    stream = StringIO()
    tagwriter = TagWriter(stream)
    tagwriter.write_tags(tags)
    lines = stream.getvalue()
    stream.close()
    assert len(lines.split('\n')) == len(BLOCKBASEPOINTPARAMETER_CVIL_3D_2018.split('\n'))
Ejemplo n.º 4
0
 def store_tags(self, tags: ExtendedTags) -> None:
     # store DXFTYPE, overrides class member
     # 1. tag of 1. subclass is the structure tag (0, DXFTYPE)
     self.xtags = tags
     self.DXFTYPE = self.base_class[0].value
     try:
         acdb_entity = tags.get_subclass('AcDbEntity')
         self.dxf.__dict__['paperspace'] = acdb_entity.get_first_value(67, 0)
     except const.DXFKeyError:
         # just fake it
         self.dxf.__dict__['paperspace'] = 0
Ejemplo n.º 5
0
def test_xrecord_with_long_closing_tag():
    tags = ExtendedTags(Tags.from_text(XRECORD_APP_DATA_LONG_CLOSING_TAG))
    assert tags.dxftype() == 'XRECORD'
    assert len(tags.appdata) == 5

    attr_rec = tags.appdata[4]
    assert attr_rec[0] == (102, '{ATTRRECORD')
    assert attr_rec[1] == (341, '2FD')
    assert len(list(tags)) * 2 + 1 == len(
        XRECORD_APP_DATA_LONG_CLOSING_TAG.split('\n'))  # +1 == appending '\n'

    # test USUAL_102_TAG_INSIDE_APP_DATA
    attr_rec = tags.appdata[1]
    assert attr_rec[0] == (102, '{ATTRRECORD')
    assert attr_rec[1] == (341, '2FA')
    assert attr_rec[2] == (102, 'USUAL_102_TAG_INSIDE_APP_DATA')

    # test USUAL_102_TAG_OUTSIDE_APP_DATA
    xrecord = tags.get_subclass('AcDbXrecord')
    assert xrecord[4] == (102, 'USUAL_102_TAG_OUTSIDE_APP_DATA')
Ejemplo n.º 6
0
def tag_processor(tags: ExtendedTags) -> ExtendedTags:
    subclass = tags.get_subclass('AcDbSubDMesh')
    handle = tags.get_handle()
    convert_and_replace_tags(subclass, handle)
    return tags
Ejemplo n.º 7
0
class Table:
    def __init__(self, entities: Iterable[Tags], drawing: 'Drawing'):
        self._table_header = None
        self._dxfname = None
        self._drawing = drawing
        self._table_entries = []
        self._build_table_entries(iter(entities))

    # start public interface

    @staticmethod
    def key(entity: Union[str, 'DXFEntity']) -> str:
        if not isinstance(entity, str):
            entity = entity.dxf.name
        return entity.lower()  # table key is lower case

    @property
    def name(self) -> str:
        return tablename(self._dxfname)

    def has_entry(self, name: str) -> bool:
        """ Check if an table-entry 'name' exists. """
        key = self.key(name)
        return any(self.key(entry) == key for entry in self)

    __contains__ = has_entry

    def new(self, name: str, dxfattribs: dict = None) -> 'DXFEntity':
        if self.has_entry(name):
            raise DXFTableEntryError('%s %s already exists!' % (self._dxfname, name))
        dxfattribs = dxfattribs or {}
        dxfattribs['name'] = name
        return self.new_entry(dxfattribs)

    def get(self, name: str) -> 'DXFEntity':
        """ Get table-entry by name as WrapperClass(). """
        key = self.key(name)
        for entry in iter(self):
            if self.key(entry) == key:
                return entry
        raise DXFTableEntryError(name)

    def remove(self, name: str) -> None:
        """ Remove table-entry from table and entitydb by name. """
        entry = self.get(name)
        handle = entry.dxf.handle
        self.remove_handle(handle)

    def __len__(self) -> int:
        return len(self._table_entries)

    def __iter__(self) -> Iterable['DXFEntity']:
        for handle in self._table_entries:
            yield self.get_table_entry_wrapper(handle)

    # end public interface

    def _build_table_entries(self, entities: Iterator[Tags]) -> None:
        table_head = next(entities)
        if table_head[0].value != 'TABLE':
            raise DXFStructureError("Critical structure error in TABLES section.")
        self._dxfname = table_head[1].value
        self._table_header = ExtendedTags(table_head)  # do not store the table head in the entity database
        for table_entry in entities:
            self._append_entry_handle(table_entry.get_handle())

    @property
    def entitydb(self) -> 'EntityDB':
        return self._drawing.entitydb

    @property
    def handles(self) -> 'HandleGenerator':
        return self._drawing.entitydb.handles

    @property
    def dxffactory(self) -> 'DXFFactoryType':
        return self._drawing.dxffactory

    def _iter_table_entries_as_tags(self) -> Iterable[ExtendedTags]:
        """ Iterate over table-entries as Tags(). """
        return (self.entitydb[handle] for handle in self._table_entries)

    def new_entry(self, dxfattribs: dict) -> 'DXFEntity':
        """ Create new table-entry of type 'self._dxfname', and add new entry
        to table.

        Does not check if an entry dxfattribs['name'] already exists!
        Duplicate entries are possible for Viewports.
        """
        handle = self.handles.next()
        entry = self.dxffactory.new_entity(self._dxfname, handle, dxfattribs)
        self._add_entry(entry)
        return entry

    def duplicate_entry(self, name: str, new_name: str) -> 'DXFEntity':
        entry = self.get(name)
        xtags = self.entitydb.duplicate_tags(entry.tags)
        new_entity = self.dxffactory.wrap_entity(xtags)
        new_entity.dxf.name = new_name
        self._add_entry(new_entity)
        return new_entity

    def _add_entry(self, entry: Union[ExtendedTags, 'DXFEntity']) -> None:
        """ Add table-entry to table and entitydb. """
        if isinstance(entry, ExtendedTags):
            tags = entry
        else:
            tags = entry.tags
        handle = self.entitydb.add_tags(tags)
        self._append_entry_handle(handle)

    def _append_entry_handle(self, handle: str) -> None:
        if handle not in self._table_entries:
            self._table_entries.append(handle)

    def get_table_entry_wrapper(self, handle: str) -> 'DXFEntity':
        tags = self.entitydb[handle]
        return self.dxffactory.wrap_entity(tags)

    def write(self, tagwriter: 'TagWriter') -> None:
        """ Write DXF representation to stream, stream opened with mode='wt'. """

        def prologue():
            self._update_owner_handles()
            self._update_meta_data()
            tagwriter.write_tags(self._table_header)

        def content():
            for tags in self._iter_table_entries_as_tags():
                tagwriter.write_tags(tags)

        def epilogue():
            tagwriter.write_tag2(0, 'ENDTAB')

        prologue()
        content()
        epilogue()

    def _update_owner_handles(self) -> None:
        if self._drawing.dxfversion <= 'AC1009':
            return  # no owner handles
        owner_handle = self._table_header.get_handle()
        for entry in iter(self):
            if not entry.supports_dxf_attrib('owner'):
                raise DXFAttributeError(repr(entry))
            entry.dxf.owner = owner_handle

    def _update_meta_data(self) -> None:
        count = len(self)
        if self._drawing.dxfversion > 'AC1009':
            subclass = self._table_header.get_subclass('AcDbSymbolTable')
        else:
            subclass = self._table_header.noclass
        subclass.set_first(DXFTag(70, count))

    def remove_handle(self, handle: str) -> None:
        """ Remove table-entry from table and entitydb by handle. """
        self._table_entries.remove(handle)
        del self.entitydb[handle]

    def audit(self, auditor) -> None:
        """
        Checks for table entries with same key.
        """
        entries = sorted(self._table_entries, key=lambda e: self.key(e))
        prev_key = None
        for entry in entries:
            key = self.key(entry)
            if key == prev_key:
                auditor.add_error(
                    code=Error.DUPLICATE_TABLE_ENTRY_NAME,
                    message="Duplicate table entry name '{1}' in table {0}".format(self.name, entry.dxf.name),
                    dxf_entity=self,
                    data=key,
                )
            prev_key = key