123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- # Purpose: database module
- # Created: 11.03.2011
- # Copyright (c) 2011-2018, Manfred Moitzi
- # License: MIT License
- from typing import Optional, Iterable, Tuple
- from ezdxf.tools.handle import HandleGenerator
- from ezdxf.lldxf.const import DXFValueError
- from ezdxf.lldxf.tags import DXFTag
- from ezdxf.lldxf.extendedtags import ExtendedTags
- from ezdxf.dxfentity import DXFEntity
- class EntityDB:
- """ A simple key/value database a.k.a. dict(), but can be replaced by other
- classes that implements all of the methods of `EntityDB`. The entities
- have no order.
- The Data Model
- Every entity/object, except tables and sections, are represented as
- tag-list (see ExtendedTags Class), this lists are stored in the drawing-associated
- database, database-key is the 'handle' tag (code == 5 or 105).
- For the entity/object manipulation this tag-list will be wrapped into
- separated classes, which are generated by the dxffactory-object.
- The dxffactory-object generates DXF-Version specific wrapper classes.
- """
- def __init__(self):
- self._database = {}
- self.handles = HandleGenerator()
- def __delitem__(self, handle: str) -> None:
- del self._database[handle]
- def __getitem__(self, handle: str) -> ExtendedTags:
- return self._database[handle]
- def get(self, handle: str) -> Optional[ExtendedTags]:
- try:
- return self.__getitem__(handle)
- except KeyError: # internal exception
- return None
- def __setitem__(self, handle: str, tags: ExtendedTags) -> None:
- self._database[handle] = tags
- def __contains__(self, handle: str) -> bool:
- """ Database contains handle? """
- return handle in self._database
- def __len__(self) -> int:
- """ Count of database items. """
- return len(self._database)
- def __iter__(self) -> Iterable[str]:
- """ Iterate over all handles. """
- return iter(self._database.keys())
- def keys(self) -> Iterable[str]:
- """ Iterate over all handles. """
- return self._database.keys()
- def values(self) -> Iterable[ExtendedTags]:
- """ Iterate over all entities. """
- return self._database.values()
- def items(self) -> Iterable[Tuple[str, ExtendedTags]]:
- """ Iterate over all (handle, entities) pairs. """
- return self._database.items()
- def add_tags(self, tags: ExtendedTags) -> str:
- try:
- handle = tags.get_handle()
- except DXFValueError: # create new handle
- handle = self.get_unique_handle()
- handle_code = 105 if tags.dxftype() == 'DIMSTYLE' else 5 # legacy shit!!!
- tags.noclass.insert(1, DXFTag(handle_code, handle)) # handle should be the 2. tag
- self.__setitem__(handle, tags)
- return handle
- def delete_entity(self, entity: DXFEntity) -> None:
- entity.destroy()
- self.delete_handle(entity.dxf.handle)
- def delete_handle(self, handle: str) -> None:
- del self._database[handle]
- def get_unique_handle(self)-> str:
- while True:
- handle = self.handles.next()
- if handle not in self._database: # you can not trust $HANDSEED value
- return handle
- def duplicate_tags(self, tags: ExtendedTags) -> ExtendedTags:
- """
- Deep copy of tags with new handle and duplicated linked entities (VERTEX, ATTRIB, SEQEND) with also new handles.
- An existing owner tag is not changed because this is not the domain of the EntityDB() class.
- The new entity tags are added to the drawing database.
- This is not a deep copy in the meaning of Python, because handle and link is changed.
-
- """
- new_tags = tags.clone()
- new_tags.noclass.replace_handle(self.get_unique_handle()) # set new handle
- self.add_tags(new_tags) # add new tags to database
- source_link = tags.link # follow link structure of original entity
- parent_copy = new_tags
- while source_link is not None: # duplicate linked entities (VERTEX, ATTRIB, SEQEND)
- source_linked_entity = self.get(source_link) # extended tags
- linked_entity_copy = source_linked_entity.clone()
- new_handle = self.get_unique_handle()
- linked_entity_copy.noclass.replace_handle(new_handle) # set new handle
- self.add_tags(linked_entity_copy) # add new tags to database
- parent_copy.link = new_handle
- source_link = source_linked_entity.link # follow link structure of original entity
- parent_copy = linked_entity_copy
- return new_tags
|