123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- # Purpose: entity section
- # Created: 13.03.2011
- # Copyright (c) 2011-2018, Manfred Moitzi
- # License: MIT License
- from typing import TYPE_CHECKING, Iterable, Tuple, cast
- import logging
- from ezdxf.modern.dxfdict import DXFDictionary
- from ezdxf.lldxf.const import DXFStructureError, DXFValueError, RASTER_UNITS, DXFKeyError
- from ezdxf.modern.dxfgroups import GroupManager
- from ezdxf.modern.material import MaterialManager
- from ezdxf.modern.mleader import MLeaderStyleManager
- from ezdxf.modern.mline import MLineStyleManager
- from ezdxf.modern.tablestyle import TableStyleManager
- from ezdxf.entityspace import EntitySpace
- from .abstract import AbstractSection
- if TYPE_CHECKING:
- from ezdxf.eztypes import Drawing, DXFEntity, GeoData
- logger = logging.getLogger('ezdxf')
- class ObjectsSection(AbstractSection):
- name = 'OBJECTS'
- def __init__(self, entities, drawing: 'Drawing'):
- entity_space = EntitySpace(drawing.entitydb)
- super(ObjectsSection, self).__init__(entity_space, entities, drawing)
- def __iter__(self) -> Iterable['DXFEntity']:
- for handle in self._entity_space:
- yield self.dxffactory.wrap_handle(handle)
- @property
- def roothandle(self) -> str:
- return self._entity_space[0]
- @property
- def rootdict(self) -> DXFDictionary:
- if len(self):
- return self.dxffactory.wrap_entity(self.entitydb[self.roothandle])
- else:
- return self.setup_rootdict()
- def setup_rootdict(self) -> DXFDictionary:
- """
- Create a root dictionary. Has to be the first object in the objects section.
- """
- if len(self):
- raise DXFStructureError("Can not create root dictionary in none empty objects section.")
- logger.debug('Creating ROOT dictionary.')
- # root directory has no owner
- return self.add_dictionary(owner='0')
- def setup_objects_management_tables(self, rootdict: DXFDictionary) -> None:
- def setup_plot_style_name_table():
- plot_style_name_dict = self.add_dictionary_with_default(owner=rootdict.dxf.handle)
- plot_style_name_dict_handle = plot_style_name_dict.dxf.handle
- placeholder = self.add_placeholder(owner=plot_style_name_dict_handle)
- placeholder_handle = placeholder.dxf.handle
- plot_style_name_dict.dxf.default = placeholder_handle
- plot_style_name_dict['Normal'] = placeholder_handle
- rootdict['ACAD_PLOTSTYLENAME'] = plot_style_name_dict_handle
- for name in _OBJECT_TABLE_NAMES:
- if name in rootdict:
- continue # just create not existing tables
- logger.info('creating {} dictionary'.format(name))
- if name == "ACAD_PLOTSTYLENAME":
- setup_plot_style_name_table()
- else:
- rootdict.add_new_dict(name)
- def add_dxf_object_with_reactor(self, dxftype: str, dxfattribs: dict) -> 'DXFEntity':
- dxfobject = self.create_new_dxf_entity(dxftype, dxfattribs)
- dxfobject.set_reactors([dxfattribs['owner']])
- return dxfobject
- def groups(self):
- return GroupManager(self.drawing)
- def materials(self):
- return MaterialManager(self.drawing)
- def mleader_styles(self):
- return MLeaderStyleManager(self.drawing)
- def mline_styles(self):
- return MLineStyleManager(self.drawing)
- def table_styles(self):
- return TableStyleManager(self.drawing)
- def add_dictionary(self, owner: str = '0') -> DXFDictionary:
- entity = self.create_new_dxf_entity('DICTIONARY', dxfattribs={'owner': owner})
- return cast(DXFDictionary, entity)
- def add_dictionary_with_default(self, owner='0', default="0") -> 'DXFDictionary':
- entity = self.create_new_dxf_entity('ACDBDICTIONARYWDFLT', dxfattribs={
- 'owner': owner,
- 'default': default,
- })
- return cast(DXFDictionary, entity)
- def add_xrecord(self, owner: str = '0') -> 'DXFEntity':
- return self.create_new_dxf_entity('XRECORD', dxfattribs={'owner': owner})
- def add_placeholder(self, owner: str = '0') -> 'DXFEntity':
- return self.create_new_dxf_entity('ACDBPLACEHOLDER', dxfattribs={'owner': owner})
- def set_raster_variables(self, frame: int = 0, quality: int = 1, units: str = 'm') -> None:
- units = RASTER_UNITS.get(units, 0)
- try:
- raster_vars = self.rootdict.get_entity('ACAD_IMAGE_VARS')
- except DXFKeyError:
- raster_vars = self.add_dxf_object_with_reactor('RASTERVARIABLES', dxfattribs={
- 'owner': self.rootdict.dxf.handle,
- 'frame': frame,
- 'quality': quality,
- 'units': units,
- })
- self.rootdict['ACAD_IMAGE_VARS'] = raster_vars.dxf.handle
- else:
- raster_vars.dxf.frame = frame
- raster_vars.dxf.quality = quality
- raster_vars.dxf.units = units
- def set_wipeout_variables(self, frame: int = 0) -> None:
- try:
- wipeout_vars = self.rootdict.get_entity('ACAD_WIPEOUT_VARS')
- except DXFKeyError:
- wipeout_vars = self.add_dxf_object_with_reactor('WIPEOUTVARIABLES', dxfattribs={
- 'owner': self.rootdict.dxf.handle,
- 'frame': int(frame),
- })
- self.rootdict['ACAD_WIPEOUT_VARS'] = wipeout_vars.dxf.handle
- else:
- wipeout_vars.dxf.frame = int(frame)
- def add_image_def(self, filename: str, size_in_pixel: Tuple[int, int], name=None) -> 'DXFEntity':
- # removed auto-generated name
- # use absolute image paths for filename and AutoCAD loads images automatically
- if name is None:
- name = filename
- image_dict = self.rootdict.get_required_dict('ACAD_IMAGE_DICT')
- image_def = self.add_dxf_object_with_reactor('IMAGEDEF', dxfattribs={
- 'owner': image_dict.dxf.handle,
- 'filename': filename,
- 'image_size': size_in_pixel,
- })
- image_dict[name] = image_def.dxf.handle
- return image_def
- def add_image_def_reactor(self, image_handle: str) -> 'DXFEntity':
- return self.create_new_dxf_entity('IMAGEDEF_REACTOR', dxfattribs={
- 'owner': image_handle,
- 'image': image_handle,
- })
- def add_underlay_def(self, filename: str, format: str = 'pdf', name: str = None) -> 'DXFEntity':
- fmt = format.upper()
- if fmt in ('PDF', 'DWF', 'DGN'):
- underlay_dict_name = 'ACAD_{}DEFINITIONS'.format(fmt)
- underlay_def_entity = "{}DEFINITION".format(fmt)
- else:
- raise DXFValueError("Unsupported file format: '{}'".format(fmt))
- if name is None:
- if fmt == 'PDF':
- name = '1' # Display first page by default
- elif fmt == 'DGN':
- name = 'default'
- else:
- name = 'Model' # Display model space for DWF ???
- underlay_dict = self.rootdict.get_required_dict(underlay_dict_name)
- underlay_def = self.create_new_dxf_entity(underlay_def_entity, dxfattribs={
- 'owner': underlay_dict.dxf.handle,
- 'filename': filename,
- 'name': name,
- })
- # auto-generated underlay key
- key = self.dxffactory.next_underlay_key(lambda k: k not in underlay_dict)
- underlay_dict[key] = underlay_def.dxf.handle
- return underlay_def
- def add_geodata(self, owner: str = '0', dxfattribs: dict = None) -> 'GeoData':
- if dxfattribs is None:
- dxfattribs = {}
- dxfattribs['owner'] = owner
- return cast('GeoData', self.add_dxf_object_with_reactor('GEODATA', dxfattribs))
- _OBJECT_TABLE_NAMES = [
- "ACAD_COLOR",
- "ACAD_GROUP",
- "ACAD_LAYOUT",
- "ACAD_MATERIAL",
- "ACAD_MLEADERSTYLE",
- "ACAD_MLINESTYLE",
- "ACAD_PLOTSETTINGS",
- "ACAD_PLOTSTYLENAME",
- "ACAD_SCALELIST",
- "ACAD_TABLESTYLE",
- "ACAD_VISUALSTYLE",
- ]
|