mirror of https://github.com/KLayout/klayout.git
Merge branch 'master' into wip
This commit is contained in:
commit
30df7a708e
|
|
@ -34,10 +34,10 @@ jobs:
|
|||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false # not working currently
|
||||
large-packages: true
|
||||
- uses: hmarr/debug-action@v2
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.12.0
|
||||
uses: styfle/cancel-workflow-action@0.12.1
|
||||
- uses: actions/checkout@v4
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
|
|
@ -52,7 +52,7 @@ jobs:
|
|||
HOST_CCACHE_DIR="$(ccache -k cache_dir)"
|
||||
mkdir -p $HOST_CCACHE_DIR
|
||||
- name: Build wheels # check https://cibuildwheel.readthedocs.io/en/stable/setup/#github-actions
|
||||
uses: pypa/cibuildwheel@v2.16.2
|
||||
uses: pypa/cibuildwheel@v2.16.5
|
||||
# to supply options, put them in 'env', like:
|
||||
# env:
|
||||
# CIBW_SOME_OPTION: value
|
||||
|
|
|
|||
25
Changelog
25
Changelog
|
|
@ -1,4 +1,27 @@
|
|||
0.28.15 (2023-01-04):
|
||||
0.28.17 (2024-02-16):
|
||||
* Enhancement: %GITHUB%/issues/1626 Technology specific grids
|
||||
|
||||
0.28.16 (2024-02-12):
|
||||
* Bugfix: %GITHUB%/issues/1623 Package installation with "-y" from command line does not work for URL or file
|
||||
* Bugfix: %GITHUB%/issues/1619 Segfault on Fedora-39 with Python 3.12.1
|
||||
* Bugfix: %GITHUB%/issues/1618 Leaking Python reference causing trouble with iterators
|
||||
* Bugfix: %GITHUB%/issues/1616 DRC doc typo
|
||||
* Bugfix: %GITHUB%/issues/1614 LEF/DEF .map should not map boundaries and fill to ALL purpose
|
||||
* Bugfix: %GITHUB%/issues/1609 Cell.read doesn't read LayoutMetaInfo
|
||||
* Bugfix: %GITHUB%/issues/1608 CustomResistorExtraction: show faulty device in GUI
|
||||
* Bugfix: %GITHUB%/issues/1603 Weird parameter dialog resizing when hiding / showing many parameters at once with callback_impl
|
||||
* Bugfix: %GITHUB%/issues/1602 [Qt6] Cannot normally quit the main application window
|
||||
* Bugfix: %GITHUB%/issues/1594 "connect" (in flat mode) + multiple top cells give an error message
|
||||
* Bugfix: %GITHUB%/issues/1592 DXF file parsing error, about spline curve
|
||||
* Enhancement: DRC enhancements related to touching edges
|
||||
- New DRC function switches: "without_touching_corners", "without_touching_edges"
|
||||
to skip width and space errors at kissing corners and touching-edge configurations
|
||||
- Kissing corners are now detected also in non-collinear edge configurations
|
||||
* Bugfix: fixed rendering of color selection buttons on High-DPI screens
|
||||
* Bugfix: cross-hair cursor should not use selection default line width and styles
|
||||
* Enhancement: OASIS reader errors out on broken OASIS with duplicate CELLNAMEs
|
||||
|
||||
0.28.15 (2024-01-04):
|
||||
* Bugfix: %GITHUB%/issues/1578 Missing strm2*.exe in the Windows portable binary package (*.zip)
|
||||
* Enhancement: %GITHUB%/issues/1569 Make "toggle (selected) layer" key-bindable
|
||||
- Plus feature: "visibility follows selection"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
klayout (0.28.17-1) unstable; urgency=low
|
||||
|
||||
* New features and bugfixes
|
||||
- See changelog
|
||||
|
||||
-- Matthias Köfferlein <matthias@koefferlein.de> Fri, 16 Feb 2024 15:52:09 +0100
|
||||
|
||||
klayout (0.28.16-1) unstable; urgency=low
|
||||
|
||||
* New features and bugfixes
|
||||
- See changelog
|
||||
|
||||
-- Matthias Köfferlein <matthias@koefferlein.de> Mon, 12 Feb 2024 00:00:00 +0100
|
||||
|
||||
klayout (0.28.15-1) unstable; urgency=low
|
||||
|
||||
* New features and bugfixes
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
Relevant KLayout version: 0.28.15<br>
|
||||
Relevant KLayout version: 0.28.17<br>
|
||||
Author: Kazzz-S<br>
|
||||
Last modified: 2024-01-05<br>
|
||||
Last modified: 2024-02-16<br>
|
||||
|
||||
# 1. Introduction
|
||||
This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.28.13 or later for different 64-bit macOS, including:
|
||||
This directory **`macbuild`** contains various files required for building KLayout (http://www.klayout.de/) version 0.28.17 or later for different 64-bit macOS, including:
|
||||
* Monterey (12.x) : the primary development environment
|
||||
* Ventura (13.x) : experimental
|
||||
* Sonoma (14.x) : -- ditto --
|
||||
|
|
@ -51,6 +51,8 @@ Some typical use cases are described in Section 6.
|
|||
# 4. Prerequisites
|
||||
You need to have the followings:
|
||||
* The latest Xcode and command-line tool kit compliant with each OS
|
||||
* https://developer.apple.com/xcode/resources/
|
||||
* https://mac.install.guide/commandlinetools/4
|
||||
* Qt5 package from Homebrew, MacPorts, or Anaconda3
|
||||
* Optionally, Ruby and Python packages from Homebrew, MacPorts, or Anaconda3
|
||||
#### For matching versions of Ruby and Python, please also refer to `build4mac_env.py`.
|
||||
|
|
@ -63,12 +65,12 @@ The operating system type is detected automatically.
|
|||
```
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
<< Usage of 'build4mac.py' >>
|
||||
for building KLayout 0.28.13 or later on different Apple macOS platforms.
|
||||
for building KLayout 0.28.17 or later on different Apple macOS platforms.
|
||||
|
||||
$ [python] ./build4mac.py
|
||||
option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details)| default value
|
||||
--------------------------------------------------------------------------------------+---------------
|
||||
[-q|--qt <type>] : case-insensitive type=['Qt5MacPorts', 'Qt5Brew', 'Qt5Ana3', | qt5brew
|
||||
[-q|--qt <type>] : case-insensitive type=['Qt5MacPorts', 'Qt5Brew', 'Qt5Ana3', | qt5macports
|
||||
: 'Qt6MacPorts', 'Qt6Brew'] |
|
||||
: Qt5MacPorts: use Qt5 from MacPorts |
|
||||
: Qt5Brew: use Qt5 from Homebrew |
|
||||
|
|
@ -76,20 +78,21 @@ $ [python] ./build4mac.py
|
|||
: Qt6MacPorts: use Qt6 from MacPorts (*) |
|
||||
: Qt6Brew: use Qt6 from Homebrew (*) |
|
||||
: (*) migration to Qt6 is ongoing |
|
||||
[-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3'] | hb32
|
||||
[-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP33', 'HB33', 'Ana3'] | sys
|
||||
: nil: don't bind Ruby |
|
||||
: Sys: use [Sonoma|Ventura|Monterey]-bundled Ruby 2.6 |
|
||||
: MP32: use Ruby 3.2 from MacPorts |
|
||||
: HB32: use Ruby 3.2 from Homebrew |
|
||||
: MP33: use Ruby 3.3 from MacPorts |
|
||||
: HB33: use Ruby 3.3 from Homebrew |
|
||||
: Ana3: use Ruby 3.2 from Anaconda3 |
|
||||
[-p|--python <type>] : case-insensitive type=['nil', 'MP311', 'HB311', 'Ana3', | hb311
|
||||
: 'MP39', 'hb311', 'HBAuto'] |
|
||||
[-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP311', 'HB311', 'Ana3', | sys
|
||||
: 'MP39', 'HB39', 'HBAuto'] |
|
||||
: nil: don't bind Python |
|
||||
: Sys: use [Sonoma|Ventura|Monterey]-bundled Python 3.9 |
|
||||
: MP311: use Python 3.11 from MacPorts |
|
||||
: HB311: use Python 3.11 from Homebrew |
|
||||
: Ana3: use Python 3.11 from Anaconda3 |
|
||||
: MP39: use Python 3.9 from MacPorts (+) |
|
||||
: hb311: use Python 3.9 from Homebrew (+) |
|
||||
: HB39: use Python 3.9 from Homebrew (+) |
|
||||
: (+) for the backward compatibility tests |
|
||||
: HBAuto: use the latest Python 3.x auto-detected from Homebrew |
|
||||
[-P|--buildPymod] : build and deploy Pymod (*.whl) for LW-*.dmg | disabled
|
||||
|
|
@ -118,24 +121,55 @@ $ [python] ./build4mac.py
|
|||
In this section, the actual file and directory names are those obtained on macOS Monterey.<br>
|
||||
On different OS, those names differ accordingly.
|
||||
|
||||
### 6A. Standard build using the OS-bundled Ruby and Python with MacPorts
|
||||
This build has been discontinued.
|
||||
### 6A. Standard build using the OS-bundled Ruby and Python with MacPorts Qt
|
||||
0. Install MacPorts, then install Qt5 and libgit2 by
|
||||
```
|
||||
$ sudo port install coreutils
|
||||
$ sudo port install findutils
|
||||
$ sudo port install qt5
|
||||
$ sudo port install libgit2
|
||||
```
|
||||
|
||||
### 6B. Fully Homebrew-flavored build with Homebrew Ruby 3.2 and Homebrew Python 3.11
|
||||
0. Install Homebrew, then install Qt5, Ruby 3.2, Python 3.11, and libgit2 by
|
||||
Confirm that you have:
|
||||
```
|
||||
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/*
|
||||
```
|
||||
As of this writing, the provided Python version is `3.9.6`.
|
||||
|
||||
1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default values for Monterey, Ventura, and Sonoma.
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5macports -r sys -p sys
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour, depending on your machine spec).
|
||||
3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-y" to deploy executables and libraries under **`klayout.app`** bundle.<br>
|
||||
The buddy command-line tools (strm*) will also be deployed under **klayout.app/Contents/Buddy/** in this step.<br>
|
||||
|
||||
```
|
||||
$ ./build4mac.py -q qt5macports -r sys -p sys -y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`ST-qt5MP.pkg.macos-Monterey-release-RsysPsys`** directory, where
|
||||
* "ST-" means this is a standard package.
|
||||
* "qt5MP" means that Qt5 from MacPorts is used.
|
||||
* "RsysPsys" means that Ruby is 2.6 provided by OS; Python is 3.9 provided by OS.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
|
||||
### 6B. Fully Homebrew-flavored build with Homebrew Ruby 3.3 and Homebrew Python 3.11
|
||||
0. Install Homebrew, then install Qt5, Ruby 3.3, Python 3.11, and libgit2 by
|
||||
```
|
||||
$ brew install qt@5
|
||||
$ brew install ruby@3.2
|
||||
$ brew install ruby@3.3
|
||||
$ brew install python@3.11
|
||||
$ brew install libgit2
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ cd macbuild
|
||||
$ ./python3HB.py -v 3.11
|
||||
```
|
||||
1. Invoke **`build4mac.py`** with the following options: **((Notes))** These options are the default values for Monterey, Ventura, and Sonoma.
|
||||
1. Invoke **`build4mac.py`** with the following options:
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5brew -r hb32 -p hb311
|
||||
$ ./build4mac.py -q qt5brew -r hb33 -p hb311
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour, depending on your machine spec).
|
||||
3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.<br>
|
||||
|
|
@ -143,13 +177,13 @@ $ ./build4mac.py -q qt5brew -r hb32 -p hb311
|
|||
If you use `--buildPymod` option in Step-1 and Step-3, the KLayout Python Module (\*.whl) will be built and deployed under **klayout.app/Contents/pymod-dist/**.
|
||||
|
||||
```
|
||||
$ ./build4mac.py -q qt5brew -r hb32 -p hb311 -Y
|
||||
$ ./build4mac.py -q qt5brew -r hb33 -p hb311 -Y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311`** directory, where
|
||||
**`LW-qt5Brew.pkg.macos-Monterey-release-Rhb33Phb311`** directory, where
|
||||
* "LW-" means this is a lightweight package.
|
||||
* "qt5Brew" means that Qt5 from Homebrew is used.
|
||||
* "Rhb32Phb311" means that Ruby is 3.2 from Homebrew; Python is 3.11 from Homebrew.
|
||||
* "Rhb33Phb311" means that Ruby is 3.3 from Homebrew; Python is 3.11 from Homebrew.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
|
||||
### 6C. Partially Homebrew-flavored build with System Ruby and Homebrew Python 3.11
|
||||
|
|
@ -184,13 +218,13 @@ $ ./build4mac.py -q qt5brew -r sys -p hb311 -y
|
|||
So far, the deployment of Homebrew Ruby is not supported.<br>
|
||||
Therefore, if you intend to use the "-y" option for deployment, you need to use the "-r sys" option for building.
|
||||
|
||||
### 6D. Fully MacPorts-flavored build with MacPorts Ruby 3.2 and MacPorts Python 3.11
|
||||
0. Install MacPorts, then install Qt5, Ruby 3.2, Python 3.11, and libgit2 by
|
||||
### 6D. Fully MacPorts-flavored build with MacPorts Ruby 3.3 and MacPorts Python 3.11
|
||||
0. Install MacPorts, then install Qt5, Ruby 3.3, Python 3.11, and libgit2 by
|
||||
```
|
||||
$ sudo port install coreutils
|
||||
$ sudo port install findutils
|
||||
$ sudo port install qt5
|
||||
$ sudo port install ruby32
|
||||
$ sudo port install ruby33
|
||||
$ sudo port install python311
|
||||
$ sudo port install py311-pip
|
||||
$ sudo port install libgit2
|
||||
|
|
@ -198,7 +232,7 @@ $ sudo port install libgit2
|
|||
1. Invoke **`build4mac.py`** with the following options:
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./build4mac.py -q qt5macports -r mp32 -p mp311
|
||||
$ ./build4mac.py -q qt5macports -r mp33 -p mp311
|
||||
```
|
||||
2. Confirm successful build (it will take about one hour, depending on your machine spec).
|
||||
3. Rerun **`build4mac.py`** with the same options used in 1. PLUS "-Y" to deploy executables and libraries under **`klayout.app`** bundle.<br>
|
||||
|
|
@ -206,13 +240,13 @@ $ ./build4mac.py -q qt5macports -r mp32 -p mp311
|
|||
If you use `--buildPymod` option in Step-1 and Step-3, the KLayout Python Module (\*.whl) will be built and deployed under **klayout.app/Contents/pymod-dist/**.
|
||||
|
||||
```
|
||||
$ ./build4mac.py -q qt5macports -r mp32 -p mp311 -Y
|
||||
$ ./build4mac.py -q qt5macports -r mp33 -p mp311 -Y
|
||||
```
|
||||
The application bundle **`klayout.app`** is located under:<br>
|
||||
**`LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311`** directory, where
|
||||
**`LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311`** directory, where
|
||||
* "LW-" means this is a lightweight package.
|
||||
* "qt5MP" means that Qt5 from MacPorts is used.
|
||||
* "Rmp32Pmp311" means that Ruby is 3.2 from MacPorts; Python is 3.11 from MacPorts.
|
||||
* "Rmp33Pmp311" means that Ruby is 3.3 from MacPorts; Python is 3.11 from MacPorts.
|
||||
4. Copy/move the generated application bundle **`klayout.app`** to your **`/Applications`** directory for installation.
|
||||
|
||||
### 6E. Fully Anaconda3-flavored build with Anaconda3 Ruby 3.2 and Anaconda3 Python 3.11
|
||||
|
|
@ -273,11 +307,11 @@ makeDMG4mac.py -> macbuild/makeDMG4mac.py
|
|||
2. Invoke **`makeDMG4mac.py`** with -p and -m options, for example,
|
||||
```
|
||||
$ cd /where/'build.sh'/exists
|
||||
$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311 -m
|
||||
$ ./makeDMG4mac.py -p LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311 -m
|
||||
```
|
||||
This command will generate the two files below:<br>
|
||||
* **`LW-klayout-0.28.13-macOS-Monterey-1-qt5MP-Rmp32Pmp311.dmg`** ---(1) the main DMG file
|
||||
* **`LW-klayout-0.28.13-macOS-Monterey-1-qt5MP-Rmp32Pmp311.dmg.md5`** ---(2) MD5-value text file
|
||||
* **`LW-klayout-0.28.17-macOS-Monterey-1-qt5MP-Rmp33Pmp311.dmg`** ---(1) the main DMG file
|
||||
* **`LW-klayout-0.28.17-macOS-Monterey-1-qt5MP-Rmp33Pmp311.dmg.md5`** ---(2) MD5-value text file
|
||||
|
||||
# Known issues
|
||||
Because we assume some specific versions of non-OS-standard Ruby and Python, updating Homebrew, MacPorts, or Anaconda3 may cause build- and link errors.<br>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -5,7 +5,7 @@
|
|||
# File: "macbuild/build4mac.py"
|
||||
#
|
||||
# The top Python script for building KLayout (http://www.klayout.de/index.php)
|
||||
# version 0.28.13 or later on different Apple Mac OSX platforms.
|
||||
# version 0.28.17 or later on different Apple Mac OSX platforms.
|
||||
#===============================================================================
|
||||
import sys
|
||||
import os
|
||||
|
|
@ -35,17 +35,17 @@ from build4mac_util import *
|
|||
#-------------------------------------------------------------------------------
|
||||
def GenerateUsage(platform):
|
||||
if platform.upper() in [ "SONOMA", "VENTURA", "MONTEREY" ]: # with Xcode [13.1 .. ]
|
||||
myQt56 = "qt5brew"
|
||||
myRuby = "hb32"
|
||||
myPython = "hb311"
|
||||
moduleset = ('qt5Brew', 'HB32', 'HB311')
|
||||
myQt56 = "qt5macports"
|
||||
myRuby = "sys"
|
||||
myPython = "sys"
|
||||
moduleset = ('Qt5MacPorts', 'Sys', 'Sys')
|
||||
else: # too obsolete
|
||||
raise Exception( "! Too obsolete platform <%s>" % platform )
|
||||
|
||||
usage = "\n"
|
||||
usage += "---------------------------------------------------------------------------------------------------------\n"
|
||||
usage += "<< Usage of 'build4mac.py' >>\n"
|
||||
usage += " for building KLayout 0.28.13 or later on different Apple macOS platforms.\n"
|
||||
usage += " for building KLayout 0.28.17 or later on different Apple macOS platforms.\n"
|
||||
usage += "\n"
|
||||
usage += "$ [python] ./build4mac.py\n"
|
||||
usage += " option & argument : descriptions (refer to 'macbuild/build4mac_env.py' for details)| default value\n"
|
||||
|
|
@ -58,15 +58,16 @@ def GenerateUsage(platform):
|
|||
usage += " : Qt6MacPorts: use Qt6 from MacPorts (*) |\n"
|
||||
usage += " : Qt6Brew: use Qt6 from Homebrew (*) |\n"
|
||||
usage += " : (*) migration to Qt6 is ongoing |\n"
|
||||
usage += " [-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3'] | %s\n" % myRuby
|
||||
usage += " [-r|--ruby <type>] : case-insensitive type=['nil', 'Sys', 'MP33', 'HB33', 'Ana3'] | %s\n" % myRuby
|
||||
usage += " : nil: don't bind Ruby |\n"
|
||||
usage += " : Sys: use [Sonoma|Ventura|Monterey]-bundled Ruby 2.6 |\n"
|
||||
usage += " : MP32: use Ruby 3.2 from MacPorts |\n"
|
||||
usage += " : HB32: use Ruby 3.2 from Homebrew |\n"
|
||||
usage += " : MP33: use Ruby 3.3 from MacPorts |\n"
|
||||
usage += " : HB33: use Ruby 3.3 from Homebrew |\n"
|
||||
usage += " : Ana3: use Ruby 3.2 from Anaconda3 |\n"
|
||||
usage += " [-p|--python <type>] : case-insensitive type=['nil', 'MP311', 'HB311', 'Ana3', | %s\n" % myPython
|
||||
usage += " [-p|--python <type>] : case-insensitive type=['nil', 'Sys', 'MP311', 'HB311', 'Ana3', | %s\n" % myPython
|
||||
usage += " : 'MP39', 'HB39', 'HBAuto'] |\n"
|
||||
usage += " : nil: don't bind Python |\n"
|
||||
usage += " : Sys: use [Sonoma|Ventura|Monterey]-bundled Python 3.9 |\n"
|
||||
usage += " : MP311: use Python 3.11 from MacPorts |\n"
|
||||
usage += " : HB311: use Python 3.11 from Homebrew |\n"
|
||||
usage += " : Ana3: use Python 3.11 from Anaconda3 |\n"
|
||||
|
|
@ -149,19 +150,19 @@ def Get_Default_Config():
|
|||
|
||||
# Set the default modules
|
||||
if Platform == "Sonoma":
|
||||
ModuleQt = "Qt5Brew"
|
||||
ModuleRuby = "Ruby32Brew"
|
||||
ModulePython = "Python311Brew"
|
||||
ModuleQt = "Qt5MacPorts"
|
||||
ModuleRuby = "Sys"
|
||||
ModulePython = "Sys"
|
||||
elif Platform == "Ventura":
|
||||
ModuleQt = "Qt5Brew"
|
||||
ModuleRuby = "Ruby32Brew"
|
||||
ModulePython = "Python311Brew"
|
||||
ModuleQt = "Qt5MacPorts"
|
||||
ModuleRuby = "Sys"
|
||||
ModulePython = "Sys"
|
||||
elif Platform == "Monterey":
|
||||
ModuleQt = "Qt5Brew"
|
||||
ModuleRuby = "Ruby32Brew"
|
||||
ModulePython = "Python311Brew"
|
||||
ModuleQt = "Qt5MacPorts"
|
||||
ModuleRuby = "Sys"
|
||||
ModulePython = "Sys"
|
||||
else:
|
||||
ModuleQt = "Qt5Brew"
|
||||
ModuleQt = "Qt5MacPorts"
|
||||
ModuleRuby = "nil"
|
||||
ModulePython = "nil"
|
||||
|
||||
|
|
@ -179,6 +180,7 @@ def Get_Default_Config():
|
|||
DeployVerbose = 1
|
||||
Version = GetKLayoutVersionFrom( "./version.sh" )
|
||||
HBPythonIs39 = False # because ModulePython == "Python311Brew" by default
|
||||
OSPython3FW = None # system Python3 frameworks in [ None, MontereyPy3FW, VenturaPy3FW, SonomaPy3FW ]
|
||||
|
||||
config = dict()
|
||||
config['ProjectDir'] = ProjectDir # project directory where "build.sh" exists
|
||||
|
|
@ -204,6 +206,7 @@ def Get_Default_Config():
|
|||
config['ModuleSet'] = ModuleSet # (Qt, Ruby, Python)-tuple
|
||||
config['ToolDebug'] = ToolDebug # debug level list for this tool
|
||||
config['HBPythonIs39'] = HBPythonIs39 # True if the Homebrew Python version <= 3.9
|
||||
config['OSPython3FW'] = OSPython3FW # system Python3 frameworks in [ None, MontereyPy3FW, VenturaPy3FW, SonomaPy3FW ]
|
||||
# auxiliary variables on platform
|
||||
config['System'] = System # 6-tuple from platform.uname()
|
||||
config['Node'] = Node # - do -
|
||||
|
|
@ -246,6 +249,7 @@ def Parse_CLI_Args(config):
|
|||
ModuleSet = config['ModuleSet']
|
||||
ToolDebug = config['ToolDebug']
|
||||
HBPythonIs39 = config['HBPythonIs39']
|
||||
OSPython3FW = config['OSPython3FW']
|
||||
|
||||
#-----------------------------------------------------
|
||||
# [2] Parse the CLI arguments
|
||||
|
|
@ -257,7 +261,7 @@ def Parse_CLI_Args(config):
|
|||
|
||||
p.add_option( '-r', '--ruby',
|
||||
dest='type_ruby',
|
||||
help="Ruby type=['nil', 'Sys', 'MP32', 'HB32', 'Ana3']" )
|
||||
help="Ruby type=['nil', 'Sys', 'MP33', 'HB33', 'Ana3']" )
|
||||
|
||||
p.add_option( '-p', '--python',
|
||||
dest='type_python',
|
||||
|
|
@ -331,9 +335,9 @@ def Parse_CLI_Args(config):
|
|||
help='check usage' )
|
||||
|
||||
if Platform.upper() in [ "SONOMA", "VENTURA", "MONTEREY" ]: # with Xcode [13.1 .. ]
|
||||
p.set_defaults( type_qt = "qt5brew",
|
||||
type_ruby = "hb32",
|
||||
type_python = "hb311",
|
||||
p.set_defaults( type_qt = "qt5macports",
|
||||
type_ruby = "sys",
|
||||
type_python = "sys",
|
||||
build_pymod = False,
|
||||
no_qt_binding = False,
|
||||
no_qt_uitools = False,
|
||||
|
|
@ -390,8 +394,8 @@ def Parse_CLI_Args(config):
|
|||
candidates = dict()
|
||||
candidates['NIL'] = 'nil'
|
||||
candidates['SYS'] = 'Sys'
|
||||
candidates['MP32'] = 'MP32'
|
||||
candidates['HB32'] = 'HB32'
|
||||
candidates['MP33'] = 'MP33'
|
||||
candidates['HB33'] = 'HB33'
|
||||
candidates['ANA3'] = 'Ana3'
|
||||
try:
|
||||
choiceRuby = candidates[ opt.type_ruby.upper() ]
|
||||
|
|
@ -403,18 +407,17 @@ def Parse_CLI_Args(config):
|
|||
if choiceRuby == "nil":
|
||||
ModuleRuby = 'nil'
|
||||
elif choiceRuby == "Sys":
|
||||
choiceRuby = "Sys"
|
||||
if Platform == "Sonoma":
|
||||
ModuleRuby = 'RubySonoma'
|
||||
elif Platform == "Ventura":
|
||||
ModuleRuby = 'RubyVentura'
|
||||
elif Platform == "Monterey":
|
||||
ModuleRuby = 'RubyMonterey'
|
||||
elif choiceRuby == "MP32":
|
||||
ModuleRuby = 'Ruby32MacPorts'
|
||||
elif choiceRuby == "MP33":
|
||||
ModuleRuby = 'Ruby33MacPorts'
|
||||
NonOSStdLang = True
|
||||
elif choiceRuby == "HB32":
|
||||
ModuleRuby = 'Ruby32Brew'
|
||||
elif choiceRuby == "HB33":
|
||||
ModuleRuby = 'Ruby33Brew'
|
||||
NonOSStdLang = True
|
||||
elif choiceRuby == "Ana3":
|
||||
ModuleRuby = 'RubyAnaconda3'
|
||||
|
|
@ -429,6 +432,7 @@ def Parse_CLI_Args(config):
|
|||
# (C) Determine the Python type
|
||||
candidates = dict()
|
||||
candidates['NIL'] = 'nil'
|
||||
candidates['SYS'] = 'Sys'
|
||||
candidates['MP311'] = 'MP311'
|
||||
candidates['HB311'] = 'HB311'
|
||||
candidates['ANA3'] = 'Ana3'
|
||||
|
|
@ -445,29 +449,49 @@ def Parse_CLI_Args(config):
|
|||
if choicePython == "nil":
|
||||
ModulePython = 'nil'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = None
|
||||
elif choicePython == "Sys":
|
||||
if Platform == "Sonoma":
|
||||
ModulePython = 'PythonSonoma'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = SonomaPy3FW
|
||||
elif Platform == "Ventura":
|
||||
ModulePython = 'PythonVentura'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = VenturaPy3FW
|
||||
elif Platform == "Monterey":
|
||||
ModulePython = 'PythonMonterey'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = MontereyPy3FW
|
||||
elif choicePython == "MP311":
|
||||
ModulePython = 'Python311MacPorts'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "HB311":
|
||||
ModulePython = 'Python311Brew'
|
||||
HBPythonIs39 = False
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "Ana3":
|
||||
ModulePython = 'PythonAnaconda3'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "MP39":
|
||||
ModulePython = 'Python39MacPorts'
|
||||
HBPythonIs39 = None
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "HB39":
|
||||
ModulePython = 'Python39Brew'
|
||||
HBPythonIs39 = True
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
elif choicePython == "HBAuto":
|
||||
ModulePython = 'PythonAutoBrew'
|
||||
HBPythonIs39 = (HBPythonAutoVersion == "3.9")
|
||||
OSPython3FW = None
|
||||
NonOSStdLang = True
|
||||
if ModulePython == '':
|
||||
print("")
|
||||
|
|
@ -524,7 +548,7 @@ def Parse_CLI_Args(config):
|
|||
else:
|
||||
message += "a lightweight (LW-) package with Pymod excluding Qt5, Ruby, and Python..."
|
||||
elif DeploymentF:
|
||||
if (ModuleRuby in RubySys) and (ModulePython in PythonSys): # won't meet this condition any more!
|
||||
if (ModuleRuby in RubySys) and (ModulePython in PythonSys):
|
||||
PackagePrefix = "ST-"
|
||||
message += "a standard (ST-) package including Qt[5|6] and using OS-bundled Ruby and Python..."
|
||||
elif ModulePython in ['Python311Brew', 'Python39Brew', 'PythonAutoBrew']:
|
||||
|
|
@ -568,6 +592,7 @@ def Parse_CLI_Args(config):
|
|||
config['ModuleSet'] = ModuleSet
|
||||
config['ToolDebug'] = ToolDebug
|
||||
config['HBPythonIs39'] = HBPythonIs39
|
||||
config['OSPython3FW'] = OSPython3FW
|
||||
|
||||
if CheckComOnly:
|
||||
pp = pprint.PrettyPrinter( indent=4, width=140 )
|
||||
|
|
@ -606,6 +631,7 @@ def Get_Build_Parameters(config):
|
|||
DeploymentF = config['DeploymentF']
|
||||
DeploymentP = config['DeploymentP']
|
||||
PackagePrefix = config['PackagePrefix']
|
||||
OSPython3FW = config['OSPython3FW']
|
||||
|
||||
#-----------------------------------------------------
|
||||
# [2] Set parameters passed to the main Bash script
|
||||
|
|
@ -652,7 +678,10 @@ def Get_Build_Parameters(config):
|
|||
|
||||
parameters['bin'] = MacBinDir
|
||||
parameters['build'] = MacBuildDir
|
||||
parameters['rpath'] = "@executable_path/../Frameworks"
|
||||
if OSPython3FW in [ MontereyPy3FW, VenturaPy3FW, SonomaPy3FW ]:
|
||||
parameters['rpath'] = OSPython3FW
|
||||
else:
|
||||
parameters['rpath'] = "@executable_path/../Frameworks"
|
||||
|
||||
# (E) want Qt bindings with Ruby scripts?
|
||||
parameters['no_qt_bindings'] = NoQtBindings
|
||||
|
|
@ -698,7 +727,7 @@ def Get_Build_Parameters(config):
|
|||
# <pymod> will be built if:
|
||||
# BuildPymod = True
|
||||
# Platform = [ 'Sonoma', 'Ventura', 'Monterey']
|
||||
# ModuleRuby = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
|
||||
# ModuleRuby = [ 'Ruby33MacPorts', 'Ruby33Brew', 'RubyAnaconda3' ]
|
||||
# ModulePython = [ 'Python311MacPorts', 'Python39MacPorts',
|
||||
# 'Python311Brew', Python39Brew', 'PythonAutoBrew',
|
||||
# 'PythonAnaconda3' ]
|
||||
|
|
@ -709,13 +738,13 @@ def Get_Build_Parameters(config):
|
|||
|
||||
PymodDistDir = dict()
|
||||
if Platform in [ 'Sonoma', 'Ventura', 'Monterey' ]:
|
||||
if ModuleRuby in [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]:
|
||||
if ModuleRuby in [ 'Ruby33MacPorts', 'Ruby33Brew', 'RubyAnaconda3' ]:
|
||||
if ModulePython in [ 'Python311MacPorts', 'Python39MacPorts' ]:
|
||||
PymodDistDir[ModulePython] = 'dist-MP3'
|
||||
PymodDistDir[ModulePython] = 'dist-MP3-%s' % ModuleQt
|
||||
elif ModulePython in [ 'Python311Brew', 'Python39Brew', 'PythonAutoBrew' ]:
|
||||
PymodDistDir[ModulePython] = 'dist-HB3'
|
||||
PymodDistDir[ModulePython] = 'dist-HB3-%s' % ModuleQt
|
||||
elif ModulePython in [ 'PythonAnaconda3' ]:
|
||||
PymodDistDir[ModulePython] = 'dist-ana3'
|
||||
PymodDistDir[ModulePython] = 'dist-ana3-%s' % ModuleQt
|
||||
parameters['pymod_dist'] = PymodDistDir
|
||||
return parameters
|
||||
|
||||
|
|
@ -732,7 +761,7 @@ def Build_pymod(parameters):
|
|||
# [1] <pymod> will be built if:
|
||||
# BuildPymod = True
|
||||
# Platform = [ 'Sonoma', 'Ventura', 'Monterey']
|
||||
# ModuleRuby = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
|
||||
# ModuleRuby = [ 'Ruby33MacPorts', 'Ruby33Brew', 'RubyAnaconda3' ]
|
||||
# ModulePython = [ 'Python311MacPorts', 'Python39MacPorts',
|
||||
# 'Python311Brew', Python39Brew', 'PythonAutoBrew',
|
||||
# 'PythonAnaconda3' ]
|
||||
|
|
@ -745,7 +774,7 @@ def Build_pymod(parameters):
|
|||
return 0
|
||||
if not Platform in [ 'Sonoma', 'Ventura', 'Monterey' ]:
|
||||
return 0
|
||||
elif not ModuleRuby in [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]:
|
||||
elif not ModuleRuby in [ 'Ruby33MacPorts', 'Ruby33Brew', 'RubyAnaconda3' ]:
|
||||
return 0
|
||||
elif not ModulePython in [ 'Python311MacPorts', 'Python39MacPorts', 'PythonAnaconda3', \
|
||||
'Python311Brew', 'Python39Brew', 'PythonAutoBrew' ]:
|
||||
|
|
@ -758,17 +787,17 @@ def Build_pymod(parameters):
|
|||
#--------------------------------------------------------------------
|
||||
PymodDistDir = parameters['pymod_dist']
|
||||
# Using MacPorts
|
||||
if PymodDistDir[ModulePython] == 'dist-MP3':
|
||||
if PymodDistDir[ModulePython].find('dist-MP3') >= 0:
|
||||
addBinPath = "/opt/local/bin"
|
||||
addIncPath = "/opt/local/include"
|
||||
addLibPath = "/opt/local/lib"
|
||||
# Using Homebrew
|
||||
elif PymodDistDir[ModulePython] == 'dist-HB3':
|
||||
elif PymodDistDir[ModulePython].find('dist-HB3') >= 0:
|
||||
addBinPath = "%s/bin" % DefaultHomebrewRoot # defined in "build4mac_env.py"
|
||||
addIncPath = "%s/include" % DefaultHomebrewRoot # -- ditto --
|
||||
addLibPath = "%s/lib" % DefaultHomebrewRoot # -- ditto --
|
||||
# Using Anaconda3
|
||||
elif PymodDistDir[ModulePython] == 'dist-ana3':
|
||||
elif PymodDistDir[ModulePython].find('dist-ana3') >= 0:
|
||||
addBinPath = "/Applications/anaconda3/bin"
|
||||
addIncPath = "/Applications/anaconda3/include"
|
||||
addLibPath = "/Applications/anaconda3/lib"
|
||||
|
|
@ -1149,7 +1178,7 @@ def Deploy_Binaries_For_Bundle(config, parameters):
|
|||
if BuildPymod:
|
||||
try:
|
||||
PymodDistDir = parameters['pymod_dist']
|
||||
pymodDistDir = PymodDistDir[ModulePython] # [ 'dist-MP3', 'dist-HB3', 'dist-ana3' ]
|
||||
pymodDistDir = PymodDistDir[ModulePython] # [ 'dist-MP3-${ModuleQt}', 'dist-HB3-${ModuleQt}', 'dist-ana3-${ModuleQt}' ]
|
||||
except KeyError:
|
||||
pymodDistDir = ""
|
||||
else:
|
||||
|
|
@ -1800,15 +1829,15 @@ def Deploy_Binaries_For_Bundle(config, parameters):
|
|||
return 1
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# [10] Special deployment of Ruby3.2 from Homebrew?
|
||||
# [10] Special deployment of Ruby3.3 from Homebrew?
|
||||
#-------------------------------------------------------------
|
||||
deploymentRuby32HB = (ModuleRuby == 'Ruby32Brew')
|
||||
deploymentRuby32HB = (ModuleRuby == 'Ruby33Brew')
|
||||
if deploymentRuby32HB and NonOSStdLang:
|
||||
|
||||
print( "" )
|
||||
print( " [10] You have reached optional deployment of Ruby from %s ..." % HBRuby32Path )
|
||||
print( " [10] You have reached optional deployment of Ruby from %s ..." % HBRuby33Path )
|
||||
print( " [!!!] Sorry, the deployed package will not work properly since deployment of" )
|
||||
print( " Ruby3.2 from Homebrew is not yet supported." )
|
||||
print( " Ruby3.3 from Homebrew is not yet supported." )
|
||||
print( " Since you have Homebrew development environment, there two options:" )
|
||||
print( " (1) Retry to make a package with '-Y|--DEPLOY' option." )
|
||||
print( " This will not deploy any of Qt[5|6], Python, and Ruby from Homebrew." )
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env python3
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#===============================================================================
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
# Here are dictionaries of ...
|
||||
# different modules for building KLayout (http://www.klayout.de/index.php)
|
||||
# version 0.28.13 or later on different Apple Mac OSX platforms.
|
||||
# version 0.28.17 or later on different Apple Mac OSX platforms.
|
||||
#
|
||||
# This file is imported by 'build4mac.py' script.
|
||||
#===============================================================================
|
||||
|
|
@ -117,7 +117,7 @@ Qt6Brew = { 'qmake' : '%s/opt/qt@6/bin/qmake' % DefaultHomebrewRoot,
|
|||
#-----------------------------------------------------
|
||||
RubyNil = [ 'nil' ]
|
||||
RubySys = [ 'RubyMonterey', 'RubyVentura', 'RubySonoma' ]
|
||||
RubyExt = [ 'Ruby32MacPorts', 'Ruby32Brew', 'RubyAnaconda3' ]
|
||||
RubyExt = [ 'Ruby33MacPorts', 'Ruby33Brew', 'RubyAnaconda3' ]
|
||||
Rubies = RubyNil + RubySys + RubyExt
|
||||
|
||||
#-----------------------------------------------------
|
||||
|
|
@ -150,21 +150,21 @@ RubySonoma = { 'exe': '/System/Library/Frameworks/Ruby.framework/Versions/
|
|||
'lib': '%s/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/libruby.tbd' % SonomaSDK
|
||||
}
|
||||
|
||||
# Ruby 3.2 from MacPorts (https://www.macports.org/)
|
||||
# install with 'sudo port install ruby32'
|
||||
# [Key Type Name] = 'MP32'
|
||||
Ruby32MacPorts = { 'exe': '/opt/local/bin/ruby3.2',
|
||||
'inc': '/opt/local/include/ruby-3.2.2',
|
||||
'lib': '/opt/local/lib/libruby.3.2.dylib'
|
||||
# Ruby 3.3 from MacPorts (https://www.macports.org/)
|
||||
# install with 'sudo port install ruby33'
|
||||
# [Key Type Name] = 'MP33'
|
||||
Ruby33MacPorts = { 'exe': '/opt/local/bin/ruby3.3',
|
||||
'inc': '/opt/local/include/ruby-3.3.0',
|
||||
'lib': '/opt/local/lib/libruby.3.3.dylib'
|
||||
}
|
||||
|
||||
# Ruby 3.2 from Homebrew
|
||||
# install with 'brew install ruby@3.2'
|
||||
# [Key Type Name] = 'HB32'
|
||||
HBRuby32Path = '%s/opt/ruby@3.2' % DefaultHomebrewRoot
|
||||
Ruby32Brew = { 'exe': '%s/bin/ruby' % HBRuby32Path,
|
||||
'inc': '%s/include/ruby-3.2.0' % HBRuby32Path,
|
||||
'lib': '%s/lib/libruby.3.2.dylib' % HBRuby32Path
|
||||
# Ruby 3.3 from Homebrew
|
||||
# install with 'brew install ruby@3.3'
|
||||
# [Key Type Name] = 'HB33'
|
||||
HBRuby33Path = '%s/opt/ruby@3.3' % DefaultHomebrewRoot
|
||||
Ruby33Brew = { 'exe': '%s/bin/ruby' % HBRuby33Path,
|
||||
'inc': '%s/include/ruby-3.3.0' % HBRuby33Path,
|
||||
'lib': '%s/lib/libruby.3.3.dylib' % HBRuby33Path
|
||||
}
|
||||
|
||||
# Ruby 3.2 bundled with anaconda3 installed under /Applications/anaconda3/
|
||||
|
|
@ -181,8 +181,8 @@ RubyDictionary = { 'nil' : None,
|
|||
'RubyMonterey' : RubyMonterey,
|
||||
'RubyVentura' : RubyVentura,
|
||||
'RubySonoma' : RubySonoma,
|
||||
'Ruby32MacPorts': Ruby32MacPorts,
|
||||
'Ruby32Brew' : Ruby32Brew,
|
||||
'Ruby33MacPorts': Ruby33MacPorts,
|
||||
'Ruby33Brew' : Ruby33Brew,
|
||||
'RubyAnaconda3' : RubyAnaconda3
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ RubyDictionary = { 'nil' : None,
|
|||
# for the previous states.
|
||||
#-----------------------------------------------------
|
||||
PythonNil = [ 'nil' ]
|
||||
PythonSys = [ ]
|
||||
PythonSys = [ 'PythonMonterey', 'PythonVentura', 'PythonSonoma' ]
|
||||
PythonExt = [ 'Python39MacPorts', 'Python39Brew' ]
|
||||
PythonExt += [ 'Python311MacPorts', 'Python311Brew' ]
|
||||
PythonExt += [ 'PythonAnaconda3', 'PythonAutoBrew' ]
|
||||
|
|
@ -204,6 +204,33 @@ Pythons = PythonNil + PythonSys + PythonExt
|
|||
#-----------------------------------------------------
|
||||
# Whereabouts of different components of Python
|
||||
#-----------------------------------------------------
|
||||
# Bundled with Monterey (12.x)
|
||||
# [Key Type Name] = 'Sys'
|
||||
MontereyPy3FWXc = "/Applications/Xcode.app/Contents/Developer/Library/Frameworks"
|
||||
MontereyPy3FW = "/Library/Developer/CommandLineTools/Library/Frameworks"
|
||||
PythonMonterey = { 'exe': '%s/Python3.framework/Versions/3.9/bin/python3.9' % MontereyPy3FW,
|
||||
'inc': '%s/Python3.framework/Versions/3.9/include/python3.9' % MontereyPy3FW,
|
||||
'lib': '%s/Python3.framework/Versions/3.9/lib/libpython3.9.dylib' % MontereyPy3FW
|
||||
}
|
||||
|
||||
# Bundled with Ventura (13.x)
|
||||
# [Key Type Name] = 'Sys'
|
||||
VenturaPy3FWXc = "/Applications/Xcode.app/Contents/Developer/Library/Frameworks"
|
||||
VenturaPy3FW = "/Library/Developer/CommandLineTools/Library/Frameworks"
|
||||
PythonVentura = { 'exe': '%s/Python3.framework/Versions/3.9/bin/python3.9' % VenturaPy3FW,
|
||||
'inc': '%s/Python3.framework/Versions/3.9/include/python3.9' % VenturaPy3FW,
|
||||
'lib': '%s/Python3.framework/Versions/3.9/lib/libpython3.9.dylib' % VenturaPy3FW
|
||||
}
|
||||
|
||||
# Bundled with Sonoma (14.x)
|
||||
# [Key Type Name] = 'Sys'
|
||||
SonomaPy3FWXc = "/Applications/Xcode.app/Contents/Developer/Library/Frameworks"
|
||||
SonomaPy3FW = "/Library/Developer/CommandLineTools/Library/Frameworks"
|
||||
PythonSonoma = { 'exe': '%s/Python3.framework/Versions/3.9/bin/python3.9' % SonomaPy3FW,
|
||||
'inc': '%s/Python3.framework/Versions/3.9/include/python3.9' % SonomaPy3FW,
|
||||
'lib': '%s/Python3.framework/Versions/3.9/lib/libpython3.9.dylib' % SonomaPy3FW
|
||||
}
|
||||
|
||||
# Python 3.9 from MacPorts (https://www.macports.org/)
|
||||
# install with 'sudo port install python39'
|
||||
# [Key Type Name] = 'MP39'
|
||||
|
|
@ -299,6 +326,9 @@ else:
|
|||
|
||||
# Consolidated dictionary kit for Python
|
||||
PythonDictionary = { 'nil' : None,
|
||||
'PythonMonterey' : PythonMonterey,
|
||||
'PythonVentura' : PythonVentura,
|
||||
'PythonSonoma' : PythonSonoma,
|
||||
'Python39MacPorts' : Python39MacPorts,
|
||||
'Python311MacPorts': Python311MacPorts,
|
||||
'Python39Brew' : Python39Brew,
|
||||
|
|
@ -312,7 +342,7 @@ if _have_Homebrew_Python:
|
|||
# [4] KLayout executables including buddy tools
|
||||
#-----------------------------------------------------
|
||||
KLayoutExecs = [ 'klayout' ]
|
||||
KLayoutExecs += [ 'strm2cif', 'strm2dxf', 'strm2gds', 'strm2gdstxt', 'strm2oas' ]
|
||||
KLayoutExecs += [ 'strm2cif', 'strm2dxf', 'strm2gds', 'strm2gdstxt', 'strm2mag', 'strm2oas' ]
|
||||
KLayoutExecs += [ 'strm2txt', 'strmclip', 'strmcmp', 'strmrun', 'strmxor' ]
|
||||
|
||||
#----------------
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env python3
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#========================================================================================
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
# Here are utility functions and classes ...
|
||||
# for building KLayout (http://www.klayout.de/index.php)
|
||||
# version 0.26.1 or later on different Apple Mac OSX platforms.
|
||||
# version 0.28.17 or later on different Apple Mac OSX platforms.
|
||||
#
|
||||
# This file is imported by 'build4mac.py' script.
|
||||
#========================================================================================
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# File: "macbuild/macQAT.py"
|
||||
#
|
||||
# The top Python script to run "ut_runner" after building KLayout
|
||||
# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
|
||||
# (http://www.klayout.de/index.php) version 0.28.17 or later on different Apple
|
||||
# ßMac OSX platforms.
|
||||
#
|
||||
# This script must be copied to a "*.macQAT/" directory to run.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# File: "macbuild/macQAT.sh"
|
||||
#
|
||||
# The top Bash script to run "ut_runner" after building KLayout
|
||||
# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
|
||||
# (http://www.klayout.de/index.php) version 0.25.17 or later on different Apple
|
||||
# Mac OSX platforms.
|
||||
#
|
||||
# This script must be copied to a "*.macQAT/" directory to run.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# File: "macbuild/macQAT2.sh"
|
||||
#
|
||||
# The top Bash script to run "ut_runner" after building KLayout
|
||||
# (http://www.klayout.de/index.php) version 0.26.1 or later on different Apple
|
||||
# (http://www.klayout.de/index.php) version 0.28.17 or later on different Apple
|
||||
# Mac OSX platforms.
|
||||
#
|
||||
# This script must be copied to a directory that can be found in $PATH.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env python3
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#=============================================================================================
|
||||
|
|
@ -63,7 +63,7 @@ def SetGlobals():
|
|||
global LatestOSHomebrew # True if 'LatestOS with Homebrew' and targeting LW-*
|
||||
global LatestOSAnaconda3 # True if 'LatestOS with Anaconda3' and targeting LW-*
|
||||
global LatestOSHomebrewH # True if 'LatestOS with Homebrew' and targeting HW-*
|
||||
global DicLightHeavyW # dictionary for LW-* and HW-* packages
|
||||
global DicStdLightHeavyW # dictionary for LW-* and HW-* packages
|
||||
global Item3AppleScript # ITEM_3 in the Apple script
|
||||
# auxiliary variables on platform
|
||||
global System # 6-tuple from platform.uname()
|
||||
|
|
@ -77,13 +77,13 @@ def SetGlobals():
|
|||
Usage = "\n"
|
||||
Usage += "---------------------------------------------------------------------------------------------------------\n"
|
||||
Usage += "<< Usage of 'makeDMG4mac.py' >>\n"
|
||||
Usage += " for making a DMG file of KLayout 0.28.13 or later on different Apple macOS platforms.\n"
|
||||
Usage += " for making a DMG file of KLayout 0.28.17 or later on different Apple macOS platforms.\n"
|
||||
Usage += "\n"
|
||||
Usage += "$ [python] ./makeDMG4mac.py\n"
|
||||
Usage += " option & argument : descriptions | default value\n"
|
||||
Usage += " ----------------------------------------------------------------------------------+-----------------\n"
|
||||
Usage += " <-p|--pkg <dir>> : package directory created by `build4mac.py` with [-y|-Y] | ``\n"
|
||||
Usage += " : like 'LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311' | \n"
|
||||
Usage += " : like 'LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311' | \n"
|
||||
Usage += " <-c|--clean> : clean the work directory | disabled\n"
|
||||
Usage += " <-m|--make> : make a compressed DMG file | disabled\n"
|
||||
Usage += " : <-c|--clean> and <-m|--make> are mutually exclusive | \n"
|
||||
|
|
@ -158,51 +158,59 @@ def SetGlobals():
|
|||
LatestOSHomebrew = False
|
||||
LatestOSAnaconda3 = False
|
||||
LatestOSHomebrewH = False
|
||||
DicLightHeavyW = dict()
|
||||
DicStdLightHeavyW = dict()
|
||||
Item3AppleScript = ""
|
||||
|
||||
# Populate DicLightHeavyW
|
||||
DicLightHeavyW[ "ports" ] = dict() # LW-*
|
||||
DicLightHeavyW[ "brew" ] = dict() # LW-*
|
||||
DicLightHeavyW[ "ana3" ] = dict() # LW-*
|
||||
DicLightHeavyW[ "brewH" ] = dict() # HW-*
|
||||
# Populate DicStdLightHeavyW
|
||||
DicStdLightHeavyW[ "std" ] = dict() # ST-*
|
||||
DicStdLightHeavyW[ "ports" ] = dict() # LW-*
|
||||
DicStdLightHeavyW[ "brew" ] = dict() # LW-*
|
||||
DicStdLightHeavyW[ "ana3" ] = dict() # LW-*
|
||||
DicStdLightHeavyW[ "brewH" ] = dict() # HW-*
|
||||
|
||||
DicLightHeavyW[ "ports" ]["zip"] = "macbuild/Resources/script-bundle-P.zip"
|
||||
DicLightHeavyW[ "ports" ]["src"] = "script-bundle-P"
|
||||
DicLightHeavyW[ "ports" ]["des"] = "MacPortsUser-ReadMeFirst"
|
||||
DicLightHeavyW[ "ports" ]["item3"] = 'set position of item "MacPortsUser-ReadMeFirst" to {700, 400}'
|
||||
DicStdLightHeavyW[ "std" ]["zip"] = "macbuild/Resources/script-bundle-S.zip"
|
||||
DicStdLightHeavyW[ "std" ]["src"] = "script-bundle-S"
|
||||
DicStdLightHeavyW[ "std" ]["des"] = "MacStdUser-ReadMeFirst"
|
||||
DicStdLightHeavyW[ "std" ]["item3"] = 'set position of item "MacStdUser-ReadMeFirst" to {700, 400}'
|
||||
|
||||
DicLightHeavyW[ "brew" ]["zip"] = "macbuild/Resources/script-bundle-B.zip"
|
||||
DicLightHeavyW[ "brew" ]["src"] = "script-bundle-B"
|
||||
DicLightHeavyW[ "brew" ]["des"] = "HomebrewUser-ReadMeFirst"
|
||||
DicLightHeavyW[ "brew" ]["item3"] = 'set position of item "HomebrewUser-ReadMeFirst" to {700, 400}'
|
||||
DicStdLightHeavyW[ "ports" ]["zip"] = "macbuild/Resources/script-bundle-P.zip"
|
||||
DicStdLightHeavyW[ "ports" ]["src"] = "script-bundle-P"
|
||||
DicStdLightHeavyW[ "ports" ]["des"] = "MacPortsUser-ReadMeFirst"
|
||||
DicStdLightHeavyW[ "ports" ]["item3"] = 'set position of item "MacPortsUser-ReadMeFirst" to {700, 400}'
|
||||
|
||||
DicLightHeavyW[ "ana3" ]["zip"] = "macbuild/Resources/script-bundle-A.zip"
|
||||
DicLightHeavyW[ "ana3" ]["src"] = "script-bundle-A"
|
||||
DicLightHeavyW[ "ana3" ]["des"] = "Anaconda3User-ReadMeFirst"
|
||||
DicLightHeavyW[ "ana3" ]["item3"] = 'set position of item "Anaconda3User-ReadMeFirst" to {700, 400}'
|
||||
DicStdLightHeavyW[ "brew" ]["zip"] = "macbuild/Resources/script-bundle-B.zip"
|
||||
DicStdLightHeavyW[ "brew" ]["src"] = "script-bundle-B"
|
||||
DicStdLightHeavyW[ "brew" ]["des"] = "HomebrewUser-ReadMeFirst"
|
||||
DicStdLightHeavyW[ "brew" ]["item3"] = 'set position of item "HomebrewUser-ReadMeFirst" to {700, 400}'
|
||||
|
||||
DicLightHeavyW[ "brewH" ]["zip"] = "macbuild/Resources/script-bundle-H.zip"
|
||||
DicLightHeavyW[ "brewH" ]["src"] = "script-bundle-H"
|
||||
DicLightHeavyW[ "brewH" ]["des"] = "Homebrew-HUser-ReadMeFirst"
|
||||
DicLightHeavyW[ "brewH" ]["item3"] = 'set position of item "Homebrew-HUser-ReadMeFirst" to {700, 400}'
|
||||
DicStdLightHeavyW[ "ana3" ]["zip"] = "macbuild/Resources/script-bundle-A.zip"
|
||||
DicStdLightHeavyW[ "ana3" ]["src"] = "script-bundle-A"
|
||||
DicStdLightHeavyW[ "ana3" ]["des"] = "Anaconda3User-ReadMeFirst"
|
||||
DicStdLightHeavyW[ "ana3" ]["item3"] = 'set position of item "Anaconda3User-ReadMeFirst" to {700, 400}'
|
||||
|
||||
DicStdLightHeavyW[ "brewH" ]["zip"] = "macbuild/Resources/script-bundle-H.zip"
|
||||
DicStdLightHeavyW[ "brewH" ]["src"] = "script-bundle-H"
|
||||
DicStdLightHeavyW[ "brewH" ]["des"] = "Homebrew-HUser-ReadMeFirst"
|
||||
DicStdLightHeavyW[ "brewH" ]["item3"] = 'set position of item "Homebrew-HUser-ReadMeFirst" to {700, 400}'
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
## To check the contents of the package directory
|
||||
#
|
||||
# The package directory name should look like:
|
||||
# * ST-qt5MP.pkg.macos-Monterey-release-RsysPsys
|
||||
# * LW-qt5Ana3.pkg.macos-Monterey-release-Rana3Pana3
|
||||
# * LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311 --- (1)
|
||||
# * LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311
|
||||
# * LW-qt5Brew.pkg.macos-Monterey-release-Rhb33Phb311 --- (1)
|
||||
# * LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311
|
||||
# * HW-qt5Brew.pkg.macos-Monterey-release-RsysPhb311
|
||||
#
|
||||
# * ST-qt6MP.pkg.macos-Monterey-release-RsysPsys
|
||||
# * LW-qt6Ana3.pkg.macos-Monterey-release-Rana3Pana3
|
||||
# * LW-qt6Brew.pkg.macos-Monterey-release-Rhb32Phb311
|
||||
# * LW-qt6MP.pkg.macos-Monterey-release-Rmp32Pmp311
|
||||
# * LW-qt6Brew.pkg.macos-Monterey-release-Rhb33Phb311
|
||||
# * LW-qt6MP.pkg.macos-Monterey-release-Rmp33Pmp311
|
||||
# * HW-qt6Brew.pkg.macos-Monterey-release-RsysPhb311
|
||||
#
|
||||
# Generated DMG will be, for example,
|
||||
# (1) ---> LW-klayout-0.28.13-macOS-Monterey-1-qt5Brew-Rhb32Phb311.dmg
|
||||
# (1) ---> LW-klayout-0.28.17-macOS-Monterey-1-qt5Brew-Rhb33Phb311.dmg
|
||||
#
|
||||
# @return on success, positive integer in [MB] that tells approx. occupied disc space;
|
||||
# on failure, -1
|
||||
|
|
@ -223,7 +231,7 @@ def CheckPkgDirectory():
|
|||
global LatestOSHomebrew
|
||||
global LatestOSAnaconda3
|
||||
global LatestOSHomebrewH
|
||||
global DicLightHeavyW
|
||||
global DicStdLightHeavyW
|
||||
global Item3AppleScript
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
|
@ -241,18 +249,20 @@ def CheckPkgDirectory():
|
|||
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
# [2] Identify (Qt, Ruby, Python) from PkgDir
|
||||
# * ST-qt5MP.pkg.macos-Monterey-release-RsysPsys
|
||||
# * LW-qt5Ana3.pkg.macos-Monterey-release-Rana3Pana3
|
||||
# * LW-qt5Brew.pkg.macos-Monterey-release-Rhb32Phb311
|
||||
# * LW-qt5MP.pkg.macos-Monterey-release-Rmp32Pmp311
|
||||
# * LW-qt5Brew.pkg.macos-Monterey-release-Rhb33Phb311
|
||||
# * LW-qt5MP.pkg.macos-Monterey-release-Rmp33Pmp311
|
||||
# * HW-qt5Brew.pkg.macos-Monterey-release-RsysPhb311
|
||||
# * EX-qt5MP.pkg.macos-Monterey-release-Rhb32Pmp311
|
||||
# * EX-qt5MP.pkg.macos-Monterey-release-Rhb33Pmp311
|
||||
#
|
||||
# * ST-qt6MP.pkg.macos-Monterey-release-RsysPsys
|
||||
# * LW-qt6Ana3.pkg.macos-Monterey-release-Rana3Pana3
|
||||
# * LW-qt6Brew.pkg.macos-Monterey-release-Rhb32Phb311
|
||||
# * LW-qt6MP.pkg.macos-Monterey-release-Rmp32Pmp311
|
||||
# * LW-qt6Brew.pkg.macos-Monterey-release-Rhb33Phb311
|
||||
# * LW-qt6MP.pkg.macos-Monterey-release-Rmp33Pmp311
|
||||
# * HW-qt6Brew.pkg.macos-Monterey-release-RsysPhb311
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
patQRP = u'(LW|HW|EX)([-])([qt5|qt6][0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-]release[-])([0-9A-Za-z]+)'
|
||||
patQRP = u'(ST|LW|HW|EX)([-])([qt5|qt6][0-9A-Za-z]+)([.]pkg[.])([A-Za-z]+[-][A-Za-z]+[-]release[-])([0-9A-Za-z]+)'
|
||||
regQRP = re.compile(patQRP)
|
||||
if not regQRP.match(PkgDir):
|
||||
print( "! Cannot identify (Qt, Ruby, Python) from the package directory name" )
|
||||
|
|
@ -277,15 +287,20 @@ def CheckPkgDirectory():
|
|||
#-----------------------------------------------------------------------------
|
||||
# [3] Check if the "LatestOS" with MacPorts / Homebrew / Anaconda3
|
||||
#-----------------------------------------------------------------------------
|
||||
LatestOSSys = Platform == LatestOS
|
||||
LatestOSSys &= PackagePrefix == "ST"
|
||||
LatestOSSys &= QtIdentification in [ "qt5MP", "qt6MP" ]
|
||||
LatestOSSys &= RubyPythonID in [ "RsysPsys" ]
|
||||
|
||||
LatestOSMacPorts = Platform == LatestOS
|
||||
LatestOSMacPorts &= PackagePrefix == "LW"
|
||||
LatestOSMacPorts &= QtIdentification in [ "qt5MP", "qt6MP" ]
|
||||
LatestOSMacPorts &= RubyPythonID in [ "Rmp32Pmp311", "Rmp32Pmp39" ]
|
||||
LatestOSMacPorts &= RubyPythonID in [ "Rmp33Pmp311", "Rmp33Pmp39" ]
|
||||
|
||||
LatestOSHomebrew = Platform == LatestOS
|
||||
LatestOSHomebrew &= PackagePrefix == "LW"
|
||||
LatestOSHomebrew &= QtIdentification in [ "qt5Brew", "qt6Brew" ]
|
||||
LatestOSHomebrew &= RubyPythonID in [ "Rhb32Phb311", "Rhb32Phb39", "Rhb32Phbauto" ]
|
||||
LatestOSHomebrew &= RubyPythonID in [ "Rhb33Phb311", "Rhb33Phb39", "Rhb33Phbauto" ]
|
||||
|
||||
LatestOSAnaconda3 = Platform == LatestOS
|
||||
LatestOSAnaconda3 &= PackagePrefix == "LW"
|
||||
|
|
@ -297,8 +312,23 @@ def CheckPkgDirectory():
|
|||
LatestOSHomebrewH &= QtIdentification in [ "qt5Brew", "qt6Brew" ]
|
||||
LatestOSHomebrewH &= RubyPythonID in [ "RsysPhb311", "RsysPhb39", "RsysPhbauto" ] # Sys-Homebre hybrid
|
||||
|
||||
if LatestOSSys:
|
||||
mydic = DicStdLightHeavyW["std"]
|
||||
srcDir = PkgDir + "/" + mydic["src"]
|
||||
desDir = PkgDir + "/" + mydic["des"]
|
||||
if OpMake:
|
||||
with zipfile.ZipFile( mydic["zip"], 'r' ) as zip_ref:
|
||||
zip_ref.extractall(PkgDir)
|
||||
os.rename( srcDir, desDir )
|
||||
if OpClean:
|
||||
if os.path.isdir(srcDir):
|
||||
shutil.rmtree(srcDir)
|
||||
if os.path.isdir(desDir):
|
||||
shutil.rmtree(desDir)
|
||||
Item3AppleScript = mydic["item3"]
|
||||
|
||||
if LatestOSMacPorts:
|
||||
mydic = DicLightHeavyW["ports"]
|
||||
mydic = DicStdLightHeavyW["ports"]
|
||||
srcDir = PkgDir + "/" + mydic["src"]
|
||||
desDir = PkgDir + "/" + mydic["des"]
|
||||
if OpMake:
|
||||
|
|
@ -313,7 +343,7 @@ def CheckPkgDirectory():
|
|||
Item3AppleScript = mydic["item3"]
|
||||
|
||||
if LatestOSHomebrew:
|
||||
mydic = DicLightHeavyW["brew"]
|
||||
mydic = DicStdLightHeavyW["brew"]
|
||||
srcDir = PkgDir + "/" + mydic["src"]
|
||||
desDir = PkgDir + "/" + mydic["des"]
|
||||
if OpMake:
|
||||
|
|
@ -328,7 +358,7 @@ def CheckPkgDirectory():
|
|||
Item3AppleScript = mydic["item3"]
|
||||
|
||||
if LatestOSAnaconda3:
|
||||
mydic = DicLightHeavyW["ana3"]
|
||||
mydic = DicStdLightHeavyW["ana3"]
|
||||
srcDir = PkgDir + "/" + mydic["src"]
|
||||
desDir = PkgDir + "/" + mydic["des"]
|
||||
if OpMake:
|
||||
|
|
@ -343,7 +373,7 @@ def CheckPkgDirectory():
|
|||
Item3AppleScript = mydic["item3"]
|
||||
|
||||
if LatestOSHomebrewH:
|
||||
mydic = DicLightHeavyW["brewH"]
|
||||
mydic = DicStdLightHeavyW["brewH"]
|
||||
srcDir = PkgDir + "/" + mydic["src"]
|
||||
desDir = PkgDir + "/" + mydic["des"]
|
||||
if OpMake:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env python3
|
||||
#!/Applications/anaconda3/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
|
|
@ -8,6 +8,20 @@ import glob
|
|||
import platform
|
||||
import optparse
|
||||
import subprocess
|
||||
#------------------------------------------------------------------------------
|
||||
# In general, avoid setting the first line to '#!/usr/bin/env python3'.
|
||||
# If so, when this script is invoked in the 'KLayoutNightlyBuild.app' script
|
||||
# bundle created by Automator, the python3 will be the macOS-bundled python3,
|
||||
# where pandas is not included by default.
|
||||
# Therefore, it is better to use one of:
|
||||
# 1) #!/Applications/anaconda3/bin/python3 (Anaconda3)
|
||||
# 2) #!/usr/local/bin/python3 (Homebrew needs 'pip3 install pandas')
|
||||
# 3) #!/opt/local/bin/python3 (MacPorts needs 'sudo pip3 install pandas')
|
||||
#
|
||||
# However, if we install 'pandas' and its dependencies to the system Python
|
||||
# environment, we can also set '#!/usr/bin/env python3'.
|
||||
#------------------------------------------------------------------------------
|
||||
import pandas as pd
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
## To test if the platform is a member of valid platforms
|
||||
|
|
@ -44,7 +58,7 @@ def Test_My_Platform( platforms=[ 'Monterey', 'Ventura', 'Sonoma' ] ):
|
|||
#------------------------------------------------------------------------------
|
||||
def Get_Build_Target_Dict():
|
||||
buildTargetDic = dict()
|
||||
# buildTargetDic[0] = 'std'
|
||||
buildTargetDic[0] = 'std'
|
||||
buildTargetDic[1] = 'ports'
|
||||
buildTargetDic[2] = 'brew'
|
||||
buildTargetDic[3] = 'brewHW'
|
||||
|
|
@ -61,45 +75,47 @@ def Get_Build_Target_Dict():
|
|||
# @param[in] platform platform name
|
||||
#
|
||||
# @return (dictionary1, dictionary2)-tupple
|
||||
# dictionary1: key=mnemonic, value=build option list
|
||||
# dictionary2: key=mnemonic, value=log file name
|
||||
# dictionary1: key=(qtVer, mnemonic), value=build option list
|
||||
# dictionary2: key=(qtVer, mnemonic), value=log file name
|
||||
#------------------------------------------------------------------------------
|
||||
def Get_Build_Options( targetDic, platform ):
|
||||
if QtType == 5:
|
||||
qtType = "Qt5"
|
||||
else:
|
||||
qtType = "Qt6"
|
||||
|
||||
buildOp = dict()
|
||||
logfile = dict()
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "std": # use 'Qt5MacPorts' that provides Qt 5.15.2~ to run on "Big Sur", too
|
||||
buildOp["std"] = [ '-q', '%sMacPorts' % qtType, '-r', 'sys', '-p', 'sys' ]
|
||||
logfile["std"] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPsys")
|
||||
elif target == "ports":
|
||||
buildOp["ports"] = [ '-q', '%sMacPorts' % qtType, '-r', 'MP32', '-p', 'MP311' ]
|
||||
logfile["ports"] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rmp32Pmp311")
|
||||
elif target == "brew":
|
||||
buildOp["brew"] = [ '-q', '%sBrew' % qtType, '-r', 'HB32', '-p', 'HB311' ]
|
||||
logfile["brew"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb32Phb311")
|
||||
elif target == "brewHW":
|
||||
buildOp["brewHW"] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HB311' ]
|
||||
logfile["brewHW"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhb311")
|
||||
elif target == "ana3":
|
||||
buildOp["ana3"] = [ '-q', '%sAna3' % qtType, '-r', 'Ana3', '-p', 'Ana3' ]
|
||||
logfile["ana3"] = "%sAna3.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rana3Pana3")
|
||||
elif target == "brewA":
|
||||
buildOp["brewA"] = [ '-q', '%sBrew' % qtType, '-r', 'HB32', '-p', 'HBAuto' ]
|
||||
logfile["brewA"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb32Phbauto")
|
||||
elif target == "brewAHW":
|
||||
buildOp["brewAHW"] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HBAuto' ]
|
||||
logfile["brewAHW"] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhbauto")
|
||||
|
||||
if WithPymod:
|
||||
buildOp["ports"] = buildOp["ports"] + ['--buildPymod']
|
||||
buildOp["brew"] = buildOp["brew"] + ['--buildPymod']
|
||||
buildOp["ana3"] = buildOp["ana3"] + ['--buildPymod']
|
||||
for qtVer in [5, 6]:
|
||||
if qtVer == 5:
|
||||
qtType = "Qt5"
|
||||
elif qtVer == 6:
|
||||
qtType = "Qt6"
|
||||
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "std":
|
||||
buildOp[(qtVer, "std")] = [ '-q', '%sMacPorts' % qtType, '-r', 'sys', '-p', 'sys' ]
|
||||
logfile[(qtVer, "std")] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPsys")
|
||||
elif target == "ports":
|
||||
buildOp[(qtVer, "ports")] = [ '-q', '%sMacPorts' % qtType, '-r', 'MP33', '-p', 'MP311' ]
|
||||
logfile[(qtVer, "ports")] = "%sMP.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rmp33Pmp311")
|
||||
elif target == "brew":
|
||||
buildOp[(qtVer, "brew")] = [ '-q', '%sBrew' % qtType, '-r', 'HB33', '-p', 'HB311' ]
|
||||
logfile[(qtVer, "brew")] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb33Phb311")
|
||||
elif target == "brewHW":
|
||||
buildOp[(qtVer, "brewHW")] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HB311' ]
|
||||
logfile[(qtVer, "brewHW")] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhb311")
|
||||
elif target == "ana3":
|
||||
buildOp[(qtVer, "ana3")] = [ '-q', '%sAna3' % qtType, '-r', 'Ana3', '-p', 'Ana3' ]
|
||||
logfile[(qtVer, "ana3")] = "%sAna3.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rana3Pana3")
|
||||
elif target == "brewA":
|
||||
buildOp[(qtVer, "brewA")] = [ '-q', '%sBrew' % qtType, '-r', 'HB33', '-p', 'HBAuto' ]
|
||||
logfile[(qtVer, "brewA")] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "Rhb33Phbauto")
|
||||
elif target == "brewAHW":
|
||||
buildOp[(qtVer, "brewAHW")] = [ '-q', '%sBrew' % qtType, '-r', 'sys', '-p', 'HBAuto' ]
|
||||
logfile[(qtVer, "brewAHW")] = "%sBrew.build.macos-%s-%s-%s.log" % (qtType.lower(), platform, "release", "RsysPhbauto")
|
||||
|
||||
if WithPymod:
|
||||
buildOp[(qtVer,"ports")] = buildOp[(qtVer,"ports")] + ['--buildPymod']
|
||||
buildOp[(qtVer,"brew")] = buildOp[(qtVer,"brew")] + ['--buildPymod']
|
||||
buildOp[(qtVer,"ana3")] = buildOp[(qtVer,"ana3")] + ['--buildPymod']
|
||||
|
||||
return (buildOp, logfile)
|
||||
|
||||
|
|
@ -109,29 +125,34 @@ def Get_Build_Options( targetDic, platform ):
|
|||
# @param[in] targetDic build target dictionary
|
||||
# @param[in] platform platform name
|
||||
#
|
||||
# @return a dictionary; key=mnemonic, value=".macQAT" directory
|
||||
# @return a dictionary; key=(qtVer, mnemonic), value=".macQAT" directory
|
||||
#------------------------------------------------------------------------------
|
||||
def Get_QAT_Directory( targetDic, platform ):
|
||||
if QtType == 5:
|
||||
qtType = "qt5"
|
||||
else:
|
||||
qtType = "qt6"
|
||||
|
||||
dirQAT = dict()
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "ports":
|
||||
dirQAT["ports"] = '%sMP.build.macos-%s-release-Rmp32Pmp311.macQAT' % (qtType, platform)
|
||||
elif target == "brew":
|
||||
dirQAT["brew"] = '%sBrew.build.macos-%s-release-Rhb32Phb311.macQAT' % (qtType, platform)
|
||||
elif target == "brewHW":
|
||||
dirQAT["brewHW"] = '%sBrew.build.macos-%s-release-RsysPhb311.macQAT' % (qtType, platform)
|
||||
elif target == "ana3":
|
||||
dirQAT["ana3"] = '%sAna3.build.macos-%s-release-Rana3Pana3.macQAT' % (qtType, platform)
|
||||
elif target == "brewA":
|
||||
dirQAT["brewA"] = '%sBrew.build.macos-%s-release-Rhb32Phbauto.macQAT' % (qtType, platform)
|
||||
elif target == "brewAHW":
|
||||
dirQAT["brewAHW"] = '%sBrew.build.macos-%s-release-RsysPhbauto.macQAT' % (qtType, platform)
|
||||
|
||||
for qtVer in [5, 6]:
|
||||
if qtVer == 5:
|
||||
qtType = "Qt5"
|
||||
elif qtVer == 6:
|
||||
qtType = "Qt6"
|
||||
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "std":
|
||||
dirQAT[(qtVer, "std")] = '%sMP.build.macos-%s-release-RsysPsys.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "ports":
|
||||
dirQAT[(qtVer, "ports")] = '%sMP.build.macos-%s-release-Rmp33Pmp311.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "brew":
|
||||
dirQAT[(qtVer, "brew")] = '%sBrew.build.macos-%s-release-Rhb33Phb311.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "brewHW":
|
||||
dirQAT[(qtVer, "brewHW")] = '%sBrew.build.macos-%s-release-RsysPhb311.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "ana3":
|
||||
dirQAT[(qtVer, "ana3")] = '%sAna3.build.macos-%s-release-Rana3Pana3.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "brewA":
|
||||
dirQAT[(qtVer, "brewA")] = '%sBrew.build.macos-%s-release-Rhb33Phbauto.macQAT' % (qtType.lower(), platform)
|
||||
elif target == "brewAHW":
|
||||
dirQAT[(qtVer, "brewAHW")] = '%sBrew.build.macos-%s-release-RsysPhbauto.macQAT' % (qtType.lower(), platform)
|
||||
|
||||
return dirQAT
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -142,40 +163,45 @@ def Get_QAT_Directory( targetDic, platform ):
|
|||
# @param[in] srlDMG serial number of DMG
|
||||
# @param[in] makeflag True to make; False to clean
|
||||
#
|
||||
# @return a dictionary; key=mnemonic, value=build option list
|
||||
# @return a dictionary; key=(qtVer, mnemonic), value=build option list
|
||||
#------------------------------------------------------------------------------
|
||||
def Get_Package_Options( targetDic, platform, srlDMG, makeflag ):
|
||||
if QtType == 5:
|
||||
qtType = "qt5"
|
||||
else:
|
||||
qtType = "qt6"
|
||||
packOp = dict()
|
||||
|
||||
if makeflag:
|
||||
flag = '-m'
|
||||
else:
|
||||
flag = '-c'
|
||||
|
||||
packOp = dict()
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "ports":
|
||||
packOp["ports"] = [ '-p', 'LW-%sMP.pkg.macos-%s-release-Rmp32Pmp311' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brew":
|
||||
packOp["brew"] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb32Phb311' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewHW":
|
||||
packOp["brewHW"] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhb311' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "ana3":
|
||||
packOp["ana3"] = [ '-p', 'LW-%sAna3.pkg.macos-%s-release-Rana3Pana3' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewA":
|
||||
packOp["brewA"] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb32Phbauto' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewAHW":
|
||||
packOp["brewAHW"] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhbauto' % (qtType, platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
for qtVer in [5, 6]:
|
||||
if qtVer == 5:
|
||||
qtType = "Qt5"
|
||||
elif qtVer == 6:
|
||||
qtType = "Qt6"
|
||||
|
||||
for key in targetDic.keys():
|
||||
target = targetDic[key]
|
||||
if target == "std":
|
||||
packOp[(qtVer, "std")] = [ '-p', 'ST-%sMP.pkg.macos-%s-release-RsysPsys' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "ports":
|
||||
packOp[(qtVer, "ports")] = [ '-p', 'LW-%sMP.pkg.macos-%s-release-Rmp33Pmp311' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brew":
|
||||
packOp[(qtVer, "brew")] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb33Phb311' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewHW":
|
||||
packOp[(qtVer, "brewHW")] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhb311' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "ana3":
|
||||
packOp[(qtVer, "ana3")] = [ '-p', 'LW-%sAna3.pkg.macos-%s-release-Rana3Pana3' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewA":
|
||||
packOp[(qtVer, "brewA")] = [ '-p', 'LW-%sBrew.pkg.macos-%s-release-Rhb33Phbauto' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
elif target == "brewAHW":
|
||||
packOp[(qtVer, "brewAHW")] = [ '-p', 'HW-%sBrew.pkg.macos-%s-release-RsysPhbauto' % (qtType.lower(), platform),
|
||||
'-s', '%d' % srlDMG, '%s' % flag ]
|
||||
return packOp
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -185,6 +211,7 @@ def Parse_CommandLine_Arguments():
|
|||
global Usage # usage
|
||||
global QtType # Qt type
|
||||
global Target # target list
|
||||
global QtTarget # list of (Qt, target)-tuple
|
||||
global Build # operation flag
|
||||
global WithPymod # operation flag
|
||||
global QATest # operation flag
|
||||
|
|
@ -198,9 +225,9 @@ def Parse_CommandLine_Arguments():
|
|||
|
||||
platform = Test_My_Platform()
|
||||
if platform in [ "Sonoma", "Ventura", "Monterey" ]:
|
||||
targetopt = "1,2,3,4"
|
||||
targetopt = "0,1,2,3,4"
|
||||
else:
|
||||
targetopt = "0"
|
||||
targetopt = None
|
||||
|
||||
Usage = "\n"
|
||||
Usage += "----------------------------------------------------------------------------------------------------------\n"
|
||||
|
|
@ -209,33 +236,39 @@ def Parse_CommandLine_Arguments():
|
|||
Usage += " macOS Monterey, Ventura, or Sonoma >>\n"
|
||||
Usage += "\n"
|
||||
Usage += "$ [python] nightlyBuild.py\n"
|
||||
Usage += " option & argument : comment on option if any | default value\n"
|
||||
Usage += " ------------------------------------------------------------------------+--------------\n"
|
||||
Usage += " [--qt <type>] : 5='qt5', 6='qt6' (migration to Qt6 is ongoing) | 5\n"
|
||||
Usage += " [--target <list>] : 1='ports', 2='brew', 3='brewHW', 4='ana3', | '%s'\n" % targetopt
|
||||
Usage += " 5='brewA', 6='brewAHW' |\n"
|
||||
Usage += " * with --qt=6, use --target='2,3' (4 is ignored) |\n"
|
||||
Usage += " [--build] : build and deploy | disabled\n"
|
||||
Usage += " [--pymod] : build and deploy Pymod, too | disabled\n"
|
||||
Usage += " [--test] : run the QA Test | disabled\n"
|
||||
Usage += " [--check] : check the QA Test results | disabled\n"
|
||||
Usage += " [--makedmg|--cleandmg <srlno>] : make or clean DMGs | disabled\n"
|
||||
Usage += " [--upload <dropbox>] : upload DMGs to $HOME/Dropbox/klayout/<dropbox> | disabled\n"
|
||||
Usage += " [--dryrun] : dry-run for --build option | disabled\n"
|
||||
Usage += " [-?|--?] : print this usage and exit | disabled\n"
|
||||
Usage += " |\n"
|
||||
Usage += " To use this script, make a symbolic link in the project root by: |\n"
|
||||
Usage += " $ ln -s ./macbuild/nightlyBuild.py . |\n"
|
||||
Usage += " |\n"
|
||||
Usage += " Regular sequence for using this script: |\n"
|
||||
Usage += " (1) $ ./nightlyBuild.py --build --pymod |\n"
|
||||
Usage += " (2) (confirm the build results) |\n"
|
||||
Usage += " (3) $ ./nightlyBuild.py --test |\n"
|
||||
Usage += " (4) $ ./nightlyBuild.py --check (confirm the QA Test results) |\n"
|
||||
Usage += " (5) $ ./nightlyBuild.py --makedmg 1 |\n"
|
||||
Usage += " (6) $ ./nightlyBuild.py --upload '0.28.12' |\n"
|
||||
Usage += " (7) $ ./nightlyBuild.py --cleandmg 1 |\n"
|
||||
Usage += "---------------------------------------------------------------------------+------------------------------\n"
|
||||
Usage += " option & argument : comment on option if any | default value\n"
|
||||
Usage += " --------------------------------------------------------------------------+--------------\n"
|
||||
Usage += " [--qt <type>] : 5='qt5', 6='qt6' (migration to Qt6 is ongoing) | 5\n"
|
||||
Usage += " [--target <list>] : 0='std', 1='ports', 2='brew', 3='brewHW', 4='ana3', | '%s'\n" % targetopt
|
||||
Usage += " 5='brewA', 6='brewAHW' |\n"
|
||||
Usage += " * with --qt=6, use --target='0,1,2,3' (4 is ignored) |\n"
|
||||
Usage += " [--qttarget <tuple list>] : ex. '5,1' for qt=5, target=1 | disabled\n"
|
||||
Usage += " + This option supersedes, if used, the --qt and --target combination. |\n"
|
||||
Usage += " + You can use this option multiple times. |\n"
|
||||
Usage += " + Or you can pass those list by the 'nightlyBuild.csv' file. |\n"
|
||||
Usage += " A sample file 'macbuild/nightlyBuild.sample.csv' is available. |\n"
|
||||
Usage += " [--build] : build and deploy | disabled\n"
|
||||
Usage += " [--pymod] : build and deploy Pymod, too | disabled\n"
|
||||
Usage += " [--test] : run the QA Test | disabled\n"
|
||||
Usage += " [--check] : check the QA Test results | disabled\n"
|
||||
Usage += " [--makedmg|--cleandmg <srlno>] : make or clean DMGs | disabled\n"
|
||||
Usage += " [--upload <dropbox>] : upload DMGs to $HOME/Dropbox/klayout/<dropbox> | disabled\n"
|
||||
Usage += " [--dryrun] : dry-run for --build option | disabled\n"
|
||||
Usage += " [-?|--?] : print this usage and exit | disabled\n"
|
||||
Usage += " |\n"
|
||||
Usage += " To use this script, make a symbolic link in the project root by: |\n"
|
||||
Usage += " $ ln -s ./macbuild/nightlyBuild.py . |\n"
|
||||
Usage += " + edit and save ./macbuild/nightlyBuild.csv (optional) |\n"
|
||||
Usage += " |\n"
|
||||
Usage += " Regular sequence for using this script: |\n"
|
||||
Usage += " (1) $ ./nightlyBuild.py --build --pymod |\n"
|
||||
Usage += " (2) (confirm the build results) |\n"
|
||||
Usage += " (3) $ ./nightlyBuild.py --test |\n"
|
||||
Usage += " (4) $ ./nightlyBuild.py --check (confirm the QA Test results) |\n"
|
||||
Usage += " (5) $ ./nightlyBuild.py --makedmg 1 |\n"
|
||||
Usage += " (6) $ ./nightlyBuild.py --upload '0.28.17' |\n"
|
||||
Usage += " (7) $ ./nightlyBuild.py --cleandmg 1 |\n"
|
||||
Usage += "-----------------------------------------------------------------------------+----------------------------\n"
|
||||
|
||||
p = optparse.OptionParser( usage=Usage )
|
||||
p.add_option( '--qt',
|
||||
|
|
@ -246,6 +279,11 @@ def Parse_CommandLine_Arguments():
|
|||
dest='targets',
|
||||
help='build target list' )
|
||||
|
||||
p.add_option( '--qttarget',
|
||||
action='append',
|
||||
dest='qt_target',
|
||||
help='(Qt, target)-tuple' )
|
||||
|
||||
p.add_option( '--build',
|
||||
action='store_true',
|
||||
dest='build',
|
||||
|
|
@ -296,6 +334,7 @@ def Parse_CommandLine_Arguments():
|
|||
|
||||
p.set_defaults( qt_type = "5",
|
||||
targets = "%s" % targetopt,
|
||||
qt_target = list(),
|
||||
build = False,
|
||||
with_pymod = False,
|
||||
qa_test = False,
|
||||
|
|
@ -331,9 +370,51 @@ def Parse_CommandLine_Arguments():
|
|||
targetDic = Get_Build_Target_Dict()
|
||||
Target = list()
|
||||
for idx in targetIdx:
|
||||
if idx in range(1, 7):
|
||||
if idx in range(0, 7):
|
||||
Target.append( targetDic[idx] )
|
||||
|
||||
# Populate QtTarget
|
||||
QtTarget = list()
|
||||
for target in Target:
|
||||
QtTarget.append( (QtType, target) )
|
||||
QtType = None
|
||||
Target = None
|
||||
print( "# The --qt and --target combination specifies..." )
|
||||
print(QtTarget)
|
||||
|
||||
if len(opt.qt_target) == 1 and opt.qt_target[0] == "nightlyBuild.csv": # reserved file name
|
||||
QtTarget = list()
|
||||
withqttarget = True
|
||||
df = pd.read_csv( opt.qt_target[0], comment="#" )
|
||||
if len(df) == 0:
|
||||
print( "! --qttarget==nightlyBuild.csv is used but DataFrame is empty" )
|
||||
print(Usage)
|
||||
quit()
|
||||
for i in range(0, len(df)):
|
||||
qt = df.iloc[i,0]
|
||||
idx = df.iloc[i,1]
|
||||
if (qt == 5 and idx in range(0, 7)) or (qt == 6 and idx in [0,1,2,3, 5,6]):
|
||||
QtTarget.append( (qt, targetDic[idx]) )
|
||||
elif len(opt.qt_target) > 0:
|
||||
QtTarget = list()
|
||||
withqttarget = True
|
||||
for item in opt.qt_target:
|
||||
qt = int(item.split(",")[0])
|
||||
idx = int(item.split(",")[1])
|
||||
if (qt == 5 and idx in range(0, 7)) or (qt == 6 and idx in [0,1,2,3, 5,6]):
|
||||
QtTarget.append( (qt, targetDic[idx]) )
|
||||
else:
|
||||
withqttarget = False
|
||||
|
||||
if withqttarget:
|
||||
if len(QtTarget) > 0:
|
||||
print( "# The --qttarget option superseded the --qt and --target combination" )
|
||||
print(QtTarget)
|
||||
else:
|
||||
print( "! --qttarget is used but there is no valid (Qt, target)-tuple" )
|
||||
print(Usage)
|
||||
quit()
|
||||
|
||||
Build = opt.build
|
||||
WithPymod = opt.with_pymod
|
||||
QATest = opt.qa_test
|
||||
|
|
@ -373,17 +454,18 @@ def Build_Deploy():
|
|||
myPlatform = Test_My_Platform()
|
||||
buildOp, logfile = Get_Build_Options( Get_Build_Target_Dict(), myPlatform )
|
||||
|
||||
for key in Target:
|
||||
if key == "ana3" and QtType == 6: # anaconda3 does not provide Qt6 so far
|
||||
for qttype, key in QtTarget:
|
||||
if key == "ana3" and qttype == 6: # anaconda3 does not provide Qt6 so far
|
||||
continue
|
||||
deplog = logfile[key].replace( ".log", ".dep.log" )
|
||||
|
||||
command1 = [ pyBuilder ] + buildOp[key]
|
||||
deplog = logfile[(qttype, key)].replace( ".log", ".dep.log" )
|
||||
|
||||
if key in [ "brewHW", "brewAHW" ] :
|
||||
command1 = [ pyBuilder ] + buildOp[(qttype, key)]
|
||||
|
||||
if key in [ "std", "brewHW", "brewAHW" ] :
|
||||
command2 = "time"
|
||||
command2 += " \\\n %s" % pyBuilder
|
||||
for option in buildOp[key]:
|
||||
for option in buildOp[(qttype, key)]:
|
||||
command2 += " \\\n %s" % option
|
||||
command2 += " \\\n %s" % '-y'
|
||||
command2 += " 2>&1 | tee %s; \\\n" % deplog
|
||||
|
|
@ -391,7 +473,7 @@ def Build_Deploy():
|
|||
else:
|
||||
command2 = "time"
|
||||
command2 += " \\\n %s" % pyBuilder
|
||||
for option in buildOp[key]:
|
||||
for option in buildOp[(qttype, key)]:
|
||||
command2 += " \\\n %s" % option
|
||||
command2 += " \\\n %s" % '-Y'
|
||||
command2 += " 2>&1 | tee %s; \\\n" % deplog
|
||||
|
|
@ -442,14 +524,14 @@ def Run_QATest( exclude ):
|
|||
myPlatform = Test_My_Platform()
|
||||
dirQAT = Get_QAT_Directory( Get_Build_Target_Dict(), myPlatform )
|
||||
|
||||
for key in Target:
|
||||
if key == 4 and QtType == 6: # anaconda3 does not provide Qt6 so far
|
||||
for qttype, key in QtTarget:
|
||||
if key == "ana3" and qttype == 6: # anaconda3 does not provide Qt6 so far
|
||||
continue
|
||||
|
||||
command1 = [ pyRunnerQAT ] + [ '--run', '--exclude', '%s' % exclude ]
|
||||
print( dirQAT[key], command1 )
|
||||
print( dirQAT[(qttype, key)], command1 )
|
||||
#continue
|
||||
os.chdir( dirQAT[key] )
|
||||
os.chdir( dirQAT[(qttype, key)] )
|
||||
|
||||
if subprocess.call( command1, shell=False ) != 0:
|
||||
print( "", file=sys.stderr )
|
||||
|
|
@ -477,14 +559,14 @@ def Check_QATest_Results( lines ):
|
|||
myPlatform = Test_My_Platform()
|
||||
dirQAT = Get_QAT_Directory( Get_Build_Target_Dict(), myPlatform )
|
||||
|
||||
for key in Target:
|
||||
if key == 4 and QtType == 6: # anaconda3 does not provide Qt6 so far
|
||||
for qttype, key in QtTarget:
|
||||
if key == "ana3" and qttype == 6: # anaconda3 does not provide Qt6 so far
|
||||
continue
|
||||
|
||||
os.chdir( dirQAT[key] )
|
||||
os.chdir( dirQAT[(qttype, key)] )
|
||||
logfile = glob.glob( "*.log" )
|
||||
command1 = [ tailCommand ] + [ '-n', '%d' % lines ] + logfile
|
||||
print( dirQAT[key], command1 )
|
||||
print( dirQAT[(qttype, key)], command1 )
|
||||
#continue
|
||||
|
||||
if subprocess.call( command1, shell=False ) != 0:
|
||||
|
|
@ -518,11 +600,11 @@ def DMG_Make( srlDMG ):
|
|||
shutil.rmtree( stashDMG )
|
||||
os.mkdir( stashDMG )
|
||||
|
||||
for key in Target:
|
||||
if key == 4 and QtType == 6: # anaconda3 does not provide Qt6 so far
|
||||
for qttype, key in QtTarget:
|
||||
if key == "ana3" and qttype == 6: # anaconda3 does not provide Qt6 so far
|
||||
continue
|
||||
|
||||
command1 = [ pyDMGmaker ] + packOp[key]
|
||||
command1 = [ pyDMGmaker ] + packOp[(qttype, key)]
|
||||
print(command1)
|
||||
#continue
|
||||
|
||||
|
|
@ -558,11 +640,11 @@ def DMG_Clean( srlDMG ):
|
|||
if os.path.isdir( stashDMG ):
|
||||
shutil.rmtree( stashDMG )
|
||||
|
||||
for key in Target:
|
||||
if key == 4 and QtType == 6: # anaconda3 does not provide Qt6 so far
|
||||
for qttype, key in QtTarget:
|
||||
if key == "ana3" and qttype == 6: # anaconda3 does not provide Qt6 so far
|
||||
continue
|
||||
|
||||
command1 = [ pyDMGmaker ] + packOp[key]
|
||||
command1 = [ pyDMGmaker ] + packOp[(qttype, key)]
|
||||
print(command1)
|
||||
#continue
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# File: 'nightlyBuild.csv'
|
||||
#
|
||||
# Descriptions:
|
||||
# This file (located where "build.sh" exists) is to be passed to
|
||||
# 'nightlyBuild.py' via the --qttarget option.
|
||||
#
|
||||
# qtVer,target
|
||||
# where
|
||||
# qtVer = 5 or 6
|
||||
# target = [0='std', 1='ports', 2='brew', 3='brewHW', 4='ana3']
|
||||
# note that
|
||||
# (qtVer,target)=(6,4) will be omitted
|
||||
#-------------------------------------------------------------------------------
|
||||
qtVer,target
|
||||
5,0
|
||||
5,1
|
||||
5,2
|
||||
5,3
|
||||
5,4
|
||||
#6,0
|
||||
#6,1
|
||||
#6,2
|
||||
#6,3
|
||||
#6,4
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 30.
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/env python3
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#==============================================================================
|
||||
|
|
|
|||
|
|
@ -177,6 +177,37 @@ run_demo gen, "input.width(1.2, projection)", "drc_width2.png"
|
|||
run_demo gen, "input.width(1.2, square)", "drc_width3.png"
|
||||
run_demo gen, "input.width(1.2, whole_edges)", "drc_width4.png"
|
||||
|
||||
class Gen
|
||||
def produce(s1, s2)
|
||||
pts = [
|
||||
RBA::Point::new(0, 0),
|
||||
RBA::Point::new(2000, 0),
|
||||
RBA::Point::new(2000, 2000),
|
||||
RBA::Point::new(0, 2000)
|
||||
];
|
||||
s1.insert(RBA::Polygon::new(pts))
|
||||
pts = [
|
||||
RBA::Point::new(2000, 2000),
|
||||
RBA::Point::new(4000, 2000),
|
||||
RBA::Point::new(4000, 4000),
|
||||
RBA::Point::new(2000, 4000)
|
||||
];
|
||||
s1.insert(RBA::Polygon::new(pts))
|
||||
pts = [
|
||||
RBA::Point::new( 500, 4000),
|
||||
RBA::Point::new(2500, 4000),
|
||||
RBA::Point::new(2500, 6000),
|
||||
RBA::Point::new( 500, 6000)
|
||||
];
|
||||
s1.insert(RBA::Polygon::new(pts))
|
||||
end
|
||||
end
|
||||
|
||||
gen = Gen::new
|
||||
|
||||
run_demo gen, "input.width(1.0)", "drc_width5.png"
|
||||
run_demo gen, "input.width(1.0, without_touching_corners)", "drc_width6.png"
|
||||
|
||||
class Gen
|
||||
def produce(s1, s2)
|
||||
pts = [
|
||||
|
|
@ -381,6 +412,45 @@ run_demo gen, "input1.sep(input2, 1.0, projection,\n" +
|
|||
" one_side_allowed,\n" +
|
||||
" two_opposite_sides_allowed)", "drc_separation11.png"
|
||||
|
||||
class Gen
|
||||
def produce(s1, s2)
|
||||
pts = [
|
||||
RBA::Point::new(0, 0),
|
||||
RBA::Point::new(2000, 0),
|
||||
RBA::Point::new(2000, 1500),
|
||||
RBA::Point::new(0, 1500)
|
||||
];
|
||||
s2.insert(RBA::Polygon::new(pts))
|
||||
pts = [
|
||||
RBA::Point::new(2000, 1500),
|
||||
RBA::Point::new(3500, 1500),
|
||||
RBA::Point::new(3500, 3500),
|
||||
RBA::Point::new(2000, 3500)
|
||||
];
|
||||
s1.insert(RBA::Polygon::new(pts))
|
||||
pts = [
|
||||
RBA::Point::new(1000, 3500),
|
||||
RBA::Point::new(3000, 3500),
|
||||
RBA::Point::new(3000, 5000),
|
||||
RBA::Point::new(1000, 5000)
|
||||
];
|
||||
s2.insert(RBA::Polygon::new(pts))
|
||||
pts = [
|
||||
RBA::Point::new(1000, 5500),
|
||||
RBA::Point::new(3000, 5500),
|
||||
RBA::Point::new(3000, 7000),
|
||||
RBA::Point::new(1000, 7000)
|
||||
];
|
||||
s1.insert(RBA::Polygon::new(pts))
|
||||
end
|
||||
end
|
||||
|
||||
gen = Gen::new
|
||||
|
||||
run_demo gen, "input1.sep(input2, 1.0)", "drc_separation12.png"
|
||||
run_demo gen, "input1.sep(input2, 1.0, without_touching_corners)", "drc_separation13.png"
|
||||
run_demo gen, "input1.sep(input2, 1.0, without_touching_edges)", "drc_separation14.png"
|
||||
|
||||
# ...
|
||||
|
||||
class Gen
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ buildopts=
|
|||
|
||||
# TODO: derive this list automatically?
|
||||
case $target in
|
||||
|
||||
debian12)
|
||||
depends="python3-dev, libc6-dev, libgcc-s1, libgit2-1.5, libqt6core5compat6, libqt6designer6, libqt6gui6, libqt6multimedia6, libqt6multimediaquick6, libqt6network6, libqt6printsupport6, libqt6sql6, libqt6svg6, libqt6widgets6, libqt6xml6, libruby3.1, libstdc++6, zlib1g"
|
||||
;;
|
||||
ubuntu16)
|
||||
depends="libqt4-designer (>= 4.8.6), libqt4-xml (>= 4.8.6), libqt4-sql (>= 4.8.6), libqt4-network (>= 4.8.6), libqtcore4 (>= 4.8.6), libqtgui4 (>= 4.8.6), zlib1g (>= 1.2.8), libgit2-24 (>= 0.24.0), libruby2.3 (>= 2.3.1), python3 (>= 3.5.1), libpython3.5 (>= 3.5.1), libstdc++6 (>= 4.6.3), libc6 (>= 2.15)"
|
||||
# No HTTPS support - that is somewhat useless
|
||||
|
|
@ -63,7 +67,7 @@ libdir="usr/lib/klayout"
|
|||
rm -rf $bininstdir
|
||||
|
||||
# do the actual build
|
||||
./build.sh -j2 \
|
||||
./build.sh -j$(nproc) \
|
||||
-bin $bininstdir \
|
||||
-build $builddir \
|
||||
-rpath /$libdir \
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>668</width>
|
||||
<height>410</height>
|
||||
<width>745</width>
|
||||
<height>438</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -845,7 +845,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle measurement (three mouse clicks)</string>
|
||||
<string>Auto measure along edge (points will be set automatically)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle or radius measurement (three mouse clicks)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ RulerModeConverter::to_string (ant::Template::ruler_mode_type m)
|
|||
return "single_click";
|
||||
} else if (m == ant::Template::RulerAutoMetric) {
|
||||
return "auto_metric";
|
||||
} else if (m == ant::Template::RulerAutoMetricEdge) {
|
||||
return "auto_metric_edge";
|
||||
} else if (m == ant::Template::RulerMultiSegment) {
|
||||
return "multi_segment";
|
||||
} else if (m == ant::Template::RulerThreeClicks) {
|
||||
|
|
@ -266,6 +268,8 @@ RulerModeConverter::from_string (const std::string &s, ant::Template::ruler_mode
|
|||
a = ant::Template::RulerSingleClick;
|
||||
} else if (t == "auto_metric") {
|
||||
a = ant::Template::RulerAutoMetric;
|
||||
} else if (t == "auto_metric_edge") {
|
||||
a = ant::Template::RulerAutoMetricEdge;
|
||||
} else if (t == "multi_segment") {
|
||||
a = ant::Template::RulerMultiSegment;
|
||||
} else if (t == "angle") {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ static std::vector<ant::Template> make_standard_templates ()
|
|||
templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
|
||||
templates.back ().set_mode (ant::Template::RulerAutoMetric);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Measure edge")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure_edge"));
|
||||
templates.back ().set_mode (ant::Template::RulerAutoMetricEdge);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Angle")), "", "", "$(sprintf('%.5g',G))°", ant::Object::STY_line, ant::Object::OL_angle, true, lay::AC_Global, "_angle"));
|
||||
templates.back ().set_mode (ant::Template::RulerThreeClicks);
|
||||
|
||||
|
|
|
|||
|
|
@ -1056,8 +1056,18 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
m_drawing (false), m_current (),
|
||||
m_move_mode (MoveNone),
|
||||
m_seg_index (0),
|
||||
m_current_template (0)
|
||||
{
|
||||
m_current_template (0),
|
||||
m_hover (false),
|
||||
m_hover_wait (false),
|
||||
m_hover_buttons (0),
|
||||
m_mouse_in_window (false)
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
m_timer.setInterval (100 /*hover time*/);
|
||||
m_timer.setSingleShot (true);
|
||||
connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timeout ()));
|
||||
#endif
|
||||
|
||||
mp_view->annotations_changed_event.add (this, &Service::annotations_changed);
|
||||
}
|
||||
|
||||
|
|
@ -1809,9 +1819,36 @@ Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int button
|
|||
return false;
|
||||
}
|
||||
|
||||
lay::TwoPointSnapToObjectResult
|
||||
Service::auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl)
|
||||
{
|
||||
// for auto-metric we need some cutline constraint - any or global won't do.
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = tpl.angle_constraint ();
|
||||
}
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = m_snap_mode;
|
||||
}
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = lay::AC_Diagonal;
|
||||
}
|
||||
|
||||
db::DVector g;
|
||||
if (m_grid_snap) {
|
||||
g = db::DVector (m_grid, m_grid);
|
||||
}
|
||||
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (m_snap_range);
|
||||
snap_range *= 0.5;
|
||||
|
||||
return lay::obj_snap2 (mp_view, p, g, ac, snap_range, snap_range * 1000.0);
|
||||
}
|
||||
|
||||
bool
|
||||
Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
hover_reset ();
|
||||
|
||||
if (prio && (buttons & lay::LeftButton) != 0) {
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
|
|
@ -1852,27 +1889,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
} else if (tpl.mode () == ant::Template::RulerAutoMetric) {
|
||||
|
||||
// for auto-metric we need some cutline constraint - any or global won't do.
|
||||
lay::angle_constraint_type ac = ac_from_buttons (buttons);
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = tpl.angle_constraint ();
|
||||
}
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = m_snap_mode;
|
||||
}
|
||||
if (ac == lay::AC_Global) {
|
||||
ac = lay::AC_Diagonal;
|
||||
}
|
||||
|
||||
db::DVector g;
|
||||
if (m_grid_snap) {
|
||||
g = db::DVector (m_grid, m_grid);
|
||||
}
|
||||
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (m_snap_range);
|
||||
snap_range *= 0.5;
|
||||
|
||||
lay::TwoPointSnapToObjectResult ee = lay::obj_snap2 (mp_view, p, g, ac, snap_range, snap_range * 1000.0);
|
||||
lay::TwoPointSnapToObjectResult ee = auto_measure (p, ac_from_buttons (buttons), tpl);
|
||||
if (ee.any) {
|
||||
|
||||
// begin the transaction
|
||||
|
|
@ -1893,6 +1910,29 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
}
|
||||
|
||||
} else if (tpl.mode () == ant::Template::RulerAutoMetricEdge) {
|
||||
|
||||
lay::PointSnapToObjectResult snap_details = snap1_details (p, true);
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::ObjectEdge) {
|
||||
|
||||
// begin the transaction
|
||||
if (manager ()) {
|
||||
tl_assert (! manager ()->transacting ());
|
||||
manager ()->transaction (tl::to_string (tr ("Create ruler")));
|
||||
}
|
||||
|
||||
m_current = ant::Object (snap_details.object_ref.p1 (), snap_details.object_ref.p2 (), 0, tpl);
|
||||
show_message ();
|
||||
|
||||
insert_ruler (m_current, true);
|
||||
|
||||
// end the transaction
|
||||
if (manager ()) {
|
||||
manager ()->commit ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
m_p1 = snap1 (p, m_obj_snap && tpl.snap ()).second;
|
||||
|
|
@ -1968,21 +2008,33 @@ Service::create_measure_ruler (const db::DPoint &pt, lay::angle_constraint_type
|
|||
bool
|
||||
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
if (prio) {
|
||||
if (! prio) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
if (m_drawing) {
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
|
||||
} else {
|
||||
const ant::Template &tpl = current_template ();
|
||||
snap_details = snap1_details (p, m_obj_snap && tpl.snap ());
|
||||
}
|
||||
if (! m_drawing && m_mouse_in_window && view ()->transient_selection_mode ()) {
|
||||
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
// Restart hover timer
|
||||
m_hover_wait = true;
|
||||
#if defined(HAVE_QT)
|
||||
m_timer.start ();
|
||||
#endif
|
||||
m_hover_point = p;
|
||||
m_hover_buttons = buttons;
|
||||
|
||||
}
|
||||
|
||||
if (m_drawing && prio) {
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
if (m_drawing) {
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
|
||||
} else {
|
||||
const ant::Template &tpl = current_template ();
|
||||
snap_details = snap1_details (p, m_obj_snap && tpl.snap () && (tpl.mode () != ant::Template::RulerAutoMetricEdge || ! view ()->transient_selection_mode ()));
|
||||
}
|
||||
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
|
||||
if (m_drawing) {
|
||||
|
||||
set_cursor (lay::Cursor::cross);
|
||||
|
||||
|
|
@ -2284,6 +2336,84 @@ Service::click_proximity (const db::DPoint &pos, lay::Editable::SelectionMode mo
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Service::enter_event (bool /*prio*/)
|
||||
{
|
||||
m_mouse_in_window = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Service::leave_event (bool)
|
||||
{
|
||||
m_mouse_in_window = false;
|
||||
hover_reset ();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Service::hover_reset ()
|
||||
{
|
||||
if (m_hover_wait) {
|
||||
#if defined(HAVE_QT)
|
||||
m_timer.stop ();
|
||||
#endif
|
||||
m_hover_wait = false;
|
||||
}
|
||||
if (m_hover) {
|
||||
// as we use the transient selection for the hover ruler, we have to remove it here
|
||||
clear_transient_selection ();
|
||||
m_hover = false;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
void
|
||||
Service::timeout ()
|
||||
{
|
||||
m_hover_wait = false;
|
||||
m_hover = true;
|
||||
|
||||
// as we use the transient selection for the hover ruler, we have to remove it here
|
||||
clear_transient_selection ();
|
||||
|
||||
// transiently create an auto-metric ruler if requested
|
||||
|
||||
ant::Object *ruler = 0;
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
if (tpl.mode () == ant::Template::RulerAutoMetric) {
|
||||
|
||||
lay::TwoPointSnapToObjectResult ee = auto_measure (m_hover_point, ac_from_buttons (m_hover_buttons), tpl);
|
||||
if (ee.any) {
|
||||
m_current = ant::Object (ee.first, ee.second, 0, tpl);
|
||||
ruler = &m_current;
|
||||
}
|
||||
|
||||
} else if (tpl.mode () == ant::Template::RulerAutoMetricEdge) {
|
||||
|
||||
lay::PointSnapToObjectResult snap_details = snap1_details (m_hover_point, true);
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::ObjectEdge) {
|
||||
m_current = ant::Object (snap_details.object_ref.p1 (), snap_details.object_ref.p2 (), 0, tpl);
|
||||
ruler = &m_current;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ruler) {
|
||||
|
||||
// HINT: there is no special style for "transient selection on rulers"
|
||||
mp_transient_ruler = new ant::View (this, ruler, true /*not selected*/);
|
||||
|
||||
if (! editables ()->has_selection ()) {
|
||||
display_status (true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
Service::transient_select (const db::DPoint &pos)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#if defined (HAVE_QT)
|
||||
# include <QTimer>
|
||||
# include <QObject>
|
||||
#endif
|
||||
|
||||
namespace ant {
|
||||
|
||||
class LayoutViewBase;
|
||||
|
|
@ -177,12 +182,19 @@ private:
|
|||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
class ANT_PUBLIC Service
|
||||
: public lay::EditorServiceBase,
|
||||
class ANT_PUBLIC Service :
|
||||
#if defined (HAVE_QT)
|
||||
public QObject,
|
||||
#endif
|
||||
public lay::EditorServiceBase,
|
||||
public lay::Drawing,
|
||||
public db::Object
|
||||
{
|
||||
public:
|
||||
#if defined (HAVE_QT)
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef lay::AnnotationShapes::iterator obj_iterator;
|
||||
|
||||
/**
|
||||
|
|
@ -341,6 +353,21 @@ public:
|
|||
*/
|
||||
virtual db::DBox selection_bbox ();
|
||||
|
||||
/**
|
||||
* @brief Implementation of the editables API
|
||||
*/
|
||||
virtual bool enter_event (bool);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the editables API
|
||||
*/
|
||||
virtual bool leave_event (bool);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the editables API
|
||||
*/
|
||||
virtual void hover_reset ();
|
||||
|
||||
/**
|
||||
* @brief Transform the selection (reimplementation of lay::Editable interface)
|
||||
*/
|
||||
|
|
@ -506,6 +533,11 @@ public:
|
|||
*/
|
||||
tl::Event annotation_selection_changed_event;
|
||||
|
||||
#if defined (HAVE_QT)
|
||||
public slots:
|
||||
void timeout ();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Ruler display and snapping configuration
|
||||
tl::Color m_color;
|
||||
|
|
@ -551,10 +583,22 @@ private:
|
|||
std::vector<ant::Template> m_ruler_templates;
|
||||
unsigned int m_current_template;
|
||||
|
||||
// Hover detector
|
||||
bool m_hover;
|
||||
bool m_hover_wait;
|
||||
db::DPoint m_hover_point;
|
||||
unsigned int m_hover_buttons;
|
||||
#if defined (HAVE_QT)
|
||||
QTimer m_timer;
|
||||
#endif
|
||||
|
||||
bool m_mouse_in_window;
|
||||
|
||||
std::pair<bool, db::DPoint> snap1 (const db::DPoint &p, bool obj_snap);
|
||||
lay::PointSnapToObjectResult snap1_details (const db::DPoint &p, bool obj_snap);
|
||||
std::pair<bool, db::DPoint> snap2 (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::TwoPointSnapToObjectResult auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl);
|
||||
|
||||
const ant::Template ¤t_template () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,15 +64,20 @@ public:
|
|||
*/
|
||||
RulerAutoMetric = 2,
|
||||
|
||||
/**
|
||||
* @brief The ruler is auto-metric along an edge: a single click will place a ruler and the ruler will extend to the edge below
|
||||
*/
|
||||
RulerAutoMetricEdge = 3,
|
||||
|
||||
/**
|
||||
* @brief The ruler an angle type (two segments, three mouse clicks) for angle and circle radius measurements
|
||||
*/
|
||||
RulerThreeClicks = 3,
|
||||
RulerThreeClicks = 4,
|
||||
|
||||
/**
|
||||
* @brief The ruler is a multi-segment type
|
||||
*/
|
||||
RulerMultiSegment = 4
|
||||
RulerMultiSegment = 5
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -434,6 +434,11 @@ static int ruler_mode_auto_metric ()
|
|||
return ant::Template::RulerAutoMetric;
|
||||
}
|
||||
|
||||
static int ruler_mode_auto_metric_edge ()
|
||||
{
|
||||
return ant::Template::RulerAutoMetricEdge;
|
||||
}
|
||||
|
||||
static int ruler_mode_three_clicks ()
|
||||
{
|
||||
return ant::Template::RulerThreeClicks;
|
||||
|
|
@ -525,6 +530,12 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This constant has been introduced in version 0.25"
|
||||
) +
|
||||
gsi::method ("RulerModeAutoMetricEdge", &gsi::ruler_mode_auto_metric_edge,
|
||||
"@brief Specifies edge-sensitive auto-metric ruler mode for the \\register_template method\n"
|
||||
"In auto-metric mode, a ruler can be placed with a single click and p1/p2 will be determined from the edge it is placed on.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.29"
|
||||
) +
|
||||
gsi::method ("RulerThreeClicks", &gsi::ruler_mode_three_clicks,
|
||||
"@brief Specifies three-click ruler mode for the \\register_template method\n"
|
||||
"In this ruler mode, two segments are created for angle and circle radius measurements. Three mouse clicks are required.\n"
|
||||
|
|
|
|||
|
|
@ -744,12 +744,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
|
|||
}
|
||||
}
|
||||
|
||||
EdgeRelationFilter check (rel, d, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d, options);
|
||||
|
||||
edge2edge_check_for_edges<db::FlatEdgePairs> edge_check (check, *result, other != 0);
|
||||
scanner.process (edge_check, d, db::box_convert<db::Edge> ());
|
||||
|
|
|
|||
|
|
@ -1163,12 +1163,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
|
|||
db::RegionIterator polygons (needs_merged_primary ? begin_merged () : begin ());
|
||||
bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d, options);
|
||||
|
||||
std::vector<db::RegionIterator> others;
|
||||
std::vector<bool> foreign;
|
||||
|
|
@ -1241,12 +1236,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
|
|||
std::unique_ptr<FlatEdgePairs> result (new FlatEdgePairs ());
|
||||
db::PropertyMapper pm (result->properties_repository (), properties_repository ());
|
||||
|
||||
EdgeRelationFilter check (rel, d, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d, options);
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
|
||||
|
|
|
|||
|
|
@ -154,13 +154,17 @@ CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string
|
|||
common_reader_error (tl::sprintf (tl::to_string (tr ("Cell named %s with ID %ld was already given name %s")), cn, id, iid->second.first));
|
||||
}
|
||||
|
||||
if (iname != m_name_map.end () && iname->second.first != null_id && iname->second.first != id) {
|
||||
common_reader_error (tl::sprintf (tl::to_string (tr ("Same cell name %s, but different IDs: %ld and %ld")), cn, id, iname->second.first));
|
||||
}
|
||||
|
||||
if (iid != m_id_map.end () && iname != m_name_map.end ()) {
|
||||
|
||||
if (iname->second.second != iid->second.second) {
|
||||
|
||||
// Both cells already exist and are not identical: merge ID-declared cell into the name-declared one
|
||||
layout.force_update ();
|
||||
merge_cell (layout, iname->second.second, iid->second.second);
|
||||
merge_cell (layout, iname->second.second, iid->second.second, true);
|
||||
iid->second.second = iname->second.second;
|
||||
|
||||
}
|
||||
|
|
@ -235,7 +239,7 @@ CommonReaderBase::cell_for_instance (db::Layout &layout, const std::string &cn)
|
|||
}
|
||||
|
||||
void
|
||||
CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
|
||||
CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const
|
||||
{
|
||||
const db::Cell &src_cell = layout.cell (src_cell_index);
|
||||
db::Cell &target_cell = layout.cell (target_cell_index);
|
||||
|
|
@ -249,11 +253,11 @@ CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cel
|
|||
}
|
||||
}
|
||||
|
||||
merge_cell_without_instances (layout, target_cell_index, src_cell_index);
|
||||
merge_cell_without_instances (layout, target_cell_index, src_cell_index, with_meta);
|
||||
}
|
||||
|
||||
void
|
||||
CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
|
||||
CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const
|
||||
{
|
||||
const db::Cell &src_cell = layout.cell (src_cell_index);
|
||||
db::Cell &target_cell = layout.cell (target_cell_index);
|
||||
|
|
@ -268,6 +272,16 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind
|
|||
// replace all instances of the new cell with the original one
|
||||
layout.replace_instances_of (src_cell.cell_index (), target_cell.cell_index ());
|
||||
|
||||
// merge meta info
|
||||
if (with_meta) {
|
||||
auto ib = layout.begin_meta (src_cell.cell_index ());
|
||||
auto ie = layout.end_meta (src_cell.cell_index ());
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
layout.add_meta_info (target_cell.cell_index (), i->first, i->second);
|
||||
}
|
||||
}
|
||||
layout.clear_meta (src_cell.cell_index ());
|
||||
|
||||
// finally delete the new cell
|
||||
layout.delete_cell (src_cell.cell_index ());
|
||||
}
|
||||
|
|
@ -371,7 +385,7 @@ CommonReaderBase::finish (db::Layout &layout)
|
|||
|
||||
layout.cell (ci_org).clear_shapes ();
|
||||
|
||||
merge_cell (layout, ci_org, ci_new);
|
||||
merge_cell (layout, ci_org, ci_new, true);
|
||||
|
||||
} else if (m_cc_resolution == SkipNewCell && ! layout.cell (ci_org).is_ghost_cell ()) {
|
||||
|
||||
|
|
@ -379,11 +393,11 @@ CommonReaderBase::finish (db::Layout &layout)
|
|||
layout.cell (ci_new).clear_shapes ();
|
||||
|
||||
// NOTE: ignore instances -> this saves us a layout update
|
||||
merge_cell_without_instances (layout, ci_org, ci_new);
|
||||
merge_cell_without_instances (layout, ci_org, ci_new, false);
|
||||
|
||||
} else {
|
||||
|
||||
merge_cell (layout, ci_org, ci_new);
|
||||
merge_cell (layout, ci_org, ci_new, m_cc_resolution != SkipNewCell);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,12 +242,12 @@ protected:
|
|||
/**
|
||||
* @brief Merge (and delete) the src_cell into target_cell
|
||||
*/
|
||||
void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
|
||||
void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const;
|
||||
|
||||
/**
|
||||
* @brief Merge (and delete) the src_cell into target_cell without instances
|
||||
*/
|
||||
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
|
||||
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the layer name map
|
||||
|
|
|
|||
|
|
@ -1625,19 +1625,13 @@ CompoundRegionEdgePairToEdgeProcessingOperationNode::do_compute_local (CompoundR
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false)
|
||||
: CompoundRegionMultiInputOperationNode (), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false)
|
||||
{
|
||||
set_description ("check");
|
||||
|
||||
m_check.set_include_zero (false);
|
||||
m_check.set_whole_edges (options.whole_edges);
|
||||
m_check.set_ignore_angle (options.ignore_angle);
|
||||
m_check.set_min_projection (options.min_projection);
|
||||
m_check.set_max_projection (options.max_projection);
|
||||
}
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (input), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false)
|
||||
: CompoundRegionMultiInputOperationNode (input), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false)
|
||||
{
|
||||
set_description ("check");
|
||||
|
||||
|
|
@ -1645,16 +1639,10 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
|||
if (pc_always_different (m_options.prop_constraint)) {
|
||||
m_different_polygons = true;
|
||||
}
|
||||
|
||||
m_check.set_include_zero (false);
|
||||
m_check.set_whole_edges (options.whole_edges);
|
||||
m_check.set_ignore_angle (options.ignore_angle);
|
||||
m_check.set_min_projection (options.min_projection);
|
||||
m_check.set_max_projection (options.max_projection);
|
||||
}
|
||||
|
||||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options)
|
||||
{
|
||||
tl_assert (input == 0); // input is a dummy parameter
|
||||
|
||||
|
|
@ -1663,12 +1651,6 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
|||
m_is_other_merged = other->is_merged ();
|
||||
|
||||
set_description ("check");
|
||||
|
||||
m_check.set_include_zero (false);
|
||||
m_check.set_whole_edges (options.whole_edges);
|
||||
m_check.set_ignore_angle (options.ignore_angle);
|
||||
m_check.set_min_projection (options.min_projection);
|
||||
m_check.set_max_projection (options.max_projection);
|
||||
}
|
||||
|
||||
db::OnEmptyIntruderHint
|
||||
|
|
|
|||
|
|
@ -1777,12 +1777,7 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord
|
|||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d, options);
|
||||
|
||||
std::unique_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (edges.derived ()));
|
||||
|
||||
|
|
|
|||
|
|
@ -1957,12 +1957,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
|
||||
const db::DeepLayer &polygons = needs_merged_primary ? merged_deep_layer () : deep_layer ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d, options);
|
||||
|
||||
std::unique_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
|
||||
|
|
@ -2025,12 +2020,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
double mag = tr.mag ();
|
||||
db::Coord d_with_mag = db::coord_traits<db::Coord>::rounded (d / mag);
|
||||
|
||||
EdgeRelationFilter check (rel, d_with_mag, options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (options.whole_edges);
|
||||
check.set_ignore_angle (options.ignore_angle);
|
||||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
EdgeRelationFilter check (rel, d_with_mag, options);
|
||||
|
||||
const db::Shapes &shapes = c->shapes (polygons.layer ());
|
||||
db::Shapes &result = c->shapes (res->deep_layer ().layer ());
|
||||
|
|
|
|||
|
|
@ -48,17 +48,53 @@ db::Edge::distance_type edge_projection (const db::Edge &a, const db::Edge &b)
|
|||
return db::coord_traits<db::Coord>::rounded (a.double_length () * fabs (l2 - l1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether zero distance is included in the checks
|
||||
*/
|
||||
static bool include_zero_flag (zero_distance_mode zd_mode, const db::Edge &a, const db::Edge &b)
|
||||
{
|
||||
if (zd_mode == AlwaysIncludeZeroDistance) {
|
||||
|
||||
return true;
|
||||
|
||||
} else if (zd_mode == NeverIncludeZeroDistance) {
|
||||
|
||||
return false;
|
||||
|
||||
} else {
|
||||
|
||||
int s1 = a.side_of (b.p1 ());
|
||||
int s2 = a.side_of (b.p2 ());
|
||||
|
||||
if (s1 == 0 && s2 == 0) {
|
||||
if (zd_mode == IncludeZeroDistanceWhenTouching || zd_mode == IncludeZeroDistanceWhenCollinearAndTouching) {
|
||||
return a.intersect (b);
|
||||
} else if (zd_mode == IncludeZeroDistanceWhenOverlapping) {
|
||||
return a.coincident (b);
|
||||
}
|
||||
} else if ((s1 == 0 || s2 == 0) && a.p1 () != b.p2 () && a.p2 () != b.p1 ()) {
|
||||
if (zd_mode == IncludeZeroDistanceWhenTouching) {
|
||||
return a.intersect (b);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the part of the "other" edge which is on the inside side of e and within distance d
|
||||
*
|
||||
* This function applies Euclidian metrics.
|
||||
* If no such part is found, this function returns false.
|
||||
*
|
||||
* The input edges are normalized to "width" orientation.
|
||||
*/
|
||||
bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
bool euclidian_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
{
|
||||
// Handle the case of point-like basic edge: cannot determine
|
||||
// orientation
|
||||
|
||||
if (e.is_degenerate ()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -67,11 +103,7 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
int s1 = e.side_of (g.p1 ());
|
||||
int s2 = e.side_of (g.p2 ());
|
||||
|
||||
// "kissing corner" issue: force include zero if the edges are collinear and overlap.
|
||||
if (! include_zero && s1 == 0 && s2 == 0 && e.intersect (g)) {
|
||||
include_zero = true;
|
||||
}
|
||||
|
||||
bool include_zero = include_zero_flag (zd_mode, e, g);
|
||||
int thr = include_zero ? 0 : -1;
|
||||
|
||||
// keep only part of other which is on the "inside" side of e
|
||||
|
|
@ -89,18 +121,18 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
|
||||
db::Point o = g.p1 ();
|
||||
|
||||
if (e.side_of (o) >= 0) {
|
||||
if (e.side_of (o) > thr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double a = e.double_sq_length ();
|
||||
double b = db::sprod (db::Vector (e.p1 () - o), e.d ());
|
||||
double c = e.p1 ().sq_double_distance (o) - d * d;
|
||||
double b = db::sprod (db::Vector (e.p1 () - o), e.d ()) / a;
|
||||
double c = (e.p1 ().sq_double_distance (o) - double (d) * double (d)) / a;
|
||||
|
||||
double s = b * b - a * c;
|
||||
if (s >= 0) {
|
||||
double l1 = std::max (0.0, (-b - sqrt (s)) / a);
|
||||
double l2 = std::min (1.0, (-b + sqrt (s)) / a);
|
||||
double s = b * b - c;
|
||||
if (s >= -db::epsilon) {
|
||||
double l1 = std::max (0.0, (-b - sqrt (s)));
|
||||
double l2 = std::min (1.0, (-b + sqrt (s)));
|
||||
if (l1 <= l2) {
|
||||
if (output) {
|
||||
*output = g;
|
||||
|
|
@ -167,13 +199,13 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
db::Point o = i ? e.p2 () : e.p1 ();
|
||||
|
||||
double a = g.double_sq_length ();
|
||||
double b = db::sprod (db::Vector (g.p1 () - o), g.d ());
|
||||
double c = g.p1 ().sq_double_distance (o) - double (d) * double (d);
|
||||
double b = db::sprod (db::Vector (g.p1 () - o), g.d ()) / a;
|
||||
double c = (g.p1 ().sq_double_distance (o) - double (d) * double (d)) / a;
|
||||
|
||||
double s = b * b - a * c;
|
||||
if (s >= 0) {
|
||||
l1 = std::min (l1, (-b - sqrt (s)) / a);
|
||||
l2 = std::max (l2, (-b + sqrt (s)) / a);
|
||||
double s = b * b - c;
|
||||
if (s >= -db::epsilon) {
|
||||
l1 = std::min (l1, -b - sqrt (s));
|
||||
l2 = std::max (l2, -b + sqrt (s));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -181,7 +213,7 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
l1 = std::max (0.0, l1);
|
||||
l2 = std::min (1.0, l2);
|
||||
|
||||
if (l1 >= l2) {
|
||||
if (l1 > l2 - db::epsilon) {
|
||||
return false;
|
||||
} else {
|
||||
if (output) {
|
||||
|
|
@ -194,10 +226,12 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
/**
|
||||
* @brief Returns the part of the "other" edge which is on the inside side of e and within distance d
|
||||
*
|
||||
* This function applies Square metrics.
|
||||
* This function applies Projection or Square metrics.
|
||||
* If no such part is found, this function returns false.
|
||||
*
|
||||
* The input edges are normalized to "width" orientation.
|
||||
*/
|
||||
static bool var_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, db::coord_traits<db::Coord>::distance_type dd, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
static bool var_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits<db::Coord>::distance_type d, db::coord_traits<db::Coord>::distance_type dd, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
{
|
||||
// Handle the case of point-like basic edge: cannot determine
|
||||
// orientation
|
||||
|
|
@ -210,11 +244,7 @@ static bool var_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord
|
|||
int s1 = e.side_of (g.p1 ());
|
||||
int s2 = e.side_of (g.p2 ());
|
||||
|
||||
// "kissing corner" issue: force include zero if the edges are collinear and overlap
|
||||
if (! include_zero && s1 == 0 && s2 == 0 && e.intersect (g)) {
|
||||
include_zero = true;
|
||||
}
|
||||
|
||||
bool include_zero = include_zero_flag (zd_mode, e, g);
|
||||
int thr = include_zero ? 0 : -1;
|
||||
|
||||
// keep only part of other which is on the "inside" side of e
|
||||
|
|
@ -229,8 +259,10 @@ static bool var_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord
|
|||
// Handle the case of point vs. edge
|
||||
|
||||
if (g.is_degenerate ()) {
|
||||
double gd = double (e.distance (g.p1 ()));
|
||||
if (gd <= -double (d) || gd >= 0) {
|
||||
if (e.side_of (g.p1 ()) > thr) {
|
||||
return false;
|
||||
}
|
||||
if (double (e.distance (g.p1 ())) <= -double (d)) {
|
||||
return false;
|
||||
}
|
||||
if (db::sprod (db::Vector (g.p1 () - e.p1 ()), e.d ()) < -(dd * e.double_length ())) {
|
||||
|
|
@ -314,9 +346,9 @@ static bool var_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord
|
|||
* This function applies Projected metrics.
|
||||
* If no such part is found, this function returns false.
|
||||
*/
|
||||
bool projected_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
bool projected_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
{
|
||||
return var_near_part_of_edge (include_zero, d, 0, e, other, output);
|
||||
return var_near_part_of_edge (zd_mode, d, 0, e, other, output);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -325,20 +357,26 @@ bool projected_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>
|
|||
* This function applies Square metrics.
|
||||
* If no such part is found, this function returns false.
|
||||
*/
|
||||
bool square_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
bool square_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output)
|
||||
{
|
||||
return var_near_part_of_edge (include_zero, d, d, e, other, output);
|
||||
return var_near_part_of_edge (zd_mode, d, d, e, other, output);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Implementation of EdgeRelationFilter
|
||||
|
||||
EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection)
|
||||
: m_whole_edges (false), m_include_zero (true), m_r (r), m_d (d), m_metrics (metrics), m_ignore_angle (0), m_min_projection (min_projection), m_max_projection (max_projection)
|
||||
EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, zero_distance_mode zd_mode)
|
||||
: m_whole_edges (false), m_zero_distance_mode (zd_mode), m_r (r), m_d (d), m_metrics (metrics), m_ignore_angle (0), m_min_projection (min_projection), m_max_projection (max_projection)
|
||||
{
|
||||
set_ignore_angle (ignore_angle);
|
||||
}
|
||||
|
||||
EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, const EdgesCheckOptions &options)
|
||||
: m_whole_edges (options.whole_edges), m_zero_distance_mode (options.zd_mode), m_r (r), m_d (d), m_metrics (options.metrics), m_ignore_angle (0), m_min_projection (options.min_projection), m_max_projection (options.max_projection)
|
||||
{
|
||||
set_ignore_angle (options.ignore_angle);
|
||||
}
|
||||
|
||||
void
|
||||
EdgeRelationFilter::set_ignore_angle (double a)
|
||||
{
|
||||
|
|
@ -399,14 +437,14 @@ EdgeRelationFilter::check (const db::Edge &a, const db::Edge &b, db::EdgePair *o
|
|||
bool in1, in2;
|
||||
|
||||
if (m_metrics == Euclidian) {
|
||||
in2 = euclidian_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = euclidian_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
in2 = euclidian_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = euclidian_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
} else if (m_metrics == Square) {
|
||||
in2 = square_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = square_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
in2 = square_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = square_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
} else {
|
||||
in2 = projected_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = projected_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
in2 = projected_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0);
|
||||
in1 = projected_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0);
|
||||
}
|
||||
|
||||
if (in1 && in2) {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,111 @@ enum edge_relation_type
|
|||
InsideRelation = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An enum specifying whether how edges with zero distance are handled in checks
|
||||
*/
|
||||
enum zero_distance_mode {
|
||||
|
||||
/**
|
||||
* @brief Never include zero-distance edges
|
||||
*/
|
||||
NeverIncludeZeroDistance = 0,
|
||||
|
||||
/**
|
||||
* @brief Include zero-distance edges when they share at least one common point
|
||||
*/
|
||||
IncludeZeroDistanceWhenTouching = 1,
|
||||
|
||||
/**
|
||||
* @brief Include zero-distance edges when they share at least one common point and are collinear
|
||||
*/
|
||||
IncludeZeroDistanceWhenCollinearAndTouching = 2,
|
||||
|
||||
/**
|
||||
* @brief Include zero-distance edges when they share more than a single common point (this implies that they are collinear)
|
||||
*/
|
||||
IncludeZeroDistanceWhenOverlapping = 3,
|
||||
|
||||
/**
|
||||
* @brief Always include zero-distance edges (hardly useful)
|
||||
*/
|
||||
AlwaysIncludeZeroDistance = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A structure holding the options for the region checks (space, width, ...)
|
||||
*/
|
||||
struct DB_PUBLIC EdgesCheckOptions
|
||||
{
|
||||
typedef db::coord_traits<db::Coord>::distance_type distance_type;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
EdgesCheckOptions (bool _whole_edges = false,
|
||||
metrics_type _metrics = db::Euclidian,
|
||||
double _ignore_angle = 90,
|
||||
distance_type _min_projection = 0,
|
||||
distance_type _max_projection = std::numeric_limits<distance_type>::max (),
|
||||
zero_distance_mode _zd_mode = IncludeZeroDistanceWhenTouching)
|
||||
: whole_edges (_whole_edges),
|
||||
metrics (_metrics),
|
||||
ignore_angle (_ignore_angle),
|
||||
min_projection (_min_projection),
|
||||
max_projection (_max_projection),
|
||||
zd_mode (_zd_mode)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Specifies is whole edges are to be delivered
|
||||
*
|
||||
* Without "whole_edges", the parts of
|
||||
* the edges are returned which violate the condition. If "whole_edges" is true, the
|
||||
* result will contain the complete edges participating in the result.
|
||||
*/
|
||||
bool whole_edges;
|
||||
|
||||
/**
|
||||
* @brief Measurement metrics
|
||||
*
|
||||
* The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected"
|
||||
* metrics are available.
|
||||
*/
|
||||
metrics_type metrics;
|
||||
|
||||
/**
|
||||
* @brief Specifies the obtuse angle threshold
|
||||
*
|
||||
* "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate
|
||||
* in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked,
|
||||
* but acute corners are for example.
|
||||
*/
|
||||
double ignore_angle;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's minimum value
|
||||
*
|
||||
* With min_projection and max_projection it is possible to specify how edges must be related
|
||||
* to each other. If the length of the projection of either edge on the other is >= min_projection
|
||||
* or < max_projection, the edges are considered for the check.
|
||||
*/
|
||||
distance_type min_projection;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's maximum value
|
||||
*/
|
||||
distance_type max_projection;
|
||||
|
||||
/**
|
||||
* @brief Specifies zero-distance edge handling
|
||||
*
|
||||
* This allows implementing the "kissing corners" case. When set to "IncludeZeroDistanceWhenTouching", kissing corners will
|
||||
* be reported as errors, when set to "NeverIncludeZeroDistance", they won't. Note that with merged inputs, edges
|
||||
* will not overlap except at the corners.
|
||||
*/
|
||||
zero_distance_mode zd_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A filter based on the edge pair relation
|
||||
*
|
||||
|
|
@ -123,9 +228,14 @@ struct DB_PUBLIC EdgeRelationFilter
|
|||
* to each other. If the length of the projection of either edge on the other is >= min_projection
|
||||
* or < max_projection, the edges are considered for the check.
|
||||
*/
|
||||
EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max ());
|
||||
EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits<distance_type>::max (), zero_distance_mode include_zero = AlwaysIncludeZeroDistance);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructs an edge relation filter from a CheckOptions structure
|
||||
*/
|
||||
EdgeRelationFilter (edge_relation_type r, distance_type d, const EdgesCheckOptions &options);
|
||||
|
||||
/**
|
||||
* @brief Tests whether two edges fulfil the check fail criterion
|
||||
*
|
||||
* If the output pointer is non-null, the object will receive the edge pair that
|
||||
|
|
@ -150,19 +260,19 @@ struct DB_PUBLIC EdgeRelationFilter
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether zero distance shall be included in the check
|
||||
* @brief Sets a value indicating whether zero-distance edges shall be included in the check
|
||||
*/
|
||||
void set_include_zero (bool f)
|
||||
void set_zero_distance_mode (zero_distance_mode f)
|
||||
{
|
||||
m_include_zero = f;
|
||||
m_zero_distance_mode = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether zero distance shall be included in the check
|
||||
* @brief Gets a value indicating whether zero-distance edges shall be included in the check
|
||||
*/
|
||||
bool include_zero () const
|
||||
zero_distance_mode get_zero_distance_mode () const
|
||||
{
|
||||
return m_include_zero;
|
||||
return m_zero_distance_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -262,7 +372,7 @@ struct DB_PUBLIC EdgeRelationFilter
|
|||
|
||||
private:
|
||||
bool m_whole_edges;
|
||||
bool m_include_zero;
|
||||
zero_distance_mode m_zero_distance_mode;
|
||||
edge_relation_type m_r;
|
||||
distance_type m_d;
|
||||
metrics_type m_metrics;
|
||||
|
|
@ -273,9 +383,9 @@ private:
|
|||
|
||||
// Internal methods exposed for testing purposes
|
||||
|
||||
DB_PUBLIC bool projected_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC bool square_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC bool projected_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC bool square_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC bool euclidian_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits<db::Coord>::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output);
|
||||
DB_PUBLIC db::Edge::distance_type edge_projection (const db::Edge &a, const db::Edge &b);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,69 +39,6 @@
|
|||
|
||||
namespace db {
|
||||
|
||||
/**
|
||||
* @brief A structure holding the options for the region checks (space, width, ...)
|
||||
*/
|
||||
struct DB_PUBLIC EdgesCheckOptions
|
||||
{
|
||||
typedef db::coord_traits<db::Coord>::distance_type distance_type;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
EdgesCheckOptions (bool _whole_edges = false,
|
||||
metrics_type _metrics = db::Euclidian,
|
||||
double _ignore_angle = 90,
|
||||
distance_type _min_projection = 0,
|
||||
distance_type _max_projection = std::numeric_limits<distance_type>::max ())
|
||||
: whole_edges (_whole_edges),
|
||||
metrics (_metrics),
|
||||
ignore_angle (_ignore_angle),
|
||||
min_projection (_min_projection),
|
||||
max_projection (_max_projection)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Specifies is whole edges are to be delivered
|
||||
*
|
||||
* Without "whole_edges", the parts of
|
||||
* the edges are returned which violate the condition. If "whole_edges" is true, the
|
||||
* result will contain the complete edges participating in the result.
|
||||
*/
|
||||
bool whole_edges;
|
||||
|
||||
/**
|
||||
* @brief Measurement metrics
|
||||
*
|
||||
* The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected"
|
||||
* metrics are available.
|
||||
*/
|
||||
metrics_type metrics;
|
||||
|
||||
/**
|
||||
* @brief Specifies the obtuse angle threshold
|
||||
*
|
||||
* "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate
|
||||
* in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked,
|
||||
* but acute corners are for example.
|
||||
*/
|
||||
double ignore_angle;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's minimum value
|
||||
*
|
||||
* With min_projection and max_projection it is possible to specify how edges must be related
|
||||
* to each other. If the length of the projection of either edge on the other is >= min_projection
|
||||
* or < max_projection, the edges are considered for the check.
|
||||
*/
|
||||
distance_type min_projection;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's maximum value
|
||||
*/
|
||||
distance_type max_projection;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A base class for edge filters
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -257,6 +257,83 @@ private:
|
|||
bool m_insert;
|
||||
};
|
||||
|
||||
struct SetLayoutMetaInfoOp
|
||||
: public LayoutOp
|
||||
{
|
||||
SetLayoutMetaInfoOp (db::Layout::meta_info_name_id_type name_id, const db::MetaInfo *f, const db::MetaInfo *t)
|
||||
: m_name_id (name_id), m_has_from (f != 0), m_has_to (t != 0)
|
||||
{
|
||||
if (f) {
|
||||
m_from = *f;
|
||||
}
|
||||
if (t) {
|
||||
m_to = *t;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void redo (db::Layout *layout) const
|
||||
{
|
||||
if (! m_has_to) {
|
||||
layout->remove_meta_info (m_name_id);
|
||||
} else {
|
||||
layout->add_meta_info (m_name_id, m_to);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo (db::Layout *layout) const
|
||||
{
|
||||
if (! m_has_from) {
|
||||
layout->remove_meta_info (m_name_id);
|
||||
} else {
|
||||
layout->add_meta_info (m_name_id, m_from);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout::meta_info_name_id_type m_name_id;
|
||||
bool m_has_from, m_has_to;
|
||||
db::MetaInfo m_from, m_to;
|
||||
};
|
||||
|
||||
struct SetCellMetaInfoOp
|
||||
: public LayoutOp
|
||||
{
|
||||
SetCellMetaInfoOp (db::cell_index_type ci, db::Layout::meta_info_name_id_type name_id, const db::MetaInfo *f, const db::MetaInfo *t)
|
||||
: m_ci (ci), m_name_id (name_id), m_has_from (f != 0), m_has_to (t != 0)
|
||||
{
|
||||
if (f) {
|
||||
m_from = *f;
|
||||
}
|
||||
if (t) {
|
||||
m_to = *t;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void redo (db::Layout *layout) const
|
||||
{
|
||||
if (! m_has_to) {
|
||||
layout->remove_meta_info (m_ci, m_name_id);
|
||||
} else {
|
||||
layout->add_meta_info (m_ci, m_name_id, m_to);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo (db::Layout *layout) const
|
||||
{
|
||||
if (! m_has_from) {
|
||||
layout->remove_meta_info (m_ci, m_name_id);
|
||||
} else {
|
||||
layout->add_meta_info (m_ci, m_name_id, m_from);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
db::cell_index_type m_ci;
|
||||
db::Layout::meta_info_name_id_type m_name_id;
|
||||
bool m_has_from, m_has_to;
|
||||
db::MetaInfo m_from, m_to;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Implementation of the ProxyContextInfo class
|
||||
|
||||
|
|
@ -848,6 +925,9 @@ Layout::delete_cells (const std::set<cell_index_type> &cells_to_delete)
|
|||
// cell child objects that must remain.
|
||||
for (std::set<cell_index_type>::const_iterator c = cells_to_delete.begin (); c != cells_to_delete.end (); ++c) {
|
||||
|
||||
// supports undo
|
||||
clear_meta (*c);
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
||||
// note the "take" method - this takes out the cell
|
||||
|
|
@ -917,9 +997,12 @@ Layout::delete_cell (cell_index_type id)
|
|||
// a backup container for the cell. This is necessary since the ID's within manager are given to
|
||||
// cell child objects that must remain.
|
||||
|
||||
// supports undo
|
||||
clear_meta (id);
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
||||
// not the "take" method - this takes out the cell
|
||||
// note the "take" method - this takes out the cell
|
||||
std::string cn (cell_name (id));
|
||||
manager ()->queue (this, new NewRemoveCellOp (id, cn, true /*remove*/, take_cell (id)));
|
||||
|
||||
|
|
@ -1869,18 +1952,36 @@ Layout::meta_info_name_id (const std::string &name) const
|
|||
void
|
||||
Layout::clear_meta ()
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
for (auto i = m_meta_info.begin (); i != m_meta_info.end (); ++i) {
|
||||
manager ()->queue (this, new SetLayoutMetaInfoOp (i->first, &i->second, 0));
|
||||
}
|
||||
}
|
||||
|
||||
m_meta_info.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
Layout::add_meta_info (meta_info_name_id_type name_id, const MetaInfo &i)
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
auto e = m_meta_info.find (name_id);
|
||||
manager ()->queue (this, new SetLayoutMetaInfoOp (name_id, e != m_meta_info.end () ? &e->second : 0, &i));
|
||||
}
|
||||
|
||||
m_meta_info[name_id] = i;
|
||||
}
|
||||
|
||||
void
|
||||
Layout::remove_meta_info (meta_info_name_id_type name_id)
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
auto e = m_meta_info.find (name_id);
|
||||
if (e != m_meta_info.end ()) {
|
||||
manager ()->queue (this, new SetLayoutMetaInfoOp (name_id, &e->second, 0));
|
||||
}
|
||||
}
|
||||
|
||||
m_meta_info.erase (name_id);
|
||||
}
|
||||
|
||||
|
|
@ -1901,12 +2002,41 @@ Layout::has_meta_info (meta_info_name_id_type name_id) const
|
|||
void
|
||||
Layout::clear_meta (db::cell_index_type ci)
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
auto ib = begin_meta (ci);
|
||||
auto ie = end_meta (ci);
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
manager ()->queue (this, new SetCellMetaInfoOp (ci, i->first, &i->second, 0));
|
||||
}
|
||||
}
|
||||
|
||||
m_meta_info_by_cell.erase (ci);
|
||||
}
|
||||
|
||||
void
|
||||
Layout::clear_all_meta ()
|
||||
{
|
||||
clear_meta ();
|
||||
while (! m_meta_info_by_cell.empty ()) {
|
||||
clear_meta (m_meta_info_by_cell.begin ()->first);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::add_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id, const MetaInfo &i)
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
const MetaInfo *from = 0;
|
||||
auto c = m_meta_info_by_cell.find (ci);
|
||||
if (c != m_meta_info_by_cell.end ()) {
|
||||
auto e = c->second.find (name_id);
|
||||
if (e != c->second.end ()) {
|
||||
from = &e->second;
|
||||
}
|
||||
}
|
||||
manager ()->queue (this, new SetCellMetaInfoOp (ci, name_id, from, &i));
|
||||
}
|
||||
|
||||
m_meta_info_by_cell[ci][name_id] = i;
|
||||
}
|
||||
|
||||
|
|
@ -1914,6 +2044,18 @@ void
|
|||
Layout::remove_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id)
|
||||
{
|
||||
auto c = m_meta_info_by_cell.find (ci);
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
const MetaInfo *from = 0;
|
||||
if (c != m_meta_info_by_cell.end ()) {
|
||||
auto e = c->second.find (name_id);
|
||||
if (e != c->second.end ()) {
|
||||
from = &e->second;
|
||||
}
|
||||
}
|
||||
manager ()->queue (this, new SetCellMetaInfoOp (ci, name_id, from, 0));
|
||||
}
|
||||
|
||||
if (c != m_meta_info_by_cell.end ()) {
|
||||
c->second.erase (name_id);
|
||||
}
|
||||
|
|
@ -1945,6 +2087,40 @@ Layout::has_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) c
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::merge_meta_info (const db::Layout &other)
|
||||
{
|
||||
for (auto mi = other.begin_meta (); mi != other.end_meta (); ++mi) {
|
||||
add_meta_info (other.meta_info_name (mi->first), mi->second);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::merge_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell)
|
||||
{
|
||||
auto mi_begin = other.begin_meta (other_cell);
|
||||
auto mi_end = other.end_meta (other_cell);
|
||||
for (auto mi = mi_begin; mi != mi_end; ++mi) {
|
||||
add_meta_info (into_cell, other.meta_info_name (mi->first), mi->second);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::merge_meta_info (const db::Layout &other, const db::CellMapping &cm)
|
||||
{
|
||||
for (auto i = cm.begin (); i != cm.end (); ++i) {
|
||||
merge_meta_info (i->second, other, i->first);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::copy_meta_info (const db::Layout &other, const db::CellMapping &cm)
|
||||
{
|
||||
for (auto i = cm.begin (); i != cm.end (); ++i) {
|
||||
copy_meta_info (i->second, other, i->first);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::swap_layers (unsigned int a, unsigned int b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1993,6 +1993,11 @@ public:
|
|||
*/
|
||||
void clear_meta (db::cell_index_type ci);
|
||||
|
||||
/**
|
||||
* @brief Clears all meta information (cells and layout)
|
||||
*/
|
||||
void clear_all_meta ();
|
||||
|
||||
/**
|
||||
* @brief Adds meta information for a given cell
|
||||
* The given meta information object is to the meta information list for the given cell.
|
||||
|
|
@ -2021,6 +2026,50 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Merges meta information from the other layout into self
|
||||
* This applies to the layout-only meta information. Same keys get overwritten, new ones are added.
|
||||
*/
|
||||
void merge_meta_info (const db::Layout &other);
|
||||
|
||||
/**
|
||||
* @brief Copies meta information from the other layout into self
|
||||
* This applies to the layout-only meta information. All keys are replaced.
|
||||
*/
|
||||
void copy_meta_info (const db::Layout &other)
|
||||
{
|
||||
clear_meta ();
|
||||
merge_meta_info (other);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Merges meta information from the other cell into the target cell from sel.
|
||||
* This applies to the cell-specific meta information. Same keys get overwritten, new ones are added.
|
||||
*/
|
||||
void merge_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell);
|
||||
|
||||
/**
|
||||
* @brief Copies meta information from the other cell into the target cell from sel.
|
||||
* This applies to the cell-specific meta information. All keys are replaced.
|
||||
*/
|
||||
void copy_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell)
|
||||
{
|
||||
clear_meta (into_cell);
|
||||
merge_meta_info (into_cell, other, other_cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Merges meta information from the other cell into the target cell from sel using the given cell mapping.
|
||||
* The cell mapping specifies which meta information to merge from which cell into which cell.
|
||||
*/
|
||||
void merge_meta_info (const db::Layout &other, const db::CellMapping &cm);
|
||||
|
||||
/**
|
||||
* @brief Copies meta information from the other cell into the target cell from sel using the given cell mapping.
|
||||
* The cell mapping specifies which meta information to copy from which cell into which cell.
|
||||
*/
|
||||
void copy_meta_info (const db::Layout &other, const db::CellMapping &cm);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether a meta info with the given name is present for the given cell
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -702,6 +702,29 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
r.dbu_differs (a.dbu (), b.dbu ());
|
||||
}
|
||||
|
||||
if ((flags & layout_diff::f_with_meta) != 0) {
|
||||
std::map<std::string, std::pair<tl::Variant, tl::Variant> > mi;
|
||||
for (auto i = a.begin_meta (); i != a.end_meta (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [a.meta_info_name (i->first)].first = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = b.begin_meta (); i != b.end_meta (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [b.meta_info_name (i->first)].second = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = mi.begin (); i != mi.end (); ++i) {
|
||||
if (i->second.first != i->second.second) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
return false;
|
||||
}
|
||||
r.layout_meta_info_differs (i->first, i->second.first, i->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool verbose = (flags & layout_diff::f_verbose);
|
||||
bool no_duplicates = (flags & layout_diff::f_ignore_duplicates);
|
||||
|
||||
|
|
@ -928,6 +951,33 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
|
||||
r.begin_cell (common_cells [cci], common_cells_a [cci], common_cells_b [cci]);
|
||||
|
||||
if ((flags & layout_diff::f_with_meta) != 0) {
|
||||
std::map<std::string, std::pair<tl::Variant, tl::Variant> > mi;
|
||||
auto ib = a.begin_meta (common_cells_a [cci]);
|
||||
auto ie = a.end_meta (common_cells_a [cci]);
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [a.meta_info_name (i->first)].first = i->second.value;
|
||||
}
|
||||
}
|
||||
ib = b.begin_meta (common_cells_b [cci]);
|
||||
ie = b.end_meta (common_cells_b [cci]);
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [b.meta_info_name (i->first)].second = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = mi.begin (); i != mi.end (); ++i) {
|
||||
if (i->second.first != i->second.second) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
return false;
|
||||
}
|
||||
r.cell_meta_info_differs (i->first, i->second.first, i->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!verbose && cell_a->bbox () != cell_b->bbox ()) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
|
|
@ -1215,6 +1265,7 @@ public:
|
|||
}
|
||||
|
||||
void dbu_differs (double dbu_a, double dbu_b);
|
||||
void layout_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b);
|
||||
void layer_in_a_only (const db::LayerProperties &la);
|
||||
void layer_in_b_only (const db::LayerProperties &lb);
|
||||
void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb);
|
||||
|
|
@ -1222,6 +1273,7 @@ public:
|
|||
void cell_in_b_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib);
|
||||
void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib);
|
||||
void cell_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b);
|
||||
void bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_inst_differences ();
|
||||
void instances_in_a (const std::vector <db::CellInstArrayWithProperties> &insts_a, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
|
|
@ -1384,6 +1436,16 @@ PrintingDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::layout_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b)
|
||||
{
|
||||
try {
|
||||
enough (tl::error) << "Global meta info differs - [" << name << "]: " << a << " vs. " << b;
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
|
|
@ -1461,6 +1523,16 @@ PrintingDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_in
|
|||
m_cellname = cellname;
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::cell_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b)
|
||||
{
|
||||
try {
|
||||
enough (tl::error) << "Meta info differs in cell " << m_cellname << " - [" << name << "]: " << a << " vs. " << b;
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::begin_inst_differences ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ const unsigned int f_no_text_orientation = 0x02;
|
|||
// Ignore properties
|
||||
const unsigned int f_no_properties = 0x04;
|
||||
|
||||
// With meta info
|
||||
const unsigned int f_with_meta = 0x08;
|
||||
|
||||
// Do not compare layer names
|
||||
const unsigned int f_no_layer_names = 0x10;
|
||||
|
||||
|
|
@ -94,6 +97,7 @@ public:
|
|||
virtual ~DifferenceReceiver () { }
|
||||
|
||||
virtual void dbu_differs (double /*dbu_a*/, double /*dbu_b*/) { }
|
||||
virtual void layout_meta_info_differs (const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/) { }
|
||||
virtual void layer_in_a_only (const db::LayerProperties & /*la*/) { }
|
||||
virtual void layer_in_b_only (const db::LayerProperties & /*lb*/) { }
|
||||
virtual void layer_name_differs (const db::LayerProperties & /*la*/, const db::LayerProperties & /*lb*/) { }
|
||||
|
|
@ -102,6 +106,7 @@ public:
|
|||
virtual void cell_in_b_only (const std::string & /*cellname*/, db::cell_index_type /*ci*/) { }
|
||||
virtual void bbox_differs (const db::Box & /*ba*/, const db::Box & /*bb*/) { }
|
||||
virtual void begin_cell (const std::string & /*cellname*/, db::cell_index_type /*cia*/, db::cell_index_type /*cib*/) { }
|
||||
virtual void cell_meta_info_differs (const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/) { }
|
||||
virtual void begin_inst_differences () { }
|
||||
virtual void instances_in_a (const std::vector <db::CellInstArrayWithProperties> & /*insts_a*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/) { }
|
||||
virtual void instances_in_b (const std::vector <db::CellInstArrayWithProperties> & /*insts_b*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/) { }
|
||||
|
|
|
|||
|
|
@ -252,6 +252,9 @@ merge_layouts (db::Layout &target,
|
|||
const db::Cell &source_cell = source.cell (*c);
|
||||
db::Cell &target_cell = target.cell (target_cell_index);
|
||||
|
||||
// merge meta info
|
||||
target.merge_meta_info (target_cell_index, source, *c);
|
||||
|
||||
// NOTE: this implementation employs the safe but cumbersome "local transformation" feature.
|
||||
// This means, all cells are transformed according to the given transformation and their
|
||||
// references are transformed to account for that effect. This will lead to somewhat strange
|
||||
|
|
|
|||
|
|
@ -287,19 +287,37 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
|
|||
extractor_cache_type::const_iterator ec = extractor_cache.find (layer_geometry);
|
||||
if (ec == extractor_cache.end ()) {
|
||||
|
||||
log_entry_list log_entries;
|
||||
m_log_entries.swap (log_entries);
|
||||
|
||||
// do the actual device extraction
|
||||
extract_devices (layer_geometry);
|
||||
|
||||
// push the new devices to the layout
|
||||
push_new_devices (disp);
|
||||
|
||||
ExtractorCacheValueType &ecv = extractor_cache [layer_geometry];
|
||||
ecv.disp = disp;
|
||||
if (m_log_entries.empty ()) {
|
||||
|
||||
// cache unless log entries are produced
|
||||
ExtractorCacheValueType &ecv = extractor_cache [layer_geometry];
|
||||
ecv.disp = disp;
|
||||
|
||||
for (std::map<size_t, std::pair<db::Device *, geometry_per_terminal_type> >::const_iterator d = m_new_devices.begin (); d != m_new_devices.end (); ++d) {
|
||||
ecv.devices.push_back (d->second.first);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// transform the marker geometries from the log entries to match the device
|
||||
db::DVector disp_dbu = db::CplxTrans (dbu ()) * disp;
|
||||
for (auto l = m_log_entries.begin (); l != m_log_entries.end (); ++l) {
|
||||
l->set_geometry (l->geometry ().moved (disp_dbu));
|
||||
}
|
||||
|
||||
for (std::map<size_t, std::pair<db::Device *, geometry_per_terminal_type> >::const_iterator d = m_new_devices.begin (); d != m_new_devices.end (); ++d) {
|
||||
ecv.devices.push_back (d->second.first);
|
||||
}
|
||||
|
||||
m_log_entries.splice (m_log_entries.begin (), log_entries);
|
||||
|
||||
m_new_devices.clear ();
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1566,23 +1566,26 @@ compute_rounded (const db::DPolygon &polygon, double rinner, double router, unsi
|
|||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of AreaMap
|
||||
// Implementation of area_map
|
||||
|
||||
AreaMap::AreaMap ()
|
||||
template <class C>
|
||||
area_map<C>::area_map ()
|
||||
: m_nx (0), m_ny (0)
|
||||
{
|
||||
mp_av = 0;
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const AreaMap &other)
|
||||
template <class C>
|
||||
area_map<C>::area_map (const area_map &other)
|
||||
: m_nx (0), m_ny (0)
|
||||
{
|
||||
mp_av = 0;
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
AreaMap &
|
||||
AreaMap::operator= (const AreaMap &other)
|
||||
template <class C>
|
||||
area_map<C> &
|
||||
area_map<C>::operator= (const area_map &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
// TODO: this could be copy on write
|
||||
|
|
@ -1594,21 +1597,24 @@ AreaMap::operator= (const AreaMap &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny)
|
||||
template <class C>
|
||||
area_map<C>::area_map (const area_map::point_type &p0, const area_map::vector_type &d, size_t nx, size_t ny)
|
||||
: m_p0 (p0), m_d (d), m_p (d), m_nx (nx), m_ny (ny)
|
||||
{
|
||||
mp_av = new area_type [nx * ny];
|
||||
clear ();
|
||||
}
|
||||
|
||||
AreaMap::AreaMap (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny)
|
||||
template <class C>
|
||||
area_map<C>::area_map (const area_map::point_type &p0, const area_map::vector_type &d, const area_map::vector_type &p, size_t nx, size_t ny)
|
||||
: m_p0 (p0), m_d (d), m_p (std::min (d.x (), p.x ()), std::min (d.y (), p.y ())), m_nx (nx), m_ny (ny)
|
||||
{
|
||||
mp_av = new area_type [nx * ny];
|
||||
clear ();
|
||||
}
|
||||
|
||||
AreaMap::~AreaMap ()
|
||||
template <class C>
|
||||
area_map<C>::~area_map ()
|
||||
{
|
||||
if (mp_av) {
|
||||
delete[] mp_av;
|
||||
|
|
@ -1616,18 +1622,20 @@ AreaMap::~AreaMap ()
|
|||
mp_av = 0;
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void
|
||||
AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny)
|
||||
area_map<C>::reinitialize (const area_map::point_type &p0, const area_map::vector_type &d, size_t nx, size_t ny)
|
||||
{
|
||||
reinitialize (p0, d, d, nx, ny);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void
|
||||
AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny)
|
||||
area_map<C>::reinitialize (const area_map::point_type &p0, const area_map::vector_type &d, const area_map::vector_type &p, size_t nx, size_t ny)
|
||||
{
|
||||
m_p0 = p0;
|
||||
m_d = d;
|
||||
m_p = db::Vector (std::min (d.x (), p.x ()), std::min (d.y (), p.y ()));
|
||||
m_p = vector_type (std::min (d.x (), p.x ()), std::min (d.y (), p.y ()));
|
||||
|
||||
if (nx != m_nx || ny != m_ny) {
|
||||
|
||||
|
|
@ -1645,8 +1653,9 @@ AreaMap::reinitialize (const db::Point &p0, const db::Vector &d, const db::Vecto
|
|||
clear ();
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void
|
||||
AreaMap::clear ()
|
||||
area_map<C>::clear ()
|
||||
{
|
||||
if (mp_av) {
|
||||
area_type *a = mp_av;
|
||||
|
|
@ -1656,8 +1665,9 @@ AreaMap::clear ()
|
|||
}
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void
|
||||
AreaMap::swap (AreaMap &other)
|
||||
area_map<C>::swap (area_map &other)
|
||||
{
|
||||
std::swap (m_p0, other.m_p0);
|
||||
std::swap (m_d, other.m_d);
|
||||
|
|
@ -1667,8 +1677,9 @@ AreaMap::swap (AreaMap &other)
|
|||
std::swap (mp_av, other.mp_av);
|
||||
}
|
||||
|
||||
AreaMap::area_type
|
||||
AreaMap::total_area () const
|
||||
template <class C>
|
||||
typename area_map<C>::area_type
|
||||
area_map<C>::total_area () const
|
||||
{
|
||||
area_type asum = 0;
|
||||
if (mp_av) {
|
||||
|
|
@ -1680,16 +1691,21 @@ AreaMap::total_area () const
|
|||
return asum;
|
||||
}
|
||||
|
||||
db::Box
|
||||
AreaMap::bbox () const
|
||||
template <class C>
|
||||
typename area_map<C>::box_type
|
||||
area_map<C>::bbox () const
|
||||
{
|
||||
if (m_nx == 0 || m_ny == 0) {
|
||||
return db::Box ();
|
||||
return box_type ();
|
||||
} else {
|
||||
return db::Box (m_p0, m_p0 + db::Vector (db::Coord (m_nx - 1) * m_d.x () + m_p.x (), db::Coord (m_ny - 1) * m_d.y () + m_p.y ()));
|
||||
return box_type (m_p0, m_p0 + vector_type (C (m_nx - 1) * m_d.x () + m_p.x (), C (m_ny - 1) * m_d.y () + m_p.y ()));
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class area_map<db::Coord>;
|
||||
template class area_map<db::DCoord>;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of rasterize
|
||||
|
||||
|
|
@ -1707,29 +1723,69 @@ static bool edge_is_partially_left_of (const db::Edge &e, const db::Edge &e_orig
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
||||
static bool edge_is_partially_left_of (const db::DEdge &e, const db::DEdge &e_original, db::DCoord x)
|
||||
{
|
||||
typedef db::AreaMap::area_type area_type;
|
||||
db::Box box = am.bbox ();
|
||||
db::Box pbox = polygon.box ();
|
||||
DCoord xmin = db::edge_xmin (e);
|
||||
if (db::coord_traits<db::DCoord>::less (xmin, x)) {
|
||||
return true;
|
||||
} else if (db::coord_traits<db::DCoord>::equal (xmin, x) && ! db::coord_traits<db::DCoord>::equal (e_original.dx (), 0)) {
|
||||
// the skew edge is cut partially rendering a straight vertical line (due to rounding)
|
||||
// which we will count as "left of"
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t npixels_floor (db::Coord d, db::Coord p)
|
||||
{
|
||||
return size_t (std::max (db::Coord (0), d / p));
|
||||
}
|
||||
|
||||
static size_t npixels_ceil (db::Coord d, db::Coord p)
|
||||
{
|
||||
return size_t (std::max (db::Coord (0), (d + p - 1) / p));
|
||||
}
|
||||
|
||||
static size_t npixels_floor (db::DCoord d, db::DCoord p)
|
||||
{
|
||||
return size_t (std::max (db::DCoord (0), floor (d / p + db::epsilon)));
|
||||
}
|
||||
|
||||
static size_t npixels_ceil (db::DCoord d, db::DCoord p)
|
||||
{
|
||||
return size_t (std::max (db::DCoord (0), ceil (d / p - db::epsilon)));
|
||||
}
|
||||
|
||||
|
||||
template <class C>
|
||||
static
|
||||
bool
|
||||
rasterize_impl (const db::polygon<C> &polygon, db::area_map<C> &am)
|
||||
{
|
||||
typedef typename db::area_map<C>::area_type area_type;
|
||||
typedef db::box<C> box_type;
|
||||
typedef db::edge<C> edge_type;
|
||||
|
||||
box_type box = am.bbox ();
|
||||
box_type pbox = polygon.box ();
|
||||
|
||||
// check if the polygon overlaps the rasterization area. Otherwise, we simply do nothing.
|
||||
if (! pbox.overlaps (box)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
db::Coord ymin = box.bottom (), ymax = box.top ();
|
||||
db::Coord dy = am.d ().y (), dx = am.d ().x ();
|
||||
db::Coord py = am.p ().y (), px = am.p ().x ();
|
||||
db::Coord y0 = am.p0 ().y (), x0 = am.p0 ().x ();
|
||||
C ymin = box.bottom (), ymax = box.top ();
|
||||
C dy = am.d ().y (), dx = am.d ().x ();
|
||||
C py = am.p ().y (), px = am.p ().x ();
|
||||
C y0 = am.p0 ().y (), x0 = am.p0 ().x ();
|
||||
size_t ny = am.ny (), nx = am.nx ();
|
||||
|
||||
size_t iy0 = std::min (ny, size_t (std::max (db::Coord (0), (pbox.bottom () - am.p0 ().y ()) / am.d ().y ())));
|
||||
size_t iy1 = std::min (ny, size_t (std::max (db::Coord (0), (pbox.top () - am.p0 ().y () + am.d ().y () - 1) / am.d ().y ())));
|
||||
size_t iy0 = std::min (ny, npixels_floor (pbox.bottom () - am.p0 ().y (), am.d ().y ()));
|
||||
size_t iy1 = std::min (ny, npixels_ceil (pbox.top () - am.p0 ().y (), am.d ().y ()));
|
||||
|
||||
size_t ix0 = std::min (nx, size_t (std::max (db::Coord (0), (pbox.left () - am.p0 ().x ()) / am.d ().x ())));
|
||||
size_t ix1 = std::min (nx, size_t (std::max (db::Coord (0), (pbox.right () - am.p0 ().x () + am.d ().x () - 1) / am.d ().x ())));
|
||||
size_t ix0 = std::min (nx, npixels_floor (pbox.left () - am.p0 ().x (), am.d ().x ()));
|
||||
size_t ix1 = std::min (nx, npixels_ceil (pbox.right () - am.p0 ().x (), am.d ().x ()));
|
||||
|
||||
// no scanning required (i.e. degenerated polygon) -> do nothing
|
||||
if (iy0 == iy1 || ix0 == ix1) {
|
||||
|
|
@ -1738,26 +1794,26 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
// collect edges
|
||||
size_t n = 0;
|
||||
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
for (typename db::polygon<C>::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
if ((*e).dy () != 0 && db::edge_ymax (*e) > ymin && db::edge_ymin (*e) < ymax) {
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector <db::Edge> edges;
|
||||
std::vector <edge_type> edges;
|
||||
edges.reserve (n);
|
||||
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
for (typename db::polygon<C>::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
if ((*e).dy () != 0 && db::edge_ymax (*e) > ymin && db::edge_ymin (*e) < ymax) {
|
||||
edges.push_back (*e);
|
||||
}
|
||||
}
|
||||
|
||||
// sort edges
|
||||
std::sort (edges.begin (), edges.end (), db::edge_ymin_compare<db::Coord> ());
|
||||
std::sort (edges.begin (), edges.end (), db::edge_ymin_compare<C> ());
|
||||
|
||||
std::vector <db::Edge>::iterator c = edges.begin ();
|
||||
typename std::vector <edge_type>::iterator c = edges.begin ();
|
||||
|
||||
db::Coord y = y0 + dy * db::Coord (iy0);
|
||||
C y = y0 + dy * C (iy0);
|
||||
|
||||
while (c != edges.end () && db::edge_ymax (*c) <= y) {
|
||||
++c;
|
||||
|
|
@ -1767,36 +1823,36 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector <db::Edge>::iterator f = c;
|
||||
typename std::vector <edge_type>::iterator f = c;
|
||||
|
||||
for (size_t iy = iy0; iy < iy1; ++iy) {
|
||||
|
||||
db::Coord yy = y + py;
|
||||
C yy = y + py;
|
||||
while (f != edges.end () && db::edge_ymin (*f) < yy) {
|
||||
++f;
|
||||
}
|
||||
|
||||
std::sort (c, f, db::edge_xmin_compare <db::Coord> ());
|
||||
std::sort (c, f, db::edge_xmin_compare <C> ());
|
||||
|
||||
db::Coord x = x0 + dx * db::Coord (ix0);
|
||||
db::Coord xl = pbox.left ();
|
||||
C x = x0 + dx * C (ix0);
|
||||
C xl = pbox.left ();
|
||||
area_type a = 0;
|
||||
|
||||
std::vector <db::Edge>::iterator cc = c;
|
||||
typename std::vector <edge_type>::iterator cc = c;
|
||||
|
||||
while (cc != edges.end () && cc != f && db::edge_xmax (*cc) <= x) {
|
||||
db::Coord y1 = std::max (y, std::min (yy, cc->p1 ().y ()));
|
||||
db::Coord y2 = std::max (y, std::min (yy, cc->p2 ().y ()));
|
||||
C y1 = std::max (y, std::min (yy, cc->p1 ().y ()));
|
||||
C y2 = std::max (y, std::min (yy, cc->p2 ().y ()));
|
||||
a += area_type (px) * area_type (y2 - y1);
|
||||
++cc;
|
||||
}
|
||||
|
||||
std::vector <db::Edge>::iterator ff = cc;
|
||||
typename std::vector <edge_type>::iterator ff = cc;
|
||||
|
||||
for (size_t ix = ix0; ix < ix1; ++ix) {
|
||||
|
||||
db::Coord xx = x + px;
|
||||
db::Coord xxx = x + dx;
|
||||
C xx = x + px;
|
||||
C xxx = x + dx;
|
||||
|
||||
// TODO: edge_xmin_at_interval(y, yy) and edge_xmax.. would be more efficient in the
|
||||
// all-angle case. However, it is crucial that the edge clipping produces
|
||||
|
|
@ -1807,7 +1863,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
++ff;
|
||||
}
|
||||
|
||||
std::vector <db::Edge>::iterator fff = ff;
|
||||
typename std::vector <edge_type>::iterator fff = ff;
|
||||
|
||||
if (xx < xxx) {
|
||||
while (fff != f && db::edge_xmin (*fff) < xxx) {
|
||||
|
|
@ -1818,11 +1874,11 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
if (xl < x) {
|
||||
|
||||
// consider all edges or parts of those left of the first cell
|
||||
db::Box left (xl, y, x, yy);
|
||||
box_type left (xl, y, x, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
for (typename std::vector <edge_type>::iterator e = cc; e != ff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (left);
|
||||
std::pair<bool, edge_type> ec = e->clipped (left);
|
||||
if (ec.first && edge_is_partially_left_of (ec.second, *e, x)) {
|
||||
a += area_type (ec.second.dy ()) * area_type (px);
|
||||
}
|
||||
|
|
@ -1835,11 +1891,11 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
if (dx == py) {
|
||||
|
||||
db::Box cell (x, y, xx, yy);
|
||||
box_type cell (x, y, xx, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
for (typename std::vector <edge_type>::iterator e = cc; e != ff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (cell);
|
||||
std::pair<bool, edge_type> ec = e->clipped (cell);
|
||||
if (ec.first && edge_is_partially_left_of (ec.second, *e, xx)) {
|
||||
aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2;
|
||||
a += area_type (ec.second.dy ()) * area_type (px);
|
||||
|
|
@ -1849,22 +1905,22 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
} else {
|
||||
|
||||
db::Box cell (x, y, xx, yy);
|
||||
box_type cell (x, y, xx, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != ff; ++e) {
|
||||
for (typename std::vector <edge_type>::iterator e = cc; e != ff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> ec = e->clipped (cell);
|
||||
std::pair<bool, edge_type> ec = e->clipped (cell);
|
||||
if (ec.first && edge_is_partially_left_of (ec.second, *e, xx)) {
|
||||
aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Box wide_cell (x, y, x + dx, yy);
|
||||
box_type wide_cell (x, y, x + dx, yy);
|
||||
|
||||
for (std::vector <db::Edge>::iterator e = cc; e != fff; ++e) {
|
||||
for (typename std::vector <edge_type>::iterator e = cc; e != fff; ++e) {
|
||||
|
||||
std::pair<bool, db::Edge> wide_ec = e->clipped (wide_cell);
|
||||
std::pair<bool, edge_type> wide_ec = e->clipped (wide_cell);
|
||||
if (wide_ec.first && edge_is_partially_left_of (wide_ec.second, *e, x + dx)) {
|
||||
a += area_type (wide_ec.second.dy ()) * area_type (px);
|
||||
}
|
||||
|
|
@ -1880,7 +1936,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
ff = fff;
|
||||
|
||||
for (std::vector <db::Edge>::iterator ccx = cc; ccx != ff; ++ccx) {
|
||||
for (typename std::vector <edge_type>::iterator ccx = cc; ccx != ff; ++ccx) {
|
||||
if (db::edge_xmax (*ccx) <= x) {
|
||||
std::swap (*ccx, *cc);
|
||||
++cc;
|
||||
|
|
@ -1898,7 +1954,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
|
||||
y = yy;
|
||||
|
||||
for (std::vector <db::Edge>::iterator cx = c; cx != f; ++cx) {
|
||||
for (typename std::vector <edge_type>::iterator cx = c; cx != f; ++cx) {
|
||||
if (db::edge_ymax (*cx) <= y) {
|
||||
std::swap (*cx, *c);
|
||||
++c;
|
||||
|
|
@ -1910,6 +1966,18 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
rasterize (const db::Polygon &polygon, db::AreaMap &am)
|
||||
{
|
||||
return rasterize_impl<db::Coord> (polygon, am);
|
||||
}
|
||||
|
||||
bool
|
||||
rasterize (const db::DPolygon &polygon, db::DAreaMap &am)
|
||||
{
|
||||
return rasterize_impl<db::DCoord> (polygon, am);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of Minkowski sum
|
||||
|
||||
|
|
|
|||
|
|
@ -493,55 +493,59 @@ bool DB_PUBLIC is_non_orientable_polygon (const db::Polygon &poly, std::vector<d
|
|||
* It is used for example by the rasterize function to collect area values
|
||||
* on a per-pixel basis.
|
||||
*/
|
||||
class DB_PUBLIC AreaMap
|
||||
template <class C>
|
||||
class DB_PUBLIC area_map
|
||||
{
|
||||
public:
|
||||
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||
typedef typename db::coord_traits<C>::area_type area_type;
|
||||
typedef db::point<C> point_type;
|
||||
typedef db::vector<C> vector_type;
|
||||
typedef db::box<C> box_type;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
AreaMap ();
|
||||
area_map ();
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
AreaMap (const AreaMap &);
|
||||
area_map (const area_map &);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
AreaMap (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
||||
area_map (const point_type &p0, const vector_type &d, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Constructor with pixel size
|
||||
*/
|
||||
AreaMap (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny);
|
||||
area_map (const point_type &p0, const vector_type &d, const vector_type &p, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~AreaMap ();
|
||||
~area_map ();
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
AreaMap &operator= (const AreaMap &);
|
||||
area_map &operator= (const area_map &);
|
||||
|
||||
/**
|
||||
* @brief Reinitialize
|
||||
*/
|
||||
void reinitialize (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
||||
void reinitialize (const point_type &p0, const vector_type &d, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Reinitialize with pixel size
|
||||
*/
|
||||
void reinitialize (const db::Point &p0, const db::Vector &d, const db::Vector &p, size_t nx, size_t ny);
|
||||
void reinitialize (const point_type &p0, const vector_type &d, const vector_type &p, size_t nx, size_t ny);
|
||||
|
||||
/**
|
||||
* @brief Swap of two maps
|
||||
*/
|
||||
void swap (AreaMap &other);
|
||||
void swap (area_map &other);
|
||||
|
||||
/**
|
||||
* @brief Get the area of one pixel
|
||||
|
|
@ -578,7 +582,7 @@ public:
|
|||
/**
|
||||
* @brief The origin
|
||||
*/
|
||||
const db::Point &p0 () const
|
||||
const point_type &p0 () const
|
||||
{
|
||||
return m_p0;
|
||||
}
|
||||
|
|
@ -586,7 +590,7 @@ public:
|
|||
/**
|
||||
* @brief Move the origin
|
||||
*/
|
||||
void move (const db::Vector &d)
|
||||
void move (const vector_type &d)
|
||||
{
|
||||
m_p0 += d;
|
||||
}
|
||||
|
|
@ -594,7 +598,7 @@ public:
|
|||
/**
|
||||
* @brief The per-pixel displacement vector (pixel size)
|
||||
*/
|
||||
const db::Vector &d () const
|
||||
const vector_type &d () const
|
||||
{
|
||||
return m_d;
|
||||
}
|
||||
|
|
@ -602,7 +606,7 @@ public:
|
|||
/**
|
||||
* @brief The pixel size (must be less than d)
|
||||
*/
|
||||
const db::Vector &p () const
|
||||
const vector_type &p () const
|
||||
{
|
||||
return m_p;
|
||||
}
|
||||
|
|
@ -610,7 +614,7 @@ public:
|
|||
/**
|
||||
* @brief Compute the bounding box of the area map
|
||||
*/
|
||||
db::Box bbox () const;
|
||||
box_type bbox () const;
|
||||
|
||||
/**
|
||||
* @brief Compute the total area
|
||||
|
|
@ -632,12 +636,15 @@ public:
|
|||
|
||||
private:
|
||||
area_type *mp_av;
|
||||
db::Point m_p0;
|
||||
db::Vector m_d;
|
||||
db::Vector m_p;
|
||||
point_type m_p0;
|
||||
vector_type m_d;
|
||||
vector_type m_p;
|
||||
size_t m_nx, m_ny;
|
||||
};
|
||||
|
||||
typedef area_map<db::Coord> AreaMap;
|
||||
typedef area_map<db::DCoord> DAreaMap;
|
||||
|
||||
/**
|
||||
* @brief Rasterize the polygon into the given area map
|
||||
*
|
||||
|
|
@ -648,6 +655,16 @@ private:
|
|||
*/
|
||||
bool DB_PUBLIC rasterize (const db::Polygon &polygon, db::AreaMap &am);
|
||||
|
||||
/**
|
||||
* @brief Rasterize the polygon into the given area map (double version)
|
||||
*
|
||||
* This will decompose the polygon and produce per-pixel area values for the given
|
||||
* polygon. The area contributions will be added to the given area map.
|
||||
*
|
||||
* Returns a value indicating whether the map will be non-empty.
|
||||
*/
|
||||
bool DB_PUBLIC rasterize (const db::DPolygon &polygon, db::DAreaMap &am);
|
||||
|
||||
/**
|
||||
* @brief Minkowski sum of an edge and a polygon
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ enum OppositeFilter
|
|||
* @brief A structure holding the options for the region checks (space, width, ...)
|
||||
*/
|
||||
struct DB_PUBLIC RegionCheckOptions
|
||||
: public EdgesCheckOptions
|
||||
{
|
||||
typedef db::coord_traits<db::Coord>::distance_type distance_type;
|
||||
|
||||
|
|
@ -128,12 +129,9 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
OppositeFilter _opposite_filter = NoOppositeFilter,
|
||||
RectFilter _rect_filter = NoRectFilter,
|
||||
bool _negative = false,
|
||||
PropertyConstraint _prop_constraint = IgnoreProperties)
|
||||
: whole_edges (_whole_edges),
|
||||
metrics (_metrics),
|
||||
ignore_angle (_ignore_angle),
|
||||
min_projection (_min_projection),
|
||||
max_projection (_max_projection),
|
||||
PropertyConstraint _prop_constraint = IgnoreProperties,
|
||||
zero_distance_mode _zd_mode = IncludeZeroDistanceWhenTouching)
|
||||
: EdgesCheckOptions (_whole_edges, _metrics, _ignore_angle, _min_projection, _max_projection, _zd_mode),
|
||||
shielded (_shielded),
|
||||
opposite_filter (_opposite_filter),
|
||||
rect_filter (_rect_filter),
|
||||
|
|
@ -141,46 +139,6 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
prop_constraint (_prop_constraint)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Specifies is whole edges are to be delivered
|
||||
*
|
||||
* Without "whole_edges", the parts of
|
||||
* the edges are returned which violate the condition. If "whole_edges" is true, the
|
||||
* result will contain the complete edges participating in the result.
|
||||
*/
|
||||
bool whole_edges;
|
||||
|
||||
/**
|
||||
* @brief Measurement metrics
|
||||
*
|
||||
* The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected"
|
||||
* metrics are available.
|
||||
*/
|
||||
metrics_type metrics;
|
||||
|
||||
/**
|
||||
* @brief Specifies the obtuse angle threshold
|
||||
*
|
||||
* "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate
|
||||
* in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked,
|
||||
* but acute corners are for example.
|
||||
*/
|
||||
double ignore_angle;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's minimum value
|
||||
*
|
||||
* With min_projection and max_projection it is possible to specify how edges must be related
|
||||
* to each other. If the length of the projection of either edge on the other is >= min_projection
|
||||
* or < max_projection, the edges are considered for the check.
|
||||
*/
|
||||
distance_type min_projection;
|
||||
|
||||
/**
|
||||
* @brief Specifies the projection limit's maximum value
|
||||
*/
|
||||
distance_type max_projection;
|
||||
|
||||
/**
|
||||
* @brief Specifies shielding
|
||||
*
|
||||
|
|
|
|||
|
|
@ -359,12 +359,7 @@ SinglePolygonCheck::process (const db::Polygon &polygon, std::vector<db::EdgePai
|
|||
{
|
||||
std::unordered_set<db::EdgePair> result;
|
||||
|
||||
EdgeRelationFilter check (m_relation, m_d, m_options.metrics);
|
||||
check.set_include_zero (false);
|
||||
check.set_whole_edges (m_options.whole_edges);
|
||||
check.set_ignore_angle (m_options.ignore_angle);
|
||||
check.set_min_projection (m_options.min_projection);
|
||||
check.set_max_projection (m_options.max_projection);
|
||||
EdgeRelationFilter check (m_relation, m_d, m_options);
|
||||
|
||||
edge2edge_check_negative_or_positive <std::unordered_set<db::EdgePair> > edge_check (check, result, m_options.negative, false /*=same polygons*/, false /*=same layers*/, m_options.shielded, true /*=symmetric*/);
|
||||
poly2poly_check<db::Polygon> poly_check (edge_check);
|
||||
|
|
|
|||
|
|
@ -283,6 +283,7 @@ Technology::~Technology ()
|
|||
Technology::Technology (const Technology &d)
|
||||
: tl::Object (),
|
||||
m_name (d.m_name), m_description (d.m_description), m_group (d.m_group), m_grain_name (d.m_grain_name), m_dbu (d.m_dbu),
|
||||
m_default_grids (d.m_default_grids),
|
||||
m_explicit_base_path (d.m_explicit_base_path), m_default_base_path (d.m_default_base_path),
|
||||
m_load_layout_options (d.m_load_layout_options),
|
||||
m_save_layout_options (d.m_save_layout_options),
|
||||
|
|
@ -303,6 +304,7 @@ Technology &Technology::operator= (const Technology &d)
|
|||
m_group = d.m_group;
|
||||
m_grain_name = d.m_grain_name;
|
||||
m_dbu = d.m_dbu;
|
||||
m_default_grids = d.m_default_grids;
|
||||
m_default_base_path = d.m_default_base_path;
|
||||
m_explicit_base_path = d.m_explicit_base_path;
|
||||
m_load_layout_options = d.m_load_layout_options;
|
||||
|
|
@ -345,6 +347,26 @@ Technology::get_display_string () const
|
|||
return d;
|
||||
}
|
||||
|
||||
std::vector<double>
|
||||
Technology::default_grid_list () const
|
||||
{
|
||||
tl::Extractor ex (m_default_grids.c_str ());
|
||||
|
||||
std::vector<double> grids;
|
||||
|
||||
// convert the list of grids to a list of doubles
|
||||
while (! ex.at_end ()) {
|
||||
double g = 0.0;
|
||||
if (! ex.try_read (g)) {
|
||||
break;
|
||||
}
|
||||
grids.push_back (g);
|
||||
ex.test (",");
|
||||
}
|
||||
|
||||
return grids;
|
||||
}
|
||||
|
||||
tl::XMLElementList
|
||||
Technology::xml_elements ()
|
||||
{
|
||||
|
|
@ -353,6 +375,7 @@ Technology::xml_elements ()
|
|||
tl::make_member (&Technology::description, &Technology::set_description, "description") +
|
||||
tl::make_member (&Technology::group, &Technology::set_group, "group") +
|
||||
tl::make_member (&Technology::dbu, &Technology::set_dbu, "dbu") +
|
||||
tl::make_member (&Technology::default_grids, &Technology::set_default_grids, "default-grids") +
|
||||
tl::make_member (&Technology::explicit_base_path, &Technology::set_explicit_base_path, "base-path") +
|
||||
tl::make_member (&Technology::default_base_path, &Technology::set_default_base_path, "original-base-path") +
|
||||
tl::make_member (&Technology::layer_properties_file, &Technology::set_layer_properties_file, "layer-properties_file") +
|
||||
|
|
|
|||
|
|
@ -467,6 +467,30 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the default grids
|
||||
*/
|
||||
const std::string &default_grids () const
|
||||
{
|
||||
return m_default_grids;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the default grids, parsed as a list of double values
|
||||
*/
|
||||
std::vector<double> default_grid_list () const;
|
||||
|
||||
/**
|
||||
* @brief Sets the default default grids
|
||||
*/
|
||||
void set_default_grids (const std::string &default_grids)
|
||||
{
|
||||
if (default_grids != m_default_grids) {
|
||||
m_default_grids = default_grids;
|
||||
technology_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layer properties file path (empty if none is specified)
|
||||
*/
|
||||
|
|
@ -650,6 +674,7 @@ private:
|
|||
std::string m_name, m_description, m_group;
|
||||
std::string m_grain_name;
|
||||
double m_dbu;
|
||||
std::string m_default_grids;
|
||||
std::string m_explicit_base_path, m_default_base_path;
|
||||
db::LoadLayoutOptions m_load_layout_options;
|
||||
db::SaveLayoutOptions m_save_layout_options;
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ void compare_layouts (tl::TestBase *_this, const db::Layout &layout, const std::
|
|||
(n > 0 ? db::layout_diff::f_silent : db::layout_diff::f_verbose)
|
||||
| ((norm & AsPolygons) != 0 ? db::layout_diff::f_boxes_as_polygons + db::layout_diff::f_paths_as_polygons : 0)
|
||||
| ((norm & WithArrays) != 0 ? 0 : db::layout_diff::f_flatten_array_insts)
|
||||
| ((norm & WithMeta) == 0 ? 0 : db::layout_diff::f_with_meta)
|
||||
/*| db::layout_diff::f_no_text_details | db::layout_diff::f_no_text_orientation*/
|
||||
, tolerance, 100 /*max diff lines*/);
|
||||
if (equal && n > 0) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ enum NormalizationMode
|
|||
NormFileMask = 7, // bits the extract for file mode
|
||||
NoContext = 8, // write tmp file without context
|
||||
AsPolygons = 16, // paths and boxes are treated as polygons
|
||||
WithArrays = 32 // do not flatten arrays
|
||||
WithArrays = 32, // do not flatten arrays
|
||||
WithMeta = 64 // with meta info
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ Triangles::find_closest_edge (const db::DPoint &p, db::Vertex *vstart, bool insi
|
|||
db::DVector r = p - *cv;
|
||||
double edge_sp = db::sprod (r, edge_d) / edge_d.length ();
|
||||
double s_sp = db::sprod (r, e_d) / e_d.length ();
|
||||
if (s_sp > edge_sp) {
|
||||
if (s_sp > edge_sp + db::epsilon) {
|
||||
edge = *e;
|
||||
vnext = edge->other (v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1004,6 +1004,22 @@ static void cell_add_meta_info (db::Cell *cell, const MetaInfo &mi)
|
|||
}
|
||||
}
|
||||
|
||||
static void cell_merge_meta_info (db::Cell *cell, const db::Cell *source)
|
||||
{
|
||||
if (! source || ! cell->layout () || ! source->layout ()) {
|
||||
return;
|
||||
}
|
||||
cell->layout ()->merge_meta_info (cell->cell_index (), *source->layout (), source->cell_index ());
|
||||
}
|
||||
|
||||
static void cell_copy_meta_info (db::Cell *cell, const db::Cell *source)
|
||||
{
|
||||
if (! source || ! cell->layout () || ! source->layout ()) {
|
||||
return;
|
||||
}
|
||||
cell->layout ()->copy_meta_info (cell->cell_index (), *source->layout (), source->cell_index ());
|
||||
}
|
||||
|
||||
static const tl::Variant &cell_meta_info_value (db::Cell *cell, const std::string &name)
|
||||
{
|
||||
if (! cell->layout ()) {
|
||||
|
|
@ -1755,6 +1771,7 @@ read_options (db::Cell *cell, const std::string &path, const db::LoadLayoutOptio
|
|||
db::CellMapping cm;
|
||||
std::vector<db::cell_index_type> new_cells = cm.create_single_mapping_full (*cell->layout (), cell->cell_index (), tmp, *tmp.begin_top_down ());
|
||||
cell->move_tree_shapes (tmp.cell (*tmp.begin_top_down ()), cm);
|
||||
cell->layout ()->merge_meta_info (tmp, cm);
|
||||
|
||||
return new_cells;
|
||||
}
|
||||
|
|
@ -1834,6 +1851,21 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.28.8."
|
||||
) +
|
||||
gsi::method_ext ("merge_meta_info", &cell_merge_meta_info, gsi::arg ("other"),
|
||||
"@brief Merges the meta information from the other cell into this cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"Existing keys in this cell will be overwritten by the respective values from the other cell.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method_ext ("copy_meta_info", &cell_copy_meta_info, gsi::arg ("other"),
|
||||
"@brief Copies the meta information from the other cell into this cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"The meta information from this cell will be replaced by the meta information from the other cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method_ext ("clear_meta_info", &cell_clear_meta_info,
|
||||
"@brief Clears the meta information of the cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
|
|
|
|||
|
|
@ -390,23 +390,27 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo
|
|||
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToSecondEdgesProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
check_non_null (other, "other");
|
||||
return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d,
|
||||
db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to<db::Region::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
||||
shielded,
|
||||
opposite_filter,
|
||||
rect_filter,
|
||||
negative)
|
||||
);
|
||||
|
||||
db::RegionCheckOptions options;
|
||||
|
||||
options.whole_edges = whole_edges;
|
||||
options.metrics = metrics;
|
||||
options.ignore_angle = ignore_angle.is_nil () ? 90 : ignore_angle.to_double ();
|
||||
options.min_projection = min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to<db::Region::distance_type> ();
|
||||
options.max_projection = max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> ();
|
||||
options.shielded = shielded;
|
||||
options.opposite_filter = opposite_filter;
|
||||
options.rect_filter = rect_filter;
|
||||
options.negative = negative;
|
||||
options.zd_mode = zd_mode;
|
||||
|
||||
return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, options);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
db::RegionCheckOptions options (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -415,28 +419,29 @@ static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole
|
|||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
||||
shielded);
|
||||
options.negative = negative;
|
||||
options.zd_mode = zd_mode;
|
||||
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::WidthRelation, d, options), new_primary (), true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative, bool isolated)
|
||||
static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative, bool isolated)
|
||||
{
|
||||
// NOTE: we have to use the "foreign" scheme with a filter because only this scheme
|
||||
// guarantees that all subject shapes are visited and receive all intruders. Having all intruders is crucial for the
|
||||
// semantics of the "drc" feature
|
||||
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, false);
|
||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative, false);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, true);
|
||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative, true);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
db::RegionCheckOptions options (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -445,27 +450,28 @@ static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole
|
|||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
||||
shielded);
|
||||
options.negative = negative;
|
||||
options.zd_mode = zd_mode;
|
||||
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::SpaceRelation, d, options), new_primary (), true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
||||
static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative)
|
||||
{
|
||||
return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
||||
return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits<db::Coord>::perimeter_type pmin, db::coord_traits<db::Coord>::perimeter_type pmax)
|
||||
|
|
@ -660,31 +666,45 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
gsi::constructor ("new_minkowski_sum|#new_minkowsky_sum", &new_minkowski_sum_node4, gsi::arg ("input"), gsi::arg ("p"),
|
||||
"@brief Creates a node providing a Minkowski sum with a point sequence forming a contour.\n"
|
||||
) +
|
||||
gsi::constructor ("new_width_check", &new_width_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_width_check", &new_width_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a width check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_space_check", &new_space_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_space_check", &new_space_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a space check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_isolated_check", &new_isolated_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_isolated_check", &new_isolated_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a isolated polygons (space between different polygons) check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_notch_check", &new_notch_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_notch_check", &new_notch_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a intra-polygon space check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing a separation check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing an overlap check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_enclosing_check", &new_enclosing_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_enclosing_check", &new_enclosing_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing an inside (enclosure) check.\n"
|
||||
"\n"
|
||||
"The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_enclosed_check", &new_enclosed_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
||||
gsi::constructor ("new_enclosed_check", &new_enclosed_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false),
|
||||
"@brief Creates a node providing an enclosed (secondary enclosing primary) check.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.5.\n"
|
||||
"This method has been added in version 0.27.5. The zero_distance_mode argument has been inserted in version 0.29.\n"
|
||||
) +
|
||||
gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits<db::coord_traits<db::Coord>::perimeter_type>::max (), "max"),
|
||||
"@brief Creates a node filtering the input by perimeter.\n"
|
||||
|
|
@ -807,9 +827,7 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
"\n"
|
||||
"The search distance for intruder shapes is determined by the operation and computed from the operation's requirements.\n"
|
||||
"\n"
|
||||
"NOTE: this feature is experimental and not deployed into the the DRC framework yet.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.27."
|
||||
"This class has been introduced in version 0.27. The API is considered internal and will change without notice."
|
||||
);
|
||||
|
||||
gsi::EnumIn<db::CompoundRegionOperationNode, db::CompoundRegionLogicalBoolOperationNode::LogicalOp> decl_dbCompoundRegionLogicalBoolOperationNode_LogicalOp ("db", "LogicalOp",
|
||||
|
|
|
|||
|
|
@ -234,63 +234,69 @@ static db::Edges with_angle3 (const db::Edges *r, db::SpecialEdgeOrientationFilt
|
|||
return r->filtered (f);
|
||||
}
|
||||
|
||||
static db::EdgePairs width2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs width2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->width_check (d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs space2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs space2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->space_check (d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs inside2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs inside2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->inside_check (other, d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs overlap2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs overlap2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->overlap_check (other, d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs enclosing2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs enclosing2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->enclosing_check (other, d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs separation2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
|
||||
static db::EdgePairs separation2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode)
|
||||
{
|
||||
return r->separation_check (other, d, db::EdgesCheckOptions (whole_edges,
|
||||
metrics,
|
||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
||||
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
|
||||
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> (),
|
||||
zd_mode)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1445,7 +1451,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"\n"
|
||||
"This variant has been introduced in version 0.27."
|
||||
) +
|
||||
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a width check with options\n"
|
||||
"@param d The minimum width for which the edges are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -1453,6 +1459,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -1470,8 +1477,10 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It is sufficient if the projection of one edge on the other matches the specified condition. "
|
||||
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
|
||||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a space check with options\n"
|
||||
"@param d The minimum distance for which the edges are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -1479,6 +1488,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the space check.\n"
|
||||
|
|
@ -1496,8 +1506,10 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It is sufficient if the projection of one edge on the other matches the specified condition. "
|
||||
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
|
||||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an inside check with options\n"
|
||||
"@param d The minimum distance for which the edges are checked\n"
|
||||
"@param other The other edge collection against which to check\n"
|
||||
|
|
@ -1506,6 +1518,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -1525,8 +1538,9 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"The 'enclosed_check' alias was introduced in version 0.27.5.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an enclosing check with options\n"
|
||||
"@param d The minimum distance for which the edges are checked\n"
|
||||
"@param other The other edge collection against which to check\n"
|
||||
|
|
@ -1535,6 +1549,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -1552,8 +1567,10 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It is sufficient if the projection of one edge on the other matches the specified condition. "
|
||||
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
|
||||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an overlap check with options\n"
|
||||
"@param d The minimum distance for which the edges are checked\n"
|
||||
"@param other The other edge collection against which to check\n"
|
||||
|
|
@ -1562,6 +1579,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -1579,8 +1597,10 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It is sufficient if the projection of one edge on the other matches the specified condition. "
|
||||
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
|
||||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
|
||||
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an overlap check with options\n"
|
||||
"@param d The minimum distance for which the edges are checked\n"
|
||||
"@param other The other edge collection against which to check\n"
|
||||
|
|
@ -1589,6 +1609,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"@param ignore_angle The threshold angle above which no check is performed\n"
|
||||
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
|
||||
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -1606,6 +1627,8 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It is sufficient if the projection of one edge on the other matches the specified condition. "
|
||||
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
|
||||
"If you don't want to specify one threshold, pass nil to the respective value.\n"
|
||||
"\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("extents", &extents0,
|
||||
"@brief Returns a region with the bounding boxes of the edges\n"
|
||||
|
|
|
|||
|
|
@ -1105,12 +1105,54 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("merge_meta_info", static_cast<void (db::Layout::*) (const db::Layout &)> (&db::Layout::merge_meta_info), gsi::arg ("other"),
|
||||
"@brief Merges the meta information from the other layout into this layout\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"Existing keys in this layout will be overwritten by the respective values from the other layout.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("merge_meta_info", static_cast<void (db::Layout::*) (const db::Layout &, const db::CellMapping &cm)> (&db::Layout::merge_meta_info), gsi::arg ("other"), gsi::arg ("cm"),
|
||||
"@brief Merges the meta information from the other layout into this layout for the cells given by the cell mapping\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"This method will use the source/target cell pairs from the cell mapping object and merge the meta information "
|
||||
"from each source cell from the 'other' layout into the mapped cell inside self.\n"
|
||||
"This method can be used with '\\copy_tree_shapes' and similar to copy meta information in addition to the shapes.\n"
|
||||
"Existing cell-specific keys in this layout will be overwritten by the respective values from the other layout.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("copy_meta_info", static_cast<void (db::Layout::*) (const db::Layout &)> (&db::Layout::copy_meta_info), gsi::arg ("other"),
|
||||
"@brief Copies the meta information from the other layout into this layout\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"The meta information from this layout will be replaced by the meta information from the other layout.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("copy_meta_info", static_cast<void (db::Layout::*) (const db::Layout &, const db::CellMapping &cm)> (&db::Layout::copy_meta_info), gsi::arg ("other"), gsi::arg ("cm"),
|
||||
"@brief Copies the meta information from the other layout into this layout for the cells given by the cell mapping\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"This method will use the source/target cell pairs from the cell mapping object and merge the meta information "
|
||||
"from each source cell from the 'other' layout into the mapped cell inside self.\n"
|
||||
"This method can be used with '\\copy_tree_shapes' and similar to copy meta information in addition to the shapes.\n"
|
||||
"All cell-specific keys in this layout will be replaced by the respective values from the other layout.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("clear_meta_info", static_cast<void (db::Layout::*) ()> (&db::Layout::clear_meta),
|
||||
"@brief Clears the meta information of the layout\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.8."
|
||||
) +
|
||||
gsi::method ("clear_all_meta_info", static_cast<void (db::Layout::*) ()> (&db::Layout::clear_all_meta),
|
||||
"@brief Clears all meta information of the layout (cell specific and global)\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("remove_meta_info", static_cast<void (db::Layout::*) (const std::string &name)> (&db::Layout::remove_meta_info), gsi::arg ("name"),
|
||||
"@brief Removes meta information from the layout\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ public:
|
|||
dbu_differs_event (dbu_a, dbu_b);
|
||||
}
|
||||
|
||||
virtual void layout_meta_info_differs (const std::string &name, const tl::Variant &value_a, const tl::Variant &value_b)
|
||||
{
|
||||
layout_meta_info_differs_event (name, value_a, value_b);
|
||||
}
|
||||
|
||||
virtual void layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
layer_in_a_only_event (la);
|
||||
|
|
@ -132,6 +137,11 @@ public:
|
|||
begin_cell_event (mp_cell_a, mp_cell_b);
|
||||
}
|
||||
|
||||
virtual void cell_meta_info_differs (const std::string &name, const tl::Variant &value_a, const tl::Variant &value_b)
|
||||
{
|
||||
cell_meta_info_differs_event (name, value_a, value_b);
|
||||
}
|
||||
|
||||
virtual void begin_inst_differences ()
|
||||
{
|
||||
begin_inst_differences_event ();
|
||||
|
|
@ -343,6 +353,7 @@ public:
|
|||
}
|
||||
|
||||
tl::event<double /*dbu_a*/, double /*dbu_a*/> dbu_differs_event;
|
||||
tl::event<const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/> layout_meta_info_differs_event;
|
||||
tl::event<const db::LayerProperties & /*a*/> layer_in_a_only_event;
|
||||
tl::event<const db::LayerProperties & /*b*/> layer_in_b_only_event;
|
||||
tl::event<const db::LayerProperties & /*a*/, const db::LayerProperties & /*b*/> layer_name_differs_event;
|
||||
|
|
@ -351,6 +362,7 @@ public:
|
|||
tl::event<const db::Cell * /*c*/> cell_in_b_only_event;
|
||||
tl::event<const db::Box & /*ba*/, const db::Box & /*bb*/> bbox_differs_event;
|
||||
tl::event<const db::Cell * /*ca*/, const db::Cell * /*cb*/> begin_cell_event;
|
||||
tl::event<const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/> cell_meta_info_differs_event;
|
||||
tl::Event begin_inst_differences_event;
|
||||
tl::event<const db::CellInstArray & /*anotb*/, db::properties_id_type /*prop_id*/> instance_in_a_only_event;
|
||||
tl::event<const db::CellInstArray & /*bnota*/, db::properties_id_type /*prop_id*/> instance_in_b_only_event;
|
||||
|
|
@ -409,6 +421,10 @@ static unsigned int f_no_properties () {
|
|||
return db::layout_diff::f_no_properties;
|
||||
}
|
||||
|
||||
static unsigned int f_with_meta () {
|
||||
return db::layout_diff::f_with_meta;
|
||||
}
|
||||
|
||||
static unsigned int f_no_layer_names () {
|
||||
return db::layout_diff::f_no_layer_names;
|
||||
}
|
||||
|
|
@ -450,7 +466,7 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"full compare.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("IgnoreDuplicates", &f_ignore_duplicates,
|
||||
"@brief Ignore duplicate instances or shapes\n"
|
||||
|
|
@ -462,17 +478,25 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
gsi::constant ("NoTextOrientation", &f_no_text_orientation,
|
||||
"@brief Ignore text orientation\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("NoProperties", &f_no_properties,
|
||||
"@brief Ignore properties\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("WithMetaInfo", &f_with_meta,
|
||||
"@brief Ignore meta info\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"combined with other constants to form a flag set. If present, this option tells the compare algorithm "
|
||||
"to include persisted meta info in the compare.\n"
|
||||
"\n"
|
||||
"This flag has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::constant ("NoLayerNames", &f_no_layer_names,
|
||||
"@brief Do not compare layer names\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("Verbose", &f_verbose,
|
||||
"@brief Enables verbose mode (gives details about the differences)\n"
|
||||
|
|
@ -480,22 +504,22 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"See the event descriptions for details about the differences in verbose and non-verbose mode.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("BoxesAsPolygons", &f_boxes_as_polygons,
|
||||
"@brief Compare boxes to polygons\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("FlattenArrayInsts", &f_flatten_array_insts,
|
||||
"@brief Compare array instances instance by instance\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("PathsAsPolygons", &f_paths_as_polygons,
|
||||
"@brief Compare paths to polygons\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("SmartCellMapping", &f_smart_cell_mapping,
|
||||
"@brief Derive smart cell mapping instead of name mapping (available only if top cells are specified)\n"
|
||||
|
|
@ -503,7 +527,7 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"cells are compared (with \\LayoutDiff#compare with cells instead of layout objects).\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set.\n"
|
||||
"combined with other constants to form a flag set.\n"
|
||||
) +
|
||||
gsi::constant ("DontSummarizeMissingLayers", &f_dont_summarize_missing_layers,
|
||||
"@brief Don't summarize missing layers\n"
|
||||
|
|
@ -511,12 +535,12 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"layer will be reported as difference.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("NoTextDetails", &f_no_text_details,
|
||||
"@brief Ignore text details (font, size, presentation)\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::method ("compare", &LayoutDiff::compare_layouts,
|
||||
gsi::arg("a"),
|
||||
|
|
@ -593,6 +617,14 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
gsi::event ("on_dbu_differs", &LayoutDiff::dbu_differs_event, gsi::arg ("dbu_a"), gsi::arg ("dbu_b"),
|
||||
"@brief This signal indicates a difference in the database units of the layouts\n"
|
||||
) +
|
||||
gsi::event ("on_layout_meta_info_differs", &LayoutDiff::layout_meta_info_differs_event, gsi::arg ("name"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This signal indicates that global meta info differs\n"
|
||||
"Meta information is only compared when \\WithMetaInfo is added to the compare flags.\n"
|
||||
"'a' and 'b' are the values for the first and second layout. 'nil' is passed to these values to indicate "
|
||||
"missing meta information on one side.\n"
|
||||
"\n"
|
||||
"This event has been added in version 0.28.16."
|
||||
) +
|
||||
gsi::event ("on_layer_in_a_only", &LayoutDiff::layer_in_a_only_event, gsi::arg ("a"),
|
||||
"@brief This signal indicates a layer that is present only in the first layout\n"
|
||||
) +
|
||||
|
|
@ -619,9 +651,17 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"In verbose mode detailed events will be issued indicating the differences.\n"
|
||||
) +
|
||||
gsi::event ("on_begin_cell", &LayoutDiff::begin_cell_event, gsi::arg ("ca"), gsi::arg ("cb"),
|
||||
"@brief This signal initiates the sequence of events for a cell pair\n"
|
||||
"@brief This signal indicates the sequence of events for a cell pair\n"
|
||||
"All cell specific events happen between \\begin_cell_event and \\end_cell_event signals."
|
||||
) +
|
||||
gsi::event ("on_cell_meta_info_differs", &LayoutDiff::cell_meta_info_differs_event, gsi::arg ("name"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This signal indicates that meta info between the current cells differs\n"
|
||||
"Meta information is only compared when \\WithMetaInfo is added to the compare flags.\n"
|
||||
"'a' and 'b' are the values for the first and second layout. 'nil' is passed to these values to indicate "
|
||||
"missing meta information on one side.\n"
|
||||
"\n"
|
||||
"This event has been added in version 0.28.16."
|
||||
) +
|
||||
gsi::event ("on_begin_inst_differences", &LayoutDiff::begin_inst_differences_event,
|
||||
"@brief This signal indicates differences in the cell instances\n"
|
||||
"In verbose mode (see \\Verbose) more events will follow that indicate the instances that are present only "
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc)
|
|||
return r->merged (min_coherence, std::max (0, min_wc - 1));
|
||||
}
|
||||
|
||||
static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->width_check (d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -537,11 +537,12 @@ static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, b
|
|||
db::NoOppositeFilter,
|
||||
db::NoRectFilter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->notch_check (d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -552,11 +553,12 @@ static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, b
|
|||
db::NoOppositeFilter,
|
||||
db::NoRectFilter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->isolated_check (d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -567,11 +569,12 @@ static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->space_check (d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -582,11 +585,12 @@ static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, b
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->inside_check (other, d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -597,11 +601,12 @@ static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db::
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->overlap_check (other, d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -612,11 +617,12 @@ static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db:
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->enclosing_check (other, d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -627,11 +633,12 @@ static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, d
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint)
|
||||
static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode)
|
||||
{
|
||||
return r->separation_check (other, d, db::RegionCheckOptions (whole_edges,
|
||||
metrics,
|
||||
|
|
@ -642,7 +649,8 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
|
|||
opposite,
|
||||
rect_filter,
|
||||
negative,
|
||||
prop_constraint)
|
||||
prop_constraint,
|
||||
zero_distance_mode)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -792,6 +800,40 @@ edges (const db::Region *region, db::PolygonToEdgeProcessor::EdgeMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
static std::vector<std::vector<double> >
|
||||
rasterize2 (const db::Region *region, const db::Point &origin, const db::Vector &pixel_distance, const db::Vector &pixel_size, unsigned int nx, unsigned int ny)
|
||||
{
|
||||
db::DAreaMap am (db::DPoint (origin), db::DVector (pixel_distance), db::DVector (pixel_size), nx, ny);
|
||||
|
||||
auto pi = region->begin ();
|
||||
pi = pi.confined (db::Box (am.bbox ()), false /*not overlapping*/);
|
||||
|
||||
while (! pi.at_end ()) {
|
||||
db::DPolygon dp (*pi);
|
||||
db::rasterize (dp, am);
|
||||
++pi;
|
||||
}
|
||||
|
||||
std::vector<std::vector<double> > result;
|
||||
result.reserve (ny);
|
||||
for (unsigned int y = 0; y < ny; ++y) {
|
||||
result.push_back (std::vector<double> ());
|
||||
std::vector<double> &row = result.back ();
|
||||
row.reserve (nx);
|
||||
for (unsigned int x = 0; x < nx; ++x) {
|
||||
row.push_back (am.get (x, y));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<std::vector<double> >
|
||||
rasterize1 (const db::Region *region, const db::Point &origin, const db::Vector &pixel_size, unsigned int nx, unsigned int ny)
|
||||
{
|
||||
return rasterize2 (region, origin, pixel_size, pixel_size, nx, ny);
|
||||
}
|
||||
|
||||
static db::Point default_origin;
|
||||
|
||||
// provided by gsiDeclDbPolygon.cc:
|
||||
|
|
@ -2606,7 +2648,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This variant was introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a width check with options\n"
|
||||
"@param d The minimum width for which the polygons are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -2617,6 +2659,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param shielded Enables shielding\n"
|
||||
"@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n"
|
||||
"@param property_constraint Only \\IgnoreProperties and \\NoPropertyConstraint are allowed - in the last case, properties are copied from the original shapes to the output. "
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"Other than 'width' allow more options here.\n"
|
||||
"\n"
|
||||
"This version is similar to the simple version with one parameter. In addition, it allows "
|
||||
|
|
@ -2647,9 +2690,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded' and 'negative' options have been introduced in version 0.27. "
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.28.16."
|
||||
) +
|
||||
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a space check with options\n"
|
||||
"@param d The minimum space for which the polygons are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -2661,6 +2705,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2690,9 +2735,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("notch_check", ¬ch2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("notch_check", ¬ch2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a space check between edges of the same polygon with options\n"
|
||||
"@param d The minimum space for which the polygons are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -2704,6 +2750,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param property_constraint Only \\IgnoreProperties and \\NoPropertyConstraint are allowed - in the last case, properties are copied from the original shapes to the output"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"This version is similar to the simple version with one parameter. In addition, it allows "
|
||||
"to specify many more options.\n"
|
||||
|
|
@ -2733,9 +2780,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded' and 'negative' options have been introduced in version 0.27.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("isolated_check", &isolated2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("isolated_check", &isolated2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a space check between edges of different polygons with options\n"
|
||||
"@param d The minimum space for which the polygons are checked\n"
|
||||
"@param whole_edges If true, deliver the whole edges\n"
|
||||
|
|
@ -2747,6 +2795,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2776,9 +2825,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an inside check with options\n"
|
||||
"@param d The minimum distance for which the polygons are checked\n"
|
||||
"@param other The other region against which to check\n"
|
||||
|
|
@ -2791,6 +2841,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative Negative output from the first input\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2827,9 +2878,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. "
|
||||
"The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n"
|
||||
"The 'enclosed_check' alias was introduced in version 0.27.5.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an overlap check with options\n"
|
||||
"@param d The minimum overlap for which the polygons are checked\n"
|
||||
"@param other The other region against which to check\n"
|
||||
|
|
@ -2842,6 +2894,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative Negative output from the first input\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2877,9 +2930,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. "
|
||||
"The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs an enclosing check with options\n"
|
||||
"@param d The minimum enclosing distance for which the polygons are checked\n"
|
||||
"@param other The other region against which to check\n"
|
||||
|
|
@ -2892,6 +2946,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative Negative output from the first input\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2927,9 +2982,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. "
|
||||
"The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"),
|
||||
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"),
|
||||
"@brief Performs a separation check with options\n"
|
||||
"@param d The minimum separation for which the polygons are checked\n"
|
||||
"@param other The other region against which to check\n"
|
||||
|
|
@ -2942,6 +2998,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@param rect_filter Specifies an error filter for rectangular input shapes\n"
|
||||
"@param negative Negative output from the first input\n"
|
||||
"@param property_constraint Specifies whether to consider only shapes with a certain property relation\n"
|
||||
"@param zero_distance_mode Specifies how to handle edges with zero distance\n"
|
||||
"\n"
|
||||
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
|
||||
"edges which contribute in the width check.\n"
|
||||
|
|
@ -2977,7 +3034,8 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. "
|
||||
"The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n"
|
||||
"'property_constraint' has been added in version 0.28.4."
|
||||
"'property_constraint' has been added in version 0.28.4.\n"
|
||||
"'zero_distance_mode' has been added in version 0.29."
|
||||
) +
|
||||
method_ext ("area", &area1,
|
||||
"@brief The area of the region\n"
|
||||
|
|
@ -3088,6 +3146,36 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Converts the region to a string\n"
|
||||
"This version allows specification of the maximum number of polygons contained in the string."
|
||||
) +
|
||||
method_ext ("rasterize", &rasterize1, gsi::arg ("origin"), gsi::arg ("pixel_size"), gsi::arg ("nx"), gsi::arg ("ny"),
|
||||
"@brief A grayscale rasterizer delivering the area covered per pixel\n"
|
||||
"@param origin The lower-left corner of the lowest-left pixel\n"
|
||||
"@param pixel_size The dimension of each pixel (the x component gives the width, the y component the height)\n"
|
||||
"@param nx The number of pixels in horizontal direction\n"
|
||||
"@param ny The number of pixels in vertical direction\n"
|
||||
"The method will create a grayscale, high-resolution density map of a rectangular region.\n"
|
||||
"The scan region is defined by the origin, the pixel size and the number of pixels in horizontal (nx) and\n"
|
||||
"vertical (ny) direction. The resulting array will contain the area covered by polygons from the region\n"
|
||||
"in square database units.\n"
|
||||
"\n"
|
||||
"For non-overlapping polygons, the maximum density value is px*py. Overlapping polygons are counted multiple\n"
|
||||
"times, so the actual values may be larger. If you want overlaps removed, you have to\n"
|
||||
"merge the region before. Merge semantics does not apply for the 'rasterize' method.\n"
|
||||
"\n"
|
||||
"The resulting area values are precise within the limits of double-precision floating point arithmetics.\n"
|
||||
"\n"
|
||||
"A second version exists that allows specifying an active pixel size which is smaller than the\n"
|
||||
"pixel distance hence allowing pixels samples that do not cover the full area, but leave gaps between the pixels.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.\n"
|
||||
) +
|
||||
method_ext ("rasterize", &rasterize2, gsi::arg ("origin"), gsi::arg ("pixel_distance"), gsi::arg ("pixel_size"), gsi::arg ("nx"), gsi::arg ("ny"),
|
||||
"@brief A version of 'rasterize' that allows a pixel step distance which is larger than the pixel size\n"
|
||||
"This version behaves like the first variant of 'rasterize', but the pixel distance (pixel-to-pixel step raster)\n"
|
||||
"can be specified separately from the pixel size. Currently, the pixel size must be equal or smaller than the\n"
|
||||
"pixel distance - i.e. the pixels must not overlap.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.29.\n"
|
||||
) +
|
||||
method ("enable_progress", &db::Region::enable_progress, gsi::arg ("label"),
|
||||
"@brief Enable progress reporting\n"
|
||||
"After calling this method, the region will report the progress through a progress bar while "
|
||||
|
|
@ -3298,6 +3386,46 @@ gsi::Enum<db::PolygonToEdgeProcessor::EdgeMode> decl_EdgeMode ("db", "EdgeMode",
|
|||
// Inject the Region::EdgeMode declarations into Region:
|
||||
gsi::ClassExt<db::Region> inject_EdgeMode_in_Region (decl_EdgeMode.defs ());
|
||||
|
||||
gsi::Enum<db::zero_distance_mode> decl_ZeroDistanceMode ("db", "ZeroDistanceMode",
|
||||
gsi::enum_const ("NeverIncludeZeroDistance", db::NeverIncludeZeroDistance,
|
||||
"@brief Specifies that check functions should never include edges with zero distance.\n"
|
||||
"With this specification, the check functions will ignore edges which are collinear or touch."
|
||||
) +
|
||||
gsi::enum_const ("AlwaysIncludeZeroDistance", db::AlwaysIncludeZeroDistance,
|
||||
"@hide\n"
|
||||
"@brief Specifies that check functions should always include edges with zero distance\n"
|
||||
"This mode has little practical value.\n"
|
||||
) +
|
||||
gsi::enum_const ("IncludeZeroDistanceWhenTouching", db::IncludeZeroDistanceWhenTouching,
|
||||
"@brief Specifies that check functions should include edges when they touch\n"
|
||||
"With this specification, the check functions will also check edges if they share at least one common point. "
|
||||
"This is the mode that includes checking the 'kissing corner' cases. This mode is default for version 0.28.16 and later. "
|
||||
) +
|
||||
gsi::enum_const ("IncludeZeroDistanceWhenCollinearAndTouching", db::IncludeZeroDistanceWhenCollinearAndTouching,
|
||||
"@brief Specifies that check functions should include edges when they are collinear and touch\n"
|
||||
"With this specification, the check functions will also check edges if they share at least one common point and are collinear. "
|
||||
"This is the mode that includes checking the 'kissing corner' cases when the kissing edges are collinear. This mode was default up to version 0.28. "
|
||||
) +
|
||||
gsi::enum_const ("IncludeZeroDistanceWhenOverlapping", db::IncludeZeroDistanceWhenOverlapping,
|
||||
"@brief Specifies that check functions should include edges when they overlap\n"
|
||||
"With this specification, the check functions will also check edges which are collinear and share more than a single point. "
|
||||
"This is the mode that excludes the 'kissing corner' cases."
|
||||
),
|
||||
"@brief This class represents the zero_distance_mode type for \\Region#width and related checks.\n"
|
||||
"This mode determines how edges with zero distance are treated in the DRC checks. Formally these edges do neither represent "
|
||||
"a space other other relation as they do not face each other. There are three modes available to treat this boundary case: "
|
||||
"Ignore such edges (\\NeverIncludeZeroDistance) or only include them "
|
||||
"if they share at least one common point (\\IncludeZeroDistanceWhenTouching). The latter mode allows activating checks for "
|
||||
"the 'kissing corner' case and is the default mode in most checks."
|
||||
"\n"
|
||||
"This enum has been introduced in version 0.28.16."
|
||||
);
|
||||
|
||||
// Inject the Region::ZeroDistanceMode declarations into Region and Edges:
|
||||
// (Edges injection has to be done here because only here defs() is available)
|
||||
gsi::ClassExt<db::Region> inject_ZeroDistanceMode_in_Region (decl_ZeroDistanceMode.defs ());
|
||||
gsi::ClassExt<db::Edges> inject_ZeroDistanceMode_in_Edges (decl_ZeroDistanceMode.defs ());
|
||||
|
||||
gsi::Enum<db::PropertyConstraint> decl_PropertyConstraint ("db", "PropertyConstraint",
|
||||
gsi::enum_const ("IgnoreProperties", db::IgnoreProperties,
|
||||
"@brief Specifies to ignore properties\n"
|
||||
|
|
|
|||
|
|
@ -135,6 +135,19 @@ gsi::Class<db::TechnologyComponent> technology_component_decl ("db", "Technology
|
|||
|
||||
DB_PUBLIC gsi::Class<db::TechnologyComponent> &decl_dbTechnologyComponent () { return technology_component_decl; }
|
||||
|
||||
static void
|
||||
set_default_grid_list (db::Technology *tech, const std::vector<double> &grids)
|
||||
{
|
||||
std::string r;
|
||||
for (auto g = grids.begin (); g != grids.end (); ++g) {
|
||||
if (! r.empty ()) {
|
||||
r += ",";
|
||||
}
|
||||
r += tl::micron_to_string (*g);
|
||||
}
|
||||
tech->set_default_grids (r);
|
||||
}
|
||||
|
||||
gsi::Class<db::Technology> technology_decl ("db", "Technology",
|
||||
gsi::method ("name", &db::Technology::name,
|
||||
"@brief Gets the name of the technology"
|
||||
|
|
@ -218,6 +231,19 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
|
|||
gsi::method ("dbu=", &db::Technology::set_dbu, gsi::arg ("dbu"),
|
||||
"@brief Sets the default database unit\n"
|
||||
) +
|
||||
gsi::method ("default_grids", &db::Technology::default_grid_list,
|
||||
"@brief Gets the default grids\n"
|
||||
"\n"
|
||||
"See \\default_grids for details.\n"
|
||||
"\n"
|
||||
"This property has been introduced in version 0.28.17."
|
||||
) +
|
||||
gsi::method_ext ("default_grids=", &set_default_grid_list, gsi::arg ("grids"),
|
||||
"@brief Sets the default grids\n"
|
||||
"If not empty, this list replaces the global grid list for this technology.\n"
|
||||
"\n"
|
||||
"This property has been introduced in version 0.28.17."
|
||||
) +
|
||||
gsi::method ("layer_properties_file", &db::Technology::layer_properties_file,
|
||||
"@brief Gets the path of the layer properties file\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -51,139 +51,139 @@ TEST(1)
|
|||
TEST(2)
|
||||
{
|
||||
db::Edge output;
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 10), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 10), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;187,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,-50;187,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-87,-50;187,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-87,-50;0,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-94,-34;164,-77)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,0;50,-100)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(40,0;90,-100)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;145,-89)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;145,-89)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(120,0;120,-98)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;100,-100)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;80,-100)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-80,0;-80,-60)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;-45,-89)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,-50;100,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(50,-50;50,-50)");
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false);
|
||||
EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false);
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
db::Edge output;
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;200,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,-50;200,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-100,-50;200,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-100,-50;0,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-100,-33;200,-83)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,0;50,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(40,0;90,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;150,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;150,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(120,0;120,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;100,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;80,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-80,0;-80,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;-60,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(-100,0;-100,-100)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,-50;100,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(50,-50;50,-50)");
|
||||
EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), true);
|
||||
EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(190,-50;190,-50)");
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
db::Edge output;
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-50)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-50)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-50)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,-50;100,-67)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(0,0;50,-100)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(40,0;90,-100)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,0;100,-100)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;80,-100)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(80,0;0,-57)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(100,-50;100,-50)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true);
|
||||
EXPECT_EQ (output.to_string (), "(50,-50;50,-50)");
|
||||
EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false);
|
||||
EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false);
|
||||
}
|
||||
|
||||
TEST(5)
|
||||
|
|
@ -291,7 +291,7 @@ TEST(7)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,30;1,20)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
f.set_include_zero (false);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, 20)), &output);
|
||||
|
|
@ -300,7 +300,7 @@ TEST(7)
|
|||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_include_zero (true);
|
||||
f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 300), db::Point (0, -200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,110;0,-100)");
|
||||
|
|
@ -309,7 +309,7 @@ TEST(7)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,110;1,-100)");
|
||||
|
||||
f.set_metrics (db::Square);
|
||||
f.set_include_zero (true);
|
||||
f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,30;0,20)");
|
||||
|
|
@ -318,7 +318,7 @@ TEST(7)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,30;1,20)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
f.set_include_zero (false);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, 20)), &output);
|
||||
|
|
@ -327,7 +327,7 @@ TEST(7)
|
|||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_include_zero (true);
|
||||
f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 300), db::Point (0, -200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,110;0,-100)");
|
||||
|
|
@ -336,7 +336,7 @@ TEST(7)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,110;1,-100)");
|
||||
|
||||
f.set_metrics (db::Projection);
|
||||
f.set_include_zero (true);
|
||||
f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, -20)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,10;0,0)");
|
||||
|
|
@ -345,7 +345,7 @@ TEST(7)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,10;1,0)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, -20)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
f.set_include_zero (false);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 11)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, -20)), &output);
|
||||
|
|
@ -361,7 +361,7 @@ TEST(8_KissingCornerProblem)
|
|||
// if the projection is >0.
|
||||
|
||||
db::EdgeRelationFilter f (db::WidthRelation, 10);
|
||||
f.set_include_zero (false);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
db::EdgePair output;
|
||||
bool res;
|
||||
|
||||
|
|
@ -382,8 +382,39 @@ TEST(8_KissingCornerProblem)
|
|||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenOverlapping);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,40;0,100):(0,110;0,50)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f = db::EdgeRelationFilter (db::SpaceRelation, 10);
|
||||
f.set_include_zero (false);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
|
||||
f.set_metrics (db::Euclidian);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
|
|
@ -401,4 +432,188 @@ TEST(8_KissingCornerProblem)
|
|||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,10;0,0):(0,-10;0,0)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenOverlapping);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,40):(0,50;0,110)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
f.set_metrics (db::Euclidian);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
}
|
||||
|
||||
TEST(9_KissingCornerProblemSquareMetrics)
|
||||
{
|
||||
// The kissing corner problem is solved by allowing distance-0 width and space relations and checking them
|
||||
// if the projection is >0.
|
||||
|
||||
db::EdgeRelationFilter f (db::WidthRelation, 10);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
db::EdgePair output;
|
||||
bool res;
|
||||
|
||||
f.set_metrics (db::Square);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,90;0,100):(0,110;0,100)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,40;0,100):(0,110;0,50)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,0;0,-10)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f = db::EdgeRelationFilter (db::SpaceRelation, 10);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
|
||||
f.set_metrics (db::Square);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,90):(0,100;0,110)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,40):(0,50;0,110)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,10;0,0):(0,-10;0,0)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
}
|
||||
|
||||
TEST(10_KissingCornerProblemProjectionMetrics)
|
||||
{
|
||||
// The kissing corner problem is solved by allowing distance-0 width and space relations and checking them
|
||||
// if the projection is >0. It is not effective in projection metrics as there is no overlap.
|
||||
|
||||
db::EdgeRelationFilter f (db::WidthRelation, 10);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
db::EdgePair output;
|
||||
bool res;
|
||||
|
||||
f.set_metrics (db::Projection);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,50;0,100):(0,100;0,50)");
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f = db::EdgeRelationFilter (db::SpaceRelation, 10);
|
||||
f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching);
|
||||
|
||||
f.set_metrics (db::Projection);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, true);
|
||||
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,50):(0,50;0,100)");
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
|
||||
f.set_zero_distance_mode (db::NeverIncludeZeroDistance);
|
||||
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||
EXPECT_EQ (res, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
std::string text () const { return m_os.str (); }
|
||||
void clear () { m_os.str (std::string ()); }
|
||||
void dbu_differs (double dbu_a, double dbu_b);
|
||||
void layout_meta_info_differs (const std::string &, const tl::Variant &, const tl::Variant &);
|
||||
void layer_in_a_only (const db::LayerProperties &la);
|
||||
void layer_in_b_only (const db::LayerProperties &lb);
|
||||
void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb);
|
||||
|
|
@ -45,6 +46,7 @@ public:
|
|||
void cell_in_b_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib);
|
||||
void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib);
|
||||
void cell_meta_info_differs (const std::string &, const tl::Variant &, const tl::Variant &);
|
||||
void bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_inst_differences ();
|
||||
void instances_in_a (const std::vector <db::CellInstArrayWithProperties> &insts_a, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
|
|
@ -155,6 +157,12 @@ TestDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b)
|
|||
m_os << "layout_diff: database units differ " << dbu_a << " vs. " << dbu_b << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::layout_meta_info_differs (const std::string &name, const tl::Variant &va, const tl::Variant &vb)
|
||||
{
|
||||
m_os << "layout_diff: global meta info differs " << name << ": " << va.to_string () << " vs. " << vb.to_string () << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
|
|
@ -204,6 +212,12 @@ TestDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_index_
|
|||
m_cellname = cellname;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::cell_meta_info_differs (const std::string &name, const tl::Variant &va, const tl::Variant &vb)
|
||||
{
|
||||
m_os << "layout_diff: cell meta info differs for cell " << m_cellname << " - " << name << ": " << va.to_string () << " vs. " << vb.to_string () << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::begin_inst_differences ()
|
||||
{
|
||||
|
|
@ -1704,4 +1718,46 @@ TEST(8)
|
|||
);
|
||||
}
|
||||
|
||||
// meta info
|
||||
TEST(9)
|
||||
{
|
||||
db::Layout a;
|
||||
db::cell_index_type caa = a.add_cell ("A");
|
||||
db::cell_index_type cab = a.add_cell ("B");
|
||||
|
||||
db::Layout b;
|
||||
db::cell_index_type cba = b.add_cell ("A");
|
||||
db::cell_index_type cbb = b.add_cell ("B");
|
||||
|
||||
a.add_meta_info ("x", db::MetaInfo ("", 17.0, true));
|
||||
a.add_meta_info ("y", db::MetaInfo ("", -1.0, false)); // not persisted
|
||||
a.add_meta_info ("z", db::MetaInfo ("", -1.0, true));
|
||||
a.add_meta_info (caa, "a1", db::MetaInfo ("", "a", true));
|
||||
a.add_meta_info (caa, "a2", db::MetaInfo ("", 42, false)); // not persisted
|
||||
a.add_meta_info (caa, "a3", db::MetaInfo ("", 41, true));
|
||||
a.add_meta_info (cab, "b1", db::MetaInfo ("", "b", true));
|
||||
a.add_meta_info (cab, "b2", db::MetaInfo ("", 3, false)); // not persisted
|
||||
a.add_meta_info (cab, "b3", db::MetaInfo ("", "q", true));
|
||||
|
||||
b.add_meta_info ("x", db::MetaInfo ("", 21.0, true));
|
||||
b.add_meta_info ("y", db::MetaInfo ("", -1.0, true));
|
||||
b.add_meta_info (cba, "a1", db::MetaInfo ("", "aa", true));
|
||||
b.add_meta_info (cba, "a2", db::MetaInfo ("", 42, true));
|
||||
b.add_meta_info (cbb, "b1", db::MetaInfo ("", "bb", true));
|
||||
b.add_meta_info (cbb, "b2", db::MetaInfo ("", 3, true));
|
||||
|
||||
TestDifferenceReceiver r;
|
||||
bool eq = db::compare_layouts (a, b, db::layout_diff::f_verbose | db::layout_diff::f_with_meta, 0, r);
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: global meta info differs x: 17 vs. 21\n"
|
||||
"layout_diff: global meta info differs y: nil vs. -1\n"
|
||||
"layout_diff: global meta info differs z: -1 vs. nil\n"
|
||||
"layout_diff: cell meta info differs for cell A - a1: a vs. aa\n"
|
||||
"layout_diff: cell meta info differs for cell A - a2: nil vs. 42\n"
|
||||
"layout_diff: cell meta info differs for cell A - a3: 41 vs. nil\n"
|
||||
"layout_diff: cell meta info differs for cell B - b1: b vs. bb\n"
|
||||
"layout_diff: cell meta info differs for cell B - b2: nil vs. 3\n"
|
||||
"layout_diff: cell meta info differs for cell B - b3: q vs. nil\n"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ TEST(insert_vertex_convex)
|
|||
tris.insert_point (0.6, 0.5);
|
||||
tris.insert_point (0.7, 0.5);
|
||||
tris.insert_point (0.6, 0.4);
|
||||
EXPECT_EQ (tris.to_string (), "((0.2, 0.2), (0.2, 0.8), (0.6, 0.5)), ((0.7, 0.5), (0.6, 0.5), (0.2, 0.8)), ((0.6, 0.5), (0.6, 0.4), (0.2, 0.2)), ((0.6, 0.5), (0.7, 0.5), (0.6, 0.4))");
|
||||
EXPECT_EQ (tris.to_string (), "((0.2, 0.2), (0.2, 0.8), (0.6, 0.5)), ((0.2, 0.8), (0.7, 0.5), (0.6, 0.5)), ((0.6, 0.4), (0.6, 0.5), (0.7, 0.5)), ((0.6, 0.4), (0.2, 0.2), (0.6, 0.5))");
|
||||
EXPECT_EQ (tris.check(), true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
<title>DRC Reference: Global Functions</title>
|
||||
<keyword name="global"/>
|
||||
<p>
|
||||
Some functions are available on global level and can be used without any object.
|
||||
Most of them are convenience functions that basically act on some default object
|
||||
or provide function-like alternatives for the methods.
|
||||
</p>
|
||||
<h2-index/>
|
||||
<a name="angle"/><h2>"angle" - In universal DRC context: selects edges based on their orientation</h2>
|
||||
<keyword name="angle"/>
|
||||
|
|
@ -828,7 +833,7 @@ The following example selects all shapes which are rectangles and
|
|||
whose area is larger than 0.5 square micrometers:
|
||||
</p><p>
|
||||
<pre>
|
||||
out = in.drc(if_all(area > 0.5, rectangle))
|
||||
out = in.drc(if_all(area > 0.5, rectangles))
|
||||
</pre>
|
||||
</p><p>
|
||||
The condition expressions may be of any type (edges, edge pairs and polygons).
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
<title>DRC Reference: Layer Object</title>
|
||||
<keyword name="Layer"/>
|
||||
<p>
|
||||
The layer object represents a collection of polygons, edges or edge pairs.
|
||||
</p>
|
||||
<h2-index/>
|
||||
<a name="&"/><h2>"&" - Boolean AND operation</h2>
|
||||
<keyword name="&"/>
|
||||
|
|
@ -2929,7 +2932,45 @@ The following image shows the effect of the separation check (input1: red, input
|
|||
</tr>
|
||||
</table>
|
||||
</p><p>
|
||||
<h3>opposite and rectangle error filtering </h3>
|
||||
<h3>Touching shapes </h3>
|
||||
</p><p>
|
||||
Like <a href="#width">width</a> and <a href="#space">space</a>, the separation check also supports the "without_touching_corners" option.
|
||||
</p><p>
|
||||
This option will turn off errors that arise due to
|
||||
edges touching in one corner (the "kissing corners" configuration).
|
||||
By default, such edges will yield an error, as they
|
||||
form a zero-distance situation. With this option in place, no errors will be reported.
|
||||
</p><p>
|
||||
The following images illustrate the effect of the "without_touching_corners" option.
|
||||
The white line at the top of the bottom red shape is actually an edge pair indicating
|
||||
the zero-distance violation of the separation check:
|
||||
</p><p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="/images/drc_separation12.png"/></td>
|
||||
<td><img src="/images/drc_separation13.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p><p>
|
||||
Another option is "without_touching_edges" which turns off errors that arise
|
||||
at coincident edges. Formally such edges represent a zero-distance situation, hence
|
||||
are flagged by default. Turning off the check in this case can be helpful when
|
||||
separating a layer into two parts (e.g. thin/wide metal separation) and an error
|
||||
between touching regions is not desired.
|
||||
</p><p>
|
||||
The "without_touching_edges" option is a stronger version of "without_touching_corners" and
|
||||
makes sense only for two-layer checks.
|
||||
</p><p>
|
||||
The following images illustrate the effect of the "without_touching_edges" option:
|
||||
</p><p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="/images/drc_separation12.png"/></td>
|
||||
<td><img src="/images/drc_separation14.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p><p>
|
||||
<h3>Opposite and rectangle error filtering </h3>
|
||||
</p><p>
|
||||
The options for the separation check are those available for the <a href="#width">width</a> or <a href="#space">space</a>
|
||||
method plus opposite and rectangle error filtering.
|
||||
|
|
@ -3440,10 +3481,15 @@ each other is more or equal than min and less than max </li>
|
|||
but is more intuitive, as "projecting" is written with a condition, like
|
||||
"projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=".
|
||||
Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". </li>
|
||||
<li><b>transparent </b>: performs the check without shielding (polygon layers only) </li>
|
||||
<li><b>shielded </b>: performs the check with shielding (polygon layers only) </li>
|
||||
<li><b>without_touching_corners </b>: With this option present, touching corners (aka "kissing
|
||||
corners") will not yield errors. The default is to produce errors in these cases. </li>
|
||||
<li><b>without_touching_edges </b>: With this option present, coincident edges will not yield errors.
|
||||
This is a stronger version of "without_touching_corners" and makes sense only for two-layer checks
|
||||
or raw-mode input layers. It is listed here for completeness. </li>
|
||||
<li><b>transparent </b>: Performs the check without shielding (polygon layers only) </li>
|
||||
<li><b>shielded </b>: Performs the check with shielding (polygon layers only) </li>
|
||||
<li><b>props_eq </b>, <b>props_ne </b>, <b>props_copy </b>: (only props_copy applies to width check) -
|
||||
see "Properties constraints" below. </li>
|
||||
See "Properties constraints" below. </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
Note that without the angle_limit, acute corners will always be reported, since two
|
||||
|
|
@ -3544,6 +3590,22 @@ shape's properties to the output too:
|
|||
space_not_connected = metal1_nets.space(0.4.um, props_ne + props_copy)
|
||||
space_connected = metal1_nets.space(0.4.um, props_eq + props_copy)
|
||||
</pre>
|
||||
</p><p>
|
||||
<h3>Touching shapes </h3>
|
||||
</p><p>
|
||||
The "without_touching_corners" option will turn off errors that arise due to
|
||||
the "kissing corner" configuration (or "checkerboard pattern"). Formally
|
||||
this is a width violation across the diagonal, but when considering this
|
||||
configuration as disconnected boxes, no error should be reported.
|
||||
</p><p>
|
||||
The following images illustrate the effect of the "without_touching_corners" option:
|
||||
</p><p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="/images/drc_width5.png"/></td>
|
||||
<td><img src="/images/drc_width6.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<a name="with_angle"/><h2>"with_angle" - Selects edges by their angle</h2>
|
||||
<keyword name="with_angle"/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/0.28/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
|
|
@ -4,6 +4,8 @@
|
|||
<file alias="drc_width2.png">doc/images/drc_width2.png</file>
|
||||
<file alias="drc_width3.png">doc/images/drc_width3.png</file>
|
||||
<file alias="drc_width4.png">doc/images/drc_width4.png</file>
|
||||
<file alias="drc_width5.png">doc/images/drc_width5.png</file>
|
||||
<file alias="drc_width6.png">doc/images/drc_width6.png</file>
|
||||
<file alias="drc_width1u.png">doc/images/drc_width1u.png</file>
|
||||
<file alias="drc_width2u.png">doc/images/drc_width2u.png</file>
|
||||
<file alias="drc_width3u.png">doc/images/drc_width3u.png</file>
|
||||
|
|
@ -29,6 +31,9 @@
|
|||
<file alias="drc_separation9.png">doc/images/drc_separation9.png</file>
|
||||
<file alias="drc_separation10.png">doc/images/drc_separation10.png</file>
|
||||
<file alias="drc_separation11.png">doc/images/drc_separation11.png</file>
|
||||
<file alias="drc_separation12.png">doc/images/drc_separation12.png</file>
|
||||
<file alias="drc_separation13.png">doc/images/drc_separation13.png</file>
|
||||
<file alias="drc_separation14.png">doc/images/drc_separation14.png</file>
|
||||
<file alias="drc_raw1.png">doc/images/drc_raw1.png</file>
|
||||
<file alias="drc_raw2.png">doc/images/drc_raw2.png</file>
|
||||
<file alias="drc_raw3.png">doc/images/drc_raw3.png</file>
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ module DRC
|
|||
# whose area is larger than 0.5 square micrometers:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(if_all(area > 0.5, rectangle))
|
||||
# out = in.drc(if_all(area > 0.5, rectangles))
|
||||
# @/code
|
||||
#
|
||||
# The condition expressions may be of any type (edges, edge pairs and polygons).
|
||||
|
|
@ -1485,6 +1485,7 @@ CODE
|
|||
shielded = nil
|
||||
opposite_filter = RBA::Region::NoOppositeFilter
|
||||
rect_filter = RBA::Region::NoRectFilter
|
||||
zd_mode = RBA::Region::IncludeZeroDistanceWhenTouching
|
||||
|
||||
n = 1
|
||||
args.each do |a|
|
||||
|
|
@ -1492,6 +1493,10 @@ CODE
|
|||
metrics = a.value
|
||||
elsif a.is_a?(DRCWholeEdges)
|
||||
whole_edges = a.value
|
||||
elsif a.is_a?(DRCPropertiesConstraint)
|
||||
prop_constraint = a.value
|
||||
elsif a.is_a?(DRCZeroDistanceMode)
|
||||
zd_mode = a.value
|
||||
elsif a.is_a?(DRCOppositeErrorFilter)
|
||||
opposite_filter = a.value
|
||||
elsif a.is_a?(DRCRectangleErrorFilter)
|
||||
|
|
@ -1523,6 +1528,8 @@ CODE
|
|||
elsif rect_filter != RBA::Region::NoRectFilter
|
||||
raise("A rectangle error filter cannot be used with this check")
|
||||
end
|
||||
|
||||
args << zd_mode
|
||||
|
||||
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
||||
other && raise("No other layer must be specified for a single-layer check")
|
||||
|
|
|
|||
|
|
@ -362,6 +362,18 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
def without_touching_corners(f = true)
|
||||
self._context("without_touching_corners") do
|
||||
DRCZeroDistanceMode::new(f ? RBA::Region::IncludeZeroDistanceWhenOverlapping : RBA::Region::IncludeZeroDistanceWhenTouching)
|
||||
end
|
||||
end
|
||||
|
||||
def without_touching_edges(f = true)
|
||||
self._context("without_touching_edges") do
|
||||
DRCZeroDistanceMode::new(f ? RBA::Region::NeverIncludeZeroDistance : RBA::Region::IncludeZeroDistanceWhenTouching)
|
||||
end
|
||||
end
|
||||
|
||||
def euclidian
|
||||
DRCMetrics::new(RBA::Region::Euclidian)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3737,10 +3737,15 @@ CODE
|
|||
# but is more intuitive, as "projecting" is written with a condition, like
|
||||
# "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=".
|
||||
# Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". @/li
|
||||
# @li @b transparent @/b: performs the check without shielding (polygon layers only) @/li
|
||||
# @li @b shielded @/b: performs the check with shielding (polygon layers only) @/li
|
||||
# @li @b without_touching_corners @/b: With this option present, touching corners (aka "kissing
|
||||
# corners") will not yield errors. The default is to produce errors in these cases. @/li
|
||||
# @li @b without_touching_edges @/b: With this option present, coincident edges will not yield errors.
|
||||
# This is a stronger version of "without_touching_corners" and makes sense only for two-layer checks
|
||||
# or raw-mode input layers. It is listed here for completeness. @/li
|
||||
# @li @b transparent @/b: Performs the check without shielding (polygon layers only) @/li
|
||||
# @li @b shielded @/b: Performs the check with shielding (polygon layers only) @/li
|
||||
# @li @b props_eq @/b, @b props_ne @/b, @b props_copy @/b: (only props_copy applies to width check) -
|
||||
# see "Properties constraints" below. @/li
|
||||
# See "Properties constraints" below. @/li
|
||||
# @/ul
|
||||
#
|
||||
# Note that without the angle_limit, acute corners will always be reported, since two
|
||||
|
|
@ -3842,6 +3847,21 @@ CODE
|
|||
# space_connected = metal1_nets.space(0.4.um, props_eq + props_copy)
|
||||
# @/code
|
||||
#
|
||||
# @h3 Touching shapes @/h3
|
||||
#
|
||||
# The "without_touching_corners" option will turn off errors that arise due to
|
||||
# the "kissing corner" configuration (or "checkerboard pattern"). Formally
|
||||
# this is a width violation across the diagonal, but when considering this
|
||||
# configuration as disconnected boxes, no error should be reported.
|
||||
#
|
||||
# The following images illustrate the effect of the "without_touching_corners" option:
|
||||
#
|
||||
# @table
|
||||
# @tr
|
||||
# @td @img(/images/drc_width5.png) @/td
|
||||
# @td @img(/images/drc_width6.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name space
|
||||
|
|
@ -3962,7 +3982,45 @@ CODE
|
|||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# @h3 opposite and rectangle error filtering @/h3
|
||||
# @h3 Touching shapes @/h3
|
||||
#
|
||||
# Like \width and \space, the separation check also supports the "without_touching_corners" option.
|
||||
#
|
||||
# This option will turn off errors that arise due to
|
||||
# edges touching in one corner (the "kissing corners" configuration).
|
||||
# By default, such edges will yield an error, as they
|
||||
# form a zero-distance situation. With this option in place, no errors will be reported.
|
||||
#
|
||||
# The following images illustrate the effect of the "without_touching_corners" option.
|
||||
# The white line at the top of the bottom red shape is actually an edge pair indicating
|
||||
# the zero-distance violation of the separation check:
|
||||
#
|
||||
# @table
|
||||
# @tr
|
||||
# @td @img(/images/drc_separation12.png) @/td
|
||||
# @td @img(/images/drc_separation13.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# Another option is "without_touching_edges" which turns off errors that arise
|
||||
# at coincident edges. Formally such edges represent a zero-distance situation, hence
|
||||
# are flagged by default. Turning off the check in this case can be helpful when
|
||||
# separating a layer into two parts (e.g. thin/wide metal separation) and an error
|
||||
# between touching regions is not desired.
|
||||
#
|
||||
# The "without_touching_edges" option is a stronger version of "without_touching_corners" and
|
||||
# makes sense only for two-layer checks.
|
||||
#
|
||||
# The following images illustrate the effect of the "without_touching_edges" option:
|
||||
#
|
||||
# @table
|
||||
# @tr
|
||||
# @td @img(/images/drc_separation12.png) @/td
|
||||
# @td @img(/images/drc_separation14.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# @h3 Opposite and rectangle error filtering @/h3
|
||||
#
|
||||
# The options for the separation check are those available for the \width or \space
|
||||
# method plus opposite and rectangle error filtering.
|
||||
|
|
@ -4171,6 +4229,7 @@ CODE
|
|||
opposite_filter = RBA::Region::NoOppositeFilter
|
||||
rect_filter = RBA::Region::NoRectFilter
|
||||
prop_constraint = RBA::Region::IgnoreProperties
|
||||
zd_mode = RBA::Region::IncludeZeroDistanceWhenTouching
|
||||
|
||||
n = 1
|
||||
args.each do |a|
|
||||
|
|
@ -4182,6 +4241,8 @@ CODE
|
|||
negative = true
|
||||
elsif a.is_a?(DRCPropertiesConstraint)
|
||||
prop_constraint = a.value
|
||||
elsif a.is_a?(DRCZeroDistanceMode)
|
||||
zd_mode = a.value
|
||||
elsif a.is_a?(DRCOppositeErrorFilter)
|
||||
opposite_filter = a.value
|
||||
elsif a.is_a?(DRCRectangleErrorFilter)
|
||||
|
|
@ -4235,6 +4296,8 @@ CODE
|
|||
raise("A rectangle error filter can only be used for polygon layers")
|
||||
end
|
||||
|
||||
args << zd_mode
|
||||
|
||||
border = (metrics == RBA::Region::Square ? value * 1.5 : value)
|
||||
|
||||
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
||||
|
|
|
|||
|
|
@ -702,7 +702,8 @@ module DRC
|
|||
@l2n = RBA::LayoutToNetlist::new(@engine._dss)
|
||||
else
|
||||
layout = @engine.source.layout
|
||||
@l2n = RBA::LayoutToNetlist::new(layout.top_cell.name, layout.dbu)
|
||||
cell_name = @engine.source.cell_name
|
||||
@l2n = RBA::LayoutToNetlist::new(cell_name, layout.dbu)
|
||||
end
|
||||
|
||||
@l2n.name = "DRC"
|
||||
|
|
|
|||
|
|
@ -103,6 +103,16 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
# A wrapper for the "zero distance mode" for
|
||||
# the DRC functions. The purpose of this class
|
||||
# is to identify the value by the class.
|
||||
class DRCZeroDistanceMode
|
||||
attr_accessor :value
|
||||
def initialize(v)
|
||||
self.value = v
|
||||
end
|
||||
end
|
||||
|
||||
# A wrapper for the "as_dots" or "as_boxes" flag for
|
||||
# some DRC functions. The purpose of this class
|
||||
# is to identify the value by the class.
|
||||
|
|
|
|||
|
|
@ -1617,6 +1617,62 @@ TEST(89_deep_with_mag_cop_size_aniso)
|
|||
run_test (_this, "89", true);
|
||||
}
|
||||
|
||||
TEST(90_zero_distance_mode)
|
||||
{
|
||||
run_test (_this, "90", false);
|
||||
}
|
||||
|
||||
TEST(90d_zero_distance_mode)
|
||||
{
|
||||
run_test (_this, "90", true);
|
||||
}
|
||||
|
||||
TEST(91_zero_distance_mode)
|
||||
{
|
||||
run_test (_this, "91", false);
|
||||
}
|
||||
|
||||
TEST(91d_zero_distance_mode)
|
||||
{
|
||||
run_test (_this, "91", true);
|
||||
}
|
||||
|
||||
TEST(92_issue1594_dual_top)
|
||||
{
|
||||
std::string rs = tl::testdata ();
|
||||
rs += "/drc/issue_1594.drc";
|
||||
|
||||
std::string input = tl::testdata ();
|
||||
input += "/drc/issue_1594.gds";
|
||||
|
||||
std::string au = tl::testdata ();
|
||||
au += "/drc/issue_1594_au.cir";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.cir");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$drc_force_gc = true\n"
|
||||
"$drc_test_source = '%s'\n"
|
||||
"$drc_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro drc;
|
||||
drc.load_from (rs);
|
||||
EXPECT_EQ (drc.run (), 0);
|
||||
|
||||
// verify
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output, au);
|
||||
}
|
||||
|
||||
TEST(100_edge_interaction_with_count)
|
||||
{
|
||||
run_test (_this, "100", false);
|
||||
|
|
|
|||
|
|
@ -548,6 +548,23 @@
|
|||
<header>layWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>lib_cbx</tabstop>
|
||||
<tabstop>browse_pb</tabstop>
|
||||
<tabstop>cell_le</tabstop>
|
||||
<tabstop>place_origin_cb</tabstop>
|
||||
<tabstop>scale_le</tabstop>
|
||||
<tabstop>angle_le</tabstop>
|
||||
<tabstop>mirror_cbx</tabstop>
|
||||
<tabstop>array_grp</tabstop>
|
||||
<tabstop>rows_le</tabstop>
|
||||
<tabstop>columns_le</tabstop>
|
||||
<tabstop>row_x_le</tabstop>
|
||||
<tabstop>row_y_le</tabstop>
|
||||
<tabstop>column_x_le</tabstop>
|
||||
<tabstop>column_y_le</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../icons/icons.qrc"/>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QScrollBar>
|
||||
#include <QScrollArea>
|
||||
#include <QToolButton>
|
||||
|
||||
namespace edt
|
||||
{
|
||||
|
|
@ -294,32 +296,32 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
mp_parameters_area = new QScrollArea (this);
|
||||
mp_parameters_area->setFrameShape (QFrame::NoFrame);
|
||||
mp_parameters_area->setWidgetResizable (true);
|
||||
QGridLayout *frame_layout = dynamic_cast<QGridLayout *> (QFrame::layout ());
|
||||
frame_layout->addWidget (mp_parameters_area, 2, 0, 1, 1);
|
||||
frame_layout->setRowStretch (2, 1);
|
||||
|
||||
QFrame *fi = new QFrame (mp_parameters_area);
|
||||
QWidget *inner_frame = fi;
|
||||
fi->setFrameShape (QFrame::NoFrame);
|
||||
mp_main_frame = new QFrame (mp_parameters_area);
|
||||
mp_main_frame->setFrameShape (QFrame::NoFrame);
|
||||
setFrameShape (QFrame::NoFrame);
|
||||
|
||||
QGridLayout *inner_grid = new QGridLayout (inner_frame);
|
||||
inner_frame->setLayout (inner_grid);
|
||||
QGridLayout *main_grid = new QGridLayout (mp_main_frame);
|
||||
mp_main_frame->setLayout (main_grid);
|
||||
if (m_dense) {
|
||||
inner_grid->setContentsMargins (4, 4, 4, 4);
|
||||
inner_grid->setHorizontalSpacing (6);
|
||||
inner_grid->setVerticalSpacing (2);
|
||||
main_grid->setContentsMargins (4, 4, 4, 4);
|
||||
main_grid->setHorizontalSpacing (6);
|
||||
main_grid->setVerticalSpacing (2);
|
||||
}
|
||||
|
||||
QWidget *main_frame = inner_frame;
|
||||
QGridLayout *main_grid = inner_grid;
|
||||
|
||||
if (! mp_pcell_decl) {
|
||||
mp_parameters_area->setWidget (main_frame);
|
||||
mp_parameters_area->setWidget (mp_main_frame);
|
||||
update_current_parameters ();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget *inner_frame = mp_main_frame;
|
||||
QGridLayout *inner_grid = main_grid;
|
||||
|
||||
int main_row = 0;
|
||||
int row = 0;
|
||||
std::string group_title;
|
||||
|
|
@ -362,7 +364,8 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
if (! gt.empty ()) {
|
||||
|
||||
// create a new group
|
||||
QGroupBox *gb = new QGroupBox (main_frame);
|
||||
QGroupBox *gb = new QGroupBox (mp_main_frame);
|
||||
mp_groups.push_back (gb);
|
||||
gb->setTitle (tl::to_qstring (gt));
|
||||
main_grid->addWidget (gb, main_row, 0, 1, 3);
|
||||
|
||||
|
|
@ -382,7 +385,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
// back to the main group
|
||||
inner_grid = main_grid;
|
||||
inner_frame = main_frame;
|
||||
inner_frame = mp_main_frame;
|
||||
row = main_row;
|
||||
|
||||
}
|
||||
|
|
@ -427,6 +430,9 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
hb->setContentsMargins (0, 0, 0, 0);
|
||||
f->setLayout (hb);
|
||||
f->setFrameShape (QFrame::NoFrame);
|
||||
QSizePolicy sp = f->sizePolicy ();
|
||||
sp.setHorizontalStretch (1);
|
||||
f->setSizePolicy (sp);
|
||||
|
||||
QLineEdit *le = new QLineEdit (f);
|
||||
hb->addWidget (le);
|
||||
|
|
@ -434,9 +440,13 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
le->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
m_widgets.push_back (le);
|
||||
|
||||
QLabel *ul = new QLabel (f);
|
||||
hb->addWidget (ul, 1);
|
||||
ul->setText (tl::to_qstring (p->get_unit ()));
|
||||
if (! p->get_unit ().empty ()) {
|
||||
QLabel *ul = new QLabel (f);
|
||||
hb->addWidget (ul, 1);
|
||||
ul->setText (tl::to_qstring (p->get_unit ()));
|
||||
}
|
||||
|
||||
hb->addStretch (1);
|
||||
|
||||
inner_grid->addWidget (f, row, 2);
|
||||
m_all_widgets.back ().push_back (f);
|
||||
|
|
@ -450,7 +460,10 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
QPushButton *pb = new QPushButton (inner_frame);
|
||||
pb->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
pb->setText (tl::to_qstring (description));
|
||||
pb->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
QSizePolicy sp = pb->sizePolicy ();
|
||||
sp.setHorizontalPolicy (QSizePolicy::Fixed);
|
||||
sp.setHorizontalStretch (1);
|
||||
pb->setSizePolicy (sp);
|
||||
m_widgets.push_back (pb);
|
||||
|
||||
inner_grid->addWidget (pb, row, 2);
|
||||
|
|
@ -466,6 +479,9 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
{
|
||||
QLineEdit *le = new QLineEdit (inner_frame);
|
||||
le->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
QSizePolicy sp = le->sizePolicy ();
|
||||
sp.setHorizontalStretch (1);
|
||||
le->setSizePolicy (sp);
|
||||
m_widgets.push_back (le);
|
||||
inner_grid->addWidget (le, row, 2);
|
||||
m_all_widgets.back ().push_back (le);
|
||||
|
|
@ -476,13 +492,29 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
case db::PCellParameterDeclaration::t_layer:
|
||||
{
|
||||
lay::LayerSelectionComboBox *ly = new lay::LayerSelectionComboBox (inner_frame);
|
||||
QFrame *f = new QFrame (inner_frame);
|
||||
QHBoxLayout *hb = new QHBoxLayout (f);
|
||||
hb->setContentsMargins (0, 0, 0, 0);
|
||||
f->setLayout (hb);
|
||||
f->setFrameShape (QFrame::NoFrame);
|
||||
QSizePolicy sp = f->sizePolicy ();
|
||||
sp.setHorizontalStretch (1);
|
||||
f->setSizePolicy (sp);
|
||||
|
||||
lay::LayerSelectionComboBox *ly = new lay::LayerSelectionComboBox (f);
|
||||
hb->addWidget (ly);
|
||||
ly->set_no_layer_available (true);
|
||||
ly->set_view (mp_view, m_cv_index, true /*all layers*/);
|
||||
ly->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
sp = ly->sizePolicy ();
|
||||
sp.setHorizontalPolicy (QSizePolicy::Fixed);
|
||||
ly->setSizePolicy (sp);
|
||||
m_widgets.push_back (ly);
|
||||
inner_grid->addWidget (ly, row, 2);
|
||||
m_all_widgets.back ().push_back (ly);
|
||||
|
||||
hb->addStretch (1);
|
||||
|
||||
inner_grid->addWidget (f, row, 2);
|
||||
m_all_widgets.back ().push_back (f);
|
||||
|
||||
connect (ly, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
|
||||
}
|
||||
|
|
@ -492,7 +524,9 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
{
|
||||
QCheckBox *cbx = new QCheckBox (inner_frame);
|
||||
// this makes the checkbox not stretch over the full width - better when navigating with tab
|
||||
cbx->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred));
|
||||
QSizePolicy sp = cbx->sizePolicy ();
|
||||
sp.setHorizontalStretch (1);
|
||||
cbx->setSizePolicy (sp);
|
||||
cbx->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
m_widgets.push_back (cbx);
|
||||
inner_grid->addWidget (cbx, row, 2);
|
||||
|
|
@ -509,8 +543,20 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
} else {
|
||||
|
||||
QComboBox *cb = new QComboBox (inner_frame);
|
||||
QFrame *f = new QFrame (inner_frame);
|
||||
QHBoxLayout *hb = new QHBoxLayout (f);
|
||||
hb->setContentsMargins (0, 0, 0, 0);
|
||||
f->setLayout (hb);
|
||||
f->setFrameShape (QFrame::NoFrame);
|
||||
QSizePolicy sp = f->sizePolicy ();
|
||||
sp.setHorizontalStretch (1);
|
||||
f->setSizePolicy (sp);
|
||||
|
||||
QComboBox *cb = new QComboBox (f);
|
||||
hb->addWidget (cb);
|
||||
cb->setObjectName (tl::to_qstring (p->get_name ()));
|
||||
cb->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
cb->setSizeAdjustPolicy (QComboBox::AdjustToContents);
|
||||
|
||||
int i = 0;
|
||||
for (std::vector<tl::Variant>::const_iterator c = p->get_choices ().begin (); c != p->get_choices ().end (); ++c, ++i) {
|
||||
|
|
@ -523,21 +569,25 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
connect (cb, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
|
||||
|
||||
cb->setMinimumContentsLength (30);
|
||||
cb->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
|
||||
m_widgets.push_back (cb);
|
||||
inner_grid->addWidget (cb, row, 2);
|
||||
m_all_widgets.back ().push_back (cb);
|
||||
|
||||
hb->addStretch (1);
|
||||
|
||||
inner_grid->addWidget (f, row, 2);
|
||||
m_all_widgets.back ().push_back (f);
|
||||
|
||||
}
|
||||
|
||||
++row;
|
||||
if (inner_frame == main_frame) {
|
||||
if (inner_frame == mp_main_frame) {
|
||||
++main_row;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// adds some default buffer space
|
||||
main_grid->setRowStretch (main_row, 1);
|
||||
|
||||
// initial callback
|
||||
|
||||
try {
|
||||
|
|
@ -556,8 +606,8 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
|
|||
|
||||
update_widgets_from_states (m_states);
|
||||
|
||||
mp_parameters_area->setWidget (main_frame);
|
||||
main_frame->show ();
|
||||
mp_parameters_area->setWidget (mp_main_frame);
|
||||
mp_main_frame->show ();
|
||||
|
||||
update_current_parameters ();
|
||||
}
|
||||
|
|
@ -944,15 +994,15 @@ PCellParametersPage::update_widgets_from_states (const db::ParameterStates &stat
|
|||
break;
|
||||
case db::ParameterState::InfoIcon:
|
||||
m_icon_widgets [i]->setPixmap (info);
|
||||
m_icon_widgets [i]->show ();
|
||||
m_icon_widgets [i]->setVisible (ps.is_visible ());
|
||||
break;
|
||||
case db::ParameterState::WarningIcon:
|
||||
m_icon_widgets [i]->setPixmap (warning);
|
||||
m_icon_widgets [i]->show ();
|
||||
m_icon_widgets [i]->setVisible (ps.is_visible ());
|
||||
break;
|
||||
case db::ParameterState::ErrorIcon:
|
||||
m_icon_widgets [i]->setPixmap (error);
|
||||
m_icon_widgets [i]->show ();
|
||||
m_icon_widgets [i]->setVisible (ps.is_visible ());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -961,6 +1011,12 @@ PCellParametersPage::update_widgets_from_states (const db::ParameterStates &stat
|
|||
}
|
||||
|
||||
set_parameters_internal (states, lazy_evaluation ());
|
||||
|
||||
// QGridLayouts are bad in handling nested QFrame (or QGroupBox) with their own layouts,
|
||||
// so we help a little here:
|
||||
for (auto g = mp_groups.begin (); g != mp_groups.end (); ++g) {
|
||||
(*g)->resize (QSize ((*g)->width (), (*g)->sizeHint ().height ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@
|
|||
#include "tlDeferredExecution.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QScrollArea>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QCheckBox>
|
||||
|
||||
class QGroupBox;
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class QToolButton;
|
||||
class QScrollArea;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -150,6 +152,8 @@ private slots:
|
|||
private:
|
||||
lay::Dispatcher *mp_dispatcher;
|
||||
QScrollArea *mp_parameters_area;
|
||||
QFrame *mp_main_frame;
|
||||
std::vector<QGroupBox *> mp_groups;
|
||||
QLabel *mp_error_label;
|
||||
QLabel *mp_error_icon;
|
||||
QLabel *mp_changed_label;
|
||||
|
|
|
|||
|
|
@ -6,25 +6,163 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>604</width>
|
||||
<height>498</height>
|
||||
<width>625</width>
|
||||
<height>587</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="11" column="0" colspan="4">
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="group_le"/>
|
||||
</item>
|
||||
<item row="7" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Database
|
||||
unit</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="4">
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="Line" name="line_2">
|
||||
<item row="4" column="3">
|
||||
<widget class="QToolButton" name="browse_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1" rowspan="2" colspan="3">
|
||||
<widget class="QListWidget" name="libs_lw">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>(Use the rename button to change this)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="desc_le"/>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>The base path is used to locate auxiliary files if those are specified with a relative path. If none is specified, the default path is used. The default path is the one from which a technology was imported.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="3">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="dbu_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>µm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="base_path_le"/>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>(Used for creating tech groups)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="libs_lbl">
|
||||
<property name="text">
|
||||
<string>Technology
|
||||
specific
|
||||
libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Grids</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -42,24 +180,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Database
|
||||
unit</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
|
|
@ -74,6 +194,53 @@ unit</string>
|
|||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="3">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="grids_le"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>µm (g1,g2,...)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="1" colspan="3">
|
||||
<widget class="QGroupBox" name="lyp_grp">
|
||||
<property name="title">
|
||||
<string>Load layer properties file</string>
|
||||
|
|
@ -127,10 +294,7 @@ unit</string>
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="desc_le"/>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Layer
|
||||
|
|
@ -141,6 +305,13 @@ properties</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="name_le">
|
||||
<property name="enabled">
|
||||
|
|
@ -148,75 +319,13 @@ properties</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>(Use the rename button to change this)</string>
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QToolButton" name="browse_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1" rowspan="2" colspan="3">
|
||||
<widget class="QListWidget" name="libs_lw">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="3">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="dbu_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>µm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
|
|
@ -224,7 +333,7 @@ properties</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="4">
|
||||
<item row="12" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
|
@ -240,55 +349,10 @@ properties</string>
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="11" column="1" colspan="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>The base path is used to locate auxiliary files if those are specified with a relative path. If none is specified, the default path is used. The default path is the one from which a technology was imported.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="base_path_le"/>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="libs_lbl">
|
||||
<property name="text">
|
||||
<string>Technology
|
||||
specific
|
||||
libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="group_le"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>(Used for creating tech groups)</string>
|
||||
<string>These grids are available for selection from the "View" menu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -458,6 +458,12 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled)
|
|||
connect (&lay::LayoutHandle::file_watcher (), SIGNAL (fileChanged (const QString &)), this, SLOT (file_changed (const QString &)));
|
||||
connect (&lay::LayoutHandle::file_watcher (), SIGNAL (fileRemoved (const QString &)), this, SLOT (file_removed (const QString &)));
|
||||
|
||||
lay::TechnologyController *tc = lay::TechnologyController::instance ();
|
||||
if (tc) {
|
||||
connect (tc, SIGNAL (active_technology_changed ()), this, SLOT (technology_changed ()));
|
||||
connect (tc, SIGNAL (technologies_edited ()), this, SLOT (technology_changed ()));
|
||||
}
|
||||
|
||||
// make the main window accept drops
|
||||
setAcceptDrops (true);
|
||||
}
|
||||
|
|
@ -555,6 +561,31 @@ MainWindow::init_menu ()
|
|||
}
|
||||
}
|
||||
|
||||
static std::string tech_string_from_name (const std::string &tn)
|
||||
{
|
||||
if (tn.empty ()) {
|
||||
return tl::to_string (QObject::tr ("(Default)"));
|
||||
} else {
|
||||
return tn;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::technology_changed ()
|
||||
{
|
||||
lay::TechnologyController *tc = lay::TechnologyController::instance ();
|
||||
if (tc) {
|
||||
if (tc->active_technology ()) {
|
||||
tech_message (tech_string_from_name (tc->active_technology ()->name ()));
|
||||
} else {
|
||||
tech_message (std::string ());
|
||||
}
|
||||
}
|
||||
|
||||
m_default_grids_updated = true; // potentially ...
|
||||
dm_do_update_menu ();
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::dock_widget_visibility_changed (bool visible)
|
||||
{
|
||||
|
|
@ -908,36 +939,7 @@ MainWindow::config_finalize ()
|
|||
|
||||
// Update the default grids menu if necessary
|
||||
if (m_default_grids_updated) {
|
||||
|
||||
m_default_grids_updated = false;
|
||||
|
||||
std::vector<std::string> group = menu ()->group ("default_grids_group");
|
||||
|
||||
for (std::vector<std::string>::const_iterator t = group.begin (); t != group.end (); ++t) {
|
||||
std::vector<std::string> items = menu ()->items (*t);
|
||||
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
||||
menu ()->delete_item (*i);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
for (std::vector<double>::const_iterator g = m_default_grids.begin (); g != m_default_grids.end (); ++g, ++i) {
|
||||
|
||||
std::string name = "default_grid_" + tl::to_string (i);
|
||||
|
||||
lay::Action *ga = new lay::ConfigureAction (tl::to_string (*g) + tl::to_string (QObject::tr (" um")), cfg_grid, tl::to_string (*g));
|
||||
ga->set_checkable (true);
|
||||
ga->set_checked (fabs (*g - m_grid_micron) < 1e-10);
|
||||
|
||||
for (std::vector<std::string>::const_iterator t = group.begin (); t != group.end (); ++t) {
|
||||
menu ()->insert_item (*t + ".end", name, ga);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// re-apply key bindings for the default grids
|
||||
apply_key_bindings ();
|
||||
|
||||
dm_do_update_menu ();
|
||||
}
|
||||
|
||||
// make the changes visible in the setup form if the form is visible
|
||||
|
|
@ -1489,7 +1491,11 @@ MainWindow::closeEvent (QCloseEvent *event)
|
|||
END_PROTECTED
|
||||
}
|
||||
|
||||
event->ignore ();
|
||||
if (! m_exited) {
|
||||
event->ignore ();
|
||||
} else {
|
||||
event->accept ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -4038,6 +4044,57 @@ MainWindow::menu_changed ()
|
|||
void
|
||||
MainWindow::do_update_menu ()
|
||||
{
|
||||
if (m_default_grids_updated) {
|
||||
|
||||
m_default_grids_updated = false;
|
||||
|
||||
const std::vector<double> *grids = &m_default_grids;
|
||||
std::vector<double> tech_grids;
|
||||
lay::TechnologyController *tc = lay::TechnologyController::instance ();
|
||||
if (tc && tc->active_technology ()) {
|
||||
tech_grids = tc->active_technology ()->default_grid_list ();
|
||||
if (! tech_grids.empty ()) {
|
||||
grids = &tech_grids;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> group = menu ()->group ("default_grids_group");
|
||||
|
||||
for (std::vector<std::string>::const_iterator t = group.begin (); t != group.end (); ++t) {
|
||||
std::vector<std::string> items = menu ()->items (*t);
|
||||
for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
|
||||
menu ()->delete_item (*i);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
for (std::vector<double>::const_iterator g = grids->begin (); g != grids->end (); ++g, ++i) {
|
||||
|
||||
std::string name = "default_grid_" + tl::to_string (i);
|
||||
|
||||
std::string gs;
|
||||
if (*g < 0.4) {
|
||||
// pick nm units below 400nm
|
||||
gs = tl::to_string (*g * 1000.0) + tl::to_string (QObject::tr (" nm"));
|
||||
} else {
|
||||
gs = tl::to_string (*g) + tl::to_string (QObject::tr (" um"));
|
||||
}
|
||||
|
||||
lay::Action *ga = new lay::ConfigureAction (gs, cfg_grid, tl::to_string (*g));
|
||||
ga->set_checkable (true);
|
||||
ga->set_checked (fabs (*g - m_grid_micron) < 1e-10);
|
||||
|
||||
for (std::vector<std::string>::const_iterator t = group.begin (); t != group.end (); ++t) {
|
||||
menu ()->insert_item (*t + ".end", name, ga);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// re-apply key bindings for the default grids
|
||||
apply_key_bindings ();
|
||||
|
||||
}
|
||||
|
||||
menu ()->build (menuBar (), mp_tool_bar);
|
||||
lay::GuiApplication *app = dynamic_cast<lay::GuiApplication *> (qApp);
|
||||
if (app) {
|
||||
|
|
|
|||
|
|
@ -697,6 +697,7 @@ protected slots:
|
|||
void message_timer ();
|
||||
void edits_enabled_changed ();
|
||||
void menu_needs_update ();
|
||||
void technology_changed ();
|
||||
|
||||
void file_changed_timer ();
|
||||
void file_changed (const QString &path);
|
||||
|
|
|
|||
|
|
@ -179,6 +179,10 @@ SaltController::install_packages (const std::vector<std::string> &packages, bool
|
|||
{
|
||||
lay::SaltDownloadManager manager;
|
||||
|
||||
// This method is used for command-line installation ignoring the package index.
|
||||
// Hence we have to download package information here:
|
||||
manager.set_always_download_package_information (true);
|
||||
|
||||
lay::Salt salt_mine;
|
||||
if (! m_salt_mine_url.empty ()) {
|
||||
tl::log << tl::to_string (tr ("Downloading package repository from %1").arg (tl::to_qstring (m_salt_mine_url)));
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ ConfirmationDialog::finish ()
|
|||
|
||||
SaltDownloadManager::SaltDownloadManager ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
m_always_download_package_information = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -344,7 +344,7 @@ SaltDownloadManager::fetch_missing (const lay::Salt &salt, const lay::Salt &salt
|
|||
|
||||
}
|
||||
|
||||
if (! p->downloaded && salt_mine.download_package_information ()) {
|
||||
if (! p->downloaded && (m_always_download_package_information || salt_mine.download_package_information ())) {
|
||||
|
||||
// If requested, download package information to complete information from index or dependencies
|
||||
if (tl::verbosity() >= 10) {
|
||||
|
|
@ -362,7 +362,7 @@ SaltDownloadManager::fetch_missing (const lay::Salt &salt, const lay::Salt &salt
|
|||
if (! p->downloaded) {
|
||||
|
||||
if (p->name.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No name given package from '%s' (from dependencies or command line installation request)")), p->url);
|
||||
throw tl::Exception (tl::to_string (tr ("No name given for package from '%s' (from dependencies or command line installation request)")), p->url);
|
||||
}
|
||||
|
||||
if (tl::verbosity() >= 10) {
|
||||
|
|
|
|||
|
|
@ -103,6 +103,22 @@ public:
|
|||
*/
|
||||
SaltDownloadManager ();
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether to always download package information
|
||||
*/
|
||||
bool always_download_package_information () const
|
||||
{
|
||||
return m_always_download_package_information;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether to always download package information
|
||||
*/
|
||||
void set_always_download_package_information (bool f)
|
||||
{
|
||||
m_always_download_package_information = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers an URL (with version) for download in the given target directory
|
||||
*
|
||||
|
|
@ -176,6 +192,7 @@ private:
|
|||
};
|
||||
|
||||
std::vector<Descriptor> m_registry;
|
||||
bool m_always_download_package_information;
|
||||
|
||||
bool needs_iteration ();
|
||||
void fetch_missing (const lay::Salt &salt, const lay::Salt &salt_mine, tl::AbsoluteProgress &progress);
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ SaltGrain::load (tl::InputStream &p)
|
|||
void
|
||||
SaltGrain::save () const
|
||||
{
|
||||
save (tl::to_string (QDir (tl::to_qstring (path ())).filePath (tl::to_qstring (grain_filename))));
|
||||
save (tl::to_string (QDir (tl::to_qstring (path ())).filePath (tl::to_qstring (SaltGrain::spec_file ()))));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -503,7 +503,7 @@ SaltGrain::from_path (const std::string &path)
|
|||
QDir dir (tl::to_qstring (path));
|
||||
|
||||
SaltGrain g;
|
||||
g.load (tl::to_string (dir.filePath (tl::to_qstring (grain_filename))));
|
||||
g.load (tl::to_string (dir.filePath (tl::to_qstring (SaltGrain::spec_file ()))));
|
||||
g.set_path (tl::to_string (dir.absolutePath ()));
|
||||
return g;
|
||||
}
|
||||
|
|
@ -552,7 +552,7 @@ SaltGrain::stream_from_url (std::string &generic_url, double timeout, tl::InputH
|
|||
|
||||
} else {
|
||||
|
||||
return new tl::InputStream (url);
|
||||
return new tl::InputStream (url + "/" + SaltGrain::spec_file ());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -576,10 +576,10 @@ SaltGrain::is_grain (const std::string &path)
|
|||
|
||||
if (path[0] != ':') {
|
||||
QDir dir (tl::to_qstring (path));
|
||||
QString gf = dir.filePath (tl::to_qstring (grain_filename));
|
||||
QString gf = dir.filePath (tl::to_qstring (SaltGrain::spec_file ()));
|
||||
return QFileInfo (gf).exists ();
|
||||
} else {
|
||||
return QResource (tl::to_qstring (path + "/" + grain_filename)).isValid ();
|
||||
return QResource (tl::to_qstring (path + "/" + SaltGrain::spec_file ())).isValid ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ TechBaseEditorPage::setup ()
|
|||
mp_ui->desc_le->setText (tl::to_qstring (tech ()->description ()));
|
||||
mp_ui->group_le->setText (tl::to_qstring (tech ()->group ()));
|
||||
mp_ui->dbu_le->setText (tl::to_qstring (tl::to_string (tech ()->dbu ())));
|
||||
mp_ui->grids_le->setText (tl::to_qstring (tl::to_string (tech ()->default_grids ())));
|
||||
mp_ui->desc_le->setEnabled (! tech ()->name ().empty ());
|
||||
mp_ui->base_path_le->setText (tl::to_qstring (tech ()->explicit_base_path ()));
|
||||
#if QT_VERSION >= 0x040700
|
||||
|
|
@ -164,6 +165,7 @@ TechBaseEditorPage::commit ()
|
|||
tech ()->set_description (tl::to_string (mp_ui->desc_le->text ()));
|
||||
tech ()->set_group (tl::to_string (mp_ui->group_le->text ()));
|
||||
tech ()->set_explicit_base_path (tl::to_string (mp_ui->base_path_le->text ()));
|
||||
tech ()->set_default_grids (tl::to_string (mp_ui->grids_le->text ()));
|
||||
|
||||
double d = 0.001;
|
||||
tl::from_string_ext (tl::to_string (mp_ui->dbu_le->text ()), d);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace lay
|
|||
|
||||
static const std::string cfg_tech_editor_window_state ("tech-editor-window-state");
|
||||
|
||||
std::string tech_string_from_name (const std::string &tn)
|
||||
static std::string tech_string_from_name (const std::string &tn)
|
||||
{
|
||||
if (tn.empty ()) {
|
||||
return tl::to_string (QObject::tr ("(Default)"));
|
||||
|
|
@ -179,21 +179,12 @@ TechnologyController::update_active_technology ()
|
|||
}
|
||||
|
||||
|
||||
mp_active_technology = active_tech;
|
||||
|
||||
if (mp_mw) {
|
||||
if (active_tech) {
|
||||
mp_mw->tech_message (tech_string_from_name (active_tech->name ()));
|
||||
} else {
|
||||
mp_mw->tech_message (std::string ());
|
||||
}
|
||||
}
|
||||
|
||||
if (mp_active_technology != active_tech) {
|
||||
mp_active_technology = active_tech;
|
||||
emit active_technology_changed ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
// Hint with this implementation, the current technology follows the current layout.
|
||||
// Although that's a nice way to display the current technology, it's pretty confusing
|
||||
lay::Dispatcher *pr = mp_plugin_root;
|
||||
|
|
|
|||
|
|
@ -105,15 +105,22 @@ MouseTracker::mouse_move_event (const db::DPoint &p, unsigned int /*buttons*/, b
|
|||
|
||||
double max_coord = 1e30; // big enough I guess
|
||||
|
||||
mp_markers.push_back (new lay::DMarker (mp_view));
|
||||
mp_markers.back ()->set_line_style (m_cursor_line_style);
|
||||
mp_markers.back ()->set_color (m_cursor_color);
|
||||
mp_markers.back ()->set (db::DEdge (db::DPoint (tp.x (), -max_coord), db::DPoint (tp.x (), max_coord)));
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
mp_markers.push_back (new lay::DMarker (mp_view));
|
||||
mp_markers.back ()->set_line_style (m_cursor_line_style);
|
||||
mp_markers.back ()->set_color (m_cursor_color);
|
||||
mp_markers.back ()->set (db::DEdge (db::DPoint (-max_coord, tp.y ()), db::DPoint (max_coord, tp.y ())));
|
||||
mp_markers.push_back (new lay::DMarker (mp_view));
|
||||
mp_markers.back ()->set_line_style (m_cursor_line_style);
|
||||
mp_markers.back ()->set_line_width (1);
|
||||
mp_markers.back ()->set_halo (false);
|
||||
mp_markers.back ()->set_dither_pattern (1);
|
||||
mp_markers.back ()->set_color (m_cursor_color.is_valid () ? m_cursor_color : mp_view->canvas ()->foreground_color ());
|
||||
|
||||
if (i == 0) {
|
||||
mp_markers.back ()->set (db::DEdge (db::DPoint (tp.x (), -max_coord), db::DPoint (tp.x (), max_coord)));
|
||||
} else {
|
||||
mp_markers.back ()->set (db::DEdge (db::DPoint (-max_coord, tp.y ()), db::DPoint (max_coord, tp.y ())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue