Merge pull request #642 from KLayout/2.5d-view-devel

2.5d view devel
This commit is contained in:
Matthias Köfferlein 2020-11-13 02:06:41 +01:00 committed by GitHub
commit 94b71cbf76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 4265 additions and 2 deletions

View File

@ -185,6 +185,7 @@ SOURCES = \
gsiDeclDbNetlistCrossReference.cc \
gsiDeclDbLayoutVsSchematic.cc \
dbNetlistObject.cc \
dbD25TechnologyComponent.cc \
gsiDeclDbTexts.cc \
dbTexts.cc \
dbDeepTexts.cc \
@ -345,6 +346,7 @@ HEADERS = \
dbLayoutVsSchematicFormatDefs.h \
dbLayoutVsSchematic.h \
dbNetlistObject.h \
dbD25TechnologyComponent.h \
dbTexts.h \
dbDeepTexts.h \
dbAsIfFlatTexts.h \

View File

@ -0,0 +1,332 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbD25TechnologyComponent.h"
#include "tlClassRegistry.h"
#include "tlString.h"
namespace db
{
std::string d25_component_name ()
{
return std::string ("d25");
}
std::string d25_description ()
{
return tl::to_string (tr ("Z stack (2.5d)"));
}
// -----------------------------------------------------------------------------------------
// D25LayerInfo implementation
D25LayerInfo::D25LayerInfo ()
: m_layer (), m_zstart (0.0), m_zstop (0.0)
{
// .. nothing yet ..
}
D25LayerInfo::~D25LayerInfo ()
{
// .. nothing yet ..
}
D25LayerInfo::D25LayerInfo (const D25LayerInfo &other)
{
operator= (other);
}
D25LayerInfo &
D25LayerInfo::operator= (const D25LayerInfo &other)
{
if (this != &other) {
m_layer = other.m_layer;
m_zstart = other.m_zstart;
m_zstop = other.m_zstop;
}
return *this;
}
bool
D25LayerInfo::operator== (const D25LayerInfo &other) const
{
return fabs (m_zstart - other.m_zstart) < db::epsilon && fabs (m_zstop - other.m_zstop) < db::epsilon;
}
void
D25LayerInfo::set_layer (const db::LayerProperties &l)
{
m_layer = l;
}
void
D25LayerInfo::set_layer_from_string (const std::string &l)
{
db::LayerProperties lp;
tl::Extractor ex (l.c_str ());
try {
lp.read (ex);
} catch (tl::Exception &) {
// ignore errors for now.
}
m_layer = lp;
}
std::string
D25LayerInfo::layer_as_string () const
{
return m_layer.to_string ();
}
void
D25LayerInfo::set_zstart (double z0)
{
m_zstart = z0;
}
void
D25LayerInfo::set_zstop (double z1)
{
m_zstop = z1;
}
// -----------------------------------------------------------------------------------
// D25TechnologyComponent implementation
D25TechnologyComponent::D25TechnologyComponent ()
: db::TechnologyComponent (d25_component_name (), d25_description ())
{
// provide some explanation for the initialization
m_src =
"# Provide z stack information here\n"
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n"
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
"# Named arguments are:\n"
"#\n"
"# zstart The lower z position of the extruded layer in µm\n"
"# zstop The upper z position of the extruded layer in µm\n"
"# height The height of the extruded layer in µm\n"
"#\n"
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', "
"# the upper level of the previous layer will be used.\n"
"#\n"
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n"
"# 'zstart' and 'zstop'.\n"
"#\n"
"# Examples:\n"
"# 1: 0.5 1.5 # extrude layer 1/0 from 0.5 to 1.5 vertically\n"
"# 1/0: 0.5 1.5 # same with explicit datatype\n"
"# 1: zstop=1.5, zstart=0.5 # same with named parameters\n"
"# 1: height=1.0, zstop=1.5 # same with z stop minus height\n"
"# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
;
}
D25TechnologyComponent::D25TechnologyComponent (const D25TechnologyComponent &d)
: db::TechnologyComponent (d25_component_name (), d25_description ())
{
m_layers = d.m_layers;
m_src = d.m_src;
}
void
D25TechnologyComponent::compile_from_source (const std::string &src)
{
int current_line = 0;
m_layers.clear ();
try {
std::vector<std::string> lines = tl::split (src, "\n");
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
++current_line;
tl::Extractor ex (l->c_str ());
if (ex.test ("#")) {
// ignore comments
} else if (ex.at_end ()) {
// ignore empty lines
} else {
db::D25LayerInfo info;
if (! m_layers.empty ()) {
info.set_zstart (m_layers.back ().zstop ());
info.set_zstop (m_layers.back ().zstop ());
}
tl::Variant z0, z1, h;
std::vector<double> args;
db::LayerProperties lp;
lp.read (ex);
info.set_layer (lp);
ex.expect (":");
while (! ex.at_end ()) {
if (ex.test ("#")) {
break;
}
double pv = 0.0;
std::string pn;
if (ex.try_read_name (pn)) {
ex.expect ("=");
ex.read (pv);
} else {
ex.read (pv);
}
ex.test (",");
if (pn.empty ()) {
args.push_back (pv);
} else if (pn == "zstart") {
z0 = pv;
} else if (pn == "zstop") {
z1 = pv;
} else if (pn == "height") {
h = pv;
} else {
throw tl::Exception (tl::to_string (tr ("Invalid parameter name: ")) + pn);
}
}
if (args.size () == 0) {
if (z0.is_nil () && z1.is_nil ()) {
if (! h.is_nil ()) {
info.set_zstop (info.zstart () + h.to_double ());
}
} else if (z0.is_nil ()) {
info.set_zstop (z1.to_double ());
if (! h.is_nil ()) {
info.set_zstart (info.zstop () - h.to_double ());
}
} else if (z1.is_nil ()) {
info.set_zstart (z0.to_double ());
if (! h.is_nil ()) {
info.set_zstop (info.zstart () + h.to_double ());
}
} else {
info.set_zstart (z0.to_double ());
info.set_zstop (z1.to_double ());
}
} else if (args.size () == 1) {
if (! h.is_nil ()) {
if (! z0.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[0] + h.to_double ());
} else {
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
}
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
}
} else if (args.size () == 2) {
if (! z0.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given")));
}
if (! h.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[1]);
} else {
throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)")));
}
m_layers.push_back (info);
}
}
} catch (tl::Exception &ex) {
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
}
m_src = src;
}
std::string
D25TechnologyComponent::to_string () const
{
std::string res;
for (const_iterator i = begin (); i != end (); ++i) {
if (! res.empty ()) {
res += "\n";
}
res += i->layer ().to_string () + ": zstart=" + tl::to_string (i->zstart ()) + ", zstop=" + tl::to_string (i->zstop ());
}
return res;
}
// -----------------------------------------------------------------------------------
// D25TechnologyComponent technology component registration
class D25TechnologyComponentProvider
: public db::TechnologyComponentProvider
{
public:
D25TechnologyComponentProvider ()
: db::TechnologyComponentProvider ()
{
// .. nothing yet ..
}
virtual db::TechnologyComponent *create_component () const
{
return new D25TechnologyComponent ();
}
virtual tl::XMLElementBase *xml_element () const
{
return new db::TechnologyComponentXMLElement<D25TechnologyComponent> (d25_component_name (),
tl::make_element ((D25TechnologyComponent::const_iterator (D25TechnologyComponent::*) () const) &D25TechnologyComponent::begin, (D25TechnologyComponent::const_iterator (D25TechnologyComponent::*) () const) &D25TechnologyComponent::end, &D25TechnologyComponent::add, "layer",
tl::make_member (&D25LayerInfo::layer_as_string, &D25LayerInfo::set_layer_from_string, "layer") +
tl::make_member (&D25LayerInfo::zstart, &D25LayerInfo::set_zstart, "zstart") +
tl::make_member (&D25LayerInfo::zstop, &D25LayerInfo::set_zstop, "zstop")
) +
tl::make_member (&D25TechnologyComponent::src, &D25TechnologyComponent::set_src, "src")
);
}
};
static tl::RegisteredClass<db::TechnologyComponentProvider> tc_decl (new D25TechnologyComponentProvider (), 3100, d25_component_name ().c_str ());
}

View File

@ -0,0 +1,154 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_dbD25TechnologyComponent
#define HDR_dbD25TechnologyComponent
#include "dbTechnology.h"
#include "dbLayerProperties.h"
namespace db
{
class DB_PUBLIC D25LayerInfo
{
public:
D25LayerInfo ();
~D25LayerInfo ();
D25LayerInfo (const D25LayerInfo &other);
D25LayerInfo &operator= (const D25LayerInfo &other);
bool operator== (const D25LayerInfo &other) const;
const db::LayerProperties &layer () const
{
return m_layer;
}
void set_layer_from_string (const std::string &l);
std::string layer_as_string () const;
void set_layer (const db::LayerProperties &l);
double zstart () const
{
return m_zstart;
}
void set_zstart (double z0);
double zstop () const
{
return m_zstop;
}
void set_zstop (double z1);
private:
db::LayerProperties m_layer;
double m_zstart, m_zstop;
};
class DB_PUBLIC D25TechnologyComponent
: public db::TechnologyComponent
{
public:
D25TechnologyComponent ();
D25TechnologyComponent (const D25TechnologyComponent &d);
typedef std::list<D25LayerInfo> layers_type;
typedef layers_type::const_iterator const_iterator;
typedef layers_type::iterator iterator;
void compile_from_source (const std::string &src);
const_iterator begin () const
{
return m_layers.begin ();
}
iterator begin ()
{
return m_layers.begin ();
}
const_iterator end () const
{
return m_layers.end ();
}
iterator end ()
{
return m_layers.end ();
}
void clear ()
{
m_layers.clear ();
}
void erase (iterator p)
{
m_layers.erase (p);
}
void insert (iterator p, const D25LayerInfo &info)
{
m_layers.insert (p, info);
}
void add (const D25LayerInfo &info)
{
m_layers.push_back (info);
}
size_t size () const
{
return m_layers.size ();
}
const std::string &src () const
{
return m_src;
}
// for persistency only, use "compile_from_source" to read from a source string
void set_src (const std::string &s)
{
m_src = s;
}
std::string to_string () const;
db::TechnologyComponent *clone () const
{
return new D25TechnologyComponent (*this);
}
private:
layers_type m_layers;
std::string m_src;
};
}
#endif

View File

@ -0,0 +1,73 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbD25TechnologyComponent.h"
#include "tlUnitTest.h"
TEST(1)
{
db::D25TechnologyComponent comp;
comp.compile_from_source ("1/0: 1.0 1.5 # a comment");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
comp.compile_from_source ("1/0: zstart=1.0 height=0.5");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
comp.compile_from_source ("1/0: 1.0 height=0.5");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
comp.compile_from_source ("1/0: zstop=1.5 height=0.5");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5");
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: height=3");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=1.5, zstop=4.5");
comp.compile_from_source ("1/0: zstart=1.0 zstop=1.5\nname: zstart=4.0 height=3\n\n# a comment line");
EXPECT_EQ (comp.to_string (), "1/0: zstart=1, zstop=1.5\nname: zstart=4, zstop=7");
try {
comp.compile_from_source ("blabla");
EXPECT_EQ (false, true);
} catch (...) { }
try {
comp.compile_from_source ("1/0: 1 2 3");
EXPECT_EQ (false, true);
} catch (...) { }
try {
comp.compile_from_source ("1/0: foo=1 bar=2");
EXPECT_EQ (false, true);
} catch (...) { }
try {
comp.compile_from_source ("1/0: 1;2");
EXPECT_EQ (false, true);
} catch (...) { }
}

View File

@ -34,6 +34,7 @@ SOURCES = \
dbPolygonToolsTests.cc \
dbTechnologyTests.cc \
dbStreamLayerTests.cc \
dbD25TechnologyComponentTests.cc \
dbVectorTests.cc \
dbVariableWidthPathTests.cc \
dbTransTests.cc \

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

View File

@ -127,6 +127,12 @@
<file alias="folder_12.png">images/folder_12.png</file>
<file alias="file_12.png">images/file_12.png</file>
<file alias="empty_12.png">images/empty_12.png</file>
<file alias="fit_front.png">images/fit_front.png</file>
<file alias="fit_back.png">images/fit_back.png</file>
<file alias="fit_left.png">images/fit_left.png</file>
<file alias="fit_right.png">images/fit_right.png</file>
<file alias="fit_top.png">images/fit_top.png</file>
<file alias="fit_bottom.png">images/fit_bottom.png</file>
<file alias="unlocked_16.png">images/unlocked_16.png</file>
<file alias="locked_16.png">images/locked_16.png</file>
</qresource>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>D25TechnologyComponentEditor</class>
<widget class="QFrame" name="D25TechnologyComponentEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>549</width>
<height>434</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>2.5d Vertical Stack Information</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lnum_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Line</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTextEdit" name="src_te">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,102 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "laybasicConfig.h"
#include "dbD25TechnologyComponent.h"
#include "layD25TechnologyComponent.h"
#include <QResource>
#include <QBuffer>
namespace lay
{
D25TechnologyComponentEditor::D25TechnologyComponentEditor (QWidget *parent)
: TechnologyComponentEditor (parent)
{
setupUi (this);
// TODO: activate_help_links (mp_ui->help_label);
QResource res (tl::to_qstring (":/syntax/d25_text.xml"));
QByteArray data ((const char *) res.data (), int (res.size ()));
if (res.isCompressed ()) {
data = qUncompress (data);
}
QBuffer input (&data);
input.open (QIODevice::ReadOnly);
mp_hl_basic_attributes.reset (new GenericSyntaxHighlighterAttributes ());
mp_hl_attributes.reset (new GenericSyntaxHighlighterAttributes (mp_hl_basic_attributes.get ()));
lay::GenericSyntaxHighlighter *hl = new GenericSyntaxHighlighter (src_te, input, mp_hl_attributes.get ());
input.close ();
hl->setDocument (src_te->document ());
connect (src_te, SIGNAL (cursorPositionChanged ()), this, SLOT (cursor_position_changed ()));
}
void
D25TechnologyComponentEditor::cursor_position_changed ()
{
int line = src_te->textCursor ().block ().firstLineNumber () + 1;
lnum_label->setText (tl::to_qstring (tl::sprintf (tl::to_string (tr ("Line %d")), line)));
}
void
D25TechnologyComponentEditor::commit ()
{
db::D25TechnologyComponent *data = dynamic_cast <db::D25TechnologyComponent *> (tech_component ());
if (! data) {
return;
}
std::string src = tl::to_string (src_te->toPlainText ());
data->compile_from_source (src);
}
void
D25TechnologyComponentEditor::setup ()
{
db::D25TechnologyComponent *data = dynamic_cast <db::D25TechnologyComponent *> (tech_component ());
if (! data) {
return;
}
src_te->setPlainText (tl::to_qstring (data->src ()));
}
class D25TechnologyComponentEditorProvider
: public lay::TechnologyEditorProvider
{
public:
virtual lay::TechnologyComponentEditor *create_editor (QWidget *parent) const
{
return new D25TechnologyComponentEditor (parent);
}
};
static tl::RegisteredClass<lay::TechnologyEditorProvider> editor_decl (new D25TechnologyComponentEditorProvider (), 3100, "d25");
} // namespace lay

View File

@ -0,0 +1,57 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25TechnologyComponent
#define HDR_layD25TechnologyComponent
#include "ui_D25TechnologyComponentEditor.h"
#include "layTechnology.h"
#include "layGenericSyntaxHighlighter.h"
#include <memory>
namespace lay {
class D25TechnologyComponentEditor
: public lay::TechnologyComponentEditor,
public Ui::D25TechnologyComponentEditor
{
Q_OBJECT
public:
D25TechnologyComponentEditor (QWidget *parent);
void commit ();
void setup ();
private slots:
void cursor_position_changed ();
private:
std::auto_ptr<lay::GenericSyntaxHighlighterAttributes> mp_hl_attributes, mp_hl_basic_attributes;
};
}
#endif

View File

@ -73,7 +73,8 @@ FORMS = \
NetInfoDialog.ui \
NetExportDialog.ui \
SelectCellViewForm.ui \
LayoutStatistics.ui
LayoutStatistics.ui \
D25TechnologyComponentEditor.ui
RESOURCES = \
laybasicResources.qrc \
@ -184,6 +185,7 @@ SOURCES = \
layDispatcher.cc \
laySelectCellViewForm.cc \
layLayoutStatisticsForm.cc \
layD25TechnologyComponent.cc \
gsiDeclLayNetlistBrowserDialog.cc
HEADERS = \
@ -285,7 +287,8 @@ HEADERS = \
layGenericSyntaxHighlighter.h \
layDispatcher.h \
laySelectCellViewForm.h \
layLayoutStatisticsForm.h
layLayoutStatisticsForm.h \
layD25TechnologyComponent.h
INCLUDEPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC
DEPENDPATH += $$TL_INC $$GSI_INC $$DB_INC $$RDB_INC $$LYM_INC

View File

@ -45,5 +45,6 @@
<file>images/icon_device_bjt_24.png</file>
<file>images/icon_device_bjt_16.png</file>
<file>syntax/ur_text.xml</file>
<file>syntax/d25_text.xml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<language name="UserPropertiesTextFormat">
<highlighting>
<contexts>
<context name="Normal" attribute="Normal Text">
<DetectChar attribute="String" char="&quot;" context="Quoted String"/>
<DetectChar attribute="Comment" char="#" context="Comment"/>
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
<RegExpr attribute="Normal" String=":" context="After LD"/>
<RegExpr attribute="Dec" String="\-?[0-9]+" context="#stay"/>
<DetectChar attribute="Normal" char="*" context="#stay"/>
<DetectChar attribute="Normal" char="(" context="#stay"/>
<DetectChar attribute="Normal" char=")" context="#stay"/>
<DetectChar attribute="Normal" char="/" context="#stay"/>
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
</context>
<context name="Comment" attribute="Comment" lineEndContext="Normal">
</context>
<context name="After LD" attribute="Normal" lineEndContext="Normal">
<DetectChar attribute="Comment" char="#" context="Comment"/>
<RegExpr attribute="Float" String="\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="#stay"/>
<DetectChar attribute="Normal" char="," context="#stay"/>
<DetectChar attribute="Normal" char="=" context="#stay"/>
<StringDetect attribute="Symbol" String="zstart" context="#stay"/>
<StringDetect attribute="Symbol" String="zstop" context="#stay"/>
<StringDetect attribute="Symbol" String="height" context="#stay"/>
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
</context>
<context name="Error" attribute="Error" lineEndContext="Normal">
</context>
<context name="Quoted String" attribute="String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\&quot;" context="#stay"/>
<DetectChar char="&quot;" attribute="String" context="Normal"/>
</context>
<context name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\'" context="#stay"/>
<DetectChar char="'" attribute="Raw String" context="Normal"/>
</context>
</contexts>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal"/>
<itemData name="Comment" defStyleNum="dsComment"/>
<itemData name="Float" defStyleNum="dsFloat"/>
<itemData name="Dec" defStyleNum="dsDecVal"/>
<itemData name="Symbol" defStyleNum="dsKeyword"/>
<itemData name="String" defStyleNum="dsString"/>
<itemData name="Raw String" defStyleNum="dsString" color="#DD4A4A" selColor="#DD4A4A"/>
<!-- use these to mark errors and alerts things -->
<itemData name="Error" defStyleNum="dsAlert"/>
</itemDatas>
</highlighting>
</language>

View File

@ -0,0 +1,325 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>D25View</class>
<widget class="QDialog" name="D25View">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>854</width>
<height>665</height>
</rect>
</property>
<property name="windowTitle">
<string>2.5d View</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>6</number>
</property>
<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="QSlider" name="zoom_slider">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>-300</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="zoom_factor">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>%</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="fit_left">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_left.png</normaloff>:/fit_left.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fit_front">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_front.png</normaloff>:/fit_front.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fit_right">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_right.png</normaloff>:/fit_right.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fit_back">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_back.png</normaloff>:/fit_back.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fit_top">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_top.png</normaloff>:/fit_top.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fit_bottom">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/fit_bottom.png</normaloff>:/fit_bottom.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="lay::D25ViewWidget" name="d25_view"/>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<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="QLabel" name="label">
<property name="text">
<string>Press and hold SHIFT for top view</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>lay::D25ViewWidget</class>
<extends>QOpenGLWidget</extends>
<header>layD25ViewWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../lay/lay/layResources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>D25View</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>530</x>
<y>626</y>
</hint>
<hint type="destinationlabel">
<x>443</x>
<y>643</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,113 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25Camera.h"
#include <QWidget>
#include "math.h"
namespace lay
{
D25Camera::D25Camera ()
{
init ();
}
D25Camera::~D25Camera ()
{
// .. nothing yet ..
}
void
D25Camera::init ()
{
m_fov = 90.0;
m_cam_azimuth = m_cam_elevation = 0.0;
m_top_view = false;
}
void
D25Camera::camera_reset ()
{
init ();
camera_changed ();
}
double
D25Camera::cam_fov () const
{
return m_fov;
}
double
D25Camera::cam_dist () const
{
return 4.0;
}
QVector3D
D25Camera::cam_direction () const
{
return cam_trans ().inverted ().map (QVector3D (0, 0, -1));
}
QVector3D
D25Camera::cam_position () const
{
return cam_direction () * -cam_dist ();
}
double
D25Camera::cam_azimuth () const
{
return m_cam_azimuth;
}
double
D25Camera::cam_elevation () const
{
return m_top_view ? -90.0 : m_cam_elevation;
}
QMatrix4x4
D25Camera::cam_perspective () const
{
QMatrix4x4 t;
t.perspective (cam_fov (), aspect_ratio (), 0.1f, 10000.0f);
t.translate (QVector3D (0.0, 0.0, -cam_dist ()));
return t;
}
QMatrix4x4
D25Camera::cam_trans () const
{
QMatrix4x4 t;
t.rotate (-cam_elevation (), 1.0, 0.0, 0.0);
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
return t;
}
}

View File

@ -0,0 +1,142 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25Camera
#define HDR_layD25Camera
#include "layPluginCommon.h"
#include <QMatrix4x4>
#include <QVector3D>
namespace lay
{
class LAY_PLUGIN_PUBLIC D25Camera
{
public:
D25Camera ();
virtual ~D25Camera ();
/**
* @brief Gets the position of the camera objective in the scene coordinate system
*/
QVector3D cam_position () const;
/**
* @brief Gets the direction the camera looks into in the scene coordinate system
*/
QVector3D cam_direction () const;
/**
* @brief Gets the perspective part of the transformation applied transform scene coordinates into the image plane
* The full transformation for scene to image plane is cam_perspective * cam_trans.
*/
QMatrix4x4 cam_perspective () const;
/**
* @brief Gets the azimuth/elevation part of the transformation applied transform scene coordinates into the image plane
* The full transformation for scene to image plane is cam_perspective * cam_trans.
*/
QMatrix4x4 cam_trans () const;
/**
* @brief Gets the distance of the objective in scene coordinates
*/
double cam_dist () const;
/**
* @brief Gets the field of view of the camera
* The field of view is the objective opening angle.
*/
double cam_fov () const;
/**
* @brief Gets a flag indicating whether top view is enabled
* In "top view" mode, the elevation is fixed to -90 degree.
*/
bool top_view () const
{
return m_top_view;
}
/**
* @brief Sets a flag indicating whether top view is enabled
*/
void set_top_view (bool f)
{
m_top_view = f;
camera_changed ();
}
/**
* @brief Gets the elevation angle
* A negative angle means the camera looks down, a positive angle means it looks up.
*/
double cam_elevation () const;
/**
* @brief Sets the elevation angle
*/
void set_cam_elevation (double e)
{
m_cam_elevation = e;
camera_changed ();
}
/**
* @brief Gets the azimuth angle
* A positive angle means we look from the left. A negative means we look from the right.
*/
double cam_azimuth () const;
/**
* @brief Sets the azimuth angle
*/
void set_cam_azimuth (double a)
{
m_cam_azimuth = a;
camera_changed ();
}
/**
* @brief Resets the camera's orientation
*/
void camera_reset ();
protected:
virtual void camera_changed () { }
virtual double aspect_ratio () const { return 1.0; }
private:
double m_cam_azimuth, m_cam_elevation;
bool m_top_view;
QVector3D m_displacement;
double m_fov;
void init ();
};
}
#endif

View File

@ -0,0 +1,24 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25MemChunks.h"

View File

@ -0,0 +1,266 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25MemChunks
#define HDR_layD25MemChunks
#include <QDialog>
#include <QOpenGLFunctions>
#include "tlObject.h"
#include <string.h> // for memcpy
namespace lay
{
template <class Obj>
struct gl_type2enum
{
GLenum operator() () const;
};
template <>
struct gl_type2enum<float>
{
GLenum operator() () const { return GL_FLOAT; }
};
/**
* @brief Provides a semi-contiguous array of objects
*
* The objects are kept in chunks of ChunkLen items.
* The blocks can be accessed individually. The array can be
* cleared and new items can be added. No insert or delete.
*
* This object is intended to be used for keeping vertex,
* color or point data for OpenGL.
*/
template <class Obj, size_t ChunkLen = 1024>
class mem_chunks
: public QDialog
{
public:
struct chunk {
public:
chunk ()
: m_len (0), m_next (0)
{
// .. nothing yet ..
}
chunk (const chunk &other)
: m_len (0), m_next (0)
{
operator= (other);
}
chunk &operator= (const chunk &other)
{
if (this != &other) {
memcpy (&m_objects, &other.m_objects, sizeof (m_objects));
m_len = other.m_len;
}
return *this;
}
const Obj *front () const { return m_objects; }
size_t size () const { return m_len; }
const chunk *next () const { return m_next; }
private:
friend class mem_chunks;
Obj m_objects [ChunkLen];
size_t m_len;
chunk *m_next;
};
class iterator
{
public:
iterator (chunk *ch = 0)
: mp_chunk (ch)
{
// .. nothing yet ..
}
bool operator== (iterator other) const
{
return mp_chunk == other.mp_chunk;
}
bool operator!= (iterator other) const
{
return mp_chunk != other.mp_chunk;
}
const chunk &operator* () const
{
return *mp_chunk;
}
const chunk *operator-> () const
{
return mp_chunk;
}
void operator++ ()
{
mp_chunk = mp_chunk->next ();
}
private:
const chunk *mp_chunk;
};
/**
* @brief Default constructor
* Creates an empty array
*/
mem_chunks ()
: mp_chunks (0), mp_last_chunk (0)
{
// .. nothing yet ..
}
/**
* @brief Destructor
*/
~mem_chunks ()
{
clear ();
}
/**
* @brief Copy constructor
*/
mem_chunks (const mem_chunks &other)
: mp_chunks (0), mp_last_chunk (0)
{
operator= (other);
}
/**
* @brief Assignment
*/
mem_chunks &operator= (const mem_chunks &other)
{
if (this != &other) {
clear ();
const chunk *ch = other.mp_chunks;
while (ch) {
if (! mp_chunks) {
mp_last_chunk = mp_chunks = new chunk (*ch);
} else {
mp_last_chunk->m_next = new chunk (*ch);
mp_last_chunk = mp_last_chunk->m_next;
}
ch = ch->next ();
}
}
return *this;
}
/**
* @brief Clears the array
*/
void clear ()
{
chunk *ch = mp_chunks;
mp_chunks = 0;
mp_last_chunk = 0;
while (ch) {
chunk *del = ch;
ch = ch->m_next;
delete del;
}
}
/**
* @brief Adds an element to the array
*/
void add (const Obj &element)
{
if (! mp_last_chunk) {
mp_chunks = mp_last_chunk = new chunk ();
}
if (mp_last_chunk->m_len >= ChunkLen) {
mp_last_chunk->m_next = new chunk ();
mp_last_chunk = mp_last_chunk->m_next;
}
mp_last_chunk->m_objects [mp_last_chunk->m_len++] = element;
}
/**
* @brief Adds two elements
*/
void add (const Obj &e1, const Obj &e2)
{
add (e1);
add (e2);
}
/**
* @brief Adds three elements
*/
void add (const Obj &e1, const Obj &e2, const Obj &e3)
{
add (e1);
add (e2);
add (e3);
}
/**
* @brief begin iterator
*/
iterator begin () const { return iterator (mp_chunks); }
/**
* @brief end iterator
*/
iterator end () const { return iterator (); }
/**
* @brief Draw to the given context
*/
void draw_to (QOpenGLFunctions *ctx, GLuint location, GLenum mode) const
{
for (iterator c = begin (); c != end (); ++c) {
ctx->glVertexAttribPointer (location, 3, gl_type2enum<Obj> () (), GL_FALSE, 0, c->front ());
ctx->glDrawArrays (mode, 0, c->size () / 3);
}
}
private:
chunk *mp_chunks;
chunk *mp_last_chunk;
};
}
#endif

View File

@ -0,0 +1,114 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25View.h"
#include "layDispatcher.h"
#include "layPlugin.h"
#include <QSurfaceFormat>
namespace lay
{
class D25Plugin
: public lay::Plugin
{
public:
D25Plugin (Plugin *parent, lay::LayoutView *view)
: lay::Plugin (parent), mp_view (view)
{
mp_dialog = new lay::D25View (0);
}
~D25Plugin ()
{
delete mp_dialog;
mp_dialog = 0;
}
void menu_activated (const std::string &symbol)
{
if (symbol == "lay::d25_view") {
if (mp_dialog->exec_dialog (mp_view)) {
// ... implementation is in layD25ToolDialog.cc ...
}
}
}
private:
lay::LayoutView *mp_view;
lay::D25View *mp_dialog;
};
class D25PluginDeclaration
: public lay::PluginDeclaration
{
public:
D25PluginDeclaration ()
{
// .. nothing yet ..
}
virtual void get_options (std::vector < std::pair<std::string, std::string> > & /*options*/) const
{
// .. nothing yet ..
}
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
{
// .. nothing yet ..
return 0;
}
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
{
lay::PluginDeclaration::get_menu_entries (menu_entries);
menu_entries.push_back (lay::menu_item ("lay::d25_view", "d25_view:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("2.5d View"))));
}
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
{
return false;
}
virtual void config_finalize ()
{
// .. nothing yet ..
}
lay::Plugin *create_plugin (db::Manager *, lay::Dispatcher *root, lay::LayoutView *view) const
{
return new D25Plugin (root, view);
}
};
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::D25PluginDeclaration (), 3100, "lay::D25Plugin");
}

View File

@ -0,0 +1,151 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25View.h"
#include "layLayoutView.h"
#include "ui_D25View.h"
#include <stdio.h>
namespace lay
{
const double initial_elevation = 3.0;
D25View::D25View (QWidget *parent)
: QDialog (parent)
{
mp_ui = new Ui::D25View ();
mp_ui->setupUi (this);
mp_ui->d25_view->setFocusPolicy (Qt::StrongFocus);
mp_ui->d25_view->setFocus ();
connect (mp_ui->fit_back, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->fit_front, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->fit_left, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->fit_right, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->fit_top, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->fit_bottom, SIGNAL (clicked ()), this, SLOT (fit_button_clicked ()));
connect (mp_ui->zoom_slider, SIGNAL (valueChanged (int)), this, SLOT (scale_slider_changed (int)));
connect (mp_ui->d25_view, SIGNAL (scale_factor_changed (double)), this, SLOT (scale_factor_changed (double)));
}
D25View::~D25View ()
{
delete mp_ui;
mp_ui = 0;
}
static QString scale_factor_to_string (double f)
{
QString s;
s.sprintf ("x %.3g", f);
return s;
}
void
D25View::scale_slider_changed (int value)
{
double f = exp (log (10.0) * -0.01 * value);
mp_ui->zoom_factor->setText (scale_factor_to_string (f));
mp_ui->d25_view->set_scale_factor (f);
}
void
D25View::scale_factor_changed (double f)
{
mp_ui->zoom_factor->setText (scale_factor_to_string (f));
int v = floor (0.5 - log10 (f) * 100.0);
mp_ui->zoom_slider->blockSignals (true);
mp_ui->zoom_slider->setValue (v);
mp_ui->zoom_slider->blockSignals (false);
}
int
D25View::exec_dialog (lay::LayoutView *view)
{
mp_view.reset (view);
bool any = mp_ui->d25_view->attach_view (view);
if (! any) {
mp_view.reset (0);
mp_ui->d25_view->attach_view (0);
throw tl::Exception (tl::to_string (tr ("No z data configured for the layers in the view.\nUse \"Tools/Manage Technologies\" to set up a z stack.")));
}
mp_ui->d25_view->reset ();
mp_ui->d25_view->set_cam_azimuth (0.0);
mp_ui->d25_view->set_cam_elevation (initial_elevation);
mp_ui->d25_view->fit ();
int ret = QDialog::exec ();
mp_ui->d25_view->attach_view (0);
mp_view.reset (0);
return ret;
}
void
D25View::fit_button_clicked ()
{
double azimuth = mp_ui->d25_view->cam_azimuth ();
double elevation = mp_ui->d25_view->cam_elevation ();
if (sender () == mp_ui->fit_back) {
azimuth = -180.0;
elevation = -initial_elevation;
} else if (sender () == mp_ui->fit_front) {
azimuth = 0.0;
elevation = -initial_elevation;
} else if (sender () == mp_ui->fit_left) {
azimuth = 90.0;
elevation = -initial_elevation;
} else if (sender () == mp_ui->fit_right) {
azimuth = -90.0;
elevation = -initial_elevation;
} else if (sender () == mp_ui->fit_top) {
elevation = -90;
} else if (sender () == mp_ui->fit_bottom) {
elevation = 90;
}
mp_ui->d25_view->set_cam_azimuth (azimuth);
mp_ui->d25_view->set_cam_elevation (elevation);
mp_ui->d25_view->fit ();
}
void
D25View::accept ()
{
QDialog::accept ();
}
}

View File

@ -0,0 +1,70 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25View
#define HDR_layD25View
#include <QDialog>
#include "tlObject.h"
namespace Ui
{
class D25View;
}
namespace lay
{
class LayoutView;
}
namespace lay
{
class D25View
: public QDialog
{
Q_OBJECT
public:
D25View (QWidget *parent);
~D25View ();
int exec_dialog (lay::LayoutView *view);
protected:
void accept ();
private slots:
void fit_button_clicked ();
void scale_factor_changed (double f);
void scale_slider_changed (int value);
private:
Ui::D25View *mp_ui;
tl::weak_ptr<lay::LayoutView> mp_view;
};
}
#endif

View File

@ -0,0 +1,228 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25ViewUtils.h"
#include <QMatrix4x4>
#include <QMatrix3x3>
#include <math.h>
namespace lay
{
const double epsilon = 1e-10;
std::pair<bool, QVector3D>
cutpoint_line_with_plane (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &plane_normal)
{
double dn = QVector3D::dotProduct (dir, plane_normal);
if (fabs (dn) < epsilon) {
return std::make_pair (false, QVector3D ());
} else {
return std::make_pair (true, line + dir * QVector3D::dotProduct (plane - line, plane_normal) / dn);
}
}
std::pair<bool, QVector3D>
cutpoint_line_with_face (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &u, const QVector3D &v)
{
QVector3D n = QVector3D::crossProduct (u, v);
std::pair<bool, QVector3D> r = cutpoint_line_with_plane (line, dir, plane, n);
if (! r.first) {
return r;
}
double pu = QVector3D::dotProduct (r.second - plane, u);
double pv = QVector3D::dotProduct (r.second - plane, v);
// test whether the cut point is inside the face
if (pu < -epsilon || pu > u.lengthSquared () + epsilon || pv < -epsilon || pv > v.lengthSquared () + epsilon) {
return std::make_pair (false, QVector3D ());
} else {
return r;
}
}
static bool somewhat_perpendicular (const QVector3D &a, const QVector3D &b)
{
// returns true if a and b are perpendicular within +/-30 degree
return fabs (QVector3D::dotProduct (a, b)) < 0.5 * a.length () * b.length ();
}
static std::pair<bool, QVector3D> plane_or_face (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &u, const QVector3D &v, bool face)
{
if (face) {
return cutpoint_line_with_face (line, line_dir, corner, u, v);
} else if (somewhat_perpendicular (u, line_dir) && somewhat_perpendicular (v, line_dir)) {
return cutpoint_line_with_plane (line, line_dir, corner, QVector3D::crossProduct (u, v));
} else {
return std::make_pair (false, QVector3D ());
}
}
std::pair<bool, QVector3D>
hit_point_with_cuboid (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &dim)
{
std::vector<std::pair<bool, QVector3D> > cutpoints;
cutpoints.reserve (6); // 6 faces
for (int pass = 0; pass < 2; ++pass) {
bool face = (pass == 0);
if (face) {
bool in_x = (line.x () > corner.x () - epsilon) && (line.x () < corner.x () + dim.x () + epsilon);
bool in_y = (line.y () > corner.y () - epsilon) && (line.y () < corner.y () + dim.y () + epsilon);
bool in_z = (line.z () > corner.z () - epsilon) && (line.z () < corner.z () + dim.z () + epsilon);
if (in_x && in_y && in_z) {
// inside cuboid
return std::make_pair (true, line);
}
}
cutpoints.clear ();
// front
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (dim.x (), 0, 0), QVector3D (0, dim.y (), 0), face));
// back
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (0, 0, dim.z ()), QVector3D (dim.x (), 0, 0), QVector3D (0, dim.y (), 0), face));
// bottom
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), face));
// top
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (0, dim.y (), 0), QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), face));
// left
cutpoints.push_back (plane_or_face (line, line_dir, corner, QVector3D (0, 0, dim.z ()), QVector3D (0, dim.y (), 0), face));
// right
cutpoints.push_back (plane_or_face (line, line_dir, corner + QVector3D (dim.x (), 0, 0), QVector3D (0, 0, dim.z ()), QVector3D (0, dim.y (), 0), face));
double min_dist = 0.0;
int min_dist_index = -1;
QVector3D ld_norm = line_dir.normalized ();
for (std::vector<std::pair<bool, QVector3D> >::const_iterator i = cutpoints.begin (); i != cutpoints.end (); ++i) {
if (i->first) {
double dist = QVector3D::dotProduct (i->second - line, ld_norm);
if (min_dist_index < 0) {
min_dist = dist;
min_dist_index = int (i - cutpoints.begin ());
} else if (dist < min_dist) {
min_dist = dist;
min_dist_index = int (i - cutpoints.begin ());
}
}
}
if (min_dist_index >= 0) {
return cutpoints [min_dist_index];
}
}
return std::make_pair (false, QVector3D ());
}
std::pair<QVector3D, QVector3D>
camera_normal (const QMatrix4x4 &camera_trans, double x, double y)
{
QVector3D p = camera_trans.inverted ().map (QVector3D (x, y, 1.0));
QVector4D pv = camera_trans.row (3);
QMatrix4x4 m (camera_trans);
float values[] = {
float (x * pv.x ()), float (x * pv.y ()), float (x * pv.z ()), 0.0f,
float (y * pv.x ()), float (y * pv.y ()), float (y * pv.z ()), 0.0f,
float (pv.x ()), float (pv.y ()), float (pv.z ()), 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
m -= QMatrix4x4 (values);
QMatrix3x3 nm = m.normalMatrix ();
QVector3D u (nm (2, 0), nm (2, 1), nm (2, 2));
return (std::make_pair (p, u.normalized ()));
}
void
normalize_scene_trans (const QMatrix4x4 &cam_trans, QVector3D &displacement, double &scale, double ztarget)
{
// Here is the theory:
// Let:
// cam = ( M t ) M = 3x3 matrix, t = 3x1 translation vector, z = scalar, p = 1x3 perspective
// ( p z )
// and:
// scene = ( S d*s ) S = s*U1 (s = scale factor, U1 = 3x3 unit matrix), d = 3x1 displacement vector
// ( 0 1 )
// then:
// cam * scene = ( M*s M*d*s+t )
// ( p*s p*d*s+z ) (p*d = dot product)
//
// this is image invariant (only x,y results are considered) against changes of s (s->s') if
//
// 1.) (p*d*s+z)/s = (p*d'*s'+z)/s' (because x and y will be devided by this value)
// 2.) (M*d*s+t)/s = (M*d'*s'+t)/s' for [x] and [y]
//
// or
//
// 1.) p*d+z/s = p*d'+z/s'
// 2.) M*d+t/s = M*d'+t/s'
//
// If we seek a solution with d'[z] == b (b = ztarget), we get these equations (f:=1/s')
//
// 2.) M[xx] * d'[x] + M[xy] * d'[y] + t[x] * f = (M*d)[x] + t[x]/s - M[xz]*b
// M[yx] * d'[x] + M[yy] * d'[y] + t[y] * f = (M*d)[y] + t[y]/s - M[yz]*b
// 1.) p[x] * d'[x] + p[y] * d'[y] + z * f = p*d + z/s - p[z]*b
//
// we can solve these equations for d'[x], d'[y] and f.
// With p[x]=M[wx], p[y]=M[wy] and z=t[w], the above equation system can be written as
//
// M[ix] * d'[x] + M[iy] * d'[y] + t[i] * f = (M*d)[i] - M[iz]*b + t[i]/s i = x,y,w
//
QMatrix4x4 m;
for (int i = 0; i < 4; ++i) {
if (i != 2) {
m (i, 0) = cam_trans (i, 0);
m (i, 1) = cam_trans (i, 1);
m (i, 3) = cam_trans (i, 3);
}
}
bool invertable = false;
QMatrix4x4 minv = m.inverted (&invertable);
if (! invertable) {
return;
}
QVector4D rhs = cam_trans.map (QVector4D (displacement.x (), displacement.y (), displacement.z () - ztarget, 1.0 / scale));
QVector4D sol = minv.map (rhs);
double f = sol.w ();
if (f > 1e-6 /*skip weird solutions*/) {
scale = 1.0 / f;
displacement = QVector3D (sol.x (), sol.y (), ztarget);
}
}
}

View File

@ -0,0 +1,92 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25ViewUtils
#define HDR_layD25ViewUtils
#include "layPluginCommon.h"
#include <QVector3D>
#include <QMatrix4x4>
#include <algorithm>
namespace lay
{
/**
* @brief Computes the cutpoint between a line and a plane
*
* The line is given by a point and a direction (line, line_dir).
* The plane is given by a point and a normal vector (plane, plane_normal)
* The "first" component of the returned pair is false if not hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
cutpoint_line_with_plane (const QVector3D &line, const QVector3D &line_dir, const QVector3D &plane, const QVector3D &plane_normal);
/**
* @brief Computes the cutpoint between a line and a face
*
* The line is given by a point and a direction (line, line_dir).
* The face is given by a plane point and two vectors spanning the face.
* The "first" component of the returned pair is false if not hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
cutpoint_line_with_face (const QVector3D &line, const QVector3D &dir, const QVector3D &plane, const QVector3D &u, const QVector3D &v);
/**
* @brief Determines a good hit point of a view line and a cuboid
*
* "corner, dim" are the coordinates for the cuboid (corner is the bottom, left, foremost corner, dim
* is (width, height, depth)
* "line, line_dir" is the view line where "line_dir" is pointing from the camera to the object.
* The returned point is a suitable hit point.
* The "first" component of the returned pair is false if no hit is present.
*/
LAY_PLUGIN_PUBLIC std::pair<bool, QVector3D>
hit_point_with_cuboid (const QVector3D &line, const QVector3D &line_dir, const QVector3D &corner, const QVector3D &dim);
/**
* @brief For a given pixel coordinate and camera transformation matrix compute a line containing all points corresponding to this pixel
*
* The returned pair contains a point and a direction vector describing the line.
*/
LAY_PLUGIN_PUBLIC std::pair<QVector3D, QVector3D>
camera_normal (const QMatrix4x4 &camera_trans, double x, double y);
/**
* @brief Normalizes a scene transformation
*
* Scene transformations consist of a scaling and displacement. Both are
* interchangeable to some extent under the presence of a perspective
* transformation (further away makes the scene smaller). This normalization
* tries to find a displacement which has "ztarget" target value for z. Without normalization
* the scene tends to "move away" with respect to z.
*/
LAY_PLUGIN_PUBLIC void
normalize_scene_trans (const QMatrix4x4 &cam_trans, QVector3D &displacement, double &scale, double ztarget = 0.0);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_layD25ViewWidget
#define HDR_layD25ViewWidget
#include "dbPolygon.h"
#include "layD25MemChunks.h"
#include "layD25Camera.h"
#include <QOpenGLWidget>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QMatrix4x4>
#include <QPoint>
#include <QVector3D>
#include <memory>
namespace db
{
class Layout;
class Cell;
}
namespace lay
{
class LayoutView;
class D25ViewWidget;
class D25InteractionMode
{
public:
D25InteractionMode (D25ViewWidget *widget);
virtual ~D25InteractionMode ();
D25ViewWidget *view () { return mp_view; }
virtual void mouse_move (QMouseEvent *event) = 0;
private:
D25ViewWidget *mp_view;
};
class D25ViewWidget
: public QOpenGLWidget,
private QOpenGLFunctions,
public D25Camera
{
Q_OBJECT
public:
D25ViewWidget (QWidget *parent);
~D25ViewWidget ();
void keyPressEvent (QKeyEvent *event);
void keyReleaseEvent (QKeyEvent *event);
void wheelEvent (QWheelEvent *event);
void mousePressEvent (QMouseEvent *event);
void mouseReleaseEvent (QMouseEvent *event);
void mouseMoveEvent (QMouseEvent *event);
bool attach_view(lay::LayoutView *view);
QVector3D hit_point_with_scene(const QVector3D &line_dir);
void refresh ();
void reset ();
QVector3D displacement () const { return m_displacement; }
void set_displacement (const QVector3D &d)
{
m_displacement = d;
refresh ();
}
double scale_factor () const { return m_scale_factor; }
void set_scale_factor (double f)
{
m_scale_factor = f;
refresh ();
}
signals:
void scale_factor_changed (double f);
protected:
virtual void camera_changed ();
virtual double aspect_ratio () const;
public slots:
void fit ();
private:
typedef lay::mem_chunks<GLfloat, 1024 * 18> chunks_type;
std::auto_ptr<D25InteractionMode> mp_mode;
QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program;
double m_scale_factor;
QVector3D m_displacement;
lay::LayoutView *mp_view;
db::DBox m_bbox;
double m_zmin, m_zmax;
std::list<chunks_type> m_vertex_chunks;
struct LayerInfo {
const chunks_type *vertex_chunk;
GLfloat color [4];
};
std::list<LayerInfo> m_layers;
void initializeGL ();
void paintGL ();
void resizeGL (int w, int h);
bool prepare_view();
void render_layout (D25ViewWidget::chunks_type &chunks, const db::Layout &layout, const db::Cell &cell, unsigned int layer, double zstart, double zstop);
void render_polygon (D25ViewWidget::chunks_type &chunks, const db::Polygon &poly, double dbu, double zstart, double zstop);
void render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &poly, double dbu, double zstart, double zstop);
};
}
#endif

View File

@ -0,0 +1,122 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layXORToolDialog.h"
#include "layDispatcher.h"
#include "layPlugin.h"
namespace lay
{
class XORPlugin
: public lay::Plugin
{
public:
XORPlugin (Plugin *parent, lay::LayoutView *view)
: lay::Plugin (parent), mp_view (view)
{
mp_dialog = new lay::XORToolDialog (0);
}
~XORPlugin ()
{
delete mp_dialog;
mp_dialog = 0;
}
void menu_activated (const std::string &symbol)
{
if (symbol == "lay::xor_tool") {
if (mp_dialog->exec_dialog (mp_view)) {
// ... implementation is in layXORToolDialog.cc ...
}
}
}
private:
lay::LayoutView *mp_view;
lay::XORToolDialog *mp_dialog;
};
class XORPluginDeclaration
: public lay::PluginDeclaration
{
public:
XORPluginDeclaration ()
{
// .. nothing yet ..
}
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
{
options.push_back (std::pair<std::string, std::string> (cfg_xor_input_mode, "all"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_output_mode, "rdb"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_nworkers, "1"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_layer_offset, ""));
options.push_back (std::pair<std::string, std::string> (cfg_xor_axorb, "true"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_anotb, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_bnota, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_summarize, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_xor_tolerances, ""));
options.push_back (std::pair<std::string, std::string> (cfg_xor_tiling, ""));
options.push_back (std::pair<std::string, std::string> (cfg_xor_region_mode, "all"));
}
virtual lay::ConfigPage *config_page (QWidget * /*parent*/, std::string & /*title*/) const
{
// .. nothing yet ..
return 0;
}
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
{
lay::PluginDeclaration::get_menu_entries (menu_entries);
menu_entries.push_back (lay::menu_item ("lay::xor_tool", "xor_tool:edit", "tools_menu.post_verification_group", tl::to_string (QObject::tr ("XOR Tool"))));
}
virtual bool configure (const std::string & /*name*/, const std::string & /*value*/)
{
return false;
}
virtual void config_finalize ()
{
// .. nothing yet ..
}
lay::Plugin *create_plugin (db::Manager *, lay::Dispatcher *root, lay::LayoutView *view) const
{
return new XORPlugin (root, view);
}
};
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new lay::XORPluginDeclaration (), 3000, "lay::XORPlugin");
}

View File

@ -0,0 +1,27 @@
TARGET = d25_ui
DESTDIR = $$OUT_PWD/../../../../lay_plugins
include($$PWD/../../../lay_plugin.pri)
INCLUDEPATH += $$RDB_INC $$ANT_INC
DEPENDPATH += $$RDB_INC $$ANT_INC
LIBS += -L$$DESTDIR/.. -lklayout_rdb -lklayout_ant
HEADERS = \
layD25View.h \
layD25ViewWidget.h \
layD25MemChunks.h \
layD25ViewUtils.h \
layD25Camera.h
SOURCES = \
layD25View.cc \
layD25ViewWidget.cc \
layD25Plugin.cc \
layD25MemChunks.cc \
layD25ViewUtils.cc \
layD25Camera.cc
FORMS = \
D25View.ui \

View File

@ -0,0 +1,102 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25Camera.h"
#include "tlUnitTest.h"
static std::string v2s (const QVector4D &v)
{
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ()) + "," + tl::to_string (v.z ());
}
static std::string v2s (const QVector3D &v)
{
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ()) + "," + tl::to_string (v.z ());
}
static std::string v2s_2d (const QVector3D &v)
{
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ());
}
TEST(1_Transformations)
{
lay::D25Camera cam;
cam.set_cam_azimuth (45.0);
EXPECT_EQ (cam.cam_azimuth (), 45.0);
cam.set_cam_elevation (22.0);
EXPECT_EQ (cam.cam_elevation (), 22.0);
cam.camera_reset ();
EXPECT_EQ (cam.cam_azimuth (), 0.0);
EXPECT_EQ (cam.cam_elevation (), 0.0);
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,0,1");
EXPECT_EQ (v2s (cam.cam_direction ()), "0,0,-1");
EXPECT_EQ (v2s (cam.cam_position ()), "0,0,4");
// looking up from the bottom, x axis stays the same (azimuth = 0)
cam.set_cam_elevation (90.0);
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,0,-1");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,1,0");
EXPECT_EQ (v2s (cam.cam_direction ()), "0,1,0");
EXPECT_EQ (v2s (cam.cam_position ()), "0,-4,0");
// looking down from the top, x axis stays the same (azimuth = 0)
cam.set_cam_elevation (-90.0);
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "1,0,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,0,1");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "0,-1,0");
EXPECT_EQ (v2s (cam.cam_direction ()), "0,-1,0");
EXPECT_EQ (v2s (cam.cam_position ()), "0,4,0");
// looking from the left, y axis stays the same (elevation = 0)
cam.set_cam_elevation (0.0);
cam.set_cam_azimuth (90.0);
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "0,0,-1");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "1,0,0");
EXPECT_EQ (v2s (cam.cam_direction ()), "1,0,0");
EXPECT_EQ (v2s (cam.cam_position ()), "-4,0,0");
// looking from the right, y axis stays the same (elevation = 0)
cam.set_cam_elevation (0.0);
cam.set_cam_azimuth (-90.0);
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (1, 0, 0, 1))), "0,0,1");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 1, 0, 1))), "0,1,0");
EXPECT_EQ (v2s (cam.cam_trans ().map (QVector4D (0, 0, 1, 1))), "-1,0,0");
EXPECT_EQ (v2s (cam.cam_direction ()), "-1,0,0");
EXPECT_EQ (v2s (cam.cam_position ()), "4,0,0");
}

View File

@ -0,0 +1,90 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25MemChunks.h"
#include "tlUnitTest.h"
TEST(1_Basic)
{
lay::mem_chunks<int, 2> ch;
EXPECT_EQ (ch.begin () == ch.end (), true);
ch.add (1);
EXPECT_EQ (ch.begin () == ch.end (), false);
EXPECT_EQ (ch.begin ()->size (), size_t (1));
EXPECT_EQ (ch.begin ()->front () [0], 1);
ch.add (17);
EXPECT_EQ (ch.begin () == ch.end (), false);
EXPECT_EQ (ch.begin ()->size (), size_t (2));
EXPECT_EQ (ch.begin ()->front () [0], 1);
EXPECT_EQ (ch.begin ()->front () [1], 17);
lay::mem_chunks<int, 2>::iterator c = ch.begin ();
EXPECT_EQ (c == ch.end (), false);
++c;
EXPECT_EQ (c == ch.end (), true);
ch.add (42);
c = ch.begin ();
EXPECT_EQ (c == ch.end (), false);
EXPECT_EQ (c->size (), size_t (2));
EXPECT_EQ (c->front () [0], 1);
EXPECT_EQ (c->front () [1], 17);
++c;
EXPECT_EQ (c == ch.end (), false);
EXPECT_EQ (c->size (), size_t (1));
EXPECT_EQ (c->front () [0], 42);
++c;
EXPECT_EQ (c == ch.end (), true);
ch.clear ();
EXPECT_EQ (ch.begin () == ch.end (), true);
}
TEST(2_Copy)
{
lay::mem_chunks<int, 2> ch1;
ch1.add (1);
ch1.add (17);
ch1.add (42);
lay::mem_chunks<int, 2> ch (ch1);
lay::mem_chunks<int, 2>::iterator c = ch.begin ();
EXPECT_EQ (c == ch.end (), false);
EXPECT_EQ (c->size (), size_t (2));
EXPECT_EQ (c->front () [0], 1);
EXPECT_EQ (c->front () [1], 17);
++c;
EXPECT_EQ (c == ch.end (), false);
EXPECT_EQ (c->size (), size_t (1));
EXPECT_EQ (c->front () [0], 42);
++c;
EXPECT_EQ (c == ch.end (), true);
ch1.clear ();
ch = ch1;
EXPECT_EQ (ch.begin () == ch.end (), true);
}

View File

@ -0,0 +1,240 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "layD25ViewUtils.h"
#include "tlUnitTest.h"
static std::string v2s (const QVector3D &v)
{
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ()) + "," + tl::to_string (v.z ());
}
static std::string v2s_2d (const QVector3D &v)
{
return tl::to_string (v.x ()) + "," + tl::to_string (v.y ());
}
TEST(1_CutPoint)
{
std::pair<bool, QVector3D> r;
r = lay::cutpoint_line_with_plane (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (0, 0, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_plane (QVector3D (1, 2, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 0, 1));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,2,6");
r = lay::cutpoint_line_with_plane (QVector3D (1, 2, 3), QVector3D (0, 0, -1), QVector3D (4, 5, 6), QVector3D (1, 1, 1));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,2,12");
}
TEST(2_Face)
{
std::pair<bool, QVector3D> r;
r = lay::cutpoint_line_with_face (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (0, 0, 0), QVector3D (0, 1, 0), QVector3D (0, 0, 1));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (1, 2, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (4, 5, 3), QVector3D (0, 0, 3), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "4,5,6");
r = lay::cutpoint_line_with_face (QVector3D (4, 7, 3), QVector3D (0, 0, 1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
r = lay::cutpoint_line_with_face (QVector3D (4, 6, 3), QVector3D (0, 0, 2), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "4,6,6");
r = lay::cutpoint_line_with_face (QVector3D (5, 6, 3), QVector3D (0, 0, -1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,6,6");
r = lay::cutpoint_line_with_face (QVector3D (6, 6, 3), QVector3D (0, 0, 1), QVector3D (4, 5, 6), QVector3D (0, 1, 0), QVector3D (1, 0, 0));
EXPECT_EQ (r.first, false);
}
TEST(3_HitWithCuboid)
{
std::pair<bool, QVector3D> r;
r = lay::hit_point_with_cuboid (QVector3D (0, 0, 0), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "0,0,3");
r = lay::hit_point_with_cuboid (QVector3D (1, 1, 4), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,1,4");
r = lay::hit_point_with_cuboid (QVector3D (1, 1, 6), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,1,3");
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 0), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,-6,3");
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 4), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,-6,3");
r = lay::hit_point_with_cuboid (QVector3D (5, -6, 6), QVector3D (0, 0, 1), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "5,-6,3");
r = lay::hit_point_with_cuboid (QVector3D (5, 0, 0), QVector3D (-1, 0, 0), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "1,0,0");
r = lay::hit_point_with_cuboid (QVector3D (-5, 0, 0), QVector3D (1, 0, 0), QVector3D (-1, -1, 3), QVector3D (2, 2, 2));
EXPECT_EQ (r.first, true);
EXPECT_EQ (v2s (r.second), "-1,0,0");
}
TEST(4_CameraNormal)
{
QMatrix4x4 matrix;
matrix.perspective (60.0f, 1.5, 0.1f, 100.0f);
std::pair<QVector3D, QVector3D> ray;
QVector3D p;
ray = lay::camera_normal (matrix, 0.0, 0.0);
EXPECT_EQ (v2s (ray.second.normalized ()), "0,0,-1");
ray = lay::camera_normal (matrix, 1.0, 0.0);
EXPECT_EQ (v2s (ray.second), "0.654654,0,-0.755929");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "1,0");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "1,0");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "1,0");
ray = lay::camera_normal (matrix, 0.0, -1.0);
EXPECT_EQ (v2s (ray.second), "0,-0.5,-0.866025");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "0,-1");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "0,-1");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "0,-1");
}
TEST(5_CameraNormal)
{
QMatrix4x4 matrix;
QVector3D p;
matrix.perspective (60.0f, 1.5, 0.1f, 100.0f);
matrix.rotate (22.0, 1.0, 0.0, 0.0);
matrix.rotate (-15.0, 0.0, 1.0, 0.0);
matrix.translate (QVector3D (0.0, 0.0, 4.0));
std::pair<QVector3D, QVector3D> ray;
ray = lay::camera_normal (matrix, 0.0, 1.0);
EXPECT_EQ (v2s (ray.second), "-0.2563,0.139173,-0.956526");
p = matrix.map (ray.first);
EXPECT_EQ (v2s_2d (p), "0,1");
p = matrix.map (ray.first + ray.second);
EXPECT_EQ (v2s_2d (p), "0,1");
p = matrix.map (ray.first + ray.second * 1000.0);
EXPECT_EQ (v2s_2d (p), "0,1");
}
TEST(6_NormalizeSceneTrans)
{
QMatrix4x4 cam;
cam.perspective (60.0f, 1.5, 0.1f, 100.0f);
cam.rotate (22.0, 1.0, 0.0, 0.0);
cam.rotate (-15.0, 0.0, 1.0, 0.0);
cam.translate (QVector3D (0.0, 0.0, 4.0));
double scale = 0.1;
QVector3D displacement (-5.0, 2.0, 20.0);
QMatrix4x4 scene1;
scene1.scale (scale);
scene1.translate (displacement);
QVector3D v1 = (cam * scene1).map (QVector3D (1.0, -1.0, 2.0));
v1.setZ (0);
QVector3D v2 = (cam * scene1).map (QVector3D (0.0, 0.0, 5.0));
v2.setZ (0);
QVector3D v3 = (cam * scene1).map (QVector3D (-1.0, 0.0, 1.0));
v3.setZ (0);
lay::normalize_scene_trans (cam, displacement, scale);
QMatrix4x4 scene2;
scene2.scale (scale);
scene2.translate (displacement);
EXPECT_EQ (tl::sprintf ("%.4f", scale), "0.0667");
QVector3D u1 = (cam * scene2).map (QVector3D (1.0, -1.0, 2.0));
u1.setZ (0);
QVector3D u2 = (cam * scene2).map (QVector3D (0.0, 0.0, 5.0));
u2.setZ (0);
QVector3D u3 = (cam * scene2).map (QVector3D (-1.0, 0.0, 1.0));
u3.setZ (0);
EXPECT_EQ ((u1 - v1).length () < 1e-4, true);
EXPECT_EQ ((u2 - v2).length () < 1e-4, true);
EXPECT_EQ ((u3 - v3).length () < 1e-4, true);
lay::normalize_scene_trans (cam, displacement, scale, 10.0);
QMatrix4x4 scene3;
scene3.scale (scale);
scene3.translate (displacement);
EXPECT_EQ (tl::sprintf ("%.4f", scale), "0.0800");
EXPECT_EQ (tl::to_string (displacement.z ()), "10");
QVector3D uu1 = (cam * scene2).map (QVector3D (1.0, -1.0, 2.0));
uu1.setZ (0);
QVector3D uu2 = (cam * scene2).map (QVector3D (0.0, 0.0, 5.0));
uu2.setZ (0);
QVector3D uu3 = (cam * scene2).map (QVector3D (-1.0, 0.0, 1.0));
uu3.setZ (0);
EXPECT_EQ ((uu1 - v1).length () < 1e-4, true);
EXPECT_EQ ((uu2 - v2).length () < 1e-4, true);
EXPECT_EQ ((uu3 - v3).length () < 1e-4, true);
}

View File

@ -0,0 +1,21 @@
DESTDIR_UT = $$OUT_PWD/../../../..
TARGET = view_25d_tests
include($$PWD/../../../../lib_ut.pri)
SOURCES = \
layD25MemChunksTests.cc \
layD25ViewUtilsTests.cc \
layD25CameraTests.cc
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../lay_plugin $$PWD/../../../common
LIBS += -L$$DESTDIR_UT -lklayout_db -lklayout_tl -lklayout_gsi
PLUGINPATH = $$OUT_PWD/../../../../lay_plugins
QMAKE_RPATHDIR += $$PLUGINPATH
LIBS += -L$$PLUGINPATH -ld25_ui

View File

@ -0,0 +1,6 @@
TEMPLATE = subdirs
equals(HAVE_QT5, "1") {
SUBDIRS = lay_plugin unit_tests
}