def set_arrows(self, blk: str = '', blk1: str = '', blk2: str = '', ldrblk: str = '') -> None: """ Set arrows by block names or AutoCAD standard arrow names, set DIMTSZ to ``0`` which disables tick. Args: blk: block/arrow name for both arrows, if DIMSAH is ``0`` blk1: block/arrow name for first arrow, if DIMSAH is ``1`` blk2: block/arrow name for second arrow, if DIMSAH is ``1`` ldrblk: block/arrow name for leader """ self.set_dxf_attrib('dimblk', blk) self.set_dxf_attrib('dimblk1', blk1) self.set_dxf_attrib('dimblk2', blk2) self.set_dxf_attrib('dimldrblk', ldrblk) self.set_dxf_attrib('dimtsz', 0) # use blocks # only existing BLOCK definitions allowed if self.doc: blocks = self.doc.blocks for b in (blk, blk1, blk2, ldrblk): if ARROWS.is_acad_arrow(b): # not real blocks ARROWS.create_block(blocks, b) continue if b and b not in blocks: raise DXFValueError( 'BLOCK "{}" does not exist.'.format(blk))
def add_dimension_line(self, start: 'Vertex', end: 'Vertex') -> None: """ Add dimension line to dimension BLOCK, adds extension DIMDLE if required, and uses DIMSD1 or DIMSD2 to suppress first or second part of dimension line. Removes line parts hidden by dimension text. Args: start: dimension line start end: dimension line end """ extension = self.dim_line_vec * self.dim_line_extension if self.arrow1_name is None or ARROWS.has_extension_line(self.arrow1_name): start = start - extension if self.arrow2_name is None or ARROWS.has_extension_line(self.arrow2_name): end = end + extension attribs = self.dim_line_attributes() if self.suppress_dim1_line or self.suppress_dim2_line: # TODO: results not as expected, but good enough # center should take into account text location center = start.lerp(end) if not self.suppress_dim1_line: self.add_line(start, center, dxfattribs=attribs, remove_hidden_lines=True) if not self.suppress_dim2_line: self.add_line(center, end, dxfattribs=attribs, remove_hidden_lines=True) else: self.add_line(start, end, dxfattribs=attribs, remove_hidden_lines=True)
def acquire_arrow(self, name: str): """ For standard AutoCAD and ezdxf arrows create block definitions if required, otherwise check if block `name` exist. (internal API) """ from ezdxf.render.arrows import ARROWS if ARROWS.is_acad_arrow(name) or ARROWS.is_ezdxf_arrow(name): ARROWS.create_block(self.blocks, name) elif name not in self.blocks: raise const.DXFValueError(f'Arrow block "{name}" does not exist.')
def create_all_arrow_blocks(self): """ For upgrading DXF R12/13/14 files to R2000, it is necessary to create all used arrow blocks before saving the DXF file, else $HANDSEED is not the next available handle, which is a problem for AutoCAD. To be save create all known AutoCAD arrows, because references to arrow blocks can be in DIMSTYLE, DIMENSION override, LEADER override and maybe other places. """ from ezdxf.render.arrows import ARROWS for arrow_name in ARROWS.__acad__: ARROWS.create_block(self.blocks, arrow_name)
def is_special_block(name: str) -> bool: name = name.upper() # Anonymous dimension, groups and table blocks do not have explicit references by INSERT entity if name.startswith('*D') or name.startswith('*A') or name.startswith('*T'): return True # Arrow blocks maybe used in LEADER override without INSERT reference. if ARROWS.is_ezdxf_arrow(name): return True if name.startswith('_'): if ARROWS.is_acad_arrow(ARROWS.arrow_name(name)): return True return False
def set_arrows(self, blk: str = '', blk1: str = '', blk2: str = '') -> None: """ Set arrows by block names or AutoCAD standard arrow names, set dimtsz = 0 which disables tick. Args: blk: block/arrow name for both arrows, if dimsah == 0 blk1: block/arrow name for first arrow, if dimsah == 1 blk2: block/arrow name for second arrow, if dimsah == 1 """ self.set_dxf_attrib('dimblk', blk) self.set_dxf_attrib('dimblk1', blk1) self.set_dxf_attrib('dimblk2', blk2) self.set_dxf_attrib('dimtsz', 0) # use blocks # only existing BLOCK definitions allowed if self.drawing: blocks = self.drawing.blocks for b in (blk, blk1, blk2): if ARROWS.is_acad_arrow(b): # not real blocks continue if b and b not in blocks: raise DXFValueError( 'BLOCK "{}" does not exist.'.format(blk))
def is_special_block(name: str) -> bool: name = name.upper() # Anonymous dimension, groups and table blocks do not have explicit # references by an INSERT entity: if is_anonymous_block(name): return True # Arrow blocks maybe used in DIMENSION or LEADER override without an # INSERT reference: if ARROWS.is_ezdxf_arrow(name): return True if name.startswith('_'): if ARROWS.is_acad_arrow(ARROWS.arrow_name(name)): return True return False
def _get_arrow_block_name(self, name: str) -> str: handle = self.get_dxf_attrib(name, None) if handle in (None, '0'): # unset handle or handle '0' is default closed filled arrow return ARROWS.closed_filled else: block_name = get_block_name_by_handle(handle, self.drawing) return ARROWS.arrow_name(block_name) # if arrow return standard arrow name else just the block name
def _set_blk_handle(self, attr: str, arrow_name: str) -> None: if arrow_name == ARROWS.closed_filled: # special arrow, no handle needed (is '0' if set) # do not create block by default, this will be done if arrow is used # and block record handle is not needed here self.del_dxf_attrib(attr) return blocks = self.drawing.blocks if ARROWS.is_acad_arrow(arrow_name): # create block, because need block record handle is needed here block_name = ARROWS.create_block(blocks, arrow_name) else: block_name = arrow_name blk = blocks.get(block_name) self.set_dxf_attrib(attr, blk.block_record_handle)
def get_arrow_block_name(self, name: str) -> str: handle = self.get_dxf_attrib(name, None) if handle in (None, '0'): # unset handle or handle '0' is default closed filled arrow return ARROWS.closed_filled else: block_name = get_block_name_by_handle(handle, self.doc) # Returns standard arrow name or the user defined block name: return ARROWS.arrow_name(block_name)
def set_arrow_handle(attrib_name, block_name): attrib_name += '_handle' if block_name in ARROWS: # create all arrows on demand block_name = ARROWS.create_block(blocks, block_name) if block_name == '_CLOSEDFILLED': # special arrow handle = '0' # set special #0 handle for closed filled arrow else: block = blocks[block_name] handle = block.block_record_handle data[attrib_name] = handle
def get_arrow_block_name(self, name: str) -> str: assert self.doc is not None, "valid DXF document required" handle = self.get_dxf_attrib(name, None) if handle in (None, "0"): # unset handle or handle '0' is default closed filled arrow return ARROWS.closed_filled else: block_name = get_block_name_by_handle(handle, self.doc) # Returns standard arrow name or the user defined block name: return ARROWS.arrow_name(block_name)
def virtual_arrow(name: str, insert: Vector = Vector(), size: float = 0.625, rotation: float = 0, dxfattribs=None, doc=None): from ezdxf.graphicsfactory import VirtualLayout from ezdxf.render.arrows import ARROWS if name in ARROWS: layout = VirtualLayout(doc) dxfattribs = dxfattribs or {} ARROWS.render_arrow( layout, name, insert=insert, size=size, rotation=rotation, dxfattribs=dxfattribs, ) yield from layout.entities
def set_blk_handle(self, attr: str, arrow_name: str) -> None: if arrow_name == ARROWS.closed_filled: # special arrow, no handle needed (is '0' if set) # do not create block by default, this will be done if arrow is used # and block record handle is not needed here self.dxf.discard(attr) return blocks = self.doc.blocks if ARROWS.is_acad_arrow(arrow_name): # create block, because need block record handle is needed here block_name = ARROWS.create_block(blocks, arrow_name) else: block_name = arrow_name blk = blocks.get(block_name) if blk is not None: self.set_dxf_attrib(attr, blk.block_record_handle) else: raise DXFValueError(f'Block {arrow_name} does not exist.')
def _create_missing_arrows(self): """ Create or import required arrows, used by LEADER or DIMSTYLE, which are not imported automatically because they are not actually used in an anonymous DIMENSION blocks. """ self.used_arrows.discard('') # standard default arrow '' needs no block definition for arrow_name in self.used_arrows: if ARROWS.is_acad_arrow(arrow_name): self.target.acquire_arrow(arrow_name) else: self.import_block(arrow_name, rename=False)
def add_dimension_line(self, start: Vec2, end: Vec2) -> None: """Add dimension line to dimension BLOCK, adds extension DIMDLE if required, and uses DIMSD1 or DIMSD2 to suppress first or second part of dimension line. Removes line parts hidden by dimension text. Args: start: dimension line start end: dimension line end """ dim_line = self.dimension_line arrows = self.arrows extension = self.dim_line_vec * dim_line.extension ticks = arrows.has_ticks if ticks or ARROWS.has_extension_line(arrows.arrow1_name): start = start - extension if ticks or ARROWS.has_extension_line(arrows.arrow2_name): end = end + extension attribs = dim_line.dxfattribs() if dim_line.suppress1 or dim_line.suppress2: # TODO: results not as expected, but good enough # center should take into account text location center = start.lerp(end) if not dim_line.suppress1: self.add_line(start, center, dxfattribs=attribs, remove_hidden_lines=True) if not dim_line.suppress2: self.add_line(center, end, dxfattribs=attribs, remove_hidden_lines=True) else: self.add_line(start, end, dxfattribs=attribs, remove_hidden_lines=True)
def test_arrow_name(): assert ARROWS.arrow_name('_CLOSEDFILLED') == '' assert ARROWS.arrow_name('') == '' assert ARROWS.arrow_name('_DOTSMALL') == 'DOTSMALL' assert ARROWS.arrow_name('_boxBlank') == 'BOXBLANK' assert ARROWS.arrow_name('EZ_ARROW') == 'EZ_ARROW' assert ARROWS.arrow_name('abcdef') == 'abcdef'
def test_arrow_name(): assert ARROWS.arrow_name("_CLOSEDFILLED") == "" assert ARROWS.arrow_name("") == "" assert ARROWS.arrow_name("_DOTSMALL") == "DOTSMALL" assert ARROWS.arrow_name("_boxBlank") == "BOXBLANK" assert ARROWS.arrow_name("EZ_ARROW") == "EZ_ARROW" assert ARROWS.arrow_name("abcdef") == "abcdef"
def set_arrow_name(attrib_name: str, handle: str): if handle == '0': # special handle for default arrow CLOSEDFILLED data[attrib_name] = '' # special name for default arrow CLOSEDFILLED return try: block_record = db[handle] except KeyError: logger.info( 'Required arrow block #{} does not exist, ignoring {} override.'.format(handle, attrib_name.upper()) ) return name = block_record.dxf.name if name.startswith('_'): # translate block name into ACAD standard name _OPEN30 -> OPEN30 acad_arrow_name = name[1:] if ARROWS.is_acad_arrow(acad_arrow_name): name = acad_arrow_name data[attrib_name] = name
def set_arrow_name(attrib_name: str, handle: str): # Special handle for default arrow CLOSEDFILLED: if handle == '0': # Special name for default arrow CLOSEDFILLED: data[attrib_name] = '' return try: block_record = db[handle] except KeyError: logger.info(f'Required arrow block #{handle} does not exist, ' f'ignoring {attrib_name.upper()} override.') return name = block_record.dxf.name # Translate block name into ACAD standard name _OPEN30 -> OPEN30 if name.startswith('_'): acad_arrow_name = name[1:] if ARROWS.is_acad_arrow(acad_arrow_name): name = acad_arrow_name data[attrib_name] = name
def test_virtual_entities(): entities = list(ARROWS.virtual_entities(ARROWS.closed, insert=(0, 0, 0))) assert len(entities) > 0
def add_arrow_blockref(self, name: str, insert: 'Vertex', size: float = 1., rotation: float = 0, dxfattribs: dict = None) -> Vector: return ARROWS.insert_arrow(self, name=name, insert=insert, size=size, rotation=rotation, dxfattribs=dxfattribs)
def test_closed_arrow_r2000(dxf2000): blocks = dxf2000.blocks name = ARROWS.create_block(blocks, ARROWS.closed) arrow_entities = list(blocks.get(name)) assert arrow_entities[0].dxftype() == 'LWPOLYLINE'
def test_render_to_virtual_layout(): from ezdxf.graphicsfactory import VirtualLayout layout = VirtualLayout() ARROWS.render_arrow(layout, ARROWS.closed, insert=(0, 0, 0)) assert len(layout.entities) > 0
def test_filled_solid_arrow(): # special name: no name "" assert "" in ARROWS ARROWS.is_acad_arrow("")
def test_render_arrow(): layout = VirtualLayout() ARROWS.render_arrow(layout, ARROWS.closed, insert=(0, 0, 0)) assert len(layout) > 0
def test_closed_arrow_doc_r2000(): doc = ezdxf.new(dxfversion="R2000", setup=True) blocks = doc.blocks name = ARROWS.create_block(blocks, ARROWS.closed) arrow_entities = list(blocks.get(name)) assert arrow_entities[0].dxftype() == "LWPOLYLINE"