Exemple #1
0
 def link_entities() -> Iterable['DXFEntity']:
     linked = entity_linker()
     for entity in entities:
         if not linked(
                 entity
         ):  # don't store linked entities (VERTEX, ATTRIB, SEQEND) in block layout
             yield entity
Exemple #2
0
    def modelspace(self, types: Iterable[str] = None) -> Iterable[DXFGraphic]:
        """

        Returns an iterator for all supported DXF entities in the modelspace. These entities are regular
        :class:`~ezdxf.entities.DXFGraphic` objects but without a valid document assigned. It is **not**
        possible to add these entities to other `ezdxf` documents.

        It is only possible to recreate the objects by factory functions base on attributes of the source entity.
        For MESH, POLYMESH and POLYFACE it is possible to use the :class:`~ezdxf.render.MeshTransformer` class to
        render (recreate) this objects as new entities in another document.

        Args:
            types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types.

        """
        linked_entity = entity_linker()
        queued = None
        requested_types = _requested_types(types)
        for entity in self.load_entities(self.sections['ENTITIES'] + 1, requested_types):
            if not linked_entity(entity) and entity.dxf.paperspace == 0:
                if queued:  # queue one entity for collecting linked entities (VERTEX, ATTRIB)
                    yield queued
                queued = entity
        if queued:
            yield queued
Exemple #3
0
    def _build(self, entities: Iterator['DXFEntity']) -> None:
        section_head = next(entities)  # type: DXFTagStorage
        if section_head.dxftype(
        ) != 'SECTION' or section_head.base_class[1] != (2, 'ENTITIES'):
            raise DXFStructureError(
                "Critical structure error in ENTITIES section.")

        def add(entity: 'DXFGraphic'):
            handle = entity.dxf.owner
            # higher priority for owner handle
            if handle == msp_layout_key:
                paperspace = 0
            elif handle == psp_layout_key:
                paperspace = 1
            else:  # paperspace flag as fallback
                paperspace = entity.dxf.paperspace

            if paperspace:
                psp.add_entity(entity)
            else:
                msp.add_entity(entity)

        msp = self.doc.block_records.get('*Model_Space')  # type: BlockRecord
        psp = self.doc.block_records.get('*Paper_Space')  # type: BlockRecord
        msp_layout_key = msp.dxf.handle
        psp_layout_key = psp.dxf.handle
        linked_entities = entity_linker()
        for entity in entities:
            if not linked_entities(
                    entity
            ):  # don't store linked entities (VERTEX, ATTRIB, SEQEND) in entity space
                add(entity)
Exemple #4
0
 def link_entities() -> Iterable['DXFEntity']:
     linked = entity_linker()
     for entity in entities:
         # Do not store linked entities (VERTEX, ATTRIB, SEQEND) in
         # the block layout, linked entities ares stored in their
         # parent entity e.g. VERTEX -> POLYLINE:
         if not linked(entity):
             yield entity
Exemple #5
0
def modelspace(filename: str,
               types: Iterable[str] = None) -> Iterable[DXFGraphic]:
    """
    Iterate over all modelspace entities as :class:`DXFGraphic` objects of a seekable file.

    Use this function to 'quick' iterate over modelspace entities of a DXF file,
    filtering DXF types may speed up things if many entity types will be skipped.

    Args:
        filename: filename of a seekable DXF file
        types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types.

    """
    info = dxf_file_info(filename)
    prev_code: int = -1
    prev_value: str = ''
    entities = False
    requested_types = _requested_types(types)

    with open(filename, mode='rt', encoding=info.encoding) as fp:
        tagger = low_level_tagger(fp)
        queued: Optional[DXFEntity] = None
        tags: List[DXFTag] = []
        factory = EntityFactory()
        linked_entity = entity_linker()
        for tag in tag_compiler(tagger):
            code = tag.code
            value = tag.value
            if entities:
                if code == 0 and value == 'ENDSEC':
                    if queued:
                        yield queued
                    return
                if code == 0:
                    if len(tags) and tags[0].value in requested_types:
                        entity = factory.entity(ExtendedTags(tags))
                        if not linked_entity(
                                entity) and entity.dxf.paperspace == 0:
                            if queued:  # queue one entity for collecting linked entities (VERTEX, ATTRIB)
                                yield queued
                            queued = entity
                    tags = [tag]
                else:
                    tags.append(tag)
                continue  # if entities - nothing else matters
            elif code == 2 and prev_code == 0 and prev_value == 'SECTION':
                entities = (value == 'ENTITIES')

            prev_code = code
            prev_value = value
Exemple #6
0
def single_pass_modelspace(stream: BinaryIO, types: Iterable[str] = None) -> Iterable[DXFGraphic]:
    """
    Iterate over all modelspace entities as :class:`DXFGraphic` objects in one single pass.

    Use this function to 'quick' iterate over modelspace entities of a **not** seekable binary DXF stream,
    filtering DXF types may speed up things if many entity types will be skipped.

    Args:
        stream: (not seekable) binary DXF stream
        types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types.

    """
    fetch_header_var: Optional[str] = None
    encoding = 'cp1252'
    version = 'AC1009'
    prev_code: int = -1
    prev_value: str = ''
    entities = False
    requested_types = _requested_types(types)

    for code, value in binary_tagger(stream):
        if code == 0 and value == b'ENDSEC':
            break
        elif code == 2 and prev_code == 0 and value != b'HEADER':
            # (0, SECTION), (2, name)
            # First section is not the HEADER section
            entities = (value == b'ENTITIES')
            break
        elif code == 9 and value == b'$DWGCODEPAGE':
            fetch_header_var = 'ENCODING'
        elif code == 9 and value == b'$ACADVER':
            fetch_header_var = 'VERSION'
        elif fetch_header_var == 'ENCODING':
            encoding = toencoding(value.decode())
            fetch_header_var = None
        elif fetch_header_var == 'VERSION':
            version = value.decode()
            fetch_header_var = None
        prev_code = code

    if version >= 'AC1021':
        encoding = 'utf-8'

    queued: Optional[DXFEntity] = None
    tags: List[DXFTag] = []
    factory = EntityFactory()
    linked_entity = entity_linker()

    for tag in tag_compiler(binary_tagger(stream, encoding)):
        code = tag.code
        value = tag.value
        if entities:
            if code == 0 and value == 'ENDSEC':
                if queued:
                    yield queued
                return
            if code == 0:
                if len(tags) and tags[0].value in requested_types:
                    entity = factory.entity(ExtendedTags(tags))
                    if not linked_entity(entity) and entity.dxf.paperspace == 0:
                        if queued:  # queue one entity for collecting linked entities (VERTEX, ATTRIB)
                            yield queued
                        queued = entity
                tags = [tag]
            else:
                tags.append(tag)
            continue  # if entities - nothing else matters
        elif code == 2 and prev_code == 0 and prev_value == 'SECTION':
            entities = (value == 'ENTITIES')

        prev_code = code
        prev_value = value