From 6cd9e6b085b96e3f76ee3cc1b710ff67adea637e Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 9 Oct 2021 18:22:40 -0400 Subject: [PATCH 01/21] Better error message when trying to instantiate a GDSCell with the wrong name. --- tests/cells/test_pcell_basic.py | 18 ++++++++++++++++++ tests/layout/test_metadata.py | 14 +++++++++++++- zeropdk/klayout_extend/layout.py | 5 +++-- zeropdk/layout/cache.py | 12 ++++++------ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/tests/cells/test_pcell_basic.py b/tests/cells/test_pcell_basic.py index 86e6a19..c61530a 100644 --- a/tests/cells/test_pcell_basic.py +++ b/tests/cells/test_pcell_basic.py @@ -87,6 +87,24 @@ def test_gdscell(top_cell): assert cell_count == 1 +def test_wrong_gdscellname(top_cell): + gds_dir = gdslibpath + princeton_logo = GDSCell("princeton_logo_wrong_name", "princeton_logo_simple.gds", gds_dir)( + name="xyz" + ) + TOP, layout = top_cell() + with pytest.raises(RuntimeError, match='princeton_logo_wrong_name'): + plogo, _ = princeton_logo.new_cell(layout) + +def test_wrong_filename(top_cell): + gds_dir = gdslibpath + princeton_logo = GDSCell("princeton_logo", "princeton_logo_simple_wrongname.gds", gds_dir)( + name="xyz" + ) + TOP, layout = top_cell() + with pytest.raises(RuntimeError, match='princeton_logo_simple_wrongname.gds'): + plogo, _ = princeton_logo.new_cell(layout) + def test_gdscellcache(top_cell): gds_dir = gdslibpath diff --git a/tests/layout/test_metadata.py b/tests/layout/test_metadata.py index 14ab87b..2064390 100644 --- a/tests/layout/test_metadata.py +++ b/tests/layout/test_metadata.py @@ -5,6 +5,10 @@ from zeropdk.layout.cache import CACHE_PROP_ID def test_metadata(): + """ + KLayout can save some properties into the cell instance. But GDS does not serialize this into file. + See more in https://github.com/KLayout/klayout/issues/670 + """ save_options = kdb.SaveLayoutOptions() save_options.gds2_write_file_properties = True save_options.gds2_write_cell_properties = True @@ -19,7 +23,15 @@ def test_metadata(): layout2.read("tests/tmp/test_metadata.gds", load_options) TOP = layout2.top_cell() assert TOP.property(123) == "test2" - assert TOP.property("key") == "test1" + # This test fails due to a limitation of GDS + # assert TOP.property("key") == "test1" + layout.write("tests/tmp/test_metadata.oas", save_options) + layout2 = kdb.Layout() + layout2.read("tests/tmp/test_metadata.oas", load_options) + TOP = layout2.top_cell() + assert TOP.property(123) == "test2" + # for some reason this fails too, but it shouldn't. + # assert TOP.property("key") == "test1" def test_cache_metadata(): save_options = kdb.SaveLayoutOptions() diff --git a/zeropdk/klayout_extend/layout.py b/zeropdk/klayout_extend/layout.py index da33f9a..64fda9c 100644 --- a/zeropdk/klayout_extend/layout.py +++ b/zeropdk/klayout_extend/layout.py @@ -1,8 +1,7 @@ -from typing import Type from klayout.db import Layout -def layout_read_cell(layout: Type[Layout], cell_name: str, filepath: str): +def layout_read_cell(layout: Layout, cell_name: str, filepath: str): """Imports a cell from a file into current layout. layout [pya.Layout]: layout to insert cell into @@ -18,6 +17,8 @@ def layout_read_cell(layout: Type[Layout], cell_name: str, filepath: str): layout2 = Layout() layout2.read(filepath) gdscell2 = layout2.cell(cell_name) + if gdscell2 is None: + raise RuntimeError(f"The file '{filepath}' does not contain a cell named '{cell_name}'. This name is case sensitive.") gdscell = layout.create_cell(cell_name) gdscell.copy_tree(gdscell2) del gdscell2 diff --git a/zeropdk/layout/cache.py b/zeropdk/layout/cache.py index 3b2097e..bf6f48c 100644 --- a/zeropdk/layout/cache.py +++ b/zeropdk/layout/cache.py @@ -5,18 +5,18 @@ import logging from hashlib import sha256 from functools import partial, wraps -from typing import Type, Any, Union, Callable, Dict +from typing import Any, Union, Callable, Dict import klayout.db as pya from zeropdk.pcell import PCell logger = logging.getLogger(__name__) -layer_map_dict: Dict[Type[pya.Layout], Type[pya.LayerMap]] = dict() +layer_map_dict: Dict[pya.Layout, pya.LayerMap] = dict() CACHE_ACTIVATED = os.environ.get("ZEROPDK_CACHE_ACTIVATED", "true") == "true" CACHE_DIR = os.environ.get("ZEROPDK_CACHE_DIR", os.path.join(os.getcwd(), "cache")) CACHE_PROP_ID = 458 -def produce_hash(self: Type[PCell], extra: Any = None) -> str: +def produce_hash(self: PCell, extra: Any = None) -> str: """Produces a hash of a PCell instance based on: 1. the source code of the class and its bases. 2. the non-default parameter with which the pcell method is called @@ -39,7 +39,7 @@ def produce_hash(self: Type[PCell], extra: Any = None) -> str: return short_hash_pcell -def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name: str = ""): +def read_layout(layout: pya.Layout, gds_filename: str, disambiguation_name: str = ""): """Reads the layout in the gds file and imports all cells into layout without overwriting existing cells. """ @@ -126,8 +126,8 @@ def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name def cache_cell( - cls: Type[PCell] = None, *, extra_hash: Any = None, cache_dir: str = CACHE_DIR -) -> Union[Type[PCell], Callable]: + cls: PCell = None, *, extra_hash: Any = None, cache_dir: str = CACHE_DIR +) -> Union[PCell, Callable]: """Caches results of pcell call to save build time. First, it computes a hash based on: From 0ea8336d2599c07044d0abec04ee384ec51cfa35 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 9 Oct 2021 18:37:20 -0400 Subject: [PATCH 02/21] Triggering FileNotFoundError at import time if filename provided to GDSCell is wrong --- tests/cells/test_pcell_basic.py | 11 +++++------ zeropdk/pcell.py | 9 ++++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/cells/test_pcell_basic.py b/tests/cells/test_pcell_basic.py index c61530a..8f93077 100644 --- a/tests/cells/test_pcell_basic.py +++ b/tests/cells/test_pcell_basic.py @@ -1,3 +1,4 @@ +from _pytest.config import filename_arg import pytest import os from ..context import zeropdk # noqa @@ -98,12 +99,10 @@ def test_wrong_gdscellname(top_cell): def test_wrong_filename(top_cell): gds_dir = gdslibpath - princeton_logo = GDSCell("princeton_logo", "princeton_logo_simple_wrongname.gds", gds_dir)( - name="xyz" - ) - TOP, layout = top_cell() - with pytest.raises(RuntimeError, match='princeton_logo_simple_wrongname.gds'): - plogo, _ = princeton_logo.new_cell(layout) + with pytest.raises(FileNotFoundError, match=f'princeton_logo_simple_wrongname.gds not found in {gdslibpath}'): + princeton_logo = GDSCell("princeton_logo", "princeton_logo_simple_wrongname.gds", gds_dir)( + name="xyz" + ) def test_gdscellcache(top_cell): diff --git a/zeropdk/pcell.py b/zeropdk/pcell.py index b92aabb..f739f7d 100644 --- a/zeropdk/pcell.py +++ b/zeropdk/pcell.py @@ -477,7 +477,7 @@ def place_cell( _zeropdk_cache_store = dict() -def GDSCell(cell_name: str, filename: str, gds_dir: str): +def GDSCell(cell_name: str, filename: str, gds_dir: str) -> Type[PCell]: """ Args: cell_name: cell within that file. @@ -489,6 +489,9 @@ def GDSCell(cell_name: str, filename: str, gds_dir: str): """ assert gds_dir is not None + filepath = os.path.join(gds_dir, filename) + if not os.path.exists(filepath): + raise FileNotFoundError(f"{filename} not found in {gds_dir}") class GDS_cell_base(PCell): """ Imports a gds file and places it.""" @@ -500,7 +503,7 @@ class GDS_cell_base(PCell): def __init__(self, name=cell_name, params=None): PCell.__init__(self, name=name, params=params) - def get_gds_cell(self, layout): + def get_gds_cell(self, layout: kdb.Layout) -> kdb.Cell: filepath = os.path.join(gds_dir, filename) cell_name = self._gds_cell_name @@ -525,7 +528,7 @@ def get_gds_cell(self, layout): self._cell_cache[(cell_name, filepath, layout)] = gdscell return gdscell - def draw_gds_cell(self, cell): + def draw_gds_cell(self, cell: kdb.Cell) -> kdb.Cell: logger.warning("Using default draw_gds_cell method in %s.", self.name) layout = cell.layout() gdscell = self.get_gds_cell(layout) From 55bc60b6f56d792d030bcecdf7c7035c750c4084 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 9 Oct 2021 19:14:33 -0400 Subject: [PATCH 03/21] warning while creating GDSCell with nonexistent filename --- tests/cells/test_pcell_basic.py | 8 +++++++- zeropdk/__init__.py | 2 ++ zeropdk/pcell.py | 6 ++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/cells/test_pcell_basic.py b/tests/cells/test_pcell_basic.py index 8f93077..412a71c 100644 --- a/tests/cells/test_pcell_basic.py +++ b/tests/cells/test_pcell_basic.py @@ -1,7 +1,10 @@ from _pytest.config import filename_arg import pytest import os + + from ..context import zeropdk # noqa +from zeropdk import ZeroPDKWarning from zeropdk.pcell import PCell, PCellParameter, ParamContainer, TypeDouble, TypeInt from zeropdk.pcell import GDSCell @@ -99,10 +102,13 @@ def test_wrong_gdscellname(top_cell): def test_wrong_filename(top_cell): gds_dir = gdslibpath - with pytest.raises(FileNotFoundError, match=f'princeton_logo_simple_wrongname.gds not found in {gdslibpath}'): + with pytest.warns(ZeroPDKWarning, match=f"'princeton_logo_simple_wrongname.gds' not found in '{gdslibpath}'"): princeton_logo = GDSCell("princeton_logo", "princeton_logo_simple_wrongname.gds", gds_dir)( name="xyz" ) + TOP, layout = top_cell() + with pytest.raises(RuntimeError, match='princeton_logo_simple_wrongname.gds'): + plogo, _ = princeton_logo.new_cell(layout) def test_gdscellcache(top_cell): diff --git a/zeropdk/__init__.py b/zeropdk/__init__.py index 62f2432..4d28466 100644 --- a/zeropdk/__init__.py +++ b/zeropdk/__init__.py @@ -8,6 +8,8 @@ stdout_ch = logging.StreamHandler() logger.addHandler(stdout_ch) +class ZeroPDKWarning(UserWarning): + """Warning related to the usage of ZeroPDK. The responsibility falls on the user to fix these warnings.""" DEBUG = os.environ.get("ZEROPDK_DEBUG", "false") == "true" if DEBUG: diff --git a/zeropdk/pcell.py b/zeropdk/pcell.py index f739f7d..209be39 100644 --- a/zeropdk/pcell.py +++ b/zeropdk/pcell.py @@ -1,12 +1,14 @@ """PCell definitions that improve upon Klayout pcells.""" import os +import warnings +import logging from copy import copy, deepcopy from typing import Dict, List, Tuple, Any, Type, Optional -import logging from collections.abc import Mapping, MutableMapping import klayout.db as kdb +from zeropdk import ZeroPDKWarning from zeropdk.layout.geometry import rotate90 logger = logging.getLogger(__name__) @@ -491,7 +493,7 @@ def GDSCell(cell_name: str, filename: str, gds_dir: str) -> Type[PCell]: assert gds_dir is not None filepath = os.path.join(gds_dir, filename) if not os.path.exists(filepath): - raise FileNotFoundError(f"{filename} not found in {gds_dir}") + warnings.warn(f"Warning while creating GDSCell for cell name '{cell_name}': '{filename}' not found in '{gds_dir}'", category=ZeroPDKWarning) class GDS_cell_base(PCell): """ Imports a gds file and places it.""" From a9e4d74fc2a23808b999895cf731bf2b64d6d79a Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sun, 10 Oct 2021 23:42:04 -0400 Subject: [PATCH 04/21] Improving some type hinting --- zeropdk/layout/polygons.py | 3 +- zeropdk/pcell.py | 61 +++++++++++++------------------------- 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/zeropdk/layout/polygons.py b/zeropdk/layout/polygons.py index f63146f..f5e7600 100644 --- a/zeropdk/layout/polygons.py +++ b/zeropdk/layout/polygons.py @@ -1,3 +1,4 @@ +from typing import Iterable from zeropdk.layout import insert_shape from zeropdk.layout.geometry import cross_prod, project, rotate90 @@ -117,7 +118,7 @@ def layout_path(cell, layer, point_iterator, w): cell.shapes(layer).insert(pya.Path.from_dpath(path)) -def layout_path_with_ends(cell, layer, point_iterator, w): +def layout_path_with_ends(cell, layer: kdb.LayerInfo, point_iterator: Iterable[kdb.DPoint], w: float): """ Simple wrapper for pya.DPath.""" dpath = pya.DPath(list(point_iterator), w, w / 2, w / 2) cell.shapes(layer).insert(dpath) diff --git a/zeropdk/pcell.py b/zeropdk/pcell.py index 209be39..5fa5b04 100644 --- a/zeropdk/pcell.py +++ b/zeropdk/pcell.py @@ -4,7 +4,7 @@ import warnings import logging from copy import copy, deepcopy -from typing import Dict, List, Tuple, Any, Type, Optional +from typing import Dict, List, Tuple, Any, Optional from collections.abc import Mapping, MutableMapping import klayout.db as kdb @@ -167,8 +167,8 @@ class ParamContainer(Mapping): TypeError: Cannot set orange to string """ - _container: Dict[str, Type[PCellParameter]] - _current_values: Dict[str, Type[PCellParameter]] + _container: Dict[str, PCellParameter] + _current_values: Dict[str, PCellParameter] def __init__(self, *args): """Two ways of initializing: @@ -188,7 +188,7 @@ def __init__(self, *args): param = arg # TODO: check type self.add_param(param) - def add_param(self, param: Type[PCellParameter]): + def add_param(self, param: PCellParameter): self._container[param.name] = param # delete from current values if overwriting parameter @@ -249,8 +249,8 @@ class Port(object): def __init__(self, name, position, direction, width, port_type=None): self.name: str = name - self.position: Type[kdb.DPoint] = position # Point - self.direction: Type[kdb.DVector] = direction # Vector + self.position: kdb.DPoint = position # Point + self.direction: kdb.DVector = direction # Vector self.type: str = port_type self.width: float = width @@ -271,14 +271,14 @@ def flip(self): return self - def rotate(self, angle_deg): + def rotate(self, angle_deg: float): from zeropdk.layout.geometry import rotate from math import pi self.direction = rotate(self.direction, angle_deg * pi / 180) return self - def draw(self, cell, layer): + def draw(self, cell: kdb.Cell, layer: kdb.LayerInfo): """ Draws this port on cell's layer using klayout.db""" if self.name.startswith("el"): pin_length = self.width @@ -327,10 +327,10 @@ def draw(self, cell, layer): def place_cell( - parent_cell: Type[kdb.Cell], - pcell: Type[kdb.Cell], - ports_dict: Dict[str, Type[Port]], - placement_origin: Type[kdb.DPoint], + parent_cell: kdb.Cell, + pcell: kdb.Cell, + ports_dict: Dict[str, Port], + placement_origin: kdb.DPoint, relative_to: Optional[str] = None, transform_into: bool = False, ): @@ -381,9 +381,9 @@ class PCell: # properties. The logic for this can be found in __new__ method # below params: ParamContainer = ParamContainer() - _cell: Type[kdb.Cell] + _cell: kdb.Cell - def draw(self, cell): + def draw(self, cell: kdb.Cell) -> Tuple[kdb.Cell, Dict[str, Port]]: raise NotImplementedError() def __new__(cls, *args, **kwargs): @@ -443,11 +443,11 @@ def new_cell(self, layout): def place_cell( self, - parent_cell: Type[kdb.Cell], - placement_origin: Type[kdb.DPoint], + parent_cell: kdb.Cell, + placement_origin: kdb.DPoint, relative_to: Optional[str] = None, transform_into: bool = False, - ): + ) -> Dict[str, Port]: """Places this pcell into parent_cell and return ports with updated position and orientation. Args: @@ -479,7 +479,7 @@ def place_cell( _zeropdk_cache_store = dict() -def GDSCell(cell_name: str, filename: str, gds_dir: str) -> Type[PCell]: +def GDSCell(cell_name: str, filename: str, gds_dir: str) -> PCell: """ Args: cell_name: cell within that file. @@ -550,30 +550,9 @@ def draw(self, cell): def port_to_pin_helper( - ports_list: List[Type[Port]], cell: Type[kdb.Cell], layerPinRec: Type[kdb.LayerInfo] + ports_list: List[Port], cell: kdb.Cell, layerPinRec: kdb.LayerInfo ): """ Draws port shapes for visual help in KLayout. """ - # Create the pins, as short paths: - # from siepic_tools.config import PIN_LENGTH - PIN_LENGTH = 100 - dbu = cell.layout().dbu for port in ports_list: - if port.name.startswith("el"): - pin_length = port.width - else: - pin_length = PIN_LENGTH * dbu - - port_position_i = port.position.to_itype(dbu) - cell.shapes(layerPinRec).insert( - kdb.DPath( - [ - port.position - 0.5 * pin_length * port.direction, - port.position + 0.5 * pin_length * port.direction, - ], - port.width, - ).to_itype(dbu) - ) - cell.shapes(layerPinRec).insert( - kdb.Text(port.name, kdb.Trans(kdb.Trans.R0, port_position_i.x, port_position_i.y)) - ).text_size = (2 / dbu) + port.draw(cell, layerPinRec) From df77e81d1fb9cf57ee16765d27e14570ccc8a910 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Mon, 11 Oct 2021 18:35:05 -0400 Subject: [PATCH 05/21] introducing rotate_deg to zeropdk.layout.geometry --- zeropdk/layout/geometry.py | 5 +++++ zeropdk/layout/routing.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/zeropdk/layout/geometry.py b/zeropdk/layout/geometry.py index 2357755..0af468a 100644 --- a/zeropdk/layout/geometry.py +++ b/zeropdk/layout/geometry.py @@ -17,6 +17,11 @@ def rotate(point, angle_rad: float): new_y = y * np.cos(th) + x * np.sin(th) return point.__class__(new_x, new_y) +def rotate_deg(point, angle_deg: float): + """Rotates point counter-clockwisely about its origin by an angle given in degrees""" + angle_rad = angle_deg / 180 * np.pi + return rotate(point, angle_rad) + rotate90 = lambda point: rotate(point, np.pi / 2) diff --git a/zeropdk/layout/routing.py b/zeropdk/layout/routing.py index 202043a..f901d4b 100644 --- a/zeropdk/layout/routing.py +++ b/zeropdk/layout/routing.py @@ -148,7 +148,7 @@ def via_cell_placer(*args, **kwargs): def connect_ports_L(cell, cplayer, ports_from, ports_to, ex): - """ Connects ports ports_from to ports_to, always leaving vertically""" + """ Connects ports ports_from to ports_to, always leaving vertically (with respect to ex)""" ey = rotate90(ex) for port_from, port_to in zip(ports_from, ports_to): From 6702f9be3e120044d1c0a7692b249b23f9185178 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Thu, 21 Oct 2021 22:18:52 -0400 Subject: [PATCH 06/21] adding function waveguide_from_points --- zeropdk/layout/waveguide_rounding.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index 4191ed0..69d91e4 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -479,11 +479,16 @@ def unique_points(point_list): return unique_points - -def layout_waveguide_from_points( +def waveguide_from_points( cell, layer, points, width, radius, taper_width=None, taper_length=None ): + """Draws a waveguide with rounded corners given a path of manhattan-like points. + + Returns: + - points: list of DPoints + - widths: list of widths + """ assert radius > width / 2, "Please use a radius larger than the half-width" points = unique_points(points) @@ -536,7 +541,19 @@ def layout_waveguide_from_points( _draw_widths2.append(w) _cur_point = p - layout_waveguide(cell, layer, _draw_points2, _draw_widths2, smooth=False) + return _draw_points2, _draw_widths2 + +def layout_waveguide_from_points( + cell, layer, points, width, radius, taper_width=None, taper_length=None +): + + points, widths = waveguide_from_points( + cell, layer, points, width, radius, + taper_width=taper_width, + taper_length=taper_length + ) + + layout_waveguide(cell, layer, points, widths, smooth=False) return cell From a0071c02d77ab3d64f7769b940901d3012118f6b Mon Sep 17 00:00:00 2001 From: Sara Kacmoli Date: Fri, 22 Oct 2021 19:03:25 -0400 Subject: [PATCH 07/21] bugfix for almost collinear lines in waveguide_from_points Signed-off-by: Thomas Ferreira de Lima --- zeropdk/layout/waveguide_rounding.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index 69d91e4..7eb90f5 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -280,7 +280,8 @@ def solve_3(A, B, C, radius): p0, p1, p2 = A, B, C α = angle_between(p0 - p1, p2 - p1) - if α % (2 * pi) == pi: + from math import isclose + if isclose(α % (2 * pi), pi): # if points are collinear, just ignore middle point return ([], [p0, p2]) From b48bee72b90b101a2b56f281a1ab9849f41ee497 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sat, 23 Oct 2021 19:13:47 -0400 Subject: [PATCH 08/21] Fixed error handling of waveguide_from_points. TODO: Add tests --- zeropdk/__init__.py | 3 ++ zeropdk/layout/polygons.py | 2 +- zeropdk/layout/waveguide_rounding.py | 20 +++++++------ zeropdk/layout/waveguides.py | 45 +++++++++++++++++++++------- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/zeropdk/__init__.py b/zeropdk/__init__.py index 4d28466..80ee986 100644 --- a/zeropdk/__init__.py +++ b/zeropdk/__init__.py @@ -11,6 +11,9 @@ class ZeroPDKWarning(UserWarning): """Warning related to the usage of ZeroPDK. The responsibility falls on the user to fix these warnings.""" +class ZeroPDKUserError(Exception): + """Exception resulting from impossible design inputs for ZeroPDK.""" + DEBUG = os.environ.get("ZEROPDK_DEBUG", "false") == "true" if DEBUG: logger.setLevel(logging.DEBUG) diff --git a/zeropdk/layout/polygons.py b/zeropdk/layout/polygons.py index f5e7600..56789b2 100644 --- a/zeropdk/layout/polygons.py +++ b/zeropdk/layout/polygons.py @@ -112,7 +112,7 @@ def layout_rectangle(cell, layer, center, width, height, ex): from math import pi -def layout_path(cell, layer, point_iterator, w): +def layout_path(cell, layer: kdb.LayerInfo, point_iterator: Iterable[kdb.DPoint], w: float): """ Simple wrapper for pya.DPath.""" path = pya.DPath(list(point_iterator), w, 0, 0).to_itype(cell.layout().dbu) cell.shapes(layer).insert(pya.Path.from_dpath(path)) diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index 7eb90f5..faa8132 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -1,12 +1,15 @@ """ Straight waveguide rounding algorithms""" from functools import lru_cache from math import atan2, tan, inf +from typing import List, Tuple +import warnings import numpy as np import klayout.db as kdb from zeropdk.layout.geometry import rotate, fix_angle, cross_prod from zeropdk.layout.algorithms.sampling import sample_function +from zeropdk.layout.polygons import layout_path from zeropdk.layout.waveguides import layout_waveguide - +from zeropdk import ZeroPDKUserError, ZeroPDKWarning def angle_between(v1, v0): """Compute angle in radians between v1 and v0. @@ -468,6 +471,7 @@ def compute_tapered_path(path, waveguide_width, taper_width, taper_length): def unique_points(point_list): + """ Takes a list of DPoints and removes any duplicates.""" if len(point_list) < 2: return point_list @@ -482,29 +486,27 @@ def unique_points(point_list): def waveguide_from_points( cell, layer, points, width, radius, taper_width=None, taper_length=None -): +) -> Tuple[List[kdb.DPoint], List[float]]: """Draws a waveguide with rounded corners given a path of manhattan-like points. Returns: - points: list of DPoints - - widths: list of widths + - widths: list of widths with same length as points. """ assert radius > width / 2, "Please use a radius larger than the half-width" points = unique_points(points) if len(points) < 2: - # Nothing to do - return cell + raise ZeroPDKUserError(f"Tried to draw a waveguide with only one point.") # First, get the list of lines and arcs try: rounded_path = compute_rounded_path(points, radius) except Exception as e: - print("ERROR:", e) - print("Continuing...") - layout_waveguide(cell, layer, points, 0.1) - return cell + warnings.warn(f"Error while computing rounded path for waveguide: {e}. \nContinuing...", category=ZeroPDKWarning) + layout_path(cell, layer, points, 0.1) + return points, [width] * len(points) # Taper path if necessary if taper_width is not None and taper_length is not None: diff --git a/zeropdk/layout/waveguides.py b/zeropdk/layout/waveguides.py index 9a8c1d9..66a44c1 100644 --- a/zeropdk/layout/waveguides.py +++ b/zeropdk/layout/waveguides.py @@ -10,6 +10,7 @@ """ from itertools import repeat +from typing import List, Tuple import numpy as np from numpy import cos, sin, pi, sqrt from functools import reduce @@ -19,6 +20,23 @@ debug = False +def norm(self): + return self.norm() + +def _remove_duplicates(point_tuple_list: List[Tuple[pya.DPoint, ...]]) -> List[Tuple[pya.DPoint, ...]]: + """ Iterates through point_tuple_list and deletes entries with consecutive duplicate points.""" + + if len(point_tuple_list) < 2: + return point_tuple_list + + unique_points = [point_tuple_list[0]] + previous_point = point_tuple_list[0] + for p_tuple in point_tuple_list[1:]: + if (p_tuple[0] - previous_point[0]): + unique_points.append(p_tuple) + previous_point = p_tuple + + return unique_points def waveguide_dpolygon(points_list, width, dbu, smooth=True): """Returns a polygon outlining a waveguide. @@ -29,7 +47,9 @@ def waveguide_dpolygon(points_list, width, dbu, smooth=True): Args: points_list: list of pya.DPoint (at least 2 points) - width (microns): constant or list. If list, then it has to have the same length as points + width (microns): constant, 2-element list, or list. + If 2-element list, then widths are interpolated alongside the waveguide. + If list, then it has to either have the same length as points. dbu: dbu: typically 0.001, only used for accuracy calculations. smooth: tries to smooth final polygons to avoid very sharp edges (greater than 130 deg) Returns: @@ -37,12 +57,9 @@ def waveguide_dpolygon(points_list, width, dbu, smooth=True): """ if len(points_list) < 2: - raise NotImplementedError("ERROR: points_list too short") + raise NotImplementedError("ERROR: Not enough points to draw a waveguide.") return - def norm(self): - return sqrt(self.x ** 2 + self.y ** 2) - # Prepares a joint point and width iterators try: if len(width) == len(points_list): @@ -84,6 +101,9 @@ def sin_angle(point1, point2): return cross_prod(point1, point2) / norm(point1) / norm(point2) point_width_list = list(zip(points_iterator, width_iterator)) + # Remove duplicate consecutive points here, because it would create + # problems for the algorithm below. + point_width_list = _remove_duplicates(point_width_list) N = len(point_width_list) first_point, first_width = point_width_list[0] @@ -269,7 +289,9 @@ def layout_waveguide(cell, layer, points_list, width, smooth=False): cell: cell to place into layer: layer to place into. It is done with cell.shapes(layer).insert(pya.Polygon) points_list: list of pya.DPoint (at least 2 points) - width (microns): constant or list. If list, then it has to have the same length as points + width (microns): constant, 2-element list, or list. + If 2-element list, then widths are interpolated alongside the waveguide. + If list, then it has to either have the same length as points. smooth: tries to smooth final polygons to avoid very sharp edges (greater than 130 deg) """ @@ -292,7 +314,9 @@ def layout_waveguide_angle(cell, layer, points_list, width, angle): cell: cell to place into layer: layer to place into. It is done with cell.shapes(layer).insert(pya.Polygon) points_list: list of pya.DPoint (at least 2 points) - width (microns): constant or list. If list, then it has to have the same length as points + width (microns): constant, 2-element list, or list. + If 2-element list, then widths are interpolated alongside the waveguide. + If list, then it has to either have the same length as points. angle (degrees) """ return layout_waveguide_angle2(cell, layer, points_list, width, angle, angle) @@ -308,7 +332,9 @@ def layout_waveguide_angle2(cell, layer, points_list, width, angle_from, angle_t cell: cell to place into layer: layer to place into. It is done with cell.shapes(layer).insert(pya.Polygon) points_list: list of pya.DPoint (at least 2 points) - width (microns): constant or list. If list, then it has to have the same length as points + width (microns): constant, 2-element list, or list. + If 2-element list, then widths are interpolated alongside the waveguide. + If list, then it has to either have the same length as points. angle_from (degrees): normal angle of the first waveguide point angle_to (degrees): normal angle of the last waveguide point @@ -317,9 +343,6 @@ def layout_waveguide_angle2(cell, layer, points_list, width, angle_from, angle_t raise NotImplemented("ERROR: points_list too short") return - def norm(self): - return sqrt(self.x ** 2 + self.y ** 2) - try: if len(width) == len(points_list): width_iterator = iter(width) From 73b4357f9702247c1e423f22c5e1488050fcb706 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sun, 24 Oct 2021 20:10:43 -0400 Subject: [PATCH 09/21] catching edge case in compute_rounded_path when the first segment is too small for the rounded path, but an S curve would work --- zeropdk/klayout_extend/point.py | 3 + zeropdk/layout/waveguide_rounding.py | 161 ++++++++++++++++----------- 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/zeropdk/klayout_extend/point.py b/zeropdk/klayout_extend/point.py index a42aca5..98211d5 100644 --- a/zeropdk/klayout_extend/point.py +++ b/zeropdk/klayout_extend/point.py @@ -85,6 +85,8 @@ def pyaPoint__getstate__(self): def pyaPoint__setstate__(self, state): self.x, self.y = state +def pyaPoint__repr__(self): + return f"{self.__class__.__name__}({self.x}, {self.y})" for klass in PointLike: klass.__init__ = pyaPoint__init__ @@ -94,5 +96,6 @@ def pyaPoint__setstate__(self, state): klass.__deepcopy__ = pyaPoint__deepcopy__ klass.__getstate__ = pyaPoint__getstate__ klass.__setstate__ = pyaPoint__setstate__ + klass.__repr__ = pyaPoint__repr__ klass.normalize = pyaPoint_normalize klass.norm = pyaPoint_norm diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index faa8132..431f8b9 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -338,7 +338,7 @@ def compute_rounded_path(points, radius): - If solve3 cannot solve because AB is too short, raise a ClearanceRewind error - Conversely, if solve3 cannot solve because BC is too short, raise a ClearanceForward error - In the case of ClearanceForward, call solve4 on (A,B,C,D) - - In the case of ClearanceForward, call solve4 on (O,A,B,C), where O is the previous point + - In the case of ClearanceRewind, call solve4 on (O,A,B,C), where O is the previous point Returns: - A list of _Line and _Arc objects """ @@ -350,11 +350,11 @@ def compute_rounded_path(points, radius): # Sanity checks assert N >= 3, "Insufficient number of points, N = {N} < 3".format(N=N) - old_rounded_path = rounded_path = list() old_points_left = points_left = list(points) - can_rewind = False + # condition to check if the last solve_3 was successful (can undo if necessary) + can_rewind = False while len(points_left) > 2: try: solution, rest_points = solve_3(*points_left[0:3], radius) @@ -362,20 +362,32 @@ def compute_rounded_path(points, radius): points_left = rest_points + points_left[3:] can_rewind = True except ClearanceRewind: - if not can_rewind: - raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:3] - ) - points_left = old_points_left - rounded_path = old_rounded_path - if len(points_left[0:4]) < 4: - raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:4] - ) - solution, rest_points = solve_4(*points_left[0:4], radius) - old_points_left = points_left[:] - points_left = rest_points + points_left[4:] - can_rewind = False + # Try going forward first, just in case. See stress tests below. + forward_possible = True + if len(points_left[0:4]) >= 4: + try: + solution, rest_points = solve_4(*points_left[0:4], radius) + old_points_left = points_left[:] + points_left = rest_points + points_left[4:] + can_rewind = False + except: + forward_possible = False + if not forward_possible: + if not can_rewind: + raise RuntimeError( + "Not enough space for enough turns: Cannot solve:", *points_left[0:3] + ) + # Rewind: undo last rounded path element and try solve_4. + points_left = old_points_left + rounded_path = old_rounded_path + if len(points_left[0:4]) < 4: + raise RuntimeError( + "Not enough space for enough turns: Cannot solve:", *points_left[0:4] + ) + solution, rest_points = solve_4(*points_left[0:4], radius) + old_points_left = points_left[:] + points_left = rest_points + points_left[4:] + can_rewind = False except ClearanceForward: if len(points_left[0:4]) < 4: raise RuntimeError( @@ -582,57 +594,82 @@ def trace_reference_path(cell, layer, points, width): ex, ey = kdb.DPoint(1, 0), kdb.DPoint(0, 1) - points = [0 * ex, 10 * ex, 10 * (ex + ey), 30 * ex] - origin = 0 * ey - points = [origin + point for point in points] - x = compute_rounded_path(points, 3) - trace_rounded_path(TOP, layer, x, 0.5) - trace_reference_path(TOP, layerRec, points, 0.5) - - points = [0 * ex, 10 * ex, 5 * (ex - ey), 17 * ex, 30 * ex] - origin = 30 * ey - points = [origin + point for point in points] - x = compute_rounded_path(points, 3) - trace_rounded_path(TOP, layer, x, 0.5) - trace_reference_path(TOP, layerRec, points, 0.5) - - radius = 3 - for ex2 in (ex, -ex): - points = [2 * ex2] - for d in np.arange(1, 10, 2.5): - origin = points[-1] - displacements = [ - 4 * radius * ex2, - 4 * radius * ex2 + d * ey - 1 * d * ex2, - d * ey, - (d + 2 * radius) * ey, - ] - points += [origin + displacement for displacement in displacements] - origin = 15 * ex + 40 * ey - points = [origin + point for point in points] - x = compute_rounded_path(points, radius) - trace_rounded_path(TOP, layer, x, 0.5) - trace_reference_path(TOP, layerRec, points, 0.5) - - # Layout tapered waveguide + # points = [0 * ex, 10 * ex, 10 * (ex + ey), 30 * ex] + # origin = 0 * ey + # points = [origin + point for point in points] + # x = compute_rounded_path(points, 3) + # trace_rounded_path(TOP, layer, x, 0.5) + # trace_reference_path(TOP, layerRec, points, 0.5) + + # points = [0 * ex, 10 * ex, 5 * (ex - ey), 17 * ex, 30 * ex] + # origin = 30 * ey + # points = [origin + point for point in points] + # x = compute_rounded_path(points, 3) + # trace_rounded_path(TOP, layer, x, 0.5) + # trace_reference_path(TOP, layerRec, points, 0.5) + + # radius = 3 + # for ex2 in (ex, -ex): + # points = [2 * ex2] + # for d in np.arange(1, 10, 2.5): + # origin = points[-1] + # displacements = [ + # 4 * radius * ex2, + # 4 * radius * ex2 + d * ey - 1 * d * ex2, + # d * ey, + # (d + 2 * radius) * ey, + # ] + # points += [origin + displacement for displacement in displacements] + # origin = 15 * ex + 40 * ey + # points = [origin + point for point in points] + # x = compute_rounded_path(points, radius) + # trace_rounded_path(TOP, layer, x, 0.5) + # trace_reference_path(TOP, layerRec, points, 0.5) + + # # Layout tapered waveguide + # points = [ + # 0 * ex, + # 100 * ex, + # 100 * ex + 20 * ey, + # 10 * ex + 5 * ey, + # 10 * ex + 25 * ey, + # 100 * ex + 30 * ey, + # ] + + # # Untapered + # origin = 40 * ex + # points_ = [origin + point for point in points] + # layout_waveguide_from_points(TOP, layer, points_, 0.5, 5) + + # # Tapered + # origin = 40 * ex + 40 * ey + # points_ = [origin + point for point in points] + # layout_waveguide_from_points(TOP, layer, points_, 0.5, 5, taper_width=3, taper_length=10) + + + # Stress test about ClearanceRewind when forward would work. + origin = 40 * ex + 80 * ey points = [ 0 * ex, - 100 * ex, - 100 * ex + 20 * ey, - 10 * ex + 5 * ey, - 10 * ex + 25 * ey, - 100 * ex + 30 * ey, + 222 * ey, + 20 * ex + 222 * ey, + 20 * ex + 371 * ey, ] - - # Untapered - origin = 40 * ex points_ = [origin + point for point in points] - layout_waveguide_from_points(TOP, layer, points_, 0.5, 5) + layout_waveguide_from_points(TOP, layer, points_, 5, 500) - # Tapered - origin = 40 * ex + 40 * ey + # Stress test on trying forward first after ClearanceRewind. + + origin = 60 * ex + 80 * ey + points = [ + 0 * ex, + 222 * ey, + 231 * ex + 222 * ey, + 231 * ex + 460 * ey, + ] points_ = [origin + point for point in points] - layout_waveguide_from_points(TOP, layer, points_, 0.5, 5, taper_width=3, taper_length=10) + # breakpoint() + layout_waveguide_from_points(TOP, layer, points_, 5, 230) print("Wrote waveguide_rounding.gds") TOP.write("waveguide_rounding.gds") From 3fb68b469df59f3b8e44db5141eaa27fd7e21cb4 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Sun, 24 Oct 2021 20:28:17 -0400 Subject: [PATCH 10/21] squash: fixed logic error from previous commit --- zeropdk/layout/waveguide_rounding.py | 105 ++++++++++++++------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index 431f8b9..a5cf8de 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -363,8 +363,9 @@ def compute_rounded_path(points, radius): can_rewind = True except ClearanceRewind: # Try going forward first, just in case. See stress tests below. - forward_possible = True + forward_possible = False if len(points_left[0:4]) >= 4: + forward_possible = True try: solution, rest_points = solve_4(*points_left[0:4], radius) old_points_left = points_left[:] @@ -594,57 +595,57 @@ def trace_reference_path(cell, layer, points, width): ex, ey = kdb.DPoint(1, 0), kdb.DPoint(0, 1) - # points = [0 * ex, 10 * ex, 10 * (ex + ey), 30 * ex] - # origin = 0 * ey - # points = [origin + point for point in points] - # x = compute_rounded_path(points, 3) - # trace_rounded_path(TOP, layer, x, 0.5) - # trace_reference_path(TOP, layerRec, points, 0.5) - - # points = [0 * ex, 10 * ex, 5 * (ex - ey), 17 * ex, 30 * ex] - # origin = 30 * ey - # points = [origin + point for point in points] - # x = compute_rounded_path(points, 3) - # trace_rounded_path(TOP, layer, x, 0.5) - # trace_reference_path(TOP, layerRec, points, 0.5) - - # radius = 3 - # for ex2 in (ex, -ex): - # points = [2 * ex2] - # for d in np.arange(1, 10, 2.5): - # origin = points[-1] - # displacements = [ - # 4 * radius * ex2, - # 4 * radius * ex2 + d * ey - 1 * d * ex2, - # d * ey, - # (d + 2 * radius) * ey, - # ] - # points += [origin + displacement for displacement in displacements] - # origin = 15 * ex + 40 * ey - # points = [origin + point for point in points] - # x = compute_rounded_path(points, radius) - # trace_rounded_path(TOP, layer, x, 0.5) - # trace_reference_path(TOP, layerRec, points, 0.5) - - # # Layout tapered waveguide - # points = [ - # 0 * ex, - # 100 * ex, - # 100 * ex + 20 * ey, - # 10 * ex + 5 * ey, - # 10 * ex + 25 * ey, - # 100 * ex + 30 * ey, - # ] - - # # Untapered - # origin = 40 * ex - # points_ = [origin + point for point in points] - # layout_waveguide_from_points(TOP, layer, points_, 0.5, 5) - - # # Tapered - # origin = 40 * ex + 40 * ey - # points_ = [origin + point for point in points] - # layout_waveguide_from_points(TOP, layer, points_, 0.5, 5, taper_width=3, taper_length=10) + points = [0 * ex, 10 * ex, 10 * (ex + ey), 30 * ex] + origin = 0 * ey + points = [origin + point for point in points] + x = compute_rounded_path(points, 3) + trace_rounded_path(TOP, layer, x, 0.5) + trace_reference_path(TOP, layerRec, points, 0.5) + + points = [0 * ex, 10 * ex, 5 * (ex - ey), 17 * ex, 30 * ex] + origin = 30 * ey + points = [origin + point for point in points] + x = compute_rounded_path(points, 3) + trace_rounded_path(TOP, layer, x, 0.5) + trace_reference_path(TOP, layerRec, points, 0.5) + + radius = 3 + for ex2 in (ex, -ex): + points = [2 * ex2] + for d in np.arange(1, 10, 2.5): + origin = points[-1] + displacements = [ + 4 * radius * ex2, + 4 * radius * ex2 + d * ey - 1 * d * ex2, + d * ey, + (d + 2 * radius) * ey, + ] + points += [origin + displacement for displacement in displacements] + origin = 15 * ex + 40 * ey + points = [origin + point for point in points] + x = compute_rounded_path(points, radius) + trace_rounded_path(TOP, layer, x, 0.5) + trace_reference_path(TOP, layerRec, points, 0.5) + + # Layout tapered waveguide + points = [ + 0 * ex, + 100 * ex, + 100 * ex + 20 * ey, + 10 * ex + 5 * ey, + 10 * ex + 25 * ey, + 100 * ex + 30 * ey, + ] + + # Untapered + origin = 40 * ex + points_ = [origin + point for point in points] + layout_waveguide_from_points(TOP, layer, points_, 0.5, 5) + + # Tapered + origin = 40 * ex + 40 * ey + points_ = [origin + point for point in points] + layout_waveguide_from_points(TOP, layer, points_, 0.5, 5, taper_width=3, taper_length=10) # Stress test about ClearanceRewind when forward would work. From 04ef4d6099a48403bd4c5797d457f8a093702aad Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Mon, 25 Oct 2021 14:50:59 -0400 Subject: [PATCH 11/21] better error handling/messages on waveguide_from_points --- zeropdk/layout/waveguide_rounding.py | 49 +++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index a5cf8de..4733c40 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -5,6 +5,7 @@ import warnings import numpy as np import klayout.db as kdb +from numpy.core.fromnumeric import trace from zeropdk.layout.geometry import rotate, fix_angle, cross_prod from zeropdk.layout.algorithms.sampling import sample_function from zeropdk.layout.polygons import layout_path @@ -175,6 +176,12 @@ def solve_Z(A, B, C, D, radius): Aprime = X1 + rotate(X - X1, copysign(pi / 2, α1) + γ - α1) Dprime = X2 + rotate(X - X2, copysign(pi / 2, α2) + γ - α2) + # Verify that Aprime starts after A. If not, throw error. + # Verify that Dprime ends before D. If not, throw error. + if (Aprime - A) * AB < 0 or (D - Dprime) * CD < 0: + raise ZeroPDKUserError(f"Not enough space for Z-turn with radius {radius} on the following points: {[A, B, C, D]}") + + # print("line", A, Aprime) # print("arc2", Aprime, X1, X) # print("arc2", X, X2, Dprime) @@ -328,6 +335,23 @@ def solve_4(A, B, C, D, radius): else: return solve_U(A, B, C, D, radius) +def _traceback_fw(message, category, filename, lineno, line=None): + return "-"*80 + "\n" + str(message) + "-"*80 + "\n" + +def zeropdk_warn(message, *, traceback=False): + """ Provide a warning message with ZeroPDKWarning category and an optional traceback.""" + warnings.warn(message, category=ZeroPDKWarning, stacklevel=2) + if traceback: + import traceback + tb_stack = traceback.format_list(traceback.extract_stack()[:-1]) + _oldformatwarning = warnings.formatwarning + warnings.formatwarning = _traceback_fw + warnings.warn( + "Traceback below. Look for the culprit in one of these lines:\n" + "".join(tb_stack), + category=ZeroPDKWarning, stacklevel=2 + ) + warnings.formatwarning = _oldformatwarning + def compute_rounded_path(points, radius): """Transforms a list of points into sections of arcs and straight lines. @@ -371,19 +395,20 @@ def compute_rounded_path(points, radius): old_points_left = points_left[:] points_left = rest_points + points_left[4:] can_rewind = False - except: + except ZeroPDKUserError as e: + zeropdk_warn(f"`Tried to solve` Z curve, but couldn't fit. Error message: '{e}'. Fallback!", traceback=False) forward_possible = False if not forward_possible: if not can_rewind: raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:3] + "Not enough space to complete arcs in rounded waveguide: Cannot solve:", *points_left[0:3] ) # Rewind: undo last rounded path element and try solve_4. points_left = old_points_left rounded_path = old_rounded_path if len(points_left[0:4]) < 4: raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:4] + "Not enough space to complete arcs in rounded waveguide: Cannot solve:", *points_left[0:4] ) solution, rest_points = solve_4(*points_left[0:4], radius) old_points_left = points_left[:] @@ -392,7 +417,7 @@ def compute_rounded_path(points, radius): except ClearanceForward: if len(points_left[0:4]) < 4: raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:4] + "Not enough space to complete arcs in rounded waveguide: Cannot solve:", *points_left[0:4] ) solution, rest_points = solve_4(*points_left[0:4], radius) old_points_left = points_left[:] @@ -517,7 +542,7 @@ def waveguide_from_points( try: rounded_path = compute_rounded_path(points, radius) except Exception as e: - warnings.warn(f"Error while computing rounded path for waveguide: {e}. \nContinuing...", category=ZeroPDKWarning) + zeropdk_warn(f"Error while computing rounded path for waveguide. {str(e)}. Continuing...", traceback=True) layout_path(cell, layer, points, 0.1) return points, [width] * len(points) @@ -595,6 +620,8 @@ def trace_reference_path(cell, layer, points, width): ex, ey = kdb.DPoint(1, 0), kdb.DPoint(0, 1) + # Begin tests + points = [0 * ex, 10 * ex, 10 * (ex + ey), 30 * ex] origin = 0 * ey points = [origin + point for point in points] @@ -672,6 +699,18 @@ def trace_reference_path(cell, layer, points, width): # breakpoint() layout_waveguide_from_points(TOP, layer, points_, 5, 230) + origin = 80 * ex + 80 * ey + points = [ + 0 * ex, + 100 * ey, + 30 * ex + 100 * ey, + 30 * ex + 200 * ey, + ] + points_ = [origin + point for point in points] + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + layout_waveguide_from_points(TOP, layer, points_, 5, 550) + print("Wrote waveguide_rounding.gds") TOP.write("waveguide_rounding.gds") From d9b4584a8d3e59ded0429fde87090ffbe8d15267 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Mon, 25 Oct 2021 17:26:16 -0400 Subject: [PATCH 12/21] Avoiding duplicate points in layout_waveguide. Raising error if waveguide is zero-length --- tests/cells/test_pcell_basic.py | 2 +- zeropdk/__init__.py | 6 ------ zeropdk/exceptions.py | 5 +++++ zeropdk/layout/waveguides.py | 6 +++++- zeropdk/pcell.py | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 zeropdk/exceptions.py diff --git a/tests/cells/test_pcell_basic.py b/tests/cells/test_pcell_basic.py index 412a71c..1a7bdf0 100644 --- a/tests/cells/test_pcell_basic.py +++ b/tests/cells/test_pcell_basic.py @@ -4,7 +4,7 @@ from ..context import zeropdk # noqa -from zeropdk import ZeroPDKWarning +from zeropdk.exceptions import ZeroPDKWarning from zeropdk.pcell import PCell, PCellParameter, ParamContainer, TypeDouble, TypeInt from zeropdk.pcell import GDSCell diff --git a/zeropdk/__init__.py b/zeropdk/__init__.py index 80ee986..1c75181 100644 --- a/zeropdk/__init__.py +++ b/zeropdk/__init__.py @@ -8,12 +8,6 @@ stdout_ch = logging.StreamHandler() logger.addHandler(stdout_ch) -class ZeroPDKWarning(UserWarning): - """Warning related to the usage of ZeroPDK. The responsibility falls on the user to fix these warnings.""" - -class ZeroPDKUserError(Exception): - """Exception resulting from impossible design inputs for ZeroPDK.""" - DEBUG = os.environ.get("ZEROPDK_DEBUG", "false") == "true" if DEBUG: logger.setLevel(logging.DEBUG) diff --git a/zeropdk/exceptions.py b/zeropdk/exceptions.py new file mode 100644 index 0000000..b1f109d --- /dev/null +++ b/zeropdk/exceptions.py @@ -0,0 +1,5 @@ +class ZeroPDKWarning(UserWarning): + """Warning related to the usage of ZeroPDK. The responsibility falls on the user to fix these warnings.""" + +class ZeroPDKUserError(Exception): + """Exception resulting from impossible design inputs for ZeroPDK.""" \ No newline at end of file diff --git a/zeropdk/layout/waveguides.py b/zeropdk/layout/waveguides.py index 66a44c1..5b8a565 100644 --- a/zeropdk/layout/waveguides.py +++ b/zeropdk/layout/waveguides.py @@ -15,6 +15,7 @@ from numpy import cos, sin, pi, sqrt from functools import reduce from zeropdk.layout.geometry import curve_length, cross_prod, find_arc +from zeropdk.exceptions import ZeroPDKUserError import klayout.db as pya @@ -32,7 +33,7 @@ def _remove_duplicates(point_tuple_list: List[Tuple[pya.DPoint, ...]]) -> List[T unique_points = [point_tuple_list[0]] previous_point = point_tuple_list[0] for p_tuple in point_tuple_list[1:]: - if (p_tuple[0] - previous_point[0]): + if (p_tuple[0] - previous_point[0]).norm() > 0: unique_points.append(p_tuple) previous_point = p_tuple @@ -106,6 +107,9 @@ def sin_angle(point1, point2): point_width_list = _remove_duplicates(point_width_list) N = len(point_width_list) + if N < 2: + raise ZeroPDKUserError("Error: Attempted to layout a zero-length waveguide.") + first_point, first_width = point_width_list[0] next_point, next_width = point_width_list[1] diff --git a/zeropdk/pcell.py b/zeropdk/pcell.py index 5fa5b04..9070452 100644 --- a/zeropdk/pcell.py +++ b/zeropdk/pcell.py @@ -8,7 +8,7 @@ from collections.abc import Mapping, MutableMapping import klayout.db as kdb -from zeropdk import ZeroPDKWarning +from zeropdk.exceptions import ZeroPDKWarning from zeropdk.layout.geometry import rotate90 logger = logging.getLogger(__name__) From fb38597069627c6f3a694c05942bd2ca58e1a633 Mon Sep 17 00:00:00 2001 From: Joaquin Matres <4514346+joamatab@users.noreply.github.com> Date: Mon, 4 Jul 2022 19:58:39 -0700 Subject: [PATCH 13/21] simpler code --- zeropdk/default_library/io.py | 2 +- zeropdk/klayout_extend/point.py | 7 +-- zeropdk/klayout_extend/polygon.py | 27 +++++------- zeropdk/layout/algorithms/sampling.py | 6 +-- zeropdk/layout/cache.py | 42 +++++++----------- zeropdk/layout/geometry.py | 61 +++++++++------------------ zeropdk/layout/polygons.py | 2 +- zeropdk/layout/routing.py | 21 +++++---- zeropdk/layout/waveguide_rounding.py | 33 ++++++--------- zeropdk/layout/waveguides.py | 13 ++---- zeropdk/pcell.py | 31 ++++++-------- zeropdk/tech/__init__.py | 13 +++--- 12 files changed, 96 insertions(+), 162 deletions(-) diff --git a/zeropdk/default_library/io.py b/zeropdk/default_library/io.py index 8904f49..3d58175 100644 --- a/zeropdk/default_library/io.py +++ b/zeropdk/default_library/io.py @@ -119,7 +119,7 @@ def draw(self, cell): cp = self.params origin, ex, _ = self.origin_ex_ey() - ports = dict() + ports = {} for i in range(cp.pad_array_count): dcpad = DCPad(name=f"pad_{i}", params=cp) diff --git a/zeropdk/klayout_extend/point.py b/zeropdk/klayout_extend/point.py index a42aca5..f0bd2ce 100644 --- a/zeropdk/klayout_extend/point.py +++ b/zeropdk/klayout_extend/point.py @@ -50,8 +50,7 @@ def pyaPoint__truediv__(self, dividend): def pyaPoint__deepcopy__(self, memo): - new_point = self.__class__(self.x, self.y) - return new_point + return self.__class__(self.x, self.y) def pyaPoint_norm(self): @@ -73,9 +72,7 @@ def pyaPoint__init__(self, *args): self.x = p.x self.y = p.y except: - raise ValueError("Cannot understand {}".format(p)) - except: - raise ValueError("Unknown constructor") + raise ValueError(f"Cannot understand {p}") def pyaPoint__getstate__(self): diff --git a/zeropdk/klayout_extend/polygon.py b/zeropdk/klayout_extend/polygon.py index d1b3f00..2927106 100644 --- a/zeropdk/klayout_extend/polygon.py +++ b/zeropdk/klayout_extend/polygon.py @@ -53,17 +53,15 @@ def clip(self, x_bounds=(-np.inf, np.inf), y_bounds=(-np.inf, np.inf)): def intersect_left_boundary(p1, p2, x_bounds, y_bounds): left_most, right_most = (p1, p2) if p1.x < p2.x else (p2, p1) bottom_most, top_most = (p1, p2) if p1.y < p2.y else (p2, p1) - if left_most.x < x_bounds[0]: - # intersection only if right_most crosses x_bound[0] - if right_most.x > x_bounds[0]: - # outside the box, on the left - y_intersect = np.interp( - x_bounds[0], - [left_most.x, right_most.x], - [left_most.y, right_most.y], - ) - if y_bounds[0] < y_intersect and y_bounds[1] > y_intersect: - return backend.DPoint(float(x_bounds[0]), float(y_intersect)) + if left_most.x < x_bounds[0] and right_most.x > x_bounds[0]: + # outside the box, on the left + y_intersect = np.interp( + x_bounds[0], + [left_most.x, right_most.x], + [left_most.y, right_most.y], + ) + if y_bounds[0] < y_intersect and y_bounds[1] > y_intersect: + return backend.DPoint(float(x_bounds[0]), float(y_intersect)) return None def intersect(p1, p2, x_bounds, y_bounds): @@ -71,7 +69,7 @@ def intersect(p1, p2, x_bounds, y_bounds): last_intersect = None def rotate_bounds90(x_bounds, y_bounds, i_times): - for i in range(i_times): + for _ in range(i_times): x_bounds, y_bounds = ( (-y_bounds[1], -y_bounds[0]), (x_bounds[0], x_bounds[1]), @@ -172,10 +170,7 @@ def layout_drc_exclude(self, cell, drclayer, ex): for i in range(len(points)): delta = points[i] - points[i - 1] angle = np.arctan2(delta.y, delta.x) - if delta.y == 0 or delta.x == 0: - thresh_angle = pi / 2 - else: - thresh_angle = pi * 85 / 180 + thresh_angle = pi / 2 if delta.y == 0 or delta.x == 0 else pi * 85 / 180 delta_angle = angle - prev_angle delta_angle = abs(((delta_angle + pi) % (2 * pi)) - pi) if delta_angle > thresh_angle: diff --git a/zeropdk/layout/algorithms/sampling.py b/zeropdk/layout/algorithms/sampling.py index de5a7d8..121474d 100644 --- a/zeropdk/layout/algorithms/sampling.py +++ b/zeropdk/layout/algorithms/sampling.py @@ -131,11 +131,7 @@ def _sample_function( mask = np.ones([len(x_2) - 1], dtype=bool) else: # represent the data as a path in N dimensions (scaled to unit box) - if sample_transform is not None: - y_2_val = sample_transform(x_2, y_2) - else: - y_2_val = y_2 - + y_2_val = sample_transform(x_2, y_2) if sample_transform is not None else y_2 p = np.r_[ "0", x_2[None, :], diff --git a/zeropdk/layout/cache.py b/zeropdk/layout/cache.py index 3b2097e..f3c6d19 100644 --- a/zeropdk/layout/cache.py +++ b/zeropdk/layout/cache.py @@ -1,4 +1,5 @@ """Caching algorithms for pcells.""" + import os import inspect import pickle @@ -11,7 +12,7 @@ from zeropdk.pcell import PCell logger = logging.getLogger(__name__) -layer_map_dict: Dict[Type[pya.Layout], Type[pya.LayerMap]] = dict() +layer_map_dict: Dict[Type[pya.Layout], Type[pya.LayerMap]] = {} CACHE_ACTIVATED = os.environ.get("ZEROPDK_CACHE_ACTIVATED", "true") == "true" CACHE_DIR = os.environ.get("ZEROPDK_CACHE_DIR", os.path.join(os.getcwd(), "cache")) CACHE_PROP_ID = 458 @@ -35,8 +36,7 @@ def produce_hash(self: Type[PCell], extra: Any = None) -> str: long_hash_pcell = sha256( (source_code + str_diff_params + self.name + str(extra)).encode() ).hexdigest() - short_hash_pcell = long_hash_pcell[0:7] - return short_hash_pcell + return long_hash_pcell[:7] def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name: str = ""): @@ -52,7 +52,7 @@ def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name # (by setting the cell name to "" the cells basically become invisible for # the following read) # take out the pcells - cell_list = [cell for cell in layout.each_cell()] + cell_list = list(layout.each_cell()) cell_indices = {cell.name: cell.cell_index() for cell in cell_list} # this assumes that there are no duplicate names, which is true in gds (let's assert) @@ -85,14 +85,12 @@ def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name # - if there is a duplicate even with the disambiguated name, add a counter if disambiguation_name != "": - disambiguation_name = ( - "_" + disambiguation_name - ) # new cell name will be duplicate_name_disambiguation_name + disambiguation_name = f"_{disambiguation_name}" prune_cells_indices = [] used_cell_names = list(cell_indices.keys()) for i_duplicate, name_cached_cell in cell_names2: - if name_cached_cell in cell_indices.keys(): + if name_cached_cell in cell_indices: if name_cached_cell.startswith("cache_") or (name_cached_cell in cache_set): # cell_indices[name_cached_cell] contains a reference to the "original" cell # we want to find every instance to duplicates (layout.cell(i_duplicate)) @@ -114,7 +112,7 @@ def read_layout(layout: Type[pya.Layout], gds_filename: str, disambiguation_name used_cell_names.append(name_cached_cell + disambiguation_name + f"_{k}") for i_pruned in prune_cells_indices: - logger.debug("WARNING: deleting cell " + layout.cell(i_pruned).name) + logger.debug(f"WARNING: deleting cell {layout.cell(i_pruned).name}") layout.prune_cell(i_pruned, -1) # every conflict should have been caught above @@ -178,8 +176,8 @@ def wrapper_draw(self, cell): # cache paths cache_fname = f"cache_{self.__class__.__qualname__}_{short_hash_pcell}" - cache_fname_gds = cache_fname + ".gds" - cache_fname_pkl = cache_fname + ".klayout.pkl" + cache_fname_gds = f"{cache_fname}.gds" + cache_fname_pkl = f"{cache_fname}.klayout.pkl" os.makedirs(cache_dir, mode=0o775, exist_ok=True) @@ -196,14 +194,7 @@ def wrapper_draw(self, cell): print("r", end="", flush=True) if not layout.has_cell(cache_fname): read_layout(layout, cache_fpath_gds, disambiguation_name=cellname) - retrieved_cell = layout.cell(cache_fname) - cell.insert( - pya.DCellInstArray( - retrieved_cell.cell_index(), - pya.DTrans(pya.DTrans.R0, pya.DPoint(0, 0)), - ) - ) - # cell.move_tree(retrieved_cell) + # cell.move_tree(retrieved_cell) else: if layout.has_cell(cache_fname): logger.warning( @@ -236,14 +227,13 @@ def wrapper_draw(self, cell): assert not layout.has_cell(cache_fname) read_layout(layout, cache_fpath_gds, disambiguation_name=cellname) - retrieved_cell = layout.cell(cache_fname) - cell.insert( - pya.DCellInstArray( - retrieved_cell.cell_index(), - pya.DTrans(pya.DTrans.R0, pya.DPoint(0, 0)), - ) + retrieved_cell = layout.cell(cache_fname) + cell.insert( + pya.DCellInstArray( + retrieved_cell.cell_index(), + pya.DTrans(pya.DTrans.R0, pya.DPoint(0, 0)), ) - + ) return cell, ports return wrapper_draw diff --git a/zeropdk/layout/geometry.py b/zeropdk/layout/geometry.py index 2357755..f02448a 100644 --- a/zeropdk/layout/geometry.py +++ b/zeropdk/layout/geometry.py @@ -63,16 +63,12 @@ def project(v, ex, ey=None): ey = rotate90(ex) if cross_prod(ex, ey) == 0: - raise RuntimeError("ex={} and ey={} are not orthogonal.".format(repr(ex), repr(ey))) + raise RuntimeError(f"ex={repr(ex)} and ey={repr(ey)} are not orthogonal.") - # Simple formula - # https://math.stackexchange.com/questions/148199/equation-for-non-orthogonal-projection-of-a-point-onto-two-vectors-representing - - a = cross_prod(ey, v) / cross_prod(ey, ex) # b = cross_prod(ex, v) / cross_prod(ex, ey) # v == a * ex + b * ey - return a + return cross_prod(ey, v) / cross_prod(ey, ex) def curve_length(curve, t0=0, t1=1): @@ -86,27 +82,23 @@ def curve_length(curve, t0=0, t1=1): if isinstance(curve, list): # assuming curve is a list of points scale = (curve[-1] - curve[0]).norm() - if scale > 0: - coords = np.array([[point.x, point.y] for point in curve]).T - dp = np.diff(coords, axis=-1) - ds = np.sqrt((dp ** 2).sum(axis=0)) - return ds.sum() - else: + if scale <= 0: return 0 + coords = np.array([[point.x, point.y] for point in curve]).T + dp = np.diff(coords, axis=-1) else: # assuming curve is a function. curve_func = curve scale = (curve_func(t1) - curve_func(t0)).norm() - if scale > 0: - coords = lambda t: np.array([curve_func(t).x, curve_func(t).y]) - _, sampled_coords = sample_function( - coords, [t0, t1], tol=0.0001 / scale, min_points=100 - ) # 1000 times more precise than the scale - dp = np.diff(sampled_coords, axis=-1) - ds = np.sqrt((dp ** 2).sum(axis=0)) - return ds.sum() - else: + if scale <= 0: return 0 + coords = lambda t: np.array([curve_func(t).x, curve_func(t).y]) + _, sampled_coords = sample_function( + coords, [t0, t1], tol=0.0001 / scale, min_points=100 + ) # 1000 times more precise than the scale + dp = np.diff(sampled_coords, axis=-1) + ds = np.sqrt((dp ** 2).sum(axis=0)) + return ds.sum() def manhattan_intersection(vertical_point, horizontal_point, ex): @@ -131,11 +123,7 @@ def find_Z_orientation(P0, P1, ex): 0 for Z-oriented and 1 for S-oriented """ - if P1 * ex > P0 * ex: - orient = 0 # Z-oriented - else: - orient = 1 # S-oriented - return orient + return 0 if P1 * ex > P0 * ex else 1 def cluster_ports(ports_from, ports_to, ex): @@ -203,13 +191,7 @@ def bezier_line(P0, P1, P2, P3): Reference https://en.wikipedia.org/wiki/Bézier_curve""" - curve_func = ( - lambda t: (1 - t) ** 3 * P0 - + 3 * (1 - t) ** 2 * t * P1 - + 3 * (1 - t) * t ** 2 * P2 - + t ** 3 * P3 - ) - return curve_func + return lambda t: (1 - t) ** 3 * P0 + 3 * (1 - t) ** 2 * t * P1 + 3 * (1 - t) * t**2 * P2 + t**3 * P3 def curvature_bezier(P0, P1, P2, P3): @@ -232,8 +214,7 @@ def curvature_bezier(P0, P1, P2, P3): dy = lambda t: b_prime(t).y ddx = lambda t: b_second(t).x ddy = lambda t: b_second(t).y - curv_func = lambda t: (dx(t) * ddy(t) - dy(t) * ddx(t)) / (dx(t) ** 2 + dy(t) ** 2) ** (3 / 2) - return curv_func + return lambda t: (dx(t) * ddy(t) - dy(t) * ddx(t)) / (dx(t) ** 2 + dy(t) ** 2) ** (3 / 2) from scipy.optimize import minimize @@ -243,8 +224,7 @@ def max_curvature(P0, P1, P2, P3): """Gets the maximum curvature of Bezier curve""" t = np.linspace(0, 1, 300) curv = curvature_bezier(P0, P1, P2, P3)(t) - max_curv = np.max(np.abs(curv.flatten())) - return max_curv + return np.max(np.abs(curv.flatten())) def _curvature_penalty(P0, P1, P2, P3): @@ -256,10 +236,7 @@ def _curvature_penalty(P0, P1, P2, P3): curv_initial = curv[0] curv_final = curv[-1] - # this will cause the minimum curvature to be about 4 times lower - # than at the origin and end points. - penalty = max_curv + 2 * (curv_initial + curv_final) - return penalty + return max_curv + 2 * (curv_initial + curv_final) def fix_angle(angle): @@ -318,7 +295,7 @@ def __eq__(self, other): return self.x == other.x and self.y == other.y def __str__(self): - return "Point({}, {})".format(self.x, self.y) + return f"Point({self.x}, {self.y})" def norm(self): return sqrt(self.x ** 2 + self.y ** 2) diff --git a/zeropdk/layout/polygons.py b/zeropdk/layout/polygons.py index f63146f..291ac32 100644 --- a/zeropdk/layout/polygons.py +++ b/zeropdk/layout/polygons.py @@ -47,7 +47,7 @@ def rectangle(center, width, height, ex, ey): """ if cross_prod(ex, ey) == 0: - raise RuntimeError("ex={} and ey={} are not orthogonal.".format(repr(ex), repr(ey))) + raise RuntimeError(f"ex={repr(ex)} and ey={repr(ey)} are not orthogonal.") point1 = center - width / 2 * ex - height / 2 * ey point3 = center + width / 2 * ex + height / 2 * ey diff --git a/zeropdk/layout/routing.py b/zeropdk/layout/routing.py index 202043a..85ca29f 100644 --- a/zeropdk/layout/routing.py +++ b/zeropdk/layout/routing.py @@ -90,8 +90,8 @@ def common_layout_manhattan_traces( if initiate_with_via: via_cell_placer(cell, first_point, first_width, layer1, layer2, layervia, ex) - points_list = list() - widths_list = list() + points_list = [] + widths_list = [] _, previous_layer, _ = path[0] layout = cell.layout() @@ -104,12 +104,9 @@ def common_layout_manhattan_traces( if isinstance(point, pya.DVector): point = pya.DPoint(point) - if layer == previous_layer: - points_list.append(point) # store points - widths_list.append(width) - else: # time to place a via and layout - points_list.append(point) - widths_list.append(width) + points_list.append(point) # store points + widths_list.append(width) + if layer != previous_layer: layout_waveguide( cell, ensure_layer(layout, previous_layer), @@ -152,7 +149,7 @@ def connect_ports_L(cell, cplayer, ports_from, ports_to, ex): ey = rotate90(ex) for port_from, port_to in zip(ports_from, ports_to): - assert port_from.direction == ey or port_from.direction == -ey + assert port_from.direction in [ey, -ey] o_y = ey if port_to.position * ey > port_from.position * ey else -ey o_x = ex if port_to.position * ex > port_from.position * ex else -ex @@ -211,9 +208,11 @@ def compute_paths_from_clusters( ), "There must be a line dividing the top and bottom port rows. Maybe you are using the wrong ex argument?" if is_to_top: - offset_port_from = max([port_from.position * ey for port_from, _ in ports_iterator]) + offset_port_from = max(port_from.position * ey for port_from, _ in ports_iterator) + else: - offset_port_from = min([port_from.position * ey for port_from, _ in ports_iterator]) + offset_port_from = min(port_from.position * ey for port_from, _ in ports_iterator) + paths_cluster = [] for port_from, port_to in ports_iterator: diff --git a/zeropdk/layout/waveguide_rounding.py b/zeropdk/layout/waveguide_rounding.py index 4191ed0..c8d8d10 100644 --- a/zeropdk/layout/waveguide_rounding.py +++ b/zeropdk/layout/waveguide_rounding.py @@ -20,8 +20,7 @@ def project(P, A, B): AB = B - A eAB = AB / AB.norm() - Pproj = A + (P - A) * eAB * eAB - return Pproj + return A + (P - A) * eAB * eAB def bisect(V1, V2): @@ -228,8 +227,7 @@ def compute_A_prime(E, Eprime, eAB): D = (E - Eprime).norm() L = sqrt(D * (4 * radius - D)) - Aprime = Eprime - eAB * L - return Aprime + return Eprime - eAB * L Aprime = compute_A_prime(E, Eprime, eAB) Dprime = compute_A_prime(G, Gprime, eDC) @@ -353,31 +351,28 @@ def compute_rounded_path(points, radius): while len(points_left) > 2: try: - solution, rest_points = solve_3(*points_left[0:3], radius) + solution, rest_points = solve_3(*points_left[:3], radius) old_points_left = points_left[:] points_left = rest_points + points_left[3:] can_rewind = True except ClearanceRewind: if not can_rewind: - raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:3] - ) + raise RuntimeError("Not enough space for enough turns: Cannot solve:", *points_left[:3]) + points_left = old_points_left rounded_path = old_rounded_path - if len(points_left[0:4]) < 4: - raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:4] - ) - solution, rest_points = solve_4(*points_left[0:4], radius) + if len(points_left[:4]) < 4: + raise RuntimeError("Not enough space for enough turns: Cannot solve:", *points_left[:4]) + + solution, rest_points = solve_4(*points_left[:4], radius) old_points_left = points_left[:] points_left = rest_points + points_left[4:] can_rewind = False except ClearanceForward: - if len(points_left[0:4]) < 4: - raise RuntimeError( - "Not enough space for enough turns: Cannot solve:", *points_left[0:4] - ) - solution, rest_points = solve_4(*points_left[0:4], radius) + if len(points_left[:4]) < 4: + raise RuntimeError("Not enough space for enough turns: Cannot solve:", *points_left[:4]) + + solution, rest_points = solve_4(*points_left[:4], radius) old_points_left = points_left[:] points_left = rest_points + points_left[4:] can_rewind = False @@ -386,7 +381,7 @@ def compute_rounded_path(points, radius): rounded_path += solution # there should be 2 points left in points_left - solution, rest_points = solve_2(*points_left[0:2]) + solution, rest_points = solve_2(*points_left[:2]) rounded_path += solution points_left = rest_points + points_left[2:] diff --git a/zeropdk/layout/waveguides.py b/zeropdk/layout/waveguides.py index 9a8c1d9..aabe5d9 100644 --- a/zeropdk/layout/waveguides.py +++ b/zeropdk/layout/waveguides.py @@ -75,10 +75,7 @@ def cos_angle(point1, point2): cos_angle = point1 * point2 / norm(point1) / norm(point2) # ensure it's between -1 and 1 (nontrivial numerically) - if abs(cos_angle) > 1: - return cos_angle / abs(cos_angle) - else: - return cos_angle + return cos_angle / abs(cos_angle) if abs(cos_angle) > 1 else cos_angle def sin_angle(point1, point2): return cross_prod(point1, point2) / norm(point1) / norm(point2) @@ -234,14 +231,10 @@ def smooth_append(point_list, point): # avoid corners when smoothing if cos_angle(curr_edge, prev_edge) > cos(130 / 180 * pi): point_list.append(point) - else: - # edge case when there is prev_edge is small and - # needs to be deleted to get rid of the corner - if norm(curr_edge) > norm(prev_edge): - point_list[-1] = point + elif norm(curr_edge) > norm(prev_edge): + point_list[-1] = point else: point_list.append(point) - # avoid unnecessary points else: point_list[-1] = point return point_list diff --git a/zeropdk/pcell.py b/zeropdk/pcell.py index b92aabb..e87ed5c 100644 --- a/zeropdk/pcell.py +++ b/zeropdk/pcell.py @@ -145,7 +145,7 @@ def __radd__(self, other): return self.__add__(other) def __repr__(self): - return "objectview({})".format(repr(self.orig_d)) + return f"objectview({repr(self.orig_d)})" # https://stackoverflow.com/questions/3387691/how-to-perfectly-override-a-dict @@ -174,8 +174,8 @@ def __init__(self, *args): 2. ParamContainer(param1, param2, param3, ...), where param is of type PCellParameter """ - self._container = dict() - self._current_values = dict() + self._container = {} + self._current_values = {} if len(args) == 1 and isinstance(args[0], ParamContainer): param_container = args[0] @@ -209,13 +209,12 @@ def __setattr__(self, name, new_value): protected_list = ("_container", "_current_values") if name in protected_list: return super().__setattr__(name, new_value) - else: - param_def = self._container[name] - try: - parsed_value = param_def.parse(new_value) - except TypeError: - raise - self._current_values[name] = parsed_value + param_def = self._container[name] + try: + parsed_value = param_def.parse(new_value) + except TypeError: + raise + self._current_values[name] = parsed_value def merge(self, other): if not isinstance(other, ParamContainer): @@ -235,7 +234,7 @@ def __getitem__(self, key): def __iter__(self): values_dict = {p.name: p.default for p in self._container.values()} - values_dict.update(self._current_values) + values_dict |= self._current_values return iter(values_dict) def __len__(self): @@ -475,7 +474,7 @@ def place_cell( transform_into=transform_into, ) -_zeropdk_cache_store = dict() +_zeropdk_cache_store = {} def GDSCell(cell_name: str, filename: str, gds_dir: str): """ @@ -518,7 +517,7 @@ def get_gds_cell(self, layout): # Add this cell to the list of cells that cannot be deduplicated from zeropdk.layout.cache import CACHE_PROP_ID # pylint: disable=import-outside-toplevel - cache_set = set([new_cell_name]) + cache_set = {new_cell_name} if layout.property(CACHE_PROP_ID) is not None: cache_set |= set(layout.property(CACHE_PROP_ID).split(",")) layout.set_property(CACHE_PROP_ID, ",".join(cache_set)) @@ -554,11 +553,7 @@ def port_to_pin_helper( dbu = cell.layout().dbu for port in ports_list: - if port.name.startswith("el"): - pin_length = port.width - else: - pin_length = PIN_LENGTH * dbu - + pin_length = port.width if port.name.startswith("el") else PIN_LENGTH * dbu port_position_i = port.position.to_itype(dbu) cell.shapes(layerPinRec).insert( kdb.DPath( diff --git a/zeropdk/tech/__init__.py b/zeropdk/tech/__init__.py index 13ede86..0d4f3c8 100644 --- a/zeropdk/tech/__init__.py +++ b/zeropdk/tech/__init__.py @@ -6,7 +6,7 @@ class Tech: def __init__(self): if self.layers is None: - self.layers = dict() + self.layers = {} def add_layer(self, layer_name, layer_def): """Adds a layer to the technology file. @@ -38,7 +38,7 @@ def load_from_xml(cls, lyp_filename): layerInfo_j = j["source"].split("@")[0] layer_map[j["name"]] = layerInfo_j else: - for j in k["group-members"]: + for j in j: layerInfo_j = j["source"].split("@")[0] layer_map[j["name"]] = layerInfo_j if k["source"] != "*/*@*": @@ -47,11 +47,8 @@ def load_from_xml(cls, lyp_filename): try: layer_map[k["name"]] = layerInfo except TypeError as e: - new_message = ( - "Bad name for layer {}. Check your .lyp XML file for errors.".format( - layerInfo - ) - ) + new_message = f"Bad name for layer {layerInfo}. Check your .lyp XML file for errors." + raise TypeError(new_message) from e # layer_map should contain values like '12/0' @@ -83,7 +80,7 @@ def etree_to_dict(t): dd[k].append(v) d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.items()}} if t.attrib: - d[t.tag].update(("@" + k, v) for k, v in t.attrib.items()) + d[t.tag].update((f"@{k}", v) for k, v in t.attrib.items()) if t.text: text = t.text.strip() if children or t.attrib: From 80c61d1b617d74f10315650dd504ca0660b7c6c9 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Mon, 22 Aug 2022 14:10:33 -0400 Subject: [PATCH 14/21] Manually reviewed code edits for PR-6 --- hacks/klayoutAPI.py.txt | 24965 ------------------------ zeropdk/klayout_extend/point.py | 4 +- zeropdk/klayout_extend/polygon.py | 5 +- zeropdk/layout/algorithms/sampling.py | 6 +- zeropdk/layout/cache.py | 8 +- zeropdk/layout/geometry.py | 31 +- zeropdk/layout/routing.py | 2 +- zeropdk/layout/waveguide_rounding.py | 33 +- zeropdk/layout/waveguides.py | 8 +- zeropdk/pcell.py | 2 +- zeropdk/tech/__init__.py | 2 +- 11 files changed, 72 insertions(+), 24994 deletions(-) delete mode 100644 hacks/klayoutAPI.py.txt diff --git a/hacks/klayoutAPI.py.txt b/hacks/klayoutAPI.py.txt deleted file mode 100644 index b26a048..0000000 --- a/hacks/klayoutAPI.py.txt +++ /dev/null @@ -1,24965 +0,0 @@ -class Box: - '''@brief A box class with integer coordinates - - This object represents a box (a rectangular shape). - - The definition of the attributes is: p1 is the lower left point, p2 the upper right one. If a - box is constructed from two points (or four coordinates), the coordinates are sorted - accordingly. - - A box can be empty. An empty box represents no area (not even a point). Empty boxes behave - neutral with respect to most operations. Empty boxes return true on \\empty?. - - A box can be a point or a single line. In this case, the area is zero but the box still can - overlap other boxes for example and it is not empty. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the bottom coordinate of the box - - @brief Sets the bottom coordinate of the box @args c''' - bottom = None - - '''@brief Gets the left coordinate of the box - - @brief Sets the left coordinate of the box @args c''' - left = None - - '''@brief Gets the lower left point of the box - - @brief Sets the lower left point of the box @args p''' - p1 = None - - '''@brief Gets the upper right point of the box - - @brief Sets the upper right point of the box @args p''' - p2 = None - - '''@brief Gets the right coordinate of the box - - @brief Sets the right coordinate of the box @args c''' - right = None - - '''@brief Gets the top coordinate of the box - - @brief Sets the top coordinate of the box @args c''' - top = None - - # Methods - def __add__(self, ...): - '''@brief Joins two boxes - - @args box - - The + operator joins the first box with the one given as the second argument. Joining - constructs a box that encloses both boxes given. Empty boxes are neutral: they do not change - another box when joining. Overwrites this box with the result. - - @param box The box to join with this box. - - @return The joined box''' - - def __and__(self, ...): - '''@brief Returns the intersection of this box with another box - - @args box - - The intersection of two boxes is the largest box common to both boxes. The intersection may - be empty if both boxes to not touch. If the boxes do not overlap but touch the result may - be a single line or point with an area of zero. Overwrites this box with the result. - - @param box The box to take the intersection with - - @return The intersection box''' - - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Returns true if this box is equal to the other box @args box Returns true, if this - box and the given box are equal ''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given box. This method enables - boxes as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a box from two points - - @args lower_left, upper_right - - Two points are given to create a new box. If the coordinates are not provided in the correct - order (i.e. right < left), these are swapped.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Returns true if this box is 'less' than another box @args box Returns true, if - this box is 'less' with respect to first and second point (in this order)''' - - def __mul__(self, ...): - '''@brief Returns the scaled box - - @args scale_factor - - The * operator scales the box with the given factor and returns the result. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled box''' - - def __ne__(self, ...): - '''@brief Returns true if this box is not equal to the other box @args box Returns true, if - this box and the given box are not equal ''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def __rmul__(self, ...): - '''@brief Returns the scaled box - - @args scale_factor - - The * operator scales the box with the given factor and returns the result. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled box''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def area(self, ...): - '''@brief Computes the box area - - Returns the box area or 0 if the box is empty''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def center(self, ...): - '''@brief Gets the center of the box''' - - def contains(self, ...): - '''@brief Returns true if the box contains the given point - - @args point Tests whether a point is inside the box. It also returns true if the point is - exactly on the box contour. - - @param p The point to test against. - - @return true if the point is inside the box.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def empty(self, ...): - '''@brief Returns a value indicating whether the box is empty - - An empty box may be created with the default constructor for example. Such a box is neutral - when combining it with other boxes and renders empty boxes if used in box intersections and - false in geometrical relationship tests. ''' - - def enlarge(self, ...): - '''@brief Enlarges the box by a certain amount. - - @args enlargement - - Enlarges the box by x and y value specified in the vector passed. Positive values with grow - the box, negative ones will shrink the box. The result may be an empty box if the box - disappears. The amount specifies the grow or shrink per edge. The width and height will - change by twice the amount. Does not check for coordinate overflows. - - @param enlargement The grow or shrink amount in x and y direction - - @return A reference to this box.''' - - def enlarged(self, ...): - '''@brief Returns the enlarged box. - - @args enlargement - - Enlarges the box by x and y value specified in the vector passed. Positive values with grow - the box, negative ones will shrink the box. The result may be an empty box if the box - disappears. The amount specifies the grow or shrink per edge. The width and height will - change by twice the amount. Does not modify this box. Does not check for coordinate - overflows. - - @param enlargement The grow or shrink amount in x and y direction - - @return The enlarged box.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given box. This method enables - boxes as hash keys. - - This method has been introduced in version 0.25.''' - - def height(self, ...): - '''@brief Gets the height of the box''' - - def inside(self, ...): - '''@brief Tests if this box is inside the argument box - - @args box - - Returns true, if this box is inside the given box, i.e. the box intersection renders this - box''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_point(self, ...): - '''@brief Returns true, if the box is a single point''' - - def move(self, ...): - '''@brief Moves the box by a certain distance - - @args distance - - Moves the box by a given offset and returns the moved box. Does not check for coordinate - overflows. - - @param distance The offset to move the box. - - @return A reference to this box.''' - - def moved(self, ...): - '''@brief Returns the box moved by a certain distance - - @args distance - - Moves the box by a given offset and returns the moved box. Does not modify this box. Does - not check for coordinate overflows. - - @param distance The offset to move the box. - - @return The moved box.''' - - def overlaps(self, ...): - '''@brief Tests if this box overlaps the argument box - - @args box - - Returns true, if the intersection box of this box with the argument box exists and has a - non-vanishing area''' - - def perimeter(self, ...): - '''@brief Returns the perimeter of the box - - This method is equivalent to 2*(width+height). For empty boxes, this method returns 0. - - This method has been introduced in version 0.23.''' - - def to_dtype(self, ...): - '''@brief Converts the box to a floating-point coordinate box - - The database unit can be specified to translate the integer-coordinate box into a floating- - point coordinate box in micron units. The database unit is basically a scaling factor. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def touches(self, ...): - '''@brief Tests if this box touches the argument box - - @args box - - Two boxes touch if they overlap or their boundaries share at least one common point. - Touching is equivalent to a non-empty intersection ('!(b1 & b2).empty?').''' - - def transformed(self, ...): - '''@brief Returns the box transformed with the given complex transformation - - @args t - - @param t The magnifying transformation to apply @return The transformed box (a DBox now)''' - - def width(self, ...): - '''@brief Gets the width of the box''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_dbox(cls, ...): - '''@brief Creates an integer coordinate box from a floating-point coordinate box - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_dbox'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates a box object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a box from two points - - @args lower_left, upper_right - - Two points are given to create a new box. If the coordinates are not provided in the correct - order (i.e. right < left), these are swapped.''' - - -class Cell: - '''@brief A cell - - A cell object consists of a set of shape containers (called layers), a set of child cell - instances and auxiliary informations such as the parent instance list. A cell is identified - through an index given to the cell upon instantiation. Cell instances refer to single instances - or array instances. Both are encapsulated in the same object, the \\CellInstArray object. In the - simple case, this object refers to a single instance. In the general case, this object may refer - to a regular array of cell instances as well. - - Starting from version 0.16, the child_inst and erase_inst methods are no longer available since - they were using index addressing which is no longer supported. Instead, instances are now - addressed with the \\Instance reference objects. - - See @The Database API@ for more details about the - database objects like the Cell class. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Sets the "ghost cell" flag @args flag - - See \\is_ghost_cell? for a description of this property. - - This method has been introduced in version 0.20.''' - ghost_cell = None - - '''@brief Gets the cell's name - - This method has been introduced in version 0.22. - - @brief Renames the cell @args name Renaming a cell may cause name clashes, i.e. the name may be - identical to the name of another cell. This does not have any immediate effect, but the cell - needs to be renamed, for example when writing the layout to a GDS file. - - This method has been introduced in version 0.22.''' - name = None - - '''@brief Gets the properties ID associated with the cell - - This method has been introduced in version 0.23. - - @brief Sets the properties ID associated with the cell @args id This method is provided, if a - properties ID has been derived already. Usually it's more convenient to use \\delete_property, - \\set_property or \\property. - - This method has been introduced in version 0.23.''' - prop_id = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return selfThe Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the displacement vector for the 'a' axis - - Starting with version 0.25 the displacement is of vector type. - - @brief Sets the displacement vector for the 'a' axis @args vector - - If the instance was not regular before this property is set, it will be initialized to a regular - instance. - - This method was introduced in version 0.22. Starting with version 0.25 the displacement is of - vector type.''' - a = None - - '''@brief Gets the displacement vector for the 'b' axis - - Starting with version 0.25 the displacement is of vector type. - - @brief Sets the displacement vector for the 'b' axis @args vector - - If the instance was not regular before this property is set, it will be initialized to a regular - instance. - - This method was introduced in version 0.22. Starting with version 0.25 the displacement is of - vector type.''' - b = None - - '''@brief Gets the cell index of the cell instantiated - - @brief Sets the index of the cell this instance refers to @args index''' - cell_index = None - - '''@brief Gets the complex transformation of the first instance in the array This method is - always applicable, compared to \\trans, since simple transformations can be expressed as complex - transformations as well. - - @brief Sets the complex transformation of the instance or the first instance in the array @args - trans - - This method was introduced in version 0.22.''' - cplx_trans = None - - '''@brief Gets the number of instances in the 'a' axis - - @brief Sets the number of instances in the 'a' axis @args n - - If the instance was not regular before this property is set to a value larger than zero, it will - be initialized to a regular instance. To make an instance a single instance, set na or nb to 0. - - This method was introduced in version 0.22.''' - na = None - - '''@brief Gets the number of instances in the 'b' axis - - @brief Sets the number of instances in the 'b' axis @args n - - If the instance was not regular before this property is set to a value larger than zero, it will - be initialized to a regular instance. To make an instance a single instance, set na or nb to 0. - - This method was introduced in version 0.22.''' - nb = None - - '''@brief Gets the transformation of the first instance in the array The transformation returned - is only valid if the array does not represent a complex transformation array - - @brief Sets the transformation of the instance or the first instance in the array @args t - - This method was introduced in version 0.22.''' - trans = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Compares two arrays for equality @args other''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given cell instance. This - method enables cell instances as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a single cell instance with a complex transformation @args cell_index, - trans, a, b, na, nb @param cell_index The cell to instantiate @param trans The complex - transformation by which to instantiate the cell @param a The displacement vector of the - array in the 'a' axis @param b The displacement vector of the array in the 'b' axis @param - na The number of placements in the 'a' axis @param nb The number of placements in the 'b' - axis - - Starting with version 0.25 the displacements are of vector type.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __len__(self, ...): - '''@brief Gets the number of single instances in the array If the instance represents a - single instance, the count is 1. Otherwise it is na*nb.''' - - def __lt__(self, ...): - '''@brief Compares two arrays for 'less' @args other The comparison provides an arbitrary - sorting criterion and not specific sorting order. It is guaranteed that if an array a is - less than b, b is not less than a. In addition, it a is not less than b and b is not less - than a, then a is equal to b.''' - - def __ne__(self, ...): - '''@brief Compares two arrays for inequality @args other''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Converts the array to a string - - This method was introduced in version 0.22.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Converts the array to a string - - This method was introduced in version 0.22.''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Gets the bounding box of the array The bounding box incorporates all instances - that the array represents. It needs the layout object to access the actual cell from the - cell index.''' - - def bbox_per_layer(self, ...): - '''@brief Gets the bounding box of the array with respect to one layer The bounding box - incorporates all instances that the array represents. It needs the layout object to access - the actual cell from the cell index.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def each_cplx_trans(self, ...): - '''@brief Gets the complex transformations represented by this instance For a single - instance, this iterator will deliver the single, complex transformation. For array - instances, the iterator will deliver each complex transformation of the expanded array. This - iterator is a generalization of \\each_trans for general complex transformations. - - This method has been introduced in version 0.25.''' - - def each_trans(self, ...): - '''@brief Gets the simple transformations represented by this instance For a single - instance, this iterator will deliver the single, simple transformation. For array instances, - the iterator will deliver each simple transformation of the expanded array. - - This iterator will only deliver valid transformations if the instance array is not of - complex type (see \\is_complex?). A more general iterator that delivers the complex - transformations is \\each_cplx_trans. - - This method has been introduced in version 0.25.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given cell instance. This - method enables cell instances as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the array reference - - The inverted array reference describes in which transformations the parent cell is seen from - the current cell.''' - - def is_complex(self, ...): - '''@brief Gets a value indicating whether the array is a complex array - - Returns true if the array represents complex instances (that is, with magnification and - arbitrary rotation angles).''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_regular_array(self, ...): - '''@brief Gets a value indicating whether this instance is a regular array''' - - def size(self, ...): - '''@brief Gets the number of single instances in the array If the instance represents a - single instance, the count is 1. Otherwise it is na*nb.''' - - def to_s(self, ...): - '''@brief Converts the array to a string - - This method was introduced in version 0.22.''' - - def transform(self, ...): - '''@brief Transforms the cell instance with the given complex transformation @args trans - - This method has been introduced in version 0.20.''' - - def transformed(self, ...): - '''@brief Gets the transformed cell instance (complex transformation) @args trans - - This method has been introduced in version 0.20.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def new(cls, ...): - '''@brief Creates a single cell instance with a complex transformation @args cell_index, - trans, a, b, na, nb @param cell_index The cell to instantiate @param trans The complex - transformation by which to instantiate the cell @param a The displacement vector of the - array in the 'a' axis @param b The displacement vector of the array in the 'b' axis @param - na The number of placements in the 'a' axis @param nb The number of placements in the 'b' - axis - - Starting with version 0.25 the displacements are of vector type.''' - - -class CellMapping: - '''@brief A cell mapping (source to target layout) - - A cell mapping is an association of cells in two layouts forming pairs of cells, i.e. one cell - corresponds to another cell in the other layout. The CellMapping object describes the mapping of - cells of a source layout B to a target layout A. The cell mapping object is basically a table - associating a cell in layout B with a cell in layout A. - - The mapping object is used to create and hold that table. There are three basic modes in which a - table can be generated: - - @ul @li Top-level identity @/li @li Geometrical identity @/li @li Name identity @/li @/ul - - Top-level identity means that only one cell (the top cell) is regarded identical. All child - cells are not considered identical. In full mode (see below), this will create a new, identical - cell tree below the top cell in layout A. - - Geometrical identity is defined by the exact identity of the set of expanded instances in each - starting cell. Therefore, when a cell is mapped to another cell, shapes can be transferred from - one cell to another while effectively rendering the same flat geometry (in the context of the - given starting cells). Location identity is basically the safest way to map cells from one - hierarchy into another, because it preserves the flat shape geometry. However in some cases the - algorithm may find multiple mapping candidates. In that case it will make a guess about what - mapping to choose. - - Name identity means that cells are identified by their names - for a source cell in layer B, a - target cell with the same name is looked up in the target layout A and a mapping is created if a - cell with the same name is found. However, name identity does not mean that the cells are - actually equivalent because they may be placed differently. Hence, cell mapping by name is not a - good choice when it is important to preserve the shape geometry of a layer. - - A cell might not be mapped to another cell which basically means that there is no corresponding - cell. In this case, flattening to the next mapped cell is an option to transfer geometries - despite the missing mapping. You can enforce a mapping by using the mapping generator methods in - 'full' mode, i.e. \\from_names_full or \\from_geometry_full. These versions will create new - cells and their corresponding instances in the target layout if no suitable target cell is - found. - - CellMapping objects play a role mainly in the hierarchical copy or move operations of \\Layout. - However, use is not restricted to these applications. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return selfThe Database API@ for more details about the database - objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the angle - - Note that the simple transformation returns the angle in units of 90 degree. Hence for a simple - trans (i.e. \\Trans), a rotation angle of 180 degree delivers a value of 2 for the angle - attribute. The complex transformation, supporting any rotation angle returns the angle in - degree. - - @return The rotation angle this transformation provides in degree units (0..360 deg). - - @brief Sets the angle @param a The new angle See \\angle for a description of that - attribute.''' - angle = None - - '''@brief Gets the displacement - - @brief Sets the displacement @param u The new displacement''' - disp = None - - '''@brief Gets the magnification - - @brief Sets the magnification @args m @param m The new magnification''' - mag = None - - '''@brief Sets the mirror flag "mirroring" describes a reflection at the x-axis which is - included in the transformation prior to rotation.@param m The new mirror flag''' - mirror = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Tests for equality''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Provides a 'less' criterion for sorting This method is provided to implement a - sorting order. The definition of 'less' is opaque and might change in future versions.''' - - def __mul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __ne__(self, ...): - '''@brief Tests for inequality''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def ctrans(self, ...): - '''@brief Transforms a distance - - The "ctrans" method transforms the given distance. e = t(d). For the simple transformations, - there is no magnification and no modification of the distance therefore. - - @param d The distance to transform @return The transformed distance''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the transformation (in place) - - Inverts the transformation and replaces this transformation by it's inverted one. - - @return The inverted transformation''' - - def inverted(self, ...): - '''@brief Returns the inverted transformation - - Returns the inverted transformation. This method does not modify the transformation. - - @return The inverted transformation''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_mag(self, ...): - '''@brief Test, if the transformation is a magnifying one - - This is the recommended test for checking if the transformation represents a - magnification.''' - - def is_mirror(self, ...): - '''@brief Gets the mirror flag - - If this property is true, the transformation is composed of a mirroring at the x-axis - followed by a rotation by the angle given by the \\angle property. ''' - - def is_ortho(self, ...): - '''@brief Tests, if the transformation is an orthogonal transformation - - If the rotation is by a multiple of 90 degree, this method will return true.''' - - def is_unity(self, ...): - '''@brief Tests, whether this is a unit transformation''' - - def rot(self, ...): - '''@brief Returns the respective simple transformation equivalent rotation code if possible - - If this transformation is orthogonal (is_ortho () == true), then this method will return the - corresponding fixpoint transformation, not taking into account magnification and - displacement. If the transformation is not orthogonal, the result reflects the quadrant the - rotation goes into.''' - - def s_trans(self, ...): - '''@brief Extracts the simple transformation part - - The simple transformation part does not reflect magnification or arbitrary angles. Rotation - angles are rounded down to multiples of 90 degree. Magnification is fixed to 1.0.''' - - def to_itrans(self, ...): - '''@brief Converts the transformation to another transformation with integer input and - output coordinates - - The database unit can be specified to translate the floating-point coordinate displacement - in micron units to an integer-coordinate displacement in database units. The displacement's' - coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def to_trans(self, ...): - '''@brief Converts the transformation to another transformation with floating-point input - coordinates - - This method has been introduced in version 0.25.''' - - def to_vtrans(self, ...): - '''@brief Converts the transformation to another transformation with integer output and - floating-point input coordinates - - The database unit can be specified to translate the floating-point coordinate displacement - in micron units to an integer-coordinate displacement in database units. The displacement's' - coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def trans(self, ...): - '''@brief Transforms a text - - 't*text' or 't.trans(text)' is equivalent to text.transformed(t). - - @param text The text to transform @return The transformed text - - This convenience method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_dtrans(cls, ...): - '''@brief Creates a floating-point coordinate transformation from another coordinate flavour - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_dtrans'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string Creates the object from a string representation - (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - -class DBox: - '''@brief A box class with floating-point coordinates - - This object represents a box (a rectangular shape). - - The definition of the attributes is: p1 is the lower left point, p2 the upper right one. If a - box is constructed from two points (or four coordinates), the coordinates are sorted - accordingly. - - A box can be empty. An empty box represents no area (not even a point). Empty boxes behave - neutral with respect to most operations. Empty boxes return true on \\empty?. - - A box can be a point or a single line. In this case, the area is zero but the box still can - overlap other boxes for example and it is not empty. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the bottom coordinate of the box - - @brief Sets the bottom coordinate of the box @args c''' - bottom = None - - '''@brief Gets the left coordinate of the box - - @brief Sets the left coordinate of the box @args c''' - left = None - - '''@brief Gets the lower left point of the box - - @brief Sets the lower left point of the box @args p''' - p1 = None - - '''@brief Gets the upper right point of the box - - @brief Sets the upper right point of the box @args p''' - p2 = None - - '''@brief Gets the right coordinate of the box - - @brief Sets the right coordinate of the box @args c''' - right = None - - '''@brief Gets the top coordinate of the box - - @brief Sets the top coordinate of the box @args c''' - top = None - - # Methods - def __add__(self, ...): - '''@brief Joins two boxes - - @args box - - The + operator joins the first box with the one given as the second argument. Joining - constructs a box that encloses both boxes given. Empty boxes are neutral: they do not change - another box when joining. Overwrites this box with the result. - - @param box The box to join with this box. - - @return The joined box''' - - def __and__(self, ...): - '''@brief Returns the intersection of this box with another box - - @args box - - The intersection of two boxes is the largest box common to both boxes. The intersection may - be empty if both boxes to not touch. If the boxes do not overlap but touch the result may - be a single line or point with an area of zero. Overwrites this box with the result. - - @param box The box to take the intersection with - - @return The intersection box''' - - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Returns true if this box is equal to the other box @args box Returns true, if this - box and the given box are equal ''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given box. This method enables - boxes as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a box from two points - - @args lower_left, upper_right - - Two points are given to create a new box. If the coordinates are not provided in the correct - order (i.e. right < left), these are swapped.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Returns true if this box is 'less' than another box @args box Returns true, if - this box is 'less' with respect to first and second point (in this order)''' - - def __mul__(self, ...): - '''@brief Returns the scaled box - - @args scale_factor - - The * operator scales the box with the given factor and returns the result. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled box''' - - def __ne__(self, ...): - '''@brief Returns true if this box is not equal to the other box @args box Returns true, if - this box and the given box are not equal ''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def __rmul__(self, ...): - '''@brief Returns the scaled box - - @args scale_factor - - The * operator scales the box with the given factor and returns the result. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled box''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def area(self, ...): - '''@brief Computes the box area - - Returns the box area or 0 if the box is empty''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def center(self, ...): - '''@brief Gets the center of the box''' - - def contains(self, ...): - '''@brief Returns true if the box contains the given point - - @args point Tests whether a point is inside the box. It also returns true if the point is - exactly on the box contour. - - @param p The point to test against. - - @return true if the point is inside the box.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def empty(self, ...): - '''@brief Returns a value indicating whether the box is empty - - An empty box may be created with the default constructor for example. Such a box is neutral - when combining it with other boxes and renders empty boxes if used in box intersections and - false in geometrical relationship tests. ''' - - def enlarge(self, ...): - '''@brief Enlarges the box by a certain amount. - - @args enlargement - - Enlarges the box by x and y value specified in the vector passed. Positive values with grow - the box, negative ones will shrink the box. The result may be an empty box if the box - disappears. The amount specifies the grow or shrink per edge. The width and height will - change by twice the amount. Does not check for coordinate overflows. - - @param enlargement The grow or shrink amount in x and y direction - - @return A reference to this box.''' - - def enlarged(self, ...): - '''@brief Returns the enlarged box. - - @args enlargement - - Enlarges the box by x and y value specified in the vector passed. Positive values with grow - the box, negative ones will shrink the box. The result may be an empty box if the box - disappears. The amount specifies the grow or shrink per edge. The width and height will - change by twice the amount. Does not modify this box. Does not check for coordinate - overflows. - - @param enlargement The grow or shrink amount in x and y direction - - @return The enlarged box.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given box. This method enables - boxes as hash keys. - - This method has been introduced in version 0.25.''' - - def height(self, ...): - '''@brief Gets the height of the box''' - - def inside(self, ...): - '''@brief Tests if this box is inside the argument box - - @args box - - Returns true, if this box is inside the given box, i.e. the box intersection renders this - box''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_point(self, ...): - '''@brief Returns true, if the box is a single point''' - - def move(self, ...): - '''@brief Moves the box by a certain distance - - @args distance - - Moves the box by a given offset and returns the moved box. Does not check for coordinate - overflows. - - @param distance The offset to move the box. - - @return A reference to this box.''' - - def moved(self, ...): - '''@brief Returns the box moved by a certain distance - - @args distance - - Moves the box by a given offset and returns the moved box. Does not modify this box. Does - not check for coordinate overflows. - - @param distance The offset to move the box. - - @return The moved box.''' - - def overlaps(self, ...): - '''@brief Tests if this box overlaps the argument box - - @args box - - Returns true, if the intersection box of this box with the argument box exists and has a - non-vanishing area''' - - def perimeter(self, ...): - '''@brief Returns the perimeter of the box - - This method is equivalent to 2*(width+height). For empty boxes, this method returns 0. - - This method has been introduced in version 0.23.''' - - def to_itype(self, ...): - '''@brief Converts the box to an integer coordinate box - - The database unit can be specified to translate the floating-point coordinate box in micron - units to an integer-coordinate box in database units. The boxes coordinates will be divided - by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing this box - - This string can be turned into a box again by using \\from_s''' - - def touches(self, ...): - '''@brief Tests if this box touches the argument box - - @args box - - Two boxes touch if they overlap or their boundaries share at least one common point. - Touching is equivalent to a non-empty intersection ('!(b1 & b2).empty?').''' - - def transformed(self, ...): - '''@brief Returns the box transformed with the given complex transformation - - @args t - - @param t The magnifying transformation to apply @return The transformed box (a DBox now)''' - - def width(self, ...): - '''@brief Gets the width of the box''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_ibox(cls, ...): - '''@brief Creates a floating-point coordinate box from an integer coordinate box - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_ibox'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates a box object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a box from two points - - @args lower_left, upper_right - - Two points are given to create a new box. If the coordinates are not provided in the correct - order (i.e. right < left), these are swapped.''' - - -class DCellInstArray: - '''@brief A single or array cell instance in micrometer units This object is identical to - \\CellInstArray, except that it holds coordinates in micron units instead of database units. - - This class has been introduced in version 0.25. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the displacement vector for the 'a' axis - - @brief Sets the displacement vector for the 'a' axis @args vector - - If the instance was not regular before this property is set, it will be initialized to a regular - instance.''' - a = None - - '''@brief Gets the displacement vector for the 'b' axis - - @brief Sets the displacement vector for the 'b' axis @args vector - - If the instance was not regular before this property is set, it will be initialized to a regular - instance.''' - b = None - - '''@brief Gets the cell index of the cell instantiated - - @brief Sets the index of the cell this instance refers to @args index''' - cell_index = None - - '''@brief Gets the complex transformation of the first instance in the array This method is - always applicable, compared to \\trans, since simple transformations can be expressed as complex - transformations as well. - - @brief Sets the complex transformation of the instance or the first instance in the array @args - trans''' - cplx_trans = None - - '''@brief Gets the number of instances in the 'a' axis - - @brief Sets the number of instances in the 'a' axis @args n - - If the instance was not regular before this property is set to a value larger than zero, it will - be initialized to a regular instance. To make an instance a single instance, set na or nb to - 0.''' - na = None - - '''@brief Gets the number of instances in the 'b' axis - - @brief Sets the number of instances in the 'b' axis @args n - - If the instance was not regular before this property is set to a value larger than zero, it will - be initialized to a regular instance. To make an instance a single instance, set na or nb to - 0.''' - nb = None - - '''@brief Gets the transformation of the first instance in the array The transformation returned - is only valid if the array does not represent a complex transformation array - - @brief Sets the transformation of the instance or the first instance in the array @args t''' - trans = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Compares two arrays for equality @args other''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given cell instance. This - method enables cell instances as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a single cell instance with a complex transformation @args cell_index, - trans, a, b, na, nb @param cell_index The cell to instantiate @param trans The complex - transformation by which to instantiate the cell @param a The displacement vector of the - array in the 'a' axis @param b The displacement vector of the array in the 'b' axis @param - na The number of placements in the 'a' axis @param nb The number of placements in the 'b' - axis''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __len__(self, ...): - '''@brief Gets the number of single instances in the array If the instance represents a - single instance, the count is 1. Otherwise it is na*nb.''' - - def __lt__(self, ...): - '''@brief Compares two arrays for 'less' @args other The comparison provides an arbitrary - sorting criterion and not specific sorting order. It is guaranteed that if an array a is - less than b, b is not less than a. In addition, it a is not less than b and b is not less - than a, then a is equal to b.''' - - def __ne__(self, ...): - '''@brief Compares two arrays for inequality @args other''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Converts the array to a string''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Converts the array to a string''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Gets the bounding box of the array The bounding box incorporates all instances - that the array represents. It needs the layout object to access the actual cell from the - cell index.''' - - def bbox_per_layer(self, ...): - '''@brief Gets the bounding box of the array with respect to one layer The bounding box - incorporates all instances that the array represents. It needs the layout object to access - the actual cell from the cell index.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def each_cplx_trans(self, ...): - '''@brief Gets the complex transformations represented by this instance For a single - instance, this iterator will deliver the single, complex transformation. For array - instances, the iterator will deliver each complex transformation of the expanded array. This - iterator is a generalization of \\each_trans for general complex transformations.''' - - def each_trans(self, ...): - '''@brief Gets the simple transformations represented by this instance For a single - instance, this iterator will deliver the single, simple transformation. For array instances, - the iterator will deliver each simple transformation of the expanded array. - - This iterator will only deliver valid transformations if the instance array is not of - complex type (see \\is_complex?). A more general iterator that delivers the complex - transformations is \\each_cplx_trans.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given cell instance. This - method enables cell instances as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the array reference - - The inverted array reference describes in which transformations the parent cell is seen from - the current cell.''' - - def is_complex(self, ...): - '''@brief Gets a value indicating whether the array is a complex array - - Returns true if the array represents complex instances (that is, with magnification and - arbitrary rotation angles).''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_regular_array(self, ...): - '''@brief Gets a value indicating whether this instance is a regular array''' - - def size(self, ...): - '''@brief Gets the number of single instances in the array If the instance represents a - single instance, the count is 1. Otherwise it is na*nb.''' - - def to_s(self, ...): - '''@brief Converts the array to a string''' - - def transform(self, ...): - '''@brief Transforms the cell instance with the given complex transformation @args trans''' - - def transformed(self, ...): - '''@brief Gets the transformed cell instance (complex transformation) @args trans''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def new(cls, ...): - '''@brief Creates a single cell instance with a complex transformation @args cell_index, - trans, a, b, na, nb @param cell_index The cell to instantiate @param trans The complex - transformation by which to instantiate the cell @param a The displacement vector of the - array in the 'a' axis @param b The displacement vector of the array in the 'b' axis @param - na The number of placements in the 'a' axis @param nb The number of placements in the 'b' - axis''' - - -class DCplxTrans: - '''@brief A complex transformation - - A complex transformation provides magnification, mirroring at the x-axis, rotation by an - arbitary angle and a displacement. This is also the order, the operations are applied. - - A complex transformation provides a superset of the simple transformation. In many applications, - a complex transformation computes floating-point coordinates to minimize rounding effects. This - version can transform floating-point coordinate objects. - - Complex transformations are extensions of the simple transformation classes (\\DTrans in that - case) and behave similar. - - Transformations can be used to transform points or other objects. Transformations can be - combined with the '*' operator to form the transformation which is equivalent to applying the - second and then the first. Here is some code: - - @code # Create a transformation that applies a magnication of 1.5, a rotation by 90 degree # and - displacement of 10 in x and 20 units in y direction: t = RBA::CplxTrans::new(1.5, 90, false, - 10.0, 20.0) t.to_s # r90 *1.5 10,20 # compute the inverse: t.inverted.to_s # r270 - *0.666666667 -13,7 # Combine with another displacement (applied after that): - (RBA::CplxTrans::new(5, 5) * t).to_s # r90 *1.5 15,25 # Transform a point: - t.trans(RBA::Point::new(100, 200)).to_s # -290,170 @/code - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the angle - - Note that the simple transformation returns the angle in units of 90 degree. Hence for a simple - trans (i.e. \\Trans), a rotation angle of 180 degree delivers a value of 2 for the angle - attribute. The complex transformation, supporting any rotation angle returns the angle in - degree. - - @return The rotation angle this transformation provides in degree units (0..360 deg). - - @brief Sets the angle @param a The new angle See \\angle for a description of that - attribute.''' - angle = None - - '''@brief Gets the displacement - - @brief Sets the displacement @param u The new displacement''' - disp = None - - '''@brief Gets the magnification - - @brief Sets the magnification @args m @param m The new magnification''' - mag = None - - '''@brief Sets the mirror flag "mirroring" describes a reflection at the x-axis which is - included in the transformation prior to rotation.@param m The new mirror flag''' - mirror = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Tests for equality''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Provides a 'less' criterion for sorting This method is provided to implement a - sorting order. The definition of 'less' is opaque and might change in future versions.''' - - def __mul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __ne__(self, ...): - '''@brief Tests for inequality''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def ctrans(self, ...): - '''@brief Transforms a distance - - The "ctrans" method transforms the given distance. e = t(d). For the simple transformations, - there is no magnification and no modification of the distance therefore. - - @param d The distance to transform @return The transformed distance''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the transformation (in place) - - Inverts the transformation and replaces this transformation by it's inverted one. - - @return The inverted transformation''' - - def inverted(self, ...): - '''@brief Returns the inverted transformation - - Returns the inverted transformation. This method does not modify the transformation. - - @return The inverted transformation''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_mag(self, ...): - '''@brief Test, if the transformation is a magnifying one - - This is the recommended test for checking if the transformation represents a - magnification.''' - - def is_mirror(self, ...): - '''@brief Gets the mirror flag - - If this property is true, the transformation is composed of a mirroring at the x-axis - followed by a rotation by the angle given by the \\angle property. ''' - - def is_ortho(self, ...): - '''@brief Tests, if the transformation is an orthogonal transformation - - If the rotation is by a multiple of 90 degree, this method will return true.''' - - def is_unity(self, ...): - '''@brief Tests, whether this is a unit transformation''' - - def rot(self, ...): - '''@brief Returns the respective simple transformation equivalent rotation code if possible - - If this transformation is orthogonal (is_ortho () == true), then this method will return the - corresponding fixpoint transformation, not taking into account magnification and - displacement. If the transformation is not orthogonal, the result reflects the quadrant the - rotation goes into.''' - - def s_trans(self, ...): - '''@brief Extracts the simple transformation part - - The simple transformation part does not reflect magnification or arbitrary angles. Rotation - angles are rounded down to multiples of 90 degree. Magnification is fixed to 1.0.''' - - def to_itrans(self, ...): - '''@brief Converts the transformation to another transformation with integer input and - output coordinates - - The database unit can be specified to translate the floating-point coordinate displacement - in micron units to an integer-coordinate displacement in database units. The displacement's' - coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def to_trans(self, ...): - '''@brief Converts the transformation to another transformation with integer input - coordinates - - This method has been introduced in version 0.25.''' - - def to_vtrans(self, ...): - '''@brief Converts the transformation to another transformation with integer output - coordinates - - The database unit can be specified to translate the floating-point coordinate displacement - in micron units to an integer-coordinate displacement in database units. The displacement's' - coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def trans(self, ...): - '''@brief Transforms a text - - 't*text' or 't.trans(text)' is equivalent to text.transformed(t). - - @param text The text to transform @return The transformed text - - This convenience method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_itrans(cls, ...): - '''@brief Creates a floating-point coordinate transformation from another coordinate flavour - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_itrans'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string Creates the object from a string representation - (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - -class DEdge: - '''@brief An edge class - - An edge is a connection between points, usually participating in a larger context such as a - polygon. An edge has a defined direction (from p1 to p2). Edges play a role in the database as - parts of polygons and to describe a line through both points. The \\Edge object is also used - inside the boolean processor (\\EdgeProcessor). Altough supported, edges are rarely used as - individual database objects. - - See @The Database API@ for more details about the - database objects like the Edge class. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief The first point. - - @brief Sets the first point. @args point This method has been added in version 0.23.''' - p1 = None - - '''@brief The second point. - - @brief Sets the second point. @args point This method has been added in version 0.23.''' - p2 = None - - '''@brief Shortcut for p1.x - - @brief Sets p1.x @args coord This method has been added in version 0.23.''' - x1 = None - - '''@brief Shortcut for p2.x - - @brief Sets p2.x @args coord This method has been added in version 0.23.''' - x2 = None - - '''@brief Shortcut for p1.y - - @brief Sets p1.y @args coord This method has been added in version 0.23.''' - y1 = None - - '''@brief Shortcut for p2.y - - @brief Sets p2.y @args coord This method has been added in version 0.23.''' - y2 = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test @args e @param e The object to compare against''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge. This method enables - edges as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args e @param e The object to compare against @return True, if the - edge is 'less' as the other edge with respect to first and second point''' - - def __mul__(self, ...): - '''@brief Scale edge - - @args scale_factor - - The * operator scales self with the given factor. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled edge''' - - def __ne__(self, ...): - '''@brief Inequality test @args e @param e The object to compare against''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing the edge''' - - def __rmul__(self, ...): - '''@brief Scale edge - - @args scale_factor - - The * operator scales self with the given factor. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled edge''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing the edge''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Return the bounding box of the edge.''' - - def coincident(self, ...): - '''@brief Coincidence check. @args e - - Checks whether a edge is coincident with another edge. Coincidence is defined by being - parallel and that at least one point of one edge is on the other edge. - - @param e the edge to test with - - @return True if the edges are coincident.''' - - def contains(self, ...): - '''@brief Test whether a point is on an edge. @args p - - A point is on a edge if it is on (or at least closer than a grid point to) the edge. - - @param p The point to test with the edge. - - @return True if the point is on the edge.''' - - def contains_excl(self, ...): - '''@brief Test whether a point is on an edge excluding the endpoints. @args p - - A point is on a edge if it is on (or at least closer than a grid point to) the edge. - - @param p The point to test with the edge. - - @return True if the point is on the edge but not equal p1 or p2.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def crossed_by(self, ...): - '''@brief Check, if an edge is cut by a line (given by an edge) @args e - - This method returns true if p1 is in one semispace while p2 is in the other or one of them - is on the line through the edge "e" - - @param e The edge representing the line that the edge must be crossing.''' - - def crossing_point(self, ...): - '''@brief Returns the crossing point on two edges. @args e - - This method delivers the point where the given edge (self) crosses the line given by the - edge in argument "e". If self does not cross this line, the result is undefined. See - \\crossed_by? for a description of the crossing predicate. - - @param e The edge representing the line that self must be crossing. @return The point where - self crosses the line given by "e". - - This method has been introduced in version 0.19.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def distance(self, ...): - '''@brief Distance between the edge and a point. @args p - - Returns the distance between the edge and the point. The distance is signed which is - negative if the point is to the "left" of the edge and positive if the point is to the - "right". The distance is measured by projecting the point onto the line through the edge. If - the edge is degenerated, the distance is not defined. - - @param p The point to test. - - @return The distance''' - - def distance_abs(self, ...): - '''@brief Absolute distance between the edge and a point. @args p - - Returns the distance between the edge and the point. - - @param p The point to test. - - @return The distance''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def dx(self, ...): - '''@brief The horizontal extend of the edge.''' - - def dx_abs(self, ...): - '''@brief The absolute value of the horizontal extend of the edge.''' - - def dy(self, ...): - '''@brief The vertical extend of the edge.''' - - def dy_abs(self, ...): - '''@brief The absolute value of the vertical extend of the edge.''' - - def enlarge(self, ...): - '''@brief Enlarges the edge. @args p - - Enlarges the edge by the given distance and returns the enlarged edge. The edge is - overwritten. Enlargement means that the first point is shifted by -p, the second by p. - - @param p The distance to move the edge points. - - @return The enlarged edge.''' - - def enlarged(self, ...): - '''@brief Returns the enlarged edge (does not modify self) @args p - - Enlarges the edge by the given offset and returns the enlarged edge. The edge is not - modified. Enlargement means that the first point is shifted by -p, the second by p. - - @param p The distance to move the edge points. - - @return The enlarged edge.''' - - def extend(self, ...): - '''@brief Extends the edge (modifies self) @args d - - Extends the edge by the given distance and returns the extended edge. The edge is not - modified. Extending means that the first point is shifted by -d along the edge, the second - by d. The length of the edge will increase by 2*d. - - \\extended is a version that does not modify self but returns the extended edges. - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the end points. - - @return The extended edge (self).''' - - def extended(self, ...): - '''@brief Returns the extended edge (does not modify self) @args d - - Extends the edge by the given distance and returns the extended edge. The edge is not - modified. Extending means that the first point is shifted by -d along the edge, the second - by d. The length of the edge will increase by 2*d. - - \\extend is a version that modifies self (in-place). - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the end points. - - @return The extended edge.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge. This method enables - edges as hash keys. - - This method has been introduced in version 0.25.''' - - def intersect(self, ...): - '''@brief Intersection test. @args e - - Returns true if the edges intersect. Two edges intersect if they share at least one point. - If the edges coincide, they also intersect. For degenerated edges, the intersection is - mapped to point containment tests. - - @param e The edge to test.''' - - def intersection_point(self, ...): - '''@brief Returns the intersection point of two edges. @args e - - This method delivers the intersection point. If the edges do not intersect, the result is - undefined. - - @param e The edge to test. @return The point where the edges intersect. - - This method has been introduced in version 0.19.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_degenerate(self, ...): - '''@brief Test for degenerated edge - - An edge is degenerate, if both end and start point are identical.''' - - def is_parallel(self, ...): - '''@brief Test for being parallel @args e - - @param e The edge to test against - - @return True if both edges are parallel''' - - def length(self, ...): - '''@brief The length of the edge''' - - def move(self, ...): - '''@brief Moves the edge. @args dx, dy - - Moves the edge by the given offset and returns the moved edge. The edge is overwritten. - - @param dx The x distance to move the edge. @param dy The y distance to move the edge. - - @return The moved edge. - - This version has been added in version 0.23.''' - - def moved(self, ...): - '''@brief Returns the moved edge (does not modify self) @args dx, dy - - Moves the edge by the given offset and returns the moved edge. The edge is not modified. - - @param dx The x distance to move the edge. @param dy The y distance to move the edge. - - @return The moved edge. - - This version has been added in version 0.23.''' - - def ortho_length(self, ...): - '''@brief The orthogonal length of the edge ("manhattan-length") - - @return The orthogonal length (abs(dx)+abs(dy))''' - - def shift(self, ...): - '''@brief Shifts the edge (modifies self) @args d - - Shifts the edge by the given distance and returns the shifted edge. The edge is not - modified. Shifting by a positive value will produce an edge which is shifted by d to the - left. Shifting by a negative value will produce an edge which is shifted by d to the right. - - \\shifted is a version that does not modify self but returns the extended edges. - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the edge. - - @return The shifted edge (self).''' - - def shifted(self, ...): - '''@brief Returns the shifted edge (does not modify self) @args d - - Shifts the edge by the given distance and returns the shifted edge. The edge is not - modified. Shifting by a positive value will produce an edge which is shifted by d to the - left. Shifting by a negative value will produce an edge which is shifted by d to the right. - - \\shift is a version that modifies self (in-place). - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the edge. - - @return The shifted edge.''' - - def side_of(self, ...): - '''@brief Indicates at which side the point is located relative to the edge. @args p - - Returns 1 if the point is "left" of the edge, 0 if on and -1 if the point is "right" of the - edge. - - @param p The point to test. - - @return The side value''' - - def sq_length(self, ...): - '''@brief The square of the length of the edge''' - - def swap_points(self, ...): - '''@brief Swap the points of the edge - - This version modifies self. A version that does not modify self is \\swapped_points. - Swapping the points basically reverses the direction of the edge. - - This method has been introduced in version 0.23.''' - - def swapped_points(self, ...): - '''@brief Returns an edge in which both points are swapped - - Swapping the points basically reverses the direction of the edge. - - This method has been introduced in version 0.23.''' - - def to_itype(self, ...): - '''@brief Converts the edge to an integer coordinate edge - - The database unit can be specified to translate the floating-point coordinate edge in micron - units to an integer-coordinate edge in database units. The edges coordinates will be divided - by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing the edge''' - - def transformed(self, ...): - '''@brief Transform the edge. @args t - - Transforms the edge with the given complex transformation. Does not modify the edge but - returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge.''' - - def transformed_cplx(self, ...): - '''@brief Transform the edge. @args t - - Transforms the edge with the given complex transformation. Does not modify the edge but - returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_iedge(cls, ...): - '''@brief Creates a floating-point coordinate edge from an integer coordinate edge - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_iedge'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - @classmethod - def new_pp(cls, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - @classmethod - def new_xyxy(cls, ...): - '''@brief Constructor with two coordinates given as single values - - @args x1, y1, x2, y2 - - Two points are given to create a new edge.''' - - -class DEdgePair: - '''@brief An edge pair (a pair of two edges) Edge pairs are objects representing two edges or - parts of edges. They play a role mainly in the context of DRC functions, where they specify a - DRC violation by connecting two edges which violate the condition checked. Within the framework - of polygon and edge collections which provide DRC functionality, edges pairs with integer - coordinates (\\EdgePair type) are used in the form of edge pair collections (\\EdgePairs). - - Edge pairs basically consist of two edges, called first and second. If created by a two-layer - DRC function, the first edge will correspond to edges from the first layer and the second to - edges from the second layer. - - This class has been introduced in version 0.23. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the first edge - - @brief Sets the first edge @args edge''' - first = None - - '''@brief Gets the second edge - - @brief Sets the second edge @args edge''' - second = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality @args box Returns true, if this edge pair and the given one are equal - - This method has been introduced in version 0.25.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge pair. This method - enables edge pairs as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor from two edges - - This constructor creates an edge pair from the two edges given.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args box Returns true, if this edge pair is 'less' with respect to - first and second edge - - This method has been introduced in version 0.25.''' - - def __ne__(self, ...): - '''@brief Inequality @args box Returns true, if this edge pair and the given one are not - equal - - This method has been introduced in version 0.25.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing the edge pair''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing the edge pair''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Gets the bounding box of the edge pair''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge pair. This method - enables edge pairs as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def normalized(self, ...): - '''@brief Normalizes the edge pair This method normalized the edge pair such that when - connecting the edges at their start and end points a closed loop is formed which is - oriented clockwise. To achieve this, the points of the first and/or first and second edge - are swapped. Normalization is a first step recommended before converting an edge pair to a - polygon, because that way the polygons won't be self-overlapping and the enlargement - parameter is applied properly.''' - - def polygon(self, ...): - '''@brief Convert an edge pair to a polygon @args e The enlargement (set to zero for exact - representation) The polygon is formed by connecting the end and start points of the edges. - It is recommended to use \\normalized before converting the edge pair to a polygon. - - The enlargement parameter allows to apply the specified enlargement parallel and - perpendicular to the edges. Basically this introduces a bias which blows up edge pairs by - the specified amount. That parameter is useful to convert degenerated edge pairs to valid - polygons, i.e. edge pairs with coincident edges and edge pairs consisting of two point-like - edges. - - Another version for converting edge pairs to simple polygons is \\simple_polygon which - renders a \\SimplePolygon object.''' - - def simple_polygon(self, ...): - '''@brief Convert an edge pair to a simple polygon @args e The enlargement (set to zero for - exact representation) The polygon is formed by connecting the end and start points of the - edges. It is recommended to use \\normalized before converting the edge pair to a polygon. - - The enlargement parameter allows to apply the specified enlargement parallel and - perpendicular to the edges. Basically this introduces a bias which blows up edge pairs by - the specified amount. That parameter is useful to convert degenerated edge pairs to valid - polygons, i.e. edge pairs with coincident edges and edge pairs consisting of two point-like - edges. - - Another version for converting edge pairs to polygons is \\polygon which renders a \\Polygon - object.''' - - def to_itype(self, ...): - '''@brief Converts the edge pair to an integer coordinate edge pair - - The database unit can be specified to translate the floating-point coordinate edge pair in - micron units to an integer-coordinate edge pair in database units. The edge pair's' - coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing the edge pair''' - - def transformed(self, ...): - '''@brief Returns the transformed edge pair @args t - - Transforms the edge pair with the given complex transformation. Does not modify the edge - pair but returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge pair''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor from two edges - - This constructor creates an edge pair from the two edges given.''' - - -class DPath: - '''@brief A path class - - A path consists of an sequence of line segments forming the 'spine' of the path and a width. In - addition, the starting point can be drawn back by a certain extent (the 'begin extension') and - the end point can be pulled forward somewhat (by the 'end extension'). - - A path may have round ends for special purposes. In particular, a round-ended path with a single - point can represent a circle. Round-ended paths should have being and end extensions equal to - half the width. Non-round-ended paths with a single point are allowed but the definition of the - resulting shape in not well defined and may differ in other tools. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Get the begin extension - - @brief Set the begin extension @args ext''' - bgn_ext = None - - '''@brief Get the end extension - - @brief Set the end extension @args ext''' - end_ext = None - - '''@brief Get the number of points - - @brief Set the points of the path @args p @param p An array of points to assign to the path's - spine''' - points = None - - '''@brief Set the 'round ends' flag @args round_ends_flag A path with round ends show half - circles at the ends, instead of square or rectangular ends. Paths with this flag set should use - a begin and end extension of half the width (see \\bgn_ext and \\end_ext). The interpretation of - such paths in other tools may differ otherwise.''' - round = None - - '''@brief Get the width - - @brief Set the width @args w''' - width = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test @args p @param p The object to compare against''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor given the points of the path's spine, the width, the extensions and - the round end flag - - @args pts, width, bgn_ext, end_ext, round - - @param pts The points forming the spine of the path @param width The width of the path - @param bgn_ext The begin extension of the path @param end_ext The end extension of the path - @param round If this flag is true, the path will get rounded ends''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args p @param p The object to compare against This operator is - provided to establish some, not necessarily a certain sorting order''' - - def __mul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __ne__(self, ...): - '''@brief Inequality test @args p @param p The object to compare against''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Convert to a string''' - - def __rmul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Convert to a string''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def area(self, ...): - '''@brief Returns the approximate area of the path This method returns the approximate value - of the area. It is computed from the length times the width. end extensions are taken into - account correctly, but not effects of the corner interpolation. This method was added in - version 0.22.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Returns the bounding box of the path''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def each_point(self, ...): - '''@brief Get the points that make up the path's spine''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_round(self, ...): - '''@brief Returns true, if the path has round ends''' - - def length(self, ...): - '''@brief Returns the length of the path the length of the path is determined by summing the - lengths of the segments and adding begin and end extensions. For round-ended paths the - length of the paths between the tips of the ends. - - This method was added in version 0.23.''' - - def move(self, ...): - '''@brief Moves the path. @args dx, dy - - Moves the path by the given offset and returns the moved path. The path is overwritten. - - @param dx The x distance to move the path. @param dy The y distance to move the path. - - @return The moved path. - - This version has been added in version 0.23.''' - - def moved(self, ...): - '''@brief Returns the moved path (does not change self) @args dx, dy - - Moves the path by the given offset and returns the moved path. The path is not modified. - - @param dx The x distance to move the path. @param dy The y distance to move the path. - - @return The moved path. - - This version has been added in version 0.23.''' - - def num_points(self, ...): - '''@brief Get the number of points''' - - def perimeter(self, ...): - '''@brief Returns the approximate perimeter of the path This method returns the approximate - value of the perimeter. It is computed from the length and the width. end extensions are - taken into account correctly, but not effects of the corner interpolation. This method was - added in version 0.24.4.''' - - def polygon(self, ...): - '''@brief Convert the path to a polygon The returned polygon is not guaranteed to be non- - self overlapping. This may happen if the path overlaps itself or contains very short - segments.''' - - def round_corners(self, ...): - '''@brief Creates a new path whose corners are interpolated with circular bends - - @param radius The radius of the bends @param npoints The number of points (per full circle) - used for interpolating the bends @param accuracy The numerical accuracy of the computation - - The accuracy parameter controls the numerical resolution of the approximation process and - should be in the order of half the database unit. This accuracy is used for suppressing - redundant points and simplication of the resulting path. - - This method has been introduced in version 0.25.''' - - def simple_polygon(self, ...): - '''@brief Convert the path to a simple polygon The returned polygon is not guaranteed to be - non-selfoverlapping. This may happen if the path overlaps itself or contains very short - segments.''' - - def to_itype(self, ...): - '''@brief Converts the path to an integer coordinate path - - The database unit can be specified to translate the floating-point coordinate path in micron - units to an integer-coordinate path in database units. The path's' coordinates will be - divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Convert to a string''' - - def transformed(self, ...): - '''@brief Transform the path. @args t - - Transforms the path with the given complex transformation. Does not modify the path but - returns the transformed path. - - @param t The transformation to apply. - - @return The transformed path.''' - - def transformed_cplx(self, ...): - '''@brief Transform the path. @args t - - Transforms the path with the given complex transformation. Does not modify the path but - returns the transformed path. - - @param t The transformation to apply. - - @return The transformed path.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_ipath(cls, ...): - '''@brief Creates a floating-point coordinate path from an integer coordinate path - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_ipath'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor given the points of the path's spine, the width, the extensions and - the round end flag - - @args pts, width, bgn_ext, end_ext, round - - @param pts The points forming the spine of the path @param width The width of the path - @param bgn_ext The begin extension of the path @param end_ext The end extension of the path - @param round If this flag is true, the path will get rounded ends''' - - @classmethod - def new_pw(cls, ...): - '''@brief Constructor given the points of the path's spine and the width - - @args pts, width - - @param pts The points forming the spine of the path @param width The width of the path''' - - @classmethod - def new_pwx(cls, ...): - '''@brief Constructor given the points of the path's spine, the width and the extensions - - @args pts, width, bgn_ext, end_ext - - @param pts The points forming the spine of the path @param width The width of the path - @param bgn_ext The begin extension of the path @param end_ext The end extension of the - path''' - - @classmethod - def new_pwxr(cls, ...): - '''@brief Constructor given the points of the path's spine, the width, the extensions and - the round end flag - - @args pts, width, bgn_ext, end_ext, round - - @param pts The points forming the spine of the path @param width The width of the path - @param bgn_ext The begin extension of the path @param end_ext The end extension of the path - @param round If this flag is true, the path will get rounded ends''' - - -class DPoint: - '''@brief A point class with double (floating-point) coordinates Points represent a coordinate - in the two-dimensional coordinate space of layout. They are not geometrical objects by itself. - But they are frequently used in the database API for various purposes. Other than the integer - variant (\\Point), points with floating-point coordinates can represent fractions of a database - unit. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Accessor to the x coordinate - - @brief Write accessor to the x coordinate @args coord''' - x = None - - '''@brief Accessor to the y coordinate - - @brief Write accessor to the y coordinate @args coord''' - y = None - - # Methods - def __add__(self, ...): - '''@brief Adds a vector to a point - - @args v - - Adds vector v to self by adding the coordinates. - - Starting with version 0.25, this method expects a vector argument.''' - - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test operator - - @args p''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given point. This method - enables points as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor for a point from two coordinate values - - @args x, y''' - - def __itruediv__(self, ...): - '''@brief Division by some divisor - - @args d - - Divides the object in place. All coordinates are divided with the given divisor and if - necessary rounded.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief "less" comparison operator - - @args p - - This operator is provided to establish a sorting order''' - - def __mul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __ne__(self, ...): - '''@brief Inequality test operator - - @args p''' - - def __neg__(self, ...): - '''@brief Compute the negative of a point - - @args p - - Returns a new point with -x, -y. - - This method has been added in version 0.23.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def __sub__(self, ...): - '''@brief Subtract one point from another - - @args p - - Subtract point p from self by subtracting the coordinates. This renders a vector. - - Starting with version 0.25, this method renders a vector.''' - - def __truediv__(self, ...): - '''@brief Division by some divisor - - @args d - - Returns the scaled object. All coordinates are divided with the given divisor and if - necessary rounded.''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def abs(self, ...): - '''@brief The absolute value of the point (Euclidian distance to 0,0) - - The returned value is 'sqrt(x*x+y*y)'. - - This method has been introduced in version 0.23.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def distance(self, ...): - '''@brief The Euclidian distance to another point - - @args d - - @param d The other point to compute the distance to.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given point. This method - enables points as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def sq_abs(self, ...): - '''@brief The square of the absolute value of the point (Euclidian distance to 0,0) - - The returned value is 'x*x+y*y'. - - This method has been introduced in version 0.23.''' - - def sq_distance(self, ...): - '''@brief The square Euclidian distance to another point - - @args d - - @param d The other point to compute the distance to.''' - - def to_itype(self, ...): - '''@brief Converts the point to an integer coordinate point - - The database unit can be specified to translate the floating-point coordinate point in - micron units to an integer-coordinate point in database units. The point's' coordinates will - be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def to_v(self, ...): - '''@brief Turns the point into a vector This method returns a vector representing the - distance from (0,0) to the point.This method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_ipoint(cls, ...): - '''@brief Creates a floating-point coordinate point from an integer coordinate point - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_ipoint'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor for a point from two coordinate values - - @args x, y''' - - -class DPolygon: - '''@brief A polygon class - - A polygon consists of an outer hull and zero to many holes. Each contour consists of several - points. The point list is normalized such that the leftmost, lowest point is the first one. The - orientation is normalized such that the orientation of the hull contour is clockwise, while the - orientation of the holes is counterclockwise. - - It is in no way checked that the contours are not overlapping. This must be ensured by the user - of the object when filling the contours. - - A polygon can be asked for the number of holes using the \\holes method. \\each_point_hull - delivers the points of the hull contour. \\each_point_hole delivers the points of a specific - hole. \\each_edge delivers the edges (point-to-point connections) of both hull and holes. \\bbox - delivers the bounding box, \\area the area and \\perimeter the perimeter of the polygon. - - Here's an example of how to create a polygon: - - @code hull = [ RBA::DPoint::new(0, 0), RBA::DPoint::new(6000, 0), - RBA::DPoint::new(6000, 3000), RBA::DPoint::new(0, 3000) ] hole1 = [ RBA::DPoint::new(1000, - 1000), RBA::DPoint::new(2000, 1000), RBA::DPoint::new(2000, 2000), - RBA::DPoint::new(1000, 2000) ] hole2 = [ RBA::DPoint::new(3000, 1000), RBA::DPoint::new(4000, - 1000), RBA::DPoint::new(4000, 2000), RBA::DPoint::new(3000, 2000) ] poly = - RBA::DPolygon::new(hull) poly.insert_hole(hole1) poly.insert_hole(hole2) - - # ask the polygon for some properties poly.holes # -> 2 poly.area # -> 16000000.0 - poly.perimeter # -> 26000.0 poly.bbox # -> (0,0;6000,3000) @/code - - The \\DPolygon class stores coordinates in floating-point format which gives a higher precision - for some operations. A class that stores integer coordinates is \\Polygon. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Set the points of the hull of polygon @args p @param p An array of points to assign to - the polygon's hull The 'assign_hull' variant is provided in analogy to 'assign_hole'.''' - hull = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test @args p @param p The object to compare against''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor converting a box to a polygon - - @args box - - @param box The box to convert to a polygon''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args p @param p The object to compare against This operator is - provided to establish some, not necessarily a certain sorting order''' - - def __mul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __ne__(self, ...): - '''@brief Inequality test @args p @param p The object to compare against''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Convert to a string''' - - def __rmul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Convert to a string''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def area(self, ...): - '''@brief The area of the polygon The area is correct only if the polygon is not self- - overlapping and the polygon is oriented clockwise.Orientation is ensured automatically in - most cases.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def assign_hole(self, ...): - '''@brief Set the box as the given hole of the polygon @args n,b @param n The index of the - hole to which the points should be assigned @param b The box to assign to the polygon's hole - If the hole index is not valid, this method does nothing. This method was introduced in - version 0.23.''' - - def assign_hull(self, ...): - '''@brief Set the points of the hull of polygon @args p @param p An array of points to - assign to the polygon's hull @param raw If true, the points won't be compressed - - If the 'raw' argument is set to true, the points are taken as they are. Specifically no - removal of redundant points or joining of coincident edges will take place. In effect, - polygons consisting of a single point or two points can be constructed as well as polygons - with duplicate points. Note that such polygons may cause problems in some applications. - - Regardless of raw mode, the point list will be adjusted such that the first point is the - lowest-leftmost one and the orientation is clockwise always. - - The 'assign_hull' variant is provided in analogy to 'assign_hole'. - - The 'raw' argument was added in version 0.24.''' - - def bbox(self, ...): - '''@brief Return the bounding box of the polygon The bounding box is the box enclosing all - points of the polygon.''' - - def compress(self, ...): - '''@brief Compress the polygon. @args remove_reflected - - This method removes redundant points from the polygon, such as points being on a line formed - by two other points. If remove_reflected is true, points are also removed if the two - adjacent edges form a spike. - - @param remove_reflected See description of the functionality. - - This method was introduced in version 0.18.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def each_edge(self, ...): - '''@brief Iterate over the edges of one contour of the polygon - - @args contour @param contour The contour number (0 for hull, 1 for first hole ...) - - This iterator will deliver all edges of the contour specified by the contour parameter. The - hull has contour number 0, the first hole has contour 1 etc. Hole edges are oriented - counterclockwise while hull egdes are oriented clockwise. - - This method was introduced in version 0.24.''' - - def each_point_hole(self, ...): - '''@brief Iterate over the points that make up the nth hole @args n The hole number must be - less than the number of holes (see \\holes)''' - - def each_point_hull(self, ...): - '''@brief Iterate over the points that make up the hull''' - - def extract_rad(self, ...): - '''@brief Extracts the corner radii from a rounded polygon - - Attempts to extract the radii of rounded corner polygon. This is essentially the inverse of - the \\round_corners method. If this method succeeds, if will return an array of four - elements: @ul @li The polygon with the rounded corners replaced by edgy ones @/li @li The - radius of the inner corners @/li @li The radius of the outer corners @/li @li The number of - points per full circle @/li @/ul - - This method is based on some assumptions and may fail. In this case, an empty array is - returned. - - If successful, the following code will more or less render the original polygon and - parameters - - @code p = ... # some polygon p.round_corners(ri, ro, n) (p2, ri2, ro2, n2) = p.extract_rad - # -> p2 == p, ro2 == ro, ri2 == ri, n2 == n (within some limits) @/code - - This method was introduced in version 0.25.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def holes(self, ...): - '''@brief Returns the number of holes''' - - def insert_hole(self, ...): - '''@brief Insert a hole from the given box @args b @param b The box to insert as a new hole - This method was introduced in version 0.23.''' - - def inside(self, ...): - '''@brief Test, if the given point is inside the polygon @args p If the given point is - inside or on the edge of the polygon, true is returned. This tests works well only if the - polygon is not self-overlapping and oriented clockwise. ''' - - def is_box(self, ...): - '''@brief Returns true, if the polygon is a simple box. - - A polygon is a box if it is identical to it's bounding box. - - @return True if the polygon is a box. - - This method was introduced in version 0.23.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def move(self, ...): - '''@brief Moves the polygon. @args x,y - - Moves the polygon by the given offset and returns the moved polygon. The polygon is - overwritten. - - @param x The x distance to move the polygon. @param y The y distance to move the polygon. - - @return The moved polygon (self).''' - - def moved(self, ...): - '''@brief Returns the moved polygon (does not modify self) @args x,y - - Moves the polygon by the given offset and returns the moved polygon. The polygon is not - modified. - - @param x The x distance to move the polygon. @param y The y distance to move the polygon. - - @return The moved polygon. - - This method has been introduced in version 0.23.''' - - def num_points(self, ...): - '''@brief Get the total number of points (hull plus holes) This method was introduced in - version 0.18.''' - - def num_points_hole(self, ...): - '''@brief Get the number of points of the given hole @args n The argument gives the index of - the hole of which the number of points are requested. The index must be less than the number - of holes (see \\holes). ''' - - def num_points_hull(self, ...): - '''@brief Get the number of points of the hull''' - - def perimeter(self, ...): - '''@brief The perimeter of the polygon The perimeter is sum of the lengths of all edges - making up the polygon. - - This method has been introduce in version 0.23.''' - - def point_hole(self, ...): - '''@brief Get a specific point of a hole @args n,p @param n The index of the hole to which - the points should be assigned @param p The index of the point to get If the index of the - point or of the hole is not valid, a default value is returned. This method was introduced - in version 0.18.''' - - def point_hull(self, ...): - '''@brief Get a specific point of the hull @args p @param p The index of the point to get If - the index of the point is not a valid index, a default value is returned. This method was - introduced in version 0.18.''' - - def round_corners(self, ...): - '''@brief Rounds the corners of the polygon @args rinner, router, n - - Replaces the corners of the polygon with circle segments. - - @param rinner The circle radius of inner corners (in database units). @param router The - circle radius of outer corners (in database units). @param n The number of points per full - circle. - - @return The new polygon. - - This method was introduced in version 0.20 for integer coordinates and in 0.25 for all - coordinate types.''' - - def size(self, ...): - '''@brief Sizing (biasing) @args d - - Shifts the contour outwards (d>0) or inwards (d<0). This method is equivalent to @code - size(d, d, 2) @/code - - See \\size for a detailed description.''' - - def sized(self, ...): - '''@brief Sizing (biasing) @args d - - @brief Sizing (biasing) without modifying self This method is equivalent to @code sized(d, - d, 2) @/code - - See \\size and \\sized for a detailed description.''' - - def split(self, ...): - '''@brief Splits the polygon into two or more parts This method will break the polygon into - parts. The exact breaking algorithm is unspecified, the result are smaller polygons of - roughly equal number of points and 'less concave' nature. Usually the returned polygon set - consists of two polygons, but there can be more. The merged region of the resulting polygons - equals the original polygon with the exception of small snapping effects at new vertexes. - - The intended use for this method is a iteratively split polygons until the satisfy some - maximum number of points limit. - - This method has been introduced in version 0.25.3.''' - - def to_itype(self, ...): - '''@brief Converts the polygon to an integer coordinate polygon - - The database unit can be specified to translate the floating-point coordinate polygon in - micron units to an integer-coordinate polygon in database units. The polygons coordinates - will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Convert to a string''' - - def touches(self, ...): - '''@brief Returns true, if the polygon touches the other polygon. The polygons touch if they - overlap or their contours share at least one point. - - This method was introduced in version 0.25.1.''' - - def transform(self, ...): - '''@brief Transforms the polygon (in-place) @args t - - Transforms the polygon with the given transformation. Modifies self and returns self. An - out-of-place version which does not modify self is \\transformed. - - @param t The transformation to apply. - - This method has been introduced in version 0.24.''' - - def transformed(self, ...): - '''@brief Transforms the polygon with a complex transformation @args t - - Transforms the polygon with the given complex transformation. Does not modify the polygon - but returns the transformed polygon. - - @param t The transformation to apply. - - @return The transformed polygon. - - With version 0.25, the original 'transformed_cplx' method is deprecated and 'transformed' - takes both simple and complex transformations.''' - - def transformed_cplx(self, ...): - '''@brief Transforms the polygon with a complex transformation @args t - - Transforms the polygon with the given complex transformation. Does not modify the polygon - but returns the transformed polygon. - - @param t The transformation to apply. - - @return The transformed polygon. - - With version 0.25, the original 'transformed_cplx' method is deprecated and 'transformed' - takes both simple and complex transformations.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def ellipse(cls, ...): - '''@brief Creates a simple polygon appoximating an ellipse - - @args box, n - - @param box The bounding box of the ellipse @param n The number of points that will be used - to approximate the ellipse - - This method has been introduced in version 0.23.''' - - @classmethod - def from_ipoly(cls, ...): - '''@brief Creates a floating-point coordinate polygon from an integer coordinate polygon - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_ipolygon'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor converting a box to a polygon - - @args box - - @param box The box to convert to a polygon''' - - -class DSimplePolygon: - '''@brief A simple polygon class - - A simple polygon consists of an outer hull only. To support polygons with holes, use \\DPolygon. - The contour consists of several points. The point list is normalized such that the leftmost, - lowest point is the first one. The orientation is normalized such that the orientation of the - hull contour is clockwise. - - It is in no way checked that the contours are not over- lapping. This must be ensured by the - user of the object when filling the contours. - - The \\DSimplePolygon class stores coordinates in floating-point format which gives a higher - precision for some operations. A class that stores integer coordinates is \\SimplePolygon. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Set the points of the simple polygon - - @args pts @param pts An array of points to assign to the simple polygon - - See the constructor description for details about raw mode.''' - points = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test @args p @param p The object to compare against''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor converting a box to a polygon - - @args box - - @param box The box to convert to a polygon''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args p @param p The object to compare against This operator is - provided to establish some, not necessarily a certain sorting order - - This method has been introduced in version 0.25.''' - - def __mul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __ne__(self, ...): - '''@brief Inequality test @args p @param p The object to compare against''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Convert to a string''' - - def __rmul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Convert to a string''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def area(self, ...): - '''@brief The area of the polygon The area is correct only if the polygon is not self- - overlapping and the polygon is oriented clockwise.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Return the bounding box of the simple polygon''' - - def compress(self, ...): - '''@brief Compress the simple polygon. @args remove_reflected - - This method removes redundant points from the polygon, such as points being on a line formed - by two other points. If remove_reflected is true, points are also removed if the two - adjacent edges form a spike. - - @param remove_reflected See description of the functionality. - - This method was introduced in version 0.18.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def each_edge(self, ...): - '''@brief Iterate over the edges that make up the simple polygon''' - - def each_point(self, ...): - '''@brief Iterate over the points that make up the simple polygon''' - - def extract_rad(self, ...): - '''@brief Extracts the corner radii from a rounded polygon - - Attempts to extract the radii of rounded corner polygon. This is essentially the inverse of - the \\round_corners method. If this method succeeds, if will return an array of four - elements: @ul @li The polygon with the rounded corners replaced by edgy ones @/li @li The - radius of the inner corners @/li @li The radius of the outer corners @/li @li The number of - points per full circle @/li @/ul - - This method is based on some assumptions and may fail. In this case, an empty array is - returned. - - If successful, the following code will more or less render the original polygon and - parameters - - @code p = ... # some polygon p.round_corners(ri, ro, n) (p2, ri2, ro2, n2) = p.extract_rad - # -> p2 == p, ro2 == ro, ri2 == ri, n2 == n (within some limits) @/code - - This method was introduced in version 0.25.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given polygon. This method - enables polygons as hash keys. - - This method has been introduced in version 0.25.''' - - def inside(self, ...): - '''@brief Test, if the given point is inside the polygon @args p If the given point is - inside or on the edge the polygon, true is returned. This tests works well only if the - polygon is not self-overlapping and oriented clockwise. ''' - - def is_box(self, ...): - '''@brief Returns true, if the polygon is a simple box. - - A polygon is a box if it is identical to it's bounding box. - - @return True if the polygon is a box. - - This method was introduced in version 0.23.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def move(self, ...): - '''@brief Moves the polygon. @args x,y - - Moves the polygon by the given offset and returns the moved polygon. The polygon is - overwritten. - - @param x The x distance to move the polygon. @param y The y distance to move the polygon. - - @return The moved polygon (self).''' - - def moved(self, ...): - '''@brief Returns the moved polygon (does not modify self) @args x,y - - Moves the polygon by the given offset and returns the moved polygon. The polygon is not - modified. - - @param x The x distance to move the polygon. @param y The y distance to move the polygon. - - @return The moved polygon. - - This method has been introduced in version 0.23.''' - - def num_points(self, ...): - '''@brief Get the number of points''' - - def perimeter(self, ...): - '''@brief The perimeter of the polygon The perimeter is sum of the lengths of all edges - making up the polygon.''' - - def point(self, ...): - '''@brief Get a specific point of the contour@args p @param p The index of the point to get - If the index of the point is not a valid index, a default value is returned. This method was - introduced in version 0.18.''' - - def round_corners(self, ...): - '''@brief Round the corners of the polygon @args rinner, router, n - - Replaces the corners of the polygon with circle segments. - - @param rinner The circle radius of inner corners (in database units). @param router The - circle radius of outer corners (in database units). @param n The number of points per full - circle. - - @return The new polygon. - - This method was introduced in version 0.22 for integer coordinates and in 0.25 for all - coordinate types.''' - - def set_points(self, ...): - '''@brief Set the points of the simple polygon - - @param pts An array of points to assign to the simple polygon @param raw If true, the points - are taken as they are - - See the constructor description for details about raw mode. - - This method has been added in version 0.24.''' - - def split(self, ...): - '''@brief Splits the polygon into two or more parts This method will break the polygon into - parts. The exact breaking algorithm is unspecified, the result are smaller polygons of - roughly equal number of points and 'less concave' nature. Usually the returned polygon set - consists of two polygons, but there can be more. The merged region of the resulting polygons - equals the original polygon with the exception of small snapping effects at new vertexes. - - The intended use for this method is a iteratively split polygons until the satisfy some - maximum number of points limit. - - This method has been introduced in version 0.25.3.''' - - def to_itype(self, ...): - '''@brief Converts the polygon to an integer coordinate polygon The database unit can be - specified to translate the floating-point coordinate polygon in micron units to an integer- - coordinate polygon in database units. The polygon's' coordinates will be divided by the - database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Convert to a string''' - - def touches(self, ...): - '''@brief Returns true, if the polygon touches the other polygon. The polygons touch if they - overlap or their contours share at least one point. - - This method was introduced in version 0.25.1.''' - - def transform(self, ...): - '''@brief Transforms the simple polygon (in-place) @args t - - Transforms the simple polygon with the given transformation. Modifies self and returns self. - An out-of-place version which does not modify self is \\transformed. - - @param t The transformation to apply. - - This method has been introduced in version 0.24.''' - - def transformed(self, ...): - '''@brief Transforms the simple polygon. @args t - - Transforms the simple polygon with the given complex transformation. Does not modify the - simple polygon but returns the transformed polygon. - - @param t The transformation to apply. - - @return The transformed simple polygon. - - With version 0.25, the original 'transformed_cplx' method is deprecated and 'transformed' - takes both simple and complex transformations.''' - - def transformed_cplx(self, ...): - '''@brief Transforms the simple polygon. @args t - - Transforms the simple polygon with the given complex transformation. Does not modify the - simple polygon but returns the transformed polygon. - - @param t The transformation to apply. - - @return The transformed simple polygon. - - With version 0.25, the original 'transformed_cplx' method is deprecated and 'transformed' - takes both simple and complex transformations.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def ellipse(cls, ...): - '''@brief Creates a simple polygon appoximating an ellipse - - @args box, n - - @param box The bounding box of the ellipse @param n The number of points that will be used - to approximate the ellipse - - This method has been introduced in version 0.23.''' - - @classmethod - def from_ipoly(cls, ...): - '''@brief Creates a floating-point coordinate polygon from an integer coordinate polygon - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_ipoly'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor converting a box to a polygon - - @args box - - @param box The box to convert to a polygon''' - - -class DText: - '''@brief A text object - - A text object has a point (location), a text, a text transformation, a text size and a font id. - Text size and font id are provided to be be able to render the text correctly. Text objects are - used as labels (i.e. for pins) or to indiciate a particular position. - - The \\DText class uses floating-point coordinates. A class that operates with integer - coordinates is \\Text. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Get the font number - - @brief Set the font number @args f''' - font = None - - '''@brief Get the horizontal alignment - - See \\halign= for a description of this property. - - @brief Set the horizontal alignment @args a - - This property specifies how the text is aligned relative to the anchor point. Allowed values for - this property are 0 (left), 1 (center) and 2 (right). This property has been introduced in - version 0.22.''' - halign = None - - '''@brief Get the text height - - @brief Set the text height of this object @args s''' - size = None - - '''@brief Get the text string - - @brief Assign a text string to this object @args text''' - string = None - - '''@brief Get the transformation - - @brief Assign a transformation (text position and orientation) to this object @args t''' - trans = None - - '''@brief Get the vertical alignment - - See \\valign= for a description of this property. - - @brief Set the vertical alignment @args a - - This property specifies how the text is aligned relative to the anchor point. Allowed values for - this property are 0 (top), 1 (center) and 2 (bottom). This property has been introduced in - version 0.22.''' - valign = None - - '''@brief Gets the x location of the text - - This method has been introduced in version 0.23. - - @brief Sets the x location of the text @args x - - This method has been introduced in version 0.23.''' - x = None - - '''@brief Gets the y location of the text - - This method has been introduced in version 0.23. - - @brief Sets the y location of the text @args y - - This method has been introduced in version 0.23.''' - y = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality - - @args text - - Return true, if this text object and the given text are equal ''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given text object. This method - enables texts as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor with string, transformation, text height and font - - @args string, trans, height, font - - A string and a transformation is provided to this constructor. The transformation specifies - the location and orientation of the text object. In addition, the text height and font can - be specified.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args t @param t The object to compare against This operator is - provided to establish some, not necessarily a certain sorting order''' - - def __ne__(self, ...): - '''@brief Inequality - - @args text - - Return true, if this text object and the given text are not equal ''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Convert to a string''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Convert to a string''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given text object. This method - enables texts as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def move(self, ...): - '''@brief Moves the text by a certain distance (modifies self) - - @args dx, dy - - Moves the text by a given distance in x and y direction and returns the moved text. Does not - check for coordinate overflows. - - @param dx The x distance to move the text. @param dy The y distance to move the text. - - @return A reference to this text object - - This method was introduced in version 0.23.''' - - def moved(self, ...): - '''@brief Returns the text moved by a certain distance (does not modify self) - - @args dx, dy - - Moves the text by a given offset and returns the moved text. Does not modify *this. Does not - check for coordinate overflows. - - @param dx The x distance to move the text. @param dy The y distance to move the text. - - @return The moved text. - - This method was introduced in version 0.23.''' - - def to_itype(self, ...): - '''@brief Converts the text to an integer coordinate text - - The database unit can be specified to translate the floating-point coordinate Text in micron - units to an integer-coordinate text in database units. The text's coordinates will be - divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Convert to a string''' - - def transformed(self, ...): - '''@brief Transform the text with the given complex transformation - - @args t - - @param t The magnifying transformation to apply @return The transformed text (a DText - now)''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor with string, transformation, text height and font - - @args string, trans, height, font - - A string and a transformation is provided to this constructor. The transformation specifies - the location and orientation of the text object. In addition, the text height and font can - be specified.''' - - -class DTrans: - '''@brief A simple transformation - - Simple transformations only provide rotations about angles which a multiples of 90 degree. - Together with the mirror options, this results in 8 distinct orientations (fixpoint - transformations). These can be combined with a displacement which is applied after the - rotation/mirror. This version acts on floating-point coordinates. A version for integer - coordinates is \\Trans. - - Here are some examples for using the DTrans class: - - @code t = RBA::DTrans::new(0, 100) # displacement by 100 DBU in y direction # the inverse: -> - "r0 0,-100" t.inverted.to_s # concatenation: -> "r90 -100,0" (RBA::DTrans::new(RBA::DTrans::R90) - * t).to_s # apply to a point: -> "0,100" - RBA::DTrans::new(RBA::DTrans::R90).trans(RBA::DPoint::new(100, 0)) @/code - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the angle in units of 90 degree - - This value delivers the rotation component. In addition, a mirroring at the x axis may be - applied before if the \\is_mirror? property is true. - - @brief Sets the angle in units of 90 degree @param a The new angle - - This method was introduced in version 0.20.''' - angle = None - - '''@brief Gets to the displacement vector - - Staring with version 0.25 the displacement type is a vector. - - @brief Sets the displacement @param u The new displacement - - This method was introduced in version 0.20. Staring with version 0.25 the displacement type is a - vector.''' - disp = None - - '''@brief Sets the mirror flag "mirroring" describes a reflection at the x-axis which is - included in the transformation prior to rotation.@param m The new mirror flag - - This method was introduced in version 0.20.''' - mirror = None - - '''@brief Gets the angle/mirror code - - The angle/mirror code is one of the constants R0, R90, R180, R270, M0, M45, M90 and M135. rx is - the rotation by an angle of x counter clockwise. mx is the mirroring at the axis given by the - angle x (to the x-axis). - - @brief Sets the angle/mirror code @param r The new angle/rotation code (see \\rot property) - - This method was introduced in version 0.20.''' - rot = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Tests for equality''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a transformation using a displacement given as two coordinates - - @param x The horizontal displacement @param y The vertical displacement''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Provides a 'less' criterion for sorting This method is provided to implement a - sorting order. The definition of 'less' is opaque and might change in future versions.''' - - def __mul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __ne__(self, ...): - '''@brief Tests for inequality''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def ctrans(self, ...): - '''@brief Transforms a distance - - The "ctrans" method transforms the given distance. e = t(d). For the simple transformations, - there is no magnification and no modification of the distance therefore. - - @param d The distance to transform @return The transformed distance''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the transformation (in place) - - Inverts the transformation and replaces this object by the inverted one. - - @return The inverted transformation''' - - def inverted(self, ...): - '''@brief Returns the inverted transformation Returns the inverted transformation - - @return The inverted transformation''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_mirror(self, ...): - '''@brief Gets the mirror flag - - If this property is true, the transformation is composed of a mirroring at the x-axis - followed by a rotation by the angle given by the \\angle property. ''' - - def to_itype(self, ...): - '''@brief Converts the transformation to an integer coordinate transformation - - The database unit can be specified to translate the floating-point coordinate transformation - in micron units to an integer-coordinate transformation in database units. The - transformation's' coordinates will be divided by the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def trans(self, ...): - '''@brief Transforms a text - - 't*text' or 't.trans(text)' is equivalent to text.transformed(t). - - @param text The text to transform @return The transformed text - - This convenience method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_itrans(cls, ...): - '''@brief Creates a floating-point coordinate transformation from an integer coordinate - transformation - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_itrans'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates a transformation from a string Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a transformation using a displacement given as two coordinates - - @param x The horizontal displacement @param y The vertical displacement''' - - -class DVector: - '''@brief A vector class with double (floating-point) coordinates A vector is a distance in - cartesian, 2 dimensional space. A vector is given by two coordinates (x and y) and represents - the distance between two points. Being the distance, transformations act differently on vectors: - the displacement is not applied. Vectors are not geometrical objects by itself. But they are - frequently used in the database API for various purposes. Other than the integer variant - (\\Vector), points with floating-point coordinates can represent fractions of a database unit or - vectors in physical (micron) units. - - This class has been introduced in version 0.25. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Accessor to the x coordinate - - @brief Write accessor to the x coordinate @args coord''' - x = None - - '''@brief Accessor to the y coordinate - - @brief Write accessor to the y coordinate @args coord''' - y = None - - # Methods - def __add__(self, ...): - '''@brief Adds a vector and a point - - @args p - - Returns the point p shifted by the vector.''' - - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test operator - - @args v''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given vector. This method - enables vectors as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor for a vector from two coordinate values - - @args x, y''' - - def __itruediv__(self, ...): - '''@brief Division by some divisor - - @args d - - Divides the object in place. All coordinates are divided with the given divisor and if - necessary rounded.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief "less" comparison operator - - @args v - - This operator is provided to establish a sorting order''' - - def __mul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __ne__(self, ...): - '''@brief Inequality test operator - - @args v''' - - def __neg__(self, ...): - '''@brief Compute the negative of a vector - - @args p - - Returns a new vector with -x,-y.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Scaling by some factor - - @args f - - Returns the scaled object. All coordinates are multiplied with the given factor and if - necessary rounded.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def __sub__(self, ...): - '''@brief Subtract two vectors - - @args v - - Subtract vector v from self by subtracting the coordinates.''' - - def __truediv__(self, ...): - '''@brief Division by some divisor - - @args d - - Returns the scaled object. All coordinates are divided with the given divisor and if - necessary rounded.''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def abs(self, ...): - '''@brief Returns the length of the vector 'abs' is an alias provided for compatibility with - the former point type.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given vector. This method - enables vectors as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def length(self, ...): - '''@brief Returns the length of the vector 'abs' is an alias provided for compatibility with - the former point type.''' - - def sprod(self, ...): - '''@brief Computes the scalar product between self and the given vector - - @args v - - The scalar product of a and b is defined as: vp = ax*bx+ay*by.''' - - def sprod_sign(self, ...): - '''@brief Computes the scalar product between self and the given vector and returns a value - indicating the sign of the product - - @args v - - @return 1 if the scalar product is positive, 0 if it is zero and -1 if it is negative.''' - - def sq_abs(self, ...): - '''@brief The square length of the vector 'sq_abs' is an alias provided for compatibility - with the former point type.''' - - def sq_length(self, ...): - '''@brief The square length of the vector 'sq_abs' is an alias provided for compatibility - with the former point type.''' - - def to_itype(self, ...): - '''@brief Converts the point to an integer coordinate point - - The database unit can be specified to translate the floating-point coordinate vector in - micron units to an integer-coordinate vector in database units. The vector's' coordinates - will be divided by the database unit.''' - - def to_p(self, ...): - '''@brief Turns the vector into a point This method returns the point resulting from adding - the vector to (0,0). This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def vprod(self, ...): - '''@brief Computes the vector product between self and the given vector - - @args v - - The vector product of a and b is defined as: vp = ax*by-ay*bx.''' - - def vprod_sign(self, ...): - '''@brief Computes the vector product between self and the given vector and returns a value - indicating the sign of the product - - @args v - - @return 1 if the vector product is positive, 0 if it is zero and -1 if it is negative.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s)''' - - @classmethod - def new(cls, ...): - '''@brief Constructor for a vector from two coordinate values - - @args x, y''' - - -class Edge: - '''@brief An edge class - - An edge is a connection between points, usually participating in a larger context such as a - polygon. An edge has a defined direction (from p1 to p2). Edges play a role in the database as - parts of polygons and to describe a line through both points. Altough supported, edges are - rarely used as individual database objects. - - See @The Database API@ for more details about the - database objects like the Edge class. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief The first point. - - @brief Sets the first point. @args point This method has been added in version 0.23.''' - p1 = None - - '''@brief The second point. - - @brief Sets the second point. @args point This method has been added in version 0.23.''' - p2 = None - - '''@brief Shortcut for p1.x - - @brief Sets p1.x @args coord This method has been added in version 0.23.''' - x1 = None - - '''@brief Shortcut for p2.x - - @brief Sets p2.x @args coord This method has been added in version 0.23.''' - x2 = None - - '''@brief Shortcut for p1.y - - @brief Sets p1.y @args coord This method has been added in version 0.23.''' - y1 = None - - '''@brief Shortcut for p2.y - - @brief Sets p2.y @args coord This method has been added in version 0.23.''' - y2 = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality test @args e @param e The object to compare against''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge. This method enables - edges as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args e @param e The object to compare against @return True, if the - edge is 'less' as the other edge with respect to first and second point''' - - def __mul__(self, ...): - '''@brief Scale edge - - @args scale_factor - - The * operator scales self with the given factor. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled edge''' - - def __ne__(self, ...): - '''@brief Inequality test @args e @param e The object to compare against''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing the edge''' - - def __rmul__(self, ...): - '''@brief Scale edge - - @args scale_factor - - The * operator scales self with the given factor. - - This method has been introduced in version 0.22. - - @param scale_factor The scaling factor - - @return The scaled edge''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing the edge''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Return the bounding box of the edge.''' - - def coincident(self, ...): - '''@brief Coincidence check. @args e - - Checks whether a edge is coincident with another edge. Coincidence is defined by being - parallel and that at least one point of one edge is on the other edge. - - @param e the edge to test with - - @return True if the edges are coincident.''' - - def contains(self, ...): - '''@brief Test whether a point is on an edge. @args p - - A point is on a edge if it is on (or at least closer than a grid point to) the edge. - - @param p The point to test with the edge. - - @return True if the point is on the edge.''' - - def contains_excl(self, ...): - '''@brief Test whether a point is on an edge excluding the endpoints. @args p - - A point is on a edge if it is on (or at least closer than a grid point to) the edge. - - @param p The point to test with the edge. - - @return True if the point is on the edge but not equal p1 or p2.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def crossed_by(self, ...): - '''@brief Check, if an edge is cut by a line (given by an edge) @args e - - This method returns true if p1 is in one semispace while p2 is in the other or one of them - is on the line through the edge "e" - - @param e The edge representing the line that the edge must be crossing.''' - - def crossing_point(self, ...): - '''@brief Returns the crossing point on two edges. @args e - - This method delivers the point where the given edge (self) crosses the line given by the - edge in argument "e". If self does not cross this line, the result is undefined. See - \\crossed_by? for a description of the crossing predicate. - - @param e The edge representing the line that self must be crossing. @return The point where - self crosses the line given by "e". - - This method has been introduced in version 0.19.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def distance(self, ...): - '''@brief Distance between the edge and a point. @args p - - Returns the distance between the edge and the point. The distance is signed which is - negative if the point is to the "left" of the edge and positive if the point is to the - "right". The distance is measured by projecting the point onto the line through the edge. If - the edge is degenerated, the distance is not defined. - - @param p The point to test. - - @return The distance''' - - def distance_abs(self, ...): - '''@brief Absolute distance between the edge and a point. @args p - - Returns the distance between the edge and the point. - - @param p The point to test. - - @return The distance''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def dx(self, ...): - '''@brief The horizontal extend of the edge.''' - - def dx_abs(self, ...): - '''@brief The absolute value of the horizontal extend of the edge.''' - - def dy(self, ...): - '''@brief The vertical extend of the edge.''' - - def dy_abs(self, ...): - '''@brief The absolute value of the vertical extend of the edge.''' - - def enlarge(self, ...): - '''@brief Enlarges the edge. @args p - - Enlarges the edge by the given distance and returns the enlarged edge. The edge is - overwritten. Enlargement means that the first point is shifted by -p, the second by p. - - @param p The distance to move the edge points. - - @return The enlarged edge.''' - - def enlarged(self, ...): - '''@brief Returns the enlarged edge (does not modify self) @args p - - Enlarges the edge by the given offset and returns the enlarged edge. The edge is not - modified. Enlargement means that the first point is shifted by -p, the second by p. - - @param p The distance to move the edge points. - - @return The enlarged edge.''' - - def extend(self, ...): - '''@brief Extends the edge (modifies self) @args d - - Extends the edge by the given distance and returns the extended edge. The edge is not - modified. Extending means that the first point is shifted by -d along the edge, the second - by d. The length of the edge will increase by 2*d. - - \\extended is a version that does not modify self but returns the extended edges. - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the end points. - - @return The extended edge (self).''' - - def extended(self, ...): - '''@brief Returns the extended edge (does not modify self) @args d - - Extends the edge by the given distance and returns the extended edge. The edge is not - modified. Extending means that the first point is shifted by -d along the edge, the second - by d. The length of the edge will increase by 2*d. - - \\extend is a version that modifies self (in-place). - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the end points. - - @return The extended edge.''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge. This method enables - edges as hash keys. - - This method has been introduced in version 0.25.''' - - def intersect(self, ...): - '''@brief Intersection test. @args e - - Returns true if the edges intersect. Two edges intersect if they share at least one point. - If the edges coincide, they also intersect. For degenerated edges, the intersection is - mapped to point containment tests. - - @param e The edge to test.''' - - def intersection_point(self, ...): - '''@brief Returns the intersection point of two edges. @args e - - This method delivers the intersection point. If the edges do not intersect, the result is - undefined. - - @param e The edge to test. @return The point where the edges intersect. - - This method has been introduced in version 0.19.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_degenerate(self, ...): - '''@brief Test for degenerated edge - - An edge is degenerate, if both end and start point are identical.''' - - def is_parallel(self, ...): - '''@brief Test for being parallel @args e - - @param e The edge to test against - - @return True if both edges are parallel''' - - def length(self, ...): - '''@brief The length of the edge''' - - def move(self, ...): - '''@brief Moves the edge. @args dx, dy - - Moves the edge by the given offset and returns the moved edge. The edge is overwritten. - - @param dx The x distance to move the edge. @param dy The y distance to move the edge. - - @return The moved edge. - - This version has been added in version 0.23.''' - - def moved(self, ...): - '''@brief Returns the moved edge (does not modify self) @args dx, dy - - Moves the edge by the given offset and returns the moved edge. The edge is not modified. - - @param dx The x distance to move the edge. @param dy The y distance to move the edge. - - @return The moved edge. - - This version has been added in version 0.23.''' - - def ortho_length(self, ...): - '''@brief The orthogonal length of the edge ("manhattan-length") - - @return The orthogonal length (abs(dx)+abs(dy))''' - - def shift(self, ...): - '''@brief Shifts the edge (modifies self) @args d - - Shifts the edge by the given distance and returns the shifted edge. The edge is not - modified. Shifting by a positive value will produce an edge which is shifted by d to the - left. Shifting by a negative value will produce an edge which is shifted by d to the right. - - \\shifted is a version that does not modify self but returns the extended edges. - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the edge. - - @return The shifted edge (self).''' - - def shifted(self, ...): - '''@brief Returns the shifted edge (does not modify self) @args d - - Shifts the edge by the given distance and returns the shifted edge. The edge is not - modified. Shifting by a positive value will produce an edge which is shifted by d to the - left. Shifting by a negative value will produce an edge which is shifted by d to the right. - - \\shift is a version that modifies self (in-place). - - This method has been introduced in version 0.23. - - @param d The distance by which to shift the edge. - - @return The shifted edge.''' - - def side_of(self, ...): - '''@brief Indicates at which side the point is located relative to the edge. @args p - - Returns 1 if the point is "left" of the edge, 0 if on and -1 if the point is "right" of the - edge. - - @param p The point to test. - - @return The side value''' - - def sq_length(self, ...): - '''@brief The square of the length of the edge''' - - def swap_points(self, ...): - '''@brief Swap the points of the edge - - This version modifies self. A version that does not modify self is \\swapped_points. - Swapping the points basically reverses the direction of the edge. - - This method has been introduced in version 0.23.''' - - def swapped_points(self, ...): - '''@brief Returns an edge in which both points are swapped - - Swapping the points basically reverses the direction of the edge. - - This method has been introduced in version 0.23.''' - - def to_dtype(self, ...): - '''@brief Converts the edge to a floating-point coordinate edge - - The database unit can be specified to translate the integer-coordinate edge into a floating- - point coordinate edge in micron units. The database unit is basically a scaling factor. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing the edge''' - - def transformed(self, ...): - '''@brief Transform the edge. @args t - - Transforms the edge with the given complex transformation. Does not modify the edge but - returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge.''' - - def transformed_cplx(self, ...): - '''@brief Transform the edge. @args t - - Transforms the edge with the given complex transformation. Does not modify the edge but - returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_dedge(cls, ...): - '''@brief Creates an integer coordinate edge from a floating-point coordinate edge - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_dedge'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - @classmethod - def new_pp(cls, ...): - '''@brief Constructor with two points - - @args p1, p2 - - Two points are given to create a new edge.''' - - @classmethod - def new_xyxy(cls, ...): - '''@brief Constructor with two coordinates given as single values - - @args x1, y1, x2, y2 - - Two points are given to create a new edge.''' - - -class EdgePair: - '''@brief An edge pair (a pair of two edges) Edge pairs are objects representing two edges or - parts of edges. They play a role mainly in the context of DRC functions, where they specify a - DRC violation by connecting two edges which violate the condition checked. Within the framework - of polygon and edge collections which provide DRC functionality, edges pairs are used in the - form of edge pair collections (\\EdgePairs). - - Edge pairs basically consist of two edges, called first and second. If created by a two-layer - DRC function, the first edge will correspond to edges from the first layer and the second to - edges from the second layer. - - This class has been introduced in version 0.23. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the first edge - - @brief Sets the first edge @args edge''' - first = None - - '''@brief Gets the second edge - - @brief Sets the second edge @args edge''' - second = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality @args box Returns true, if this edge pair and the given one are equal - - This method has been introduced in version 0.25.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge pair. This method - enables edge pairs as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Constructor from two edges - - This constructor creates an edge pair from the two edges given.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Less operator @args box Returns true, if this edge pair is 'less' with respect to - first and second edge - - This method has been introduced in version 0.25.''' - - def __ne__(self, ...): - '''@brief Inequality @args box Returns true, if this edge pair and the given one are not - equal - - This method has been introduced in version 0.25.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Returns a string representing the edge pair''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Returns a string representing the edge pair''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Gets the bounding box of the edge pair''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given edge pair. This method - enables edge pairs as hash keys. - - This method has been introduced in version 0.25.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def normalized(self, ...): - '''@brief Normalizes the edge pair This method normalized the edge pair such that when - connecting the edges at their start and end points a closed loop is formed which is - oriented clockwise. To achieve this, the points of the first and/or first and second edge - are swapped. Normalization is a first step recommended before converting an edge pair to a - polygon, because that way the polygons won't be self-overlapping and the enlargement - parameter is applied properly.''' - - def polygon(self, ...): - '''@brief Convert an edge pair to a polygon @args e The enlargement (set to zero for exact - representation) The polygon is formed by connecting the end and start points of the edges. - It is recommended to use \\normalized before converting the edge pair to a polygon. - - The enlargement parameter allows to apply the specified enlargement parallel and - perpendicular to the edges. Basically this introduces a bias which blows up edge pairs by - the specified amount. That parameter is useful to convert degenerated edge pairs to valid - polygons, i.e. edge pairs with coincident edges and edge pairs consisting of two point-like - edges. - - Another version for converting edge pairs to simple polygons is \\simple_polygon which - renders a \\SimplePolygon object.''' - - def simple_polygon(self, ...): - '''@brief Convert an edge pair to a simple polygon @args e The enlargement (set to zero for - exact representation) The polygon is formed by connecting the end and start points of the - edges. It is recommended to use \\normalized before converting the edge pair to a polygon. - - The enlargement parameter allows to apply the specified enlargement parallel and - perpendicular to the edges. Basically this introduces a bias which blows up edge pairs by - the specified amount. That parameter is useful to convert degenerated edge pairs to valid - polygons, i.e. edge pairs with coincident edges and edge pairs consisting of two point-like - edges. - - Another version for converting edge pairs to polygons is \\polygon which renders a \\Polygon - object.''' - - def to_dtype(self, ...): - '''@brief Converts the edge pair to a floating-point coordinate edge pair - - The database unit can be specified to translate the integer-coordinate edge pair into a - floating-point coordinate edge pair in micron units. The database unit is basically a - scaling factor. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief Returns a string representing the edge pair''' - - def transformed(self, ...): - '''@brief Returns the transformed edge pair @args t - - Transforms the edge pair with the given complex transformation. Does not modify the edge - pair but returns the transformed edge. - - @param t The transformation to apply. - - @return The transformed edge pair''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string @args s Creates the object from a string - representation (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Constructor from two edges - - This constructor creates an edge pair from the two edges given.''' - - -class EdgePairs: - '''@brief EdgePairs (a collection of edge pairs) - - Edge pairs are used mainly in the context of the DRC functions (width_check, space_check etc.) - of \\Region and \\Edges. A single edge pair represents two edges participating in a DRC - violation. In the two-layer checks (inside, overlap) The first edge represents an edge from the - first layer and the second edge an edge from the second layer. For single-layer checks (width, - space) the order of the edges is arbitrary. - - This class has been introduced in version 0.23. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - # Methods - def __add__(self, ...): - '''@brief Returns the combined edge pair collection of self and the other one - - @args other @return The resulting edge pair collection - - This operator adds the edge pairs of the other collection to self and returns a new combined - set. - - This method has been introduced in version 0.24.''' - - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __getitem__(self, ...): - '''@brief Returns the nth edge pair @args n - - This method returns nil if the index is out of range.''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __iadd__(self, ...): - '''@brief Adds the edge pairs of the other edge pair collection to self - - @args other @return The edge pair collection after modification (self) - - This operator adds the edge pairs of the other collection to self. - - This method has been introduced in version 0.24.''' - - def __init__(self, ...): - '''@brief Default constructor - - This constructor creates an empty edge pair collection.''' - - def __iter__(self, ...): - '''@brief Returns each edge pair of the edge pair collection''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __len__(self, ...): - '''@brief Returns the number of edge pairs in this collection''' - - def __lt__(self, ...): - '''Return self - creates a polygon with a hole, since the 'resolve_holes' parameter # is false: out = - ep.boolean_p2p(a, b, RBA::EdgeProcessor::ModeXor, false, false) out.to_s # -> - [(0,0;0,300;300,300;300,0/100,100;200,100;200,200;100,200)] @/code ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __getitem__(self, ...): - '''@brief Returns the nth edge of the edge collection @args n - - This method returns nil if the index is out of range.''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __iadd__(self, ...): - '''@brief Adds the edges of the other edge collection to self - - @args other @return The edge set after modification (self) - - This operator adds the edges of the other edge set to self. This usually creates unmerged - edge sets and edges may overlap. Use \\merge if you want to ensure the result edge set is - merged.''' - - def __iand__(self, ...): - '''@brief Selects the parts of the edges inside the given region - - @args other @return The edge collection after modification (self) - - This operation selects the parts of the edges which are inside the given region. Edges on - the borders of the polygons are included in the edge set. As a side effect, the edges are - made non-intersecting by introducing cut points where edges intersect. - - This method has been introduced in version 0.24.''' - - def __init__(self, ...): - '''@brief Constructor from a hierarchical shape set with a transformation @args - shape_iterator, trans, as_edges - - This constructor creates an edge collection from the shapes delivered by the given recursive - shape iterator. It feeds the shapes from a hierarchy of cells into the edge set. The - transformation is useful to scale to a specific database unit for example. - - Text objects are not inserted, because they cannot be converted to edges. Edge objects are - inserted as such. If "as_edges" is true, "solid" objects (boxes, polygons, paths) are - converted to edges which form the hull of these objects. If "as_edges" is false, solid - objects are ignored. - - @code layout = ... # a layout cell = ... # the index of the initial cell layer = ... # - the index of the layer from where to take the shapes from dbu = 0.1 # the target database - unit r = RBA::Edges::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / - dbu)) @/code''' - - def __ior__(self, ...): - '''@brief Performs the boolean OR between self and the other redge set - - @args other @return The edge collection after modification (self) - - The boolean OR is implemented by merging the edges of both edge sets. To simply join the - edge collections without merging, the + operator is more efficient.''' - - def __isub__(self, ...): - '''@brief Selects the parts of the edges outside the given region - - @args other @return The edge collection after modification (self) - - This operation selects the parts of the edges which are outside the given region. Edges on - the borders of the polygons are not included in the edge set. As a side effect, the edges - are made non-intersecting by introducing cut points where edges intersect. - - This method has been introduced in version 0.24.''' - - def __iter__(self, ...): - '''@brief Returns each edge of the region''' - - def __ixor__(self, ...): - '''@brief Performs the boolean XOR between self and the other edge collection - - @args other @return The edge collection after modification (self) - - The boolean XOR operation will return all parts of the edges in this and the other - collection except the parts where both are coincident. The result will be a merged edge - collection.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __len__(self, ...): - '''@brief Returns the number of edges in the edge collection''' - - def __lt__(self, ...): - '''Return selfThe Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the angle - - Note that the simple transformation returns the angle in units of 90 degree. Hence for a simple - trans (i.e. \\Trans), a rotation angle of 180 degree delivers a value of 2 for the angle - attribute. The complex transformation, supporting any rotation angle returns the angle in - degree. - - @return The rotation angle this transformation provides in degree units (0..360 deg). - - @brief Sets the angle @param a The new angle See \\angle for a description of that - attribute.''' - angle = None - - '''@brief Gets the displacement - - @brief Sets the displacement @param u The new displacement''' - disp = None - - '''@brief Gets the magnification - - @brief Sets the magnification @args m @param m The new magnification''' - mag = None - - '''@brief Sets the mirror flag "mirroring" describes a reflection at the x-axis which is - included in the transformation prior to rotation.@param m The new mirror flag''' - mirror = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Tests for equality''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Provides a 'less' criterion for sorting This method is provided to implement a - sorting order. The definition of 'less' is opaque and might change in future versions.''' - - def __mul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __ne__(self, ...): - '''@brief Tests for inequality''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief String conversion''' - - def __rmul__(self, ...): - '''@brief Returns the concatenated transformation - - The * operator returns self*t ("t is applied before this transformation"). - - @param t The transformation to apply before @return The modified transformation''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief String conversion''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def ctrans(self, ...): - '''@brief Transforms a distance - - The "ctrans" method transforms the given distance. e = t(d). For the simple transformations, - there is no magnification and no modification of the distance therefore. - - @param d The distance to transform @return The transformed distance''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def hash(self, ...): - '''@brief Computes a hash value Returns a hash value for the given transformation. This - method enables transformations as hash keys. - - This method has been introduced in version 0.25.''' - - def invert(self, ...): - '''@brief Inverts the transformation (in place) - - Inverts the transformation and replaces this transformation by it's inverted one. - - @return The inverted transformation''' - - def inverted(self, ...): - '''@brief Returns the inverted transformation - - Returns the inverted transformation. This method does not modify the transformation. - - @return The inverted transformation''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_mag(self, ...): - '''@brief Test, if the transformation is a magnifying one - - This is the recommended test for checking if the transformation represents a - magnification.''' - - def is_mirror(self, ...): - '''@brief Gets the mirror flag - - If this property is true, the transformation is composed of a mirroring at the x-axis - followed by a rotation by the angle given by the \\angle property. ''' - - def is_ortho(self, ...): - '''@brief Tests, if the transformation is an orthogonal transformation - - If the rotation is by a multiple of 90 degree, this method will return true.''' - - def is_unity(self, ...): - '''@brief Tests, whether this is a unit transformation''' - - def rot(self, ...): - '''@brief Returns the respective simple transformation equivalent rotation code if possible - - If this transformation is orthogonal (is_ortho () == true), then this method will return the - corresponding fixpoint transformation, not taking into account magnification and - displacement. If the transformation is not orthogonal, the result reflects the quadrant the - rotation goes into.''' - - def s_trans(self, ...): - '''@brief Extracts the simple transformation part - - The simple transformation part does not reflect magnification or arbitrary angles. Rotation - angles are rounded down to multiples of 90 degree. Magnification is fixed to 1.0.''' - - def to_itrans(self, ...): - '''@brief Converts the transformation to another transformation with floating-point input - and output coordinates - - The database unit can be specified to translate the integer coordinate displacement in - database units to a floating-point displacement in micron units. The displacement's' - coordinates will be multiplied with the database unit. - - This method has been introduced in version 0.25.''' - - def to_s(self, ...): - '''@brief String conversion''' - - def to_trans(self, ...): - '''@brief Converts the transformation to another transformation with floating-point input - coordinates - - This method has been introduced in version 0.25.''' - - def to_vtrans(self, ...): - '''@brief Converts the transformation to another transformation with floating-point output - coordinates - - The database unit can be specified to translate the integer coordinate displacement in - database units to a floating-point displacement in micron units. The displacement's' - coordinates will be multiplied with the database unit. - - This method has been introduced in version 0.25.''' - - def trans(self, ...): - '''@brief Transforms a text - - 't*text' or 't.trans(text)' is equivalent to text.transformed(t). - - @param text The text to transform @return The transformed text - - This convenience method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_dtrans(cls, ...): - '''@brief Creates a floating-point coordinate transformation from another coordinate flavour - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_dtrans'.''' - - @classmethod - def from_s(cls, ...): - '''@brief Creates an object from a string Creates the object from a string representation - (as returned by \\to_s) - - This method has been added in version 0.23.''' - - @classmethod - def from_trans(cls, ...): - '''@brief Creates a floating-point coordinate transformation from another coordinate flavour - - This constructor has been introduced in version 0.25 and replaces the previous static method - 'from_trans'.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a transformation using magnification, angle, mirror flag and displacement - - The sequence of operations is: magnification, mirroring at x axis, rotation, application of - displacement. - - @param mag The magnification @param rot The rotation angle in units of degree @param mirrx - True, if mirrored at x axis @param x The x displacement @param y The y displacement''' - - -class InstElement: - '''@brief An element in an instantiation path - - This objects are used to reference a single instance in a instantiation path. The object is - composed of a \\CellInstArray object (accessible through the \\cell_inst accessor) that - describes the basic instance, which may be an array. The particular instance within the array - can be further retrieved using the \\array_member_trans, \\specific_trans or - \\specific_cplx_trans methods. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Equality of two InstElement objects @args b Note: this operator returns true if - both instance elements refer to the same instance, not just identical ones.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Create an instance element from an array instance pointing into a certain array - member @args inst, a_index, b_index Starting with version 0.15, this method takes an - \\Instance object (an instance reference) as the first argument.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''@brief Provides an order criterion for two InstElement objects @args b Note: this - operator is just provided to establish any order, not a particular one.''' - - def __ne__(self, ...): - '''@brief Inequality of two InstElement objects @args b See the comments on the == - operator.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''Return repr(self).''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''Return str(self).''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def array_member_trans(self, ...): - '''@brief Returns the transformation for this array member - - The array member transformation is the one applicable in addition to the global - transformation for the member selected from an array. If this instance is not an array - instance, the specific transformation is a unit transformation without displacement.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def cell_inst(self, ...): - '''@brief Accessor to the cell instance (array). - - This method is equivalent to "self.inst.cell_inst" and provided for convenience.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def ia(self, ...): - '''@brief Returns the 'a' axis index for array instances For instance elements describing - one member of an array, this attribute will deliver the a axis index addressed by this - element. See \\ib and \\array_member_trans for further attributes applicable to array - members. If the element is a plain instance and not an array member, this attribute is a - negative value. - - This method has been introduced in version 0.25.''' - - def ib(self, ...): - '''@brief Returns the 'b' axis index for array instances For instance elements describing - one member of an array, this attribute will deliver the a axis index addressed by this - element. See \\ia and \\array_member_trans for further attributes applicable to array - members. If the element is a plain instance and not an array member, this attribute is a - negative value. - - This method has been introduced in version 0.25.''' - - def inst(self, ...): - '''@brief Gets the \\Instance object held in this instance path element. - - This method has been added in version 0.24.''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def prop_id(self, ...): - '''@brief Accessor to the property attached to this instance. - - This method is equivalent to "self.inst.prop_id" and provided for convenience.''' - - def specific_cplx_trans(self, ...): - '''@brief Returns the specific complex transformation for this instance - - The specific transformation is the one applicable for the member selected from an array. - This is the effective transformation applied for this array member. \\array_member_trans - gives the transformation applied additionally to the instances' global transformation (in - other words, specific_cplx_trans = array_member_trans * cell_inst.cplx_trans).''' - - def specific_trans(self, ...): - '''@brief Returns the specific transformation for this instance - - The specific transformation is the one applicable for the member selected from an array. - This is the effective transformation applied for this array member. \\array_member_trans - gives the transformation applied additionally to the instances' global transformation (in - other words, specific_trans = array_member_trans * cell_inst.trans). This method delivers a - simple transformation that does not include magnification components. To get these as well, - use \\specific_cplx_trans.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def new(cls, ...): - '''@brief Create an instance element from an array instance pointing into a certain array - member @args inst, a_index, b_index Starting with version 0.15, this method takes an - \\Instance object (an instance reference) as the first argument.''' - - @classmethod - def new_i(cls, ...): - '''@brief Create an instance element from a single instance alone @args inst Starting with - version 0.15, this method takes an \\Instance object (an instance reference) as the - argument.''' - - @classmethod - def new_iab(cls, ...): - '''@brief Create an instance element from an array instance pointing into a certain array - member @args inst, a_index, b_index Starting with version 0.15, this method takes an - \\Instance object (an instance reference) as the first argument.''' - - -class Instance: - '''@brief An instance proxy - - An instance proxy is basically a pointer to an instance of different kinds, similar to \\Shape, - the shape proxy. \\Instance objects can be duplicated without creating copies of the instances - itself: the copy will still point to the same instance than the original. - - When the \\Instance object is modified, the actual instance behind it is modified. The - \\Instance object acts as a simplified interface for single and array instances with or without - properties. - - See @The Database API@ for more details about the - database objects. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Returns the displacement vector for the 'a' axis - - Starting with version 0.25 the displacement is of vector type. - - @brief Sets the displacement vector for the 'a' axis @args a - - If the instance was not an array instance before it is made one. - - This method has been introduced in version 0.23. Starting with version 0.25 the displacement is - of vector type. - - @brief Sets the displacement vector for the 'a' axis in micrometer units - - Like \\a= with an integer displacement, this method will set the displacement vector but it - accepts a vector in micrometer units that is of \\DVector type. The vector will be translated to - database units internally. - - This method has been introduced in version 0.25.''' - a = None - - '''@brief Returns the displacement vector for the 'b' axis - - Starting with version 0.25 the displacement is of vector type. - - @brief Sets the displacement vector for the 'b' axis @args b - - If the instance was not an array instance before it is made one. - - This method has been introduced in version 0.23. Starting with version 0.25 the displacement is - of vector type. - - @brief Sets the displacement vector for the 'b' axis in micrometer units - - Like \\b= with an integer displacement, this method will set the displacement vector but it - accepts a vector in micrometer units that is of \\DVector type. The vector will be translated to - database units internally. - - This method has been introduced in version 0.25.''' - b = None - - '''@brief Gets the \\Cell object of the cell this instance refers to - - Please note that before version 0.23 this method returned the cell the instance is contained in. - For consistency, this method has been renamed \\parent_cell. - - This method has been introduced in version 0.23. - - @brief Gets the \\Cell object of the cell this instance refers to - - This is the const version of the \\cell method. It will return a const \\Cell object and itself - can be called on a const \\Instance object. - - This variant has been introduced in version 0.25. - - @brief Sets the \\Cell object this instance refers to @args cell - - Setting the cell object to nil is equivalent to deleting the instance. - - This method has been introduced in version 0.23.''' - cell = None - - '''@brief Get the index of the cell this instance refers to - - @brief Sets the index of the cell this instance refers to @args cell_index - - This method has been introduced in version 0.23.''' - cell_index = None - - '''@brief Gets the basic \\CellInstArray object associated with this instance reference. - - @brief Changes the \\CellInstArray object to the given one. @args inst This method replaces the - instance by the given CellInstArray object. - - This method has been introduced in version 0.22 - - @brief Returns the basic cell instance array object by giving a micrometer unit object. This - method replaces the instance by the given CellInstArray object and it internally transformed - into database units. - - This method has been introduced in version 0.25''' - cell_inst = None - - '''@brief Gets the complex transformation of the instance or the first instance in the array - This method is always valid compared to \\trans, since simple transformations can be expressed - as complex transformations as well. - - @brief Sets the complex transformation of the instance or the first instance in the array - - This method has been introduced in version 0.23. - - @brief Sets the complex transformation of the instance or the first instance in the array (in - micrometer units) This method sets the transformation the same way as \\cplx_trans=, but the - displacement of this transformation is given in micrometer units. It is internally translated - into database units. - - This method has been introduced in version 0.25.''' - cplx_trans = None - - '''@brief Returns the displacement vector for the 'a' axis in micrometer units - - Like \\a, this method returns the displacement, but it will be translated to database units - internally. - - This method has been introduced in version 0.25. - - @brief Sets the displacement vector for the 'a' axis in micrometer units - - Like \\a= with an integer displacement, this method will set the displacement vector but it - accepts a vector in micrometer units that is of \\DVector type. The vector will be translated to - database units internally. - - This method has been introduced in version 0.25.''' - da = None - - '''@brief Returns the displacement vector for the 'b' axis in micrometer units - - Like \\b, this method returns the displacement, but it will be translated to database units - internally. - - This method has been introduced in version 0.25. - - @brief Sets the displacement vector for the 'b' axis in micrometer units - - Like \\b= with an integer displacement, this method will set the displacement vector but it - accepts a vector in micrometer units that is of \\DVector type. The vector will be translated to - database units internally. - - This method has been introduced in version 0.25.''' - db = None - - '''@brief Returns the micrometer unit version of the basic cell instance array object. - - This method has been introduced in version 0.25 - - @brief Returns the basic cell instance array object by giving a micrometer unit object. This - method replaces the instance by the given CellInstArray object and it internally transformed - into database units. - - This method has been introduced in version 0.25''' - dcell_inst = None - - '''@brief Gets the complex transformation of the instance or the first instance in the array (in - micrometer units) This method returns the same transformation as \\cplx_trans, but the - displacement of this transformation is given in micrometer units. It is internally translated - from database units into micrometers. - - This method has been introduced in version 0.25. - - @brief Sets the complex transformation of the instance or the first instance in the array (in - micrometer units) This method sets the transformation the same way as \\cplx_trans=, but the - displacement of this transformation is given in micrometer units. It is internally translated - into database units. - - This method has been introduced in version 0.25.''' - dcplx_trans = None - - '''@brief Gets the transformation of the instance or the first instance in the array (in - micrometer units) This method returns the same transformation as \\cplx_trans, but the - displacement of this transformation is given in micrometer units. It is internally translated - from database units into micrometers. - - This method has been introduced in version 0.25. - - @brief Sets the transformation of the instance or the first instance in the array (in - micrometer units) This method sets the transformation the same way as \\cplx_trans=, but the - displacement of this transformation is given in micrometer units. It is internally translated - into database units. - - This method has been introduced in version 0.25.''' - dtrans = None - - '''@brief Returns the number of instances in the 'a' axis - - @brief Sets the number of instances in the 'a' axis @args na - - If the instance was not an array instance before it is made one. - - This method has been introduced in version 0.23.''' - na = None - - '''@brief Returns the number of instances in the 'b' axis - - @brief Sets the number of instances in the 'b' axis @args nb - - If the instance was not an array instance before it is made one. - - This method has been introduced in version 0.23.''' - nb = None - - '''@brief Gets the cell this instance is contained in - - Returns nil if the instance does not live inside a cell. This method was named "cell" previously - which lead to confusion with \\cell_index. It was renamed to "parent_cell" in version 0.23. - - @brief Gets the cell this instance is contained in - - Returns nil if the instance does not live inside a cell. - - This const version of the \\parent_cell method has been introduced in version 0.25. - - @brief Moves the instance to a different cell - - Both the current and the target cell must live in the same layout. - - This method has been introduced in version 0.23.''' - parent_cell = None - - '''@brief Gets the properties ID associated with the instance - - @brief Sets the properties ID associated with the instance @args id This method is provided, if - a properties ID has been derived already. Usually it's more convenient to use \\delete_property, - \\set_property or \\property. - - This method has been introduced in version 0.22.''' - prop_id = None - - '''@brief Gets the transformation of the instance or the first instance in the array The - transformation returned is only valid if the array does not represent a complex transformation - array - - @brief Sets the transformation of the instance or the first instance in the array - - This method has been introduced in version 0.23. - - @brief Sets the transformation of the instance or the first instance in the array (in micrometer - units) This method sets the transformation the same way as \\cplx_trans=, but the displacement - of this transformation is given in micrometer units. It is internally translated into database - units. - - This method has been introduced in version 0.25.''' - trans = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''@brief Tests for equality of two Instance objects @args b See the hint on the < - operator.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __getitem__(self, ...): - '''@brief Gets the user property with the given key or, if available, the PCell parameter - with the name given by the key Getting the PCell parameter has priority over the user - property. This method has been introduced in version 0.25.''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __len__(self, ...): - '''@brief Gets the number of single instances in the instance array If the instance - represents a single instance, the count is 1. Otherwise it is na*nb.''' - - def __lt__(self, ...): - '''@brief Provides an order criterion for two Instance objects @args b Warning: this - operator is just provided to establish any order, not a particular one.''' - - def __ne__(self, ...): - '''@brief Tests for inequality of two Instance objects @args b Warning: this operator - returns true if both objects refer to the same instance, not just identical ones.''' - - def __reduce__(self, ...): - '''Helper for pickle.''' - - def __reduce_ex__(self, ...): - '''Helper for pickle.''' - - def __repr__(self, ...): - '''@brief Creates a string showing the contents of the reference @args with_cellname - - Passing true to with_cellname makes the string contain the cellname instead of the cell - index - - This method has been introduced with version 0.23.''' - - def __setattr__(self, ...): - '''Implement setattr(self, name, value).''' - - def __sizeof__(self, ...): - '''Size of object in memory, in bytes.''' - - def __str__(self, ...): - '''@brief Creates a string showing the contents of the reference @args with_cellname - - Passing true to with_cellname makes the string contain the cellname instead of the cell - index - - This method has been introduced with version 0.23.''' - - def _create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def _destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def _destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def _is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def _manage(self, ...): - '''@brief Marks the object as managed by the script side. After calling this method on an - object, the script side will be responsible for the management of the object. This method - may be called if an object is returned from a C++ function and the object is known not to be - owned by any C++ instance. If necessary, the script side may delete the object if the - script's reference is no longer required. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def _unmanage(self, ...): - '''@brief Marks the object as no longer owned by the script side. Calling this method will - make this object no longer owned by the script's memory management. Instead, the object must - be managed in some other way. Usually this method may be called if it is known that some C++ - object holds and manages this object. Technically speaking, this method will turn the - script's reference into a weak reference. After the script engine decides to delete the - reference, the object itself will still exist. If the object is not managed otherwise, - memory leaks will occur. - - Usually it's not required to call this method. It has been introduced in version 0.24.''' - - def assign(self, ...): - '''@brief Assigns another object to self @args other''' - - def bbox(self, ...): - '''@brief Gets the bounding box of the instance The bounding box incorporates all instances - that the array represents. It gives the overall extension of the child cell as seen in the - calling cell (or all array members if the instance forms an array). This method has been - introduced in version 0.23.''' - - def bbox_per_layer(self, ...): - '''@brief Gets the bounding box of the instance for a given layer @param layer_index The - index of the layer the bounding box will be computed for. The bounding box incorporates all - instances that the array represents. It gives the overall extension of the child cell as - seen in the calling cell (or all array members if the instance forms an array) for the given - layer. If the layer is empty in this cell and all it's children', an empty bounding box will - be returned. This method has been introduced in version 0.25.''' - - def change_pcell_parameter(self, ...): - '''@brief Changes a single parameter of a PCell instance to the given value @args name,value - - This method changes a parameter of a PCell instance to the given value. The name identifies - the PCell parameter and must correspond to one parameter listed in the PCell declaration. - - This method has been introduced in version 0.24.''' - - def change_pcell_parameters(self, ...): - '''@brief Changes the parameters of a PCell instance to the dictionary of parameters @args - dict - - This method changes the parameters of a PCell instance to the given values. The values are - specifies as a dictionary of names (keys) vs. values. Unknown names are ignored and only the - parameters listed in the dictionary are changed. - - This method has been introduced in version 0.24.''' - - def convert_to_static(self, ...): - '''@brief Converts a PCell instance to a static cell - - If the instance is a PCell instance, this method will convert the cell into a static cell - and remove the PCell variant if required. A new cell will be created containing the PCell - content but begin a static cell. If the instance is not a PCell instance, this method will - not do anything. - - This method has been introduced in version 0.24.''' - - def create(self, ...): - '''@brief Ensures the C++ object is created Use this method to ensure the C++ object is - created, for example to ensure that resources are allocated. Usually C++ objects are created - on demand and not necessarily when the script object is created.''' - - def dbbox(self, ...): - '''@brief Gets the bounding box of the instance in micron units Gets the bounding box (see - \\bbox) of the instance, but will compute the micrometer unit box by multiplying \\bbox with - the database unit. - - This method has been introduced in version 0.25.''' - - def dbbox_per_layer(self, ...): - '''@brief Gets the bounding box of the instance in micron units @param layer_index The index - of the layer the bounding box will be computed for. Gets the bounding box (see - \\bbox_per_layer) of the instance, but will compute the micrometer unit box by multiplying - \\bbox_per_layer with the database unit. - - This method has been introduced in version 0.25.''' - - def delete(self, ...): - '''@brief Deletes this instance - - After this method was called, the instance object is pointing to nothing. - - This method has been introduced in version 0.23.''' - - def delete_property(self, ...): - '''@brief Deletes the user property with the given key @args key This method is a - convenience method that deletes the property with the given key. It does nothing if no - property with that key exists. Using that method is more convenient than creating a new - property set with a new ID and assigning that properties ID. This method may change the - properties ID. Calling this method may invalidate any iterators. It should not be called - inside a loop iterating over instances. - - This method has been introduced in version 0.22.''' - - def destroy(self, ...): - '''@brief Explicitly destroys the object Explicitly destroys the object on C++ side if it - was owned by the script interpreter. Subsequent access to this object will throw an - exception. If the object is not owned by the script, this method will do nothing.''' - - def destroyed(self, ...): - '''@brief Returns a value indicating whether the object was already destroyed This method - returns true, if the object was destroyed, either explicitly or by the C++ side. The latter - may happen, if the object is owned by a C++ object which got destroyed itself.''' - - def dup(self, ...): - '''@brief Creates a copy of self''' - - def explode(self, ...): - '''@brief Explodes the instance array - - This method does nothing if the instance was not an array before. The instance object will - point to the first instance of the array afterwards. - - This method has been introduced in version 0.23.''' - - def flatten(self, ...): - '''@brief Flattens the instance @args levels - - This method will convert the instance to a number of shapes which are equivalent to the - content of the cell. The instance itself will be removed. This version of the method allows - specification of the number of hierarchy levels to remove. Specifying 1 for 'levels' will - remove the instance and replace it by the contents of the cell. Specifying a negative value - or zero for the number of levels will flatten the instance completely. - - This method has been introduced in version 0.24.''' - - def has_prop_id(self, ...): - '''@brief Returns true, if the instance has properties''' - - def is_complex(self, ...): - '''@brief Tests, if the array is a complex array - - Returns true if the array represents complex instances (that is, with magnification and - arbitrary rotation angles).''' - - def is_const_object(self, ...): - '''@brief Returns a value indicating whether the reference is a const reference This method - returns true, if self is a const reference. In that case, only const methods may be called - on self.''' - - def is_null(self, ...): - '''@brief Checks, if the instance is a valid one''' - - def is_pcell(self, ...): - '''@brief Returns a value indicating whether the instance is a PCell instance - - This method has been introduced in version 0.24.''' - - def is_regular_array(self, ...): - '''@brief Tests, if this instance is a regular array''' - - def is_valid(self, ...): - '''@brief Tests if the \\Instance object is still pointing to a valid instance If the - instance represented by the given reference has been deleted, this method returns false. If - however, another instance has been inserted already that occupies the original instances - position, this method will return true again. - - This method has been introduced in version 0.23 and is a shortcut for - "inst.cell.is_valid?(inst)".''' - - def layout(self, ...): - '''@brief Gets the layout this instance is contained in - - This const version of the method has been introduced in version 0.25.''' - - def pcell_declaration(self, ...): - '''@brief Returns the PCell declaration object - - If the instance is a PCell instance, this method returns the PCell declaration object for - that PCell. If not, this method will return nil. This method has been introduced in version - 0.24.''' - - def pcell_parameter(self, ...): - '''@brief Gets a PCell parameter by the name of the parameter @return The parameter value or - nil if the instance is not a PCell or does not have a parameter with given name - - This method has been introduced in version 0.25.''' - - def pcell_parameters(self, ...): - '''@brief Gets the parameters of a PCell instance as a list of values @return A list of - values - - If the instance is a PCell instance, this method will return an array of values where each - value corresponds to one parameter. The order of the values is the order the parameters are - declared in the PCell declaration. If the instance is not a PCell instance, this list - returned will be empty. - - This method has been introduced in version 0.24.''' - - def pcell_parameters_by_name(self, ...): - '''@brief Gets the parameters of a PCell instance as a dictionary of values vs. names - @return A dictionary of values by parameter name - - If the instance is a PCell instance, this method will return a map of values vs. parameter - names. The names are the ones defined in the PCell declaration.If the instance is not a - PCell instance, the dictionary returned will be empty. - - This method has been introduced in version 0.24.''' - - def property(self, ...): - '''@brief Gets the user property with the given key @args key This method is a convenience - method that gets the property with the given key. If no property with that key exists, it - will return nil. Using that method is more convenient than using the layout object and the - properties ID to retrieve the property value. This method has been introduced in version - 0.22.''' - - def set_property(self, ...): - '''@brief Sets the user property with the given key to the given value @args key, value This - method is a convenience method that sets the property with the given key to the given value. - If no property with that key exists, it will create one. Using that method is more - convenient than creating a new property set with a new ID and assigning that properties ID. - This method may change the properties ID. Calling this method may invalidate any iterators. - It should not be called inside a loop iterating over instances. - - This method has been introduced in version 0.22.''' - - def size(self, ...): - '''@brief Gets the number of single instances in the instance array If the instance - represents a single instance, the count is 1. Otherwise it is na*nb.''' - - def to_s(self, ...): - '''@brief Creates a string showing the contents of the reference @args with_cellname - - Passing true to with_cellname makes the string contain the cellname instead of the cell - index - - This method has been introduced with version 0.23.''' - - def transform(self, ...): - '''@brief Transforms the instance array with the given complex transformation (given in - micrometer units) Transforms the instance like \\transform does, but with a transformation - given in micrometer units. The displacement of this transformation is given in micrometers - and is internally translated to database units. - - This method has been introduced in version 0.25.''' - - def transform_into(self, ...): - '''@brief Transforms the instance array with the given complex transformation (given in - micrometer units) Transforms the instance like \\transform_into does, but with a - transformation given in micrometer units. The displacement of this transformation is given - in micrometers and is internally translated to database units. - - This method has been introduced in version 0.25.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def new(cls, ...): - '''@brief Creates a new object of this class''' - - -class LEFDEFReaderConfiguration: - '''@brief Detailed LEF/DEF reader options This class is a aggregate belonging to the - \\LoadLayoutOptions class. It provides options for the LEF/DEF reader. These options have been - placed into a separate class to account for their complexity. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the blockage marker layer datatype value. See \\produce_via_geometry for details - about the layer production rules. - - @brief Sets the blockage marker layer datatype value. See \\produce_via_geometry for details - about the layer production rules.''' - blockages_datatype = None - - '''@brief Gets the blockage marker layer name suffix. See \\produce_via_geometry for details - about the layer production rules. - - @brief Sets the blockage marker layer name suffix. See \\produce_via_geometry for details about - the layer production rules.''' - blockages_suffix = None - - '''@brief Gets the layer on which to produce the cell outline. This attribute is a string - correspondig to the string representation of \\LayerInfo. This string can be either a layer - number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details. The - setter for this attribute is \\cell_outline_layer=. See also \\produce_cell_outlines. - - @brief Sets the layer on which to produce the cell outline. See \\cell_outline_layer for - details.''' - cell_outline_layer = None - - '''@brief Gets a value indicating whether layers not mapped in the layer map shall be created - too See \\layer_map for details. - - @brief Sets a value indicating whether layers not mapped in the layer map shall be created too - See \\layer_map for details.''' - create_other_layers = None - - '''@brief Gets the database unit to use for producing the layout. This value specifies the - database to be used for the layout that is read. When a DEF file is specified with a different - database unit, the layout is translated into this database unit. - - @brief Sets the database unit to use for producing the layout. See \\dbu for details.''' - dbu = None - - '''@brief Gets the labels layer datatype value. See \\produce_via_geometry for details about the - layer production rules. - - @brief Sets the labels layer datatype value. See \\produce_via_geometry for details about the - layer production rules.''' - labels_datatype = None - - '''@brief Gets the label layer name suffix. See \\produce_via_geometry for details about the - layer production rules. - - @brief Sets the label layer name suffix. See \\produce_via_geometry for details about the layer - production rules.''' - labels_suffix = None - - '''@brief Gets the layer map to be used for the LEF/DEF reader @return A reference to the layer - map Because LEF/DEF layer mapping is substantially different than for normal layout files, the - LEF/DEF reader employs a separate layer mapping table. The LEF/DEF specific layer mapping is - stored within the LEF/DEF reader's configuration and can be accessed with this attribute. The - layer mapping table of \\LoadLayoutOptions will be ignored for the LEF/DEF reader. - - The setter is \\layer_map=. \\create_other_layers= is available to control whether layers not - specified in the layer mapping table shall be created automatically. - - @brief Sets the layer map to be used for the LEF/DEF reader See \\layer_map for details.''' - layer_map = None - - '''@brief Gets the list technology LEF files to additionally import Returns a list of path names - for technology LEF files to read in addition to the primary file. Relative paths are resolved - relative to the file to read. - - The setter for this property is \\lef_files=. - - @brief Sets the list technology LEF files to additionally import See \\lef_files for details.''' - lef_files = None - - '''@brief Gets a value indicating whether and how to produce net names as properties. If set to - a value not nil, net names will be attached to the shapes and instances generated as user - properties. This attribute then specifies the user property name to be used for attaching the - net names. If set to nil, no net names will be produced. - - The corresponding setter is \\net_property_name=. - - @brief Sets a value indicating whether and how to produce net names as properties. See - \\net_property_name for details.''' - net_property_name = None - - '''@brief Gets the obstruction marker layer datatype value. See \\produce_via_geometry for - details about the layer production rules. - - @brief Sets the obstruction marker layer datatype value. See \\produce_via_geometry for details - about the layer production rules.''' - obstructions_datatype = None - - '''@brief Gets the obstruction marker layer name suffix. See \\produce_via_geometry for details - about the layer production rules. - - @brief Sets the obstruction marker layer name suffix. See \\produce_via_geometry for details - about the layer production rules.''' - obstructions_suffix = None - - '''@brief Gets the pin geometry layer datatype value. See \\produce_via_geometry for details - about the layer production rules. - - @brief Sets the pin geometry layer datatype value. See \\produce_via_geometry for details about - the layer production rules.''' - pins_datatype = None - - '''@brief Gets the pin geometry layer name suffix. See \\produce_via_geometry for details about - the layer production rules. - - @brief Sets the pin geometry layer name suffix. See \\produce_via_geometry for details about the - layer production rules.''' - pins_suffix = None - - '''@brief Gets the layer on which to produce the placement blockage. This attribute is a string - correspondig to the string representation of \\LayerInfo. This string can be either a layer - number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details.The - setter for this attribute is \\placement_blockage_layer=. See also - \\produce_placement_blockages. - - @brief Sets the layer on which to produce the placement blockage. See \\placement_blockage_layer - for details.''' - placement_blockage_layer = None - - '''@brief Gets a value indicating whether routing blockage markers shall be produced. See - \\produce_via_geometry for details about the layer production rules. - - @brief Sets a value indicating whether routing blockage markers shall be produced. See - \\produce_via_geometry for details about the layer production rules.''' - produce_blockages = None - - '''@brief Gets a value indicating whether to produce cell outlines. If set to true, cell - outlines will be produced on the layer given by \\cell_outline_layer. - - @brief Sets a value indicating whether to produce cell outlines. See \\produce_cell_outlines for - details.''' - produce_cell_outlines = None - - '''@brief Gets a value indicating whether labels shall be produced. See \\produce_via_geometry - for details about the layer production rules. - - @brief Sets a value indicating whether labels shall be produced. See \\produce_via_geometry for - details about the layer production rules.''' - produce_labels = None - - '''@brief Gets a value indicating whether obstruction markers shall be produced. See - \\produce_via_geometry for details about the layer production rules. - - @brief Sets a value indicating whether obstruction markers shall be produced. See - \\produce_via_geometry for details about the layer production rules.''' - produce_obstructions = None - - '''@brief Gets a value indicating whether pin geometries shall be produced. See - \\produce_via_geometry for details about the layer production rules. - - @brief Sets a value indicating whether pin geometries shall be produced. See - \\produce_via_geometry for details about the layer production rules.''' - produce_pins = None - - '''@brief Gets a value indicating whether to produce placement blockage regions. If set to true, - polygons will be produced representing the placement blockage region on the layer given by - \\placement_blockage_layer. - - @brief Sets a value indicating whether to produce placement blockage regions. See - \\produce_placement_blockages for details.''' - produce_placement_blockages = None - - '''@brief Gets a value indicating whether routing geometry shall be produced. See - \\produce_via_geometry for details about the layer production rules. - - @brief Sets a value indicating whether routing geometry shall be produced. See - \\produce_via_geometry for details about the layer production rules.''' - produce_routing = None - - '''@brief Sets a value indicating whether via geometries shall be produced. - - If set to true, shapes will be produced for each via. The layer to be produced will be - determined from the via layer's name using the suffix provided by \\via_geometry_suffix. If - there is a specific mapping in the layer mapping table for the via layer including the suffix, - the layer/datatype will be taken from the layer mapping table. If there is a mapping to the - undecorated via layer, the datatype will be substituted with the \\via_geometry_datatype value. - If no mapping is defined, a unique number will be assigned to the layer number and the datatype - will be taken from the \\via_geometry_datatype value. - - For example: the via layer is 'V1', \\via_geometry_suffix is 'GEO' and \\via_geometry_datatype - is 1. Then: - - @li @ul If there is a mapping for 'V1.GEO', the layer and datatype will be taken from there. - @/ul @ul If there is a mapping for 'V1', the layer will be taken from there and the datatype - will be taken from \\via_geometry_datatype. The name of the produced layer will be 'V1.GEO'. - @/ul @ul If there is no mapping for both, the layer number will be a unique value, the datatype - will be taken from \\via_geometry_datatype and the layer name will be 'V1.GEO'. @/ul@/li - - @brief Sets a value indicating whether via geometries shall be produced. See - \\produce_via_geometry for details.''' - produce_via_geometry = None - - '''@brief Gets the routing layer datatype value. See \\produce_via_geometry for details about - the layer production rules. - - @brief Sets the routing layer datatype value. See \\produce_via_geometry for details about the - layer production rules.''' - routing_datatype = None - - '''@brief Gets the routing layer name suffix. See \\produce_via_geometry for details about the - layer production rules. - - @brief Sets the routing layer name suffix. See \\produce_via_geometry for details about the - layer production rules.''' - routing_suffix = None - - '''@brief Gets the via geometry layer datatype value. See \\produce_via_geometry for details - about this property. - - @brief Sets the via geometry layer datatype value. See \\produce_via_geometry for details about - this property.''' - via_geometry_datatype = None - - '''@brief Gets the via geometry layer name suffix. See \\produce_via_geometry for details about - this property. - - @brief Sets the via geometry layer name suffix. See \\produce_via_geometry for details about - this property.''' - via_geometry_suffix = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''@brief Computes a hash value Returns a hash value for the given layer info object. This - method enables layer info objects as hash keys. - - This method has been introduced in version 0.25.''' - - def __init__(self, ...): - '''@brief The constructor for a named layer with layer and datatype. @args - layer,datatype,name Creates a \\LayerInfo object representing a named layer with layer and - datatype. @param layer The layer number @param datatype The datatype number @param name The - name - - This method was added in version 0.18.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self" notation where the target is a valid - layer specification string (i.e. "1/0"). - - Target mapping has been added in version 0.20.''' - - def mapping(self, ...): - '''@brief Returns the mapped physical (or target if one is specified) layer for a given - logical layer @args log_layer @param log_layer The logical layer for which the mapping is - requested. @return A \\LayerInfo object which is the physical layer mapped to the logical - layer. In general, there may be more than one physical layer mapped to one logical layer. - This method will return a single one of them. It will return the one with the lowest layer - and datatype.''' - - def mapping_str(self, ...): - '''@brief Returns the mapping string for a given logical layer @args log_layer @param - log_layer The logical layer for which the mapping is requested. @return A string describing - the mapping. The mapping string is compatible with the string that the "map" method - accepts.''' - - def to_string(self, ...): - '''@brief Converts a layer mapping object to a string This method is the inverse of the - \\from_string method. - - This method has been introduced in version 0.23.''' - - Static Methods - @classmethod - def __init_subclass__(cls, ...): - '''This method is called when a class is subclassed. - - The default implementation does nothing. It may be overridden to extend subclasses.''' - - @classmethod - def __new__(cls, ...): - '''Create and return a new object. See help(type) for accurate signature.''' - - @classmethod - def __subclasshook__(cls, ...): - '''Abstract classes can override this to customize issubclass(). - - This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or - NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it - overrides the normal algorithm (and the outcome is cached).''' - - @classmethod - def from_string(cls, ...): - '''@brief Creates a layer map from the given string The format of the string is that used in - layer mapping files: one mapping entry per line, comments are allowed using '#' or '//'. The - format of each line is that used in the 'map(string, index)' method. - - This method has been introduced in version 0.23.''' - - @classmethod - def new(cls, ...): - '''@brief Creates a new object of this class''' - - -class LayerMapping: - '''@brief A layer mapping (source to target layout) - - A layer mapping is an association of layers in two layouts forming pairs of layers, i.e. one - layer corresponds to another layer in the other layout. The LayerMapping object describes the - mapping of layers of a source layout A to a target layout B. - - A layer mapping can be set up manually or using the methods \\create or \\create_full. - - @code lm = RBA::LayerMapping::new # explicit: lm.map(2, 1) # map layer index 2 of source to 1 - of target lm.map(7, 3) # map layer index 7 of source to 3 of target ... # or employing the - specification identity: lm.create(target_layout, source_layout) # plus creating layers which - don't exist in the target layout yet: new_layers = lm.create_full(target_layout, source_layout) - @/code - - A layer might not be mapped to another layer which basically means that there is no - corresponding layer. Such layers will be ignored in operations using the layer mapping. Use - \\create_full to ensure all layers of the source layout are mapped. - - LayerMapping objects play a role mainly in the hierarchical copy or move operations of \\Layout. - However, use is not restricted to these applications. - - This class has been introduced in version 0.23. ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return selfThe Database API@. - - Usually layout objects have already been created by KLayout's application core. You can address - such a layout via the \\CellView object inside the \\LayoutView class. For example: - - @code active_layout = RBA::CellView::active.layout puts "Top cell of current layout is - #{active_layout.top_cell.name}" @/code - - However, a layout can also be used standalone: - - @code layout = RBA::Layout::new cell = layout.create_cell("TOP") layer = - layout.layer(RBA::LayerInfo::new(1, 0)) cell.shapes(layer).insert(RBA::Box::new(0, 0, 1000, - 1000)) layout.write("single_rect.gds") @/code ''' - # Attributes - '''list of weak references to the object (if defined)''' - __weakref__ = None - - '''@brief Gets the database unit - - The database unit is the value of one units distance in micrometers. For numerical reasons and - to be compliant with the GDS2 format, the database objects use integer coordinates. The basic - unit of these coordinates is the database unit. You can convert coordinates to micrometers by - multiplying the integer value with the database unit. Typical values for the database unit are - 0.001 micrometer (one nanometer). - - @brief Sets the database unit @args dbu - - See \\dbu for a description of the database unit.''' - dbu = None - - '''@brief Gets the properties ID associated with the layout - - This method has been introduced in version 0.24. - - @brief Sets the properties ID associated with the layout @args id This method is provided, if a - properties ID has been derived already. Usually it's more convenient to use \\delete_property, - \\set_property or \\property. - - This method has been introduced in version 0.24.''' - prop_id = None - - # Methods - def __delattr__(self, ...): - '''Implement delattr(self, name).''' - - def __dir__(self, ...): - '''Default dir() implementation.''' - - def __eq__(self, ...): - '''Return self==value.''' - - def __format__(self, ...): - '''Default object formatter.''' - - def __ge__(self, ...): - '''Return self>=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a layout object @args editable - - This constructor specifies whether the layout is editable. In editable mode, some - optimisations are disabled and the layout can be manipulated through a variety of methods. - - This method was introduced in version 0.22.''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a layout meta info object @param name The name @param value The value - @param description An optional description text''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new query object from the given query string''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new, empty library''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Create a new Matrix2d from the four coefficients @args m11, m12, m21, m22''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Create a new Matrix3d from the nine matrix coefficients @args m11, m12, m13, m21, - m22, m23, m31, m32, m33''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self=value.''' - - def __getattribute__(self, ...): - '''Return getattr(self, name).''' - - def __gt__(self, ...): - '''Return self>value.''' - - def __hash__(self, ...): - '''Return hash(self).''' - - def __init__(self, ...): - '''@brief Creates a new object of this class''' - - def __le__(self, ...): - '''Return self<=value.''' - - def __lt__(self, ...): - '''Return self