Source code for ACG.VirtualInst

from ACG.VirtualObj import VirtualObj
from ACG.XY import XY

from typing import Optional, Tuple, Union
point_type = Union[float, int]
coord_type = Union[Tuple[point_type, point_type], XY]


[docs]class VirtualInst(VirtualObj): """ A class to enable movement/access of low level instances without directly accessing the master class """ edges = ('l', 'b', 'r', 't') vertices = ('ll', 'lr', 'ur', 'ul', 'c', 'cl', 'cb', 'cr', 'ct') valid_orientation = ('R0', 'MX', 'MY', 'R180') def __init__(self, master, origin=(0, 0), orient='R0', inst_name=None): VirtualObj.__init__(self) # Init internal properties self._origin = None self._orient = None # Init local variables self.master = master self.origin = origin self.orient = orient self.inst_name = inst_name self.loc = {} # Init locations self.export_locations() def __repr__(self): temp = 'VirtualInst(master={}, origin={}, orient={})' return temp.format(self.master.__class__.__name__, self.origin, self.orient) def __str__(self): temp = '{}:\n\torigin: {} \n\torient: {}' return temp.format(self.master.__class__.__name__, self.origin, self.orient) """ Properties """ @property def origin(self) -> XY: return self._origin @origin.setter def origin(self, xy: coord_type) -> None: self._origin = XY(xy) # feed it into XY class to check/condition input @property def orient(self) -> str: return self._orient @orient.setter def orient(self, value: str): if value in VirtualInst.valid_orientation: self._orient = value else: raise ValueError('{} is not a valid orientation'.format(value)) """ Utility Methods """
[docs] def export_locations(self) -> dict: """ Recursively shift all of the elements in the location dictionary """ self.loc = {} try: old_db = self.master.export_locations() except AttributeError: print(f"{self.master.__class__.__name__} is not an ACG class, and does not have a location dict") old_db = {} for key in old_db: # Iterate over all relevant locations in master if isinstance(old_db[key], list): # If its a list, init an empty list and iterate self.loc[key] = [] for elem in old_db[key]: self.loc[key].append(elem.shift_origin(origin=self.origin, orient=self.orient)) elif old_db[key] is None: print('{} is not a valid location object'.format(key)) print(old_db[key]) else: # If its not a list self.loc[key] = old_db[key].shift_origin(origin=self.origin, orient=self.orient) return self.loc
[docs] def move(self, origin=None, orient=None) -> 'VirtualInst': """ Set the origin and orientation to new values """ if origin is not None: self.origin = origin if orient is not None: self.orient = orient # Update locations self.export_locations() return self
[docs] def shift_origin(self, origin=None, orient=None) -> 'VirtualInst': """ Moves the instance origin to the provided coordinates and performs transformation""" if origin is not None: new_origin = self.origin + XY(origin) self.move(new_origin, orient) # Move the block else: self.move(origin) return self
[docs] def align(self, target_handle: str, target_rect: VirtualObj = None, ref_rect: VirtualObj = None, ref_handle: str = None, align_opt: Tuple[bool, bool] = (True, True), offset: coord_type = (0, 0) ) -> 'VirtualInst': """ Moves the instance to co-locate target rect handle and reference rect handle """ if target_rect is None: # If an explicit target is not provided, assume that the boundary should be used target_rect = self.loc['bnd'] if (target_handle in VirtualInst.edges) or (ref_handle in VirtualInst.edges): # If you provided an edge handle instead of a corner handle throw an error ValueError('Please use the align_edge method to align edges') if (ref_rect is not None) and (ref_handle in ref_rect.loc): # if a reference rectangle and handle are provided diff = target_rect.loc[target_handle] - ref_rect.loc[ref_handle] diff -= XY(offset) else: # otherwise align only to offset coordinates diff = target_rect.loc[target_handle] - XY(offset) # if the corresponding align opt is true, shift the origin appropriately if align_opt[0]: self.origin.x -= diff.x if align_opt[1]: self.origin.y -= diff.y # Update locations self.export_locations() return self