This commit is contained in:
Matthias Koefferlein 2020-04-11 11:21:59 +02:00
parent 731dfffe1e
commit b5a51f15d0
9 changed files with 699 additions and 577 deletions

View File

@ -30,7 +30,7 @@
<number>9</number>
</property>
<item>
<widget class="lay::D25ViewWidget" name="openGLWidget"/>
<widget class="lay::D25ViewWidget" name="d25_view"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">

View File

@ -0,0 +1,23 @@
/*
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,222 @@
/*
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 "tlObject.h"
#include <string.h> // for memcpy
namespace lay
{
/**
* @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 begin iterator
*/
iterator begin () const { return iterator (mp_chunks); }
/**
* @brief end iterator
*/
iterator end () const { return iterator (); }
private:
chunk *mp_chunks;
chunk *mp_last_chunk;
};
}
#endif

View File

@ -50,10 +50,13 @@ int
D25View::exec_dialog (lay::LayoutView *view)
{
mp_view.reset (view);
mp_ui->d25_view->attach_view (view);
// @@@
return QDialog::exec ();
int ret = QDialog::exec ();
mp_ui->d25_view->attach_view (0);
return ret;
}
void

View File

@ -22,6 +22,13 @@
#include "layD25ViewWidget.h"
#include "layLayoutView.h"
#include "dbRecursiveShapeIterator.h"
#include "dbEdgeProcessor.h"
#include "dbPolygonGenerators.h"
#include "dbPolygonTools.h"
#include "tlException.h"
#include <QWheelEvent>
@ -32,9 +39,11 @@
namespace lay
{
// ------------------------------------------------------------------------------
D25ViewWidget::D25ViewWidget (QWidget *parent)
: QOpenGLWidget (parent),
m_program (0), m_dragging (false), m_rotating (false), m_cam_azimuth (0.0), m_cam_elevation (0.0)
m_shapes_program (0), m_dragging (false), m_rotating (false), m_cam_azimuth (0.0), m_cam_elevation (0.0)
{
QSurfaceFormat format;
format.setDepthBufferSize (24);
@ -50,7 +59,7 @@ D25ViewWidget::~D25ViewWidget ()
// destroy all underlying OpenGL resources.
makeCurrent();
delete m_program;
delete m_shapes_program;
doneCurrent();
}
@ -63,40 +72,110 @@ D25ViewWidget::initializeGL ()
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
// @@@ dark background
// glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// @@@ white background
glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
// @@@ glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"uniform highp mat4 matrix;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
static const char *shapes_vertex_shader_source =
"#version 320 es\n"
"#undef lowp\n"
"#undef highp\n"
"#undef mediump\n"
"layout (location = 0) in vec4 posAttr;\n"
"\n"
"void main() {\n"
" gl_Position = posAttr;\n"
"}\n";
static const char *shapes_geometry_shader_source =
"#version 320 es\n"
"#undef lowp\n"
"#undef highp\n"
"#undef mediump\n"
"\n"
"uniform vec4 color;\n"
"uniform vec3 illum;\n"
"out lowp vec4 vertexColor;\n"
"uniform mat4 matrix;\n"
"layout (triangles) in;\n"
"layout (triangle_strip, max_vertices = 3) out;\n"
"\n"
"void main() {\n"
" vec4 p0 = gl_in[0].gl_Position;\n"
" vec4 p1 = gl_in[1].gl_Position;\n"
" vec4 p2 = gl_in[2].gl_Position;\n"
" vec3 n = cross(p1.xyz - p0.xyz, p2.xyz - p0.xyz);\n"
" vertexColor.rgb = color.rgb * (max(0.0, dot(normalize(n), illum)) * 0.5 + 0.5);\n"
" vertexColor.a = 1.0;\n"
" gl_Position = matrix * p0;\n"
" EmitVertex();\n"
" gl_Position = matrix * p1;\n"
" EmitVertex();\n"
" gl_Position = matrix * p2;\n"
" EmitVertex();\n"
" EndPrimitive();\n"
"}\n";
static const char *shapes_fragment_shader_source =
"#version 320 es\n"
"#undef lowp\n"
"#undef highp\n"
"#undef mediump\n"
"in lowp vec4 vertexColor;\n"
"out lowp vec4 fragColor;\n"
"void main() {\n"
" fragColor = vertexColor;\n"
"}\n";
m_shapes_program = new QOpenGLShaderProgram (this);
if (! m_shapes_program->addShaderFromSourceCode (QOpenGLShader::Vertex, shapes_vertex_shader_source)) {
throw tl::Exception (std::string ("Shapes vertex shader compilation failed:\n") + tl::to_string (m_shapes_program->log ()));
}
if (! m_shapes_program->addShaderFromSourceCode (QOpenGLShader::Geometry, shapes_geometry_shader_source)) {
throw tl::Exception (std::string ("Shapes geometry shader compilation failed:\n") + tl::to_string (m_shapes_program->log ()));
}
if (! m_shapes_program->addShaderFromSourceCode (QOpenGLShader::Fragment, shapes_fragment_shader_source)) {
throw tl::Exception (std::string ("Shapes fragment shader compilation failed:\n") + tl::to_string (m_shapes_program->log ()));
}
if (! m_shapes_program->link ()) {
throw tl::Exception (std::string ("Shapes shader program linking failed failed:\n") + tl::to_string (m_shapes_program->log ()));
}
// grid plane shader source
static const char *gridplan_vertex_shader_source =
"#version 320 es\n"
"#undef lowp\n"
"#undef highp\n"
"#undef mediump\n"
"layout (location = 0) in vec4 posAttr;\n"
"uniform mat4 matrix;\n"
"\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix * posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
static const char *gridplan_fragment_shader_source =
"#version 320 es\n"
"#undef lowp\n"
"#undef highp\n"
"#undef mediump\n"
"uniform lowp vec4 color;\n"
"out lowp vec4 fragColor;\n"
"void main() {\n"
" gl_FragColor = col;\n"
" fragColor = color;\n"
"}\n";
m_program = new QOpenGLShaderProgram (this);
if (! m_program->addShaderFromSourceCode (QOpenGLShader::Vertex, vertexShaderSource)) {
throw tl::Exception (std::string ("Vertex shader compilation failed:\n") + tl::to_string (m_program->log ()));
m_gridplane_program = new QOpenGLShaderProgram (this);
if (! m_gridplane_program->addShaderFromSourceCode (QOpenGLShader::Vertex, gridplan_vertex_shader_source)) {
throw tl::Exception (std::string ("Grid plane vertex shader compilation failed:\n") + tl::to_string (m_gridplane_program->log ()));
}
if (! m_program->addShaderFromSourceCode (QOpenGLShader::Fragment, fragmentShaderSource)) {
throw tl::Exception (std::string ("Fragment shader compilation failed:\n") + tl::to_string (m_program->log ()));
if (! m_gridplane_program->addShaderFromSourceCode (QOpenGLShader::Fragment, gridplan_fragment_shader_source)) {
throw tl::Exception (std::string ("Grid plane fragment shader compilation failed:\n") + tl::to_string (m_gridplane_program->log ()));
}
if (! m_program->link ()) {
throw tl::Exception (std::string ("Linking failed:\n") + tl::to_string (m_program->log ()));
if (! m_gridplane_program->link ()) {
throw tl::Exception (std::string ("Grid plane shader program linking failed:\n") + tl::to_string (m_gridplane_program->log ()));
}
m_posAttr = m_program->attributeLocation ("posAttr");
m_colAttr = m_program->attributeLocation ("colAttr");
m_matrixUniform = m_program->uniformLocation ("matrix");
}
static QVector3D cam_direction (double azimuth, double elevation)
@ -143,7 +222,7 @@ D25ViewWidget::mousePressEvent (QMouseEvent *event)
}
void
D25ViewWidget::mouseReleaseEvent (QMouseEvent *event)
D25ViewWidget::mouseReleaseEvent (QMouseEvent * /*event*/)
{
m_dragging = false;
}
@ -210,6 +289,225 @@ printf("@@@ e=%g a=%g x,y,z=%g,%g,%g\n", m_cam_elevation, m_cam_azimuth, m
update ();
}
void
D25ViewWidget::attach_view (LayoutView *view)
{
if (mp_view != view) {
mp_view = view;
m_layers.clear ();
m_vertex_chunks.clear ();
if (mp_view) {
prepare_view ();
}
}
}
void
D25ViewWidget::prepare_view ()
{
double z = 0.0, dz = 0.2; // @@@
for (lay::LayerPropertiesConstIterator lp = mp_view->begin_layers (); ! lp.at_end (); ++lp) {
if (! lp->has_children () && lp->visible (true) && lp->cellview_index () >= 0 && lp->cellview_index () < int (mp_view->cellviews ())) {
lay::color_t color = lp->fill_color (true);
m_vertex_chunks.push_back (chunks_type ());
LayerInfo info;
// @@@ use alpha?
info.color[0] = (color & 0xff) / 255.0f;
info.color[1] = ((color >> 8) & 0xff) / 255.0f;
info.color[2] = ((color >> 16) & 0xff) / 255.0f;
info.color[3] = 1.0;
info.vertex_chunk = &m_vertex_chunks.back ();
m_layers.push_back (info);
const lay::CellView &cv = mp_view->cellview ((unsigned int) lp->cellview_index ());
render_layout (m_vertex_chunks.back (), cv->layout (), *cv.cell (), (unsigned int) lp->layer_index (), z, z + dz);
z += dz; // @@@
}
}
}
void
D25ViewWidget::render_polygon (D25ViewWidget::chunks_type &chunks, const db::Polygon &poly, double dbu, double zstart, double zstop)
{
if (poly.hull ().size () > 4) {
std::vector<db::Polygon> poly_heap;
db::split_polygon (poly, poly_heap);
for (std::vector<db::Polygon>::const_iterator p = poly_heap.begin (); p != poly_heap.end (); ++p) {
render_polygon (chunks, *p, dbu, zstart, zstop);
}
} else if (poly.hull ().size () >= 3) {
db::Point pts [4];
std::copy (poly.hull ().begin (), poly.hull ().end (), &pts [0]);
// triangle bottom
chunks.add (pts[0].x () * dbu);
chunks.add (zstart);
chunks.add (pts[0].y () * dbu);
chunks.add (pts[2].x () * dbu);
chunks.add (zstart);
chunks.add (pts[2].y () * dbu);
chunks.add (pts[1].x () * dbu);
chunks.add (zstart);
chunks.add (pts[1].y () * dbu);
// triangle top
chunks.add (pts[0].x () * dbu);
chunks.add (zstop);
chunks.add (pts[0].y () * dbu);
chunks.add (pts[1].x () * dbu);
chunks.add (zstop);
chunks.add (pts[1].y () * dbu);
chunks.add (pts[2].x () * dbu);
chunks.add (zstop);
chunks.add (pts[2].y () * dbu);
if (poly.hull ().size () == 4) {
// triangle bottom
chunks.add (pts[0].x () * dbu);
chunks.add (zstart);
chunks.add (pts[0].y () * dbu);
chunks.add (pts[3].x () * dbu);
chunks.add (zstart);
chunks.add (pts[3].y () * dbu);
chunks.add (pts[2].x () * dbu);
chunks.add (zstart);
chunks.add (pts[2].y () * dbu);
// triangle top
chunks.add (pts[0].x () * dbu);
chunks.add (zstop);
chunks.add (pts[0].y () * dbu);
chunks.add (pts[2].x () * dbu);
chunks.add (zstop);
chunks.add (pts[2].y () * dbu);
chunks.add (pts[3].x () * dbu);
chunks.add (zstop);
chunks.add (pts[3].y () * dbu);
}
}
}
void
D25ViewWidget::render_wall (D25ViewWidget::chunks_type &chunks, const db::Edge &edge, double dbu, double zstart, double zstop)
{
chunks.add (edge.p1 ().x () * dbu);
chunks.add (zstart);
chunks.add (edge.p1 ().y () * dbu);
chunks.add (edge.p2 ().x () * dbu);
chunks.add (zstop);
chunks.add (edge.p2 ().y () * dbu);
chunks.add (edge.p1 ().x () * dbu);
chunks.add (zstop);
chunks.add (edge.p1 ().y () * dbu);
chunks.add (edge.p1 ().x () * dbu);
chunks.add (zstart);
chunks.add (edge.p1 ().y () * dbu);
chunks.add (edge.p2 ().x () * dbu);
chunks.add (zstart);
chunks.add (edge.p2 ().y () * dbu);
chunks.add (edge.p2 ().x () * dbu);
chunks.add (zstop);
chunks.add (edge.p2 ().y () * dbu);
}
void
D25ViewWidget::render_layout (D25ViewWidget::chunks_type &chunks, const db::Layout &layout, const db::Cell &cell, unsigned int layer, double zstart, double zstop)
{
db::EdgeProcessor ep;
std::vector<db::Polygon> poly_heap;
// @@@ hidden cells, hierarchy depth ...
db::RecursiveShapeIterator s (layout, cell, layer);
s.shape_flags (db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes);
for ( ; ! s.at_end (); ++s) {
db::Polygon polygon;
s->polygon (polygon);
polygon.transform (s.trans ());
if (polygon.holes () == 0 && polygon.hull ().size () <= 4) {
render_polygon (chunks, polygon, layout.dbu (), zstart, zstop);
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
render_wall (chunks, *e, layout.dbu (), zstart, zstop);
}
} else {
poly_heap.clear ();
ep.clear ();
ep.insert_sequence (polygon.begin_edge ());
{
db::PolygonContainer pc (poly_heap);
db::PolygonGenerator out (pc, true /*resolve holes*/, false /*min coherence for splitting*/);
db::SimpleMerge op;
ep.process (out, op);
}
for (std::vector<db::Polygon>::const_iterator p = poly_heap.begin (); p != poly_heap.end (); ++p) {
render_polygon (chunks, *p, layout.dbu (), zstart, zstop);
}
poly_heap.clear ();
ep.clear ();
ep.insert_sequence (polygon.begin_edge ());
{
db::PolygonContainer pc (poly_heap);
db::PolygonGenerator out (pc, false /*don't resolve holes*/, false /*min coherence for splitting*/);
db::SimpleMerge op;
ep.process (out, op);
}
for (std::vector<db::Polygon>::const_iterator p = poly_heap.begin (); p != poly_heap.end (); ++p) {
for (db::Polygon::polygon_edge_iterator e = p->begin_edge (); ! e.at_end (); ++e) {
render_wall (chunks, *e, layout.dbu (), zstart, zstop);
}
}
}
}
}
void
D25ViewWidget::paintGL ()
{
@ -217,70 +515,52 @@ D25ViewWidget::paintGL ()
glViewport (0, 0, width () * retinaScale, height () * retinaScale);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor (1.0, 1.0, 1.0, 1.0);
// @@@ white background: glClearColor (1.0, 1.0, 1.0, 1.0);
m_program->bind ();
const int positions = 0;
m_shapes_program->bind ();
QMatrix4x4 matrix;
matrix.perspective (60.0f, float (width ()) / float (height ()), 0.1f, 100.0f);
matrix *= m_cam_trans;
m_program->setUniformValue (m_matrixUniform, matrix);
m_shapes_program->setUniformValue ("matrix", matrix);
m_shapes_program->setUniformValue ("illum", QVector3D (-3.0, -4.0, 2.0).normalized ());
glEnableVertexAttribArray (m_posAttr);
glEnableVertexAttribArray (m_colAttr);
glEnableVertexAttribArray (positions);
GLfloat vertices[] = {
0.0f, 0.707f, -1.0,
-0.5f, -0.5f, -1.0,
0.5f, -0.5f, -1.0,
-0.6 + 0.0f, 0.0707f, -1.0,
-0.6 + -0.05f, -0.05f, -1.0,
-0.6 + 0.05f, -0.05f, -1.0,
0.0f, 0.707f, -1.5,
-0.5f, -0.5f, -1.5,
0.5f, -0.5f, -1.5,
0.0f, 0.707f, -2.0,
-0.5f, -0.5f, -2.0,
0.5f, -0.5f, -2.0
};
for (std::list<LayerInfo>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f
};
m_shapes_program->setUniformValue ("color", l->color [0], l->color [1], l->color [2], l->color [3]);
glVertexAttribPointer (m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer (m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
for (chunks_type::iterator c = l->vertex_chunk->begin (); c != l->vertex_chunk->end (); ++c) {
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, c->front ());
glDrawArrays (GL_TRIANGLES, 0, c->size () / 3);
}
glDrawArrays (GL_TRIANGLES, 0, 12);
}
glDisableVertexAttribArray (positions);
m_shapes_program->release ();
m_gridplane_program->bind ();
glEnableVertexAttribArray (positions);
m_gridplane_program->setUniformValue ("matrix", matrix);
// @@@
GLfloat plane_vertices[] = {
-1.05, 0.0, -2.05, -1.05, 0.0, 0.05, 1.05, 0.0, 0.05,
-1.05, 0.0, -2.05, 1.05, 0.0, 0.05, 1.05, 0.0, -2.05
};
GLfloat plane_colors[] = {
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f
};
m_gridplane_program->setUniformValue ("color", 1.0, 1.0, 1.0, 0.2f);
glVertexAttribPointer (m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, plane_vertices);
glVertexAttribPointer (m_colAttr, 4, GL_FLOAT, GL_FALSE, 0, plane_colors);
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, plane_vertices);
glDrawArrays (GL_TRIANGLES, 0, 6);
@ -305,55 +585,16 @@ D25ViewWidget::paintGL ()
1.0, 0.0, 0.0, -1.0, 0.0, 0.0
};
GLfloat gridline_colors[] = {
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f,
1.0f, 1.0f, 1.0f, 0.2f
};
m_shapes_program->setUniformValue ("vertexColor", 1.0, 1.0, 1.0, 0.2f);
glVertexAttribPointer (m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, gridline_vertices);
glVertexAttribPointer (m_colAttr, 4, GL_FLOAT, GL_FALSE, 0, gridline_colors);
glVertexAttribPointer (positions, 3, GL_FLOAT, GL_FALSE, 0, gridline_vertices);
glLineWidth (2.0);
glDrawArrays (GL_LINES, 0, 36);
glDisableVertexAttribArray (m_posAttr);
glDisableVertexAttribArray (m_colAttr);
glDisableVertexAttribArray (positions);
m_program->release ();
m_shapes_program->release ();
}
void

View File

@ -32,9 +32,21 @@
#include <QPoint>
#include <QVector3D>
#include "dbPolygon.h"
#include "layD25MemChunks.h"
namespace db
{
class Layout;
class Cell;
}
namespace lay
{
class LayoutView;
class D25ViewWidget
: public QOpenGLWidget,
private QOpenGLFunctions
@ -50,11 +62,12 @@ public:
void mouseReleaseEvent (QMouseEvent *event);
void mouseMoveEvent (QMouseEvent *event);
void attach_view (lay::LayoutView *view);
private:
QOpenGLShaderProgram *m_program;
GLuint m_posAttr;
GLuint m_colAttr;
GLuint m_matrixUniform;
typedef lay::mem_chunks<GLfloat, 1024 * 9> chunks_type;
QOpenGLShaderProgram *m_shapes_program, *m_gridplane_program;
QMatrix4x4 m_cam_trans;
bool m_dragging, m_rotating;
QVector3D m_cam_position;
@ -62,12 +75,26 @@ private:
QPoint m_start_pos;
QVector3D m_start_cam_position;
double m_start_cam_azimuth, m_start_cam_elevation;
lay::LayoutView *mp_view;
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);
void update_cam_trans ();
void 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);
};
}

View File

@ -11,11 +11,13 @@ LIBS += -L$$DESTDIR/.. -lklayout_rdb -lklayout_ant
HEADERS = \
layD25View.h \
layD25ViewWidget.h \
layD25MemChunks.h
SOURCES = \
layD25View.cc \
layD25ViewWidget.cc \
layD25Plugin.cc
layD25Plugin.cc \
layD25MemChunks.cc
FORMS = \
D25View.ui \

View File

@ -21,466 +21,70 @@
*/
#include "dbDXFReader.h"
#include "dbTestSupport.h"
#include "layD25MemChunks.h"
#include "tlUnitTest.h"
#include <stdlib.h>
static db::LayerMap string2lm (const char *map)
TEST(1_Basic)
{
db::LayerMap lm;
unsigned int ln = 0;
tl::Extractor ex (map);
while (! ex.at_end ()) {
std::string n;
int l;
ex.read_word_or_quoted (n);
ex.test (":");
ex.read (l);
ex.test (",");
lm.map (n, ln++, db::LayerProperties (l, 0));
}
return lm;
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);
}
static void do_run_test (tl::TestBase *_this, const std::string &fn, const std::string &fn_au, const db::DXFReaderOptions &opt, bool as_oas)
TEST(2_Copy)
{
db::LoadLayoutOptions options;
options.set_options (new db::DXFReaderOptions (opt));
lay::mem_chunks<int, 2> ch1;
ch1.add (1);
ch1.add (17);
ch1.add (42);
db::Layout layout;
lay::mem_chunks<int, 2> ch (ch1);
{
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout, options);
}
lay::mem_chunks<int, 2>::iterator c = ch.begin ();
db::compare_layouts (_this, layout, fn_au, as_oas ? db::WriteOAS : db::WriteGDS2, 1);
}
static void run_test (tl::TestBase *_this, const char *file, const char *file_au, const db::DXFReaderOptions &opt = db::DXFReaderOptions (), bool as_oas = false)
{
std::string fn = tl::testsrc_private () + "/testdata/dxf/" + file;
std::string fn_au = tl::testsrc_private () + std::string ("/testdata/dxf/") + file_au;
do_run_test (_this, fn, fn_au, opt, as_oas);
}
static void run_test_public (tl::TestBase *_this, const char *file, const char *file_au, const db::DXFReaderOptions &opt = db::DXFReaderOptions (), bool as_oas = false)
{
std::string fn = tl::testsrc () + "/testdata/dxf/" + file;
std::string fn_au = tl::testsrc () + std::string ("/testdata/dxf/") + file_au;
do_run_test (_this, fn, fn_au, opt, as_oas);
}
TEST(KeepLN1)
{
db::DXFReaderOptions opt;
run_test_public (_this, "keep_ln.dxf.gz", "keep_ln1_au.oas.gz", opt, true /*because of layer names*/);
}
TEST(KeepLN2)
{
db::DXFReaderOptions opt;
opt.keep_layer_names = true;
run_test_public (_this, "keep_ln.dxf.gz", "keep_ln2_au.oas.gz", opt, true /*because of layer names*/);
}
TEST(1a)
{
run_test (_this, "t1.dxf.gz", "t1a_au.gds.gz");
}
TEST(1b)
{
db::DXFReaderOptions opt;
opt.dbu = 0.01;
opt.unit = 5.0;
run_test (_this, "t1.dxf.gz", "t1b_au.gds.gz", opt);
}
TEST(2)
{
run_test (_this, "t2.dxf.gz", "t2_au.gds.gz");
}
TEST(3)
{
run_test (_this, "t3.dxf.gz", "t3_au.gds.gz");
}
TEST(4)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("Metal:1,Metal2:5");
opt.create_other_layers = true;
run_test (_this, "t4.dxf.gz", "t4_au.gds.gz", opt);
}
TEST(5)
{
run_test (_this, "t5.dxf.gz", "t5_au.gds.gz");
}
TEST(6)
{
run_test (_this, "t6.dxf.gz", "t6_au.gds.gz");
}
TEST(7)
{
run_test (_this, "t7.dxf.gz", "t7_au.gds.gz");
}
TEST(8)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("Metal:4,Kommentare:3,Bemassung:2");
opt.create_other_layers = true;
run_test (_this, "t8.dxf.gz", "t8_au.gds.gz", opt);
}
TEST(9)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("Bemassung:2,Metal:5,Kommentare:4");
opt.create_other_layers = true;
run_test (_this, "t9.dxf.gz", "t9_au.gds.gz", opt);
}
TEST(10)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("METAL:1,KOMMENTARE:4");
opt.create_other_layers = true;
run_test (_this, "t10.dxf.gz", "t10_au.gds.gz", opt);
}
TEST(11)
{
run_test (_this, "t11.dxf.gz", "t11_au.gds.gz");
}
TEST(12)
{
run_test (_this, "t12.dxf.gz", "t12_au.gds.gz");
}
TEST(14)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("'A11-STRUKTUR__E_TYP_':10,A21_NITRID:11,'B11-KONTAKT':9,'B11-STRUKTUR':3,HELLFELD:7,MASKE:5,NORM_MIN_MAX_WAFER:6,RASTER:2,_BEGRENZUNG_A11_A21_A31_B1:8");
opt.create_other_layers = true;
run_test (_this, "t14.dxf.gz", "t14_au.gds.gz", opt);
}
TEST(15)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("TEXT:4,IGBT:5,Wire:7,Ceramic:11,LAYER_1:14,Diode:18,'DBC TOP Plate':19,'Terminal Position':20");
opt.create_other_layers = true;
run_test (_this, "t15.dxf.gz", "t15_au.gds.gz", opt);
}
TEST(16)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("TEXT:4,IGBT:5,Wire:7,Ceramic:11,LAYER_1:14,Diode:18,'DBC TOP Plate':19,'Terminal Position':20");
opt.create_other_layers = true;
run_test (_this, "t16.dxf.gz", "t16_au.gds.gz", opt);
}
TEST(17)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("TEXT:4,IGBT:5,Wire:7,Ceramic:11,LAYER_1:14,Diode:18,'DBC TOP Plate':19,'Terminal Position':20");
opt.create_other_layers = true;
run_test (_this, "t17.dxf.gz", "t17_au.gds.gz", opt);
}
TEST(18)
{
run_test (_this, "t18.dxf.gz", "t18_au.gds.gz");
}
TEST(19)
{
run_test (_this, "t19.dxf.gz", "t19_au.gds.gz");
}
TEST(20)
{
run_test (_this, "t20.dxf.gz", "t20_au.gds.gz");
}
TEST(21)
{
run_test (_this, "t21.dxf.gz", "t21_au.gds.gz");
}
TEST(22)
{
run_test (_this, "t22.dxf.gz", "t22_au.gds.gz");
}
TEST(23a)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 0;
opt.circle_points = 10;
run_test (_this, "t23.dxf.gz", "t23a_au.gds.gz", opt);
}
TEST(23b)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 1;
opt.circle_points = 10;
run_test (_this, "t23.dxf.gz", "t23b_au.gds.gz", opt);
}
TEST(23c)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 2;
opt.circle_points = 10;
run_test (_this, "t23.dxf.gz", "t23c_au.gds.gz", opt);
}
TEST(23d)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 3;
opt.circle_points = 10;
run_test (_this, "t23.dxf.gz", "t23d_au.gds.gz", opt);
}
TEST(23e)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 10;
run_test (_this, "t23.dxf.gz", "t23e_au.gds.gz", opt);
}
TEST(26a)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 0;
opt.circle_points = 100;
run_test (_this, "t26.dxf.gz", "t26a_au.gds.gz", opt);
}
TEST(26b)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 1;
opt.circle_points = 100;
run_test (_this, "t26.dxf.gz", "t26b_au.gds.gz", opt);
}
TEST(26c)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 2;
opt.circle_points = 100;
run_test (_this, "t26.dxf.gz", "t26c_au.gds.gz", opt);
}
TEST(26d)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 3;
opt.circle_points = 100;
run_test (_this, "t26.dxf.gz", "t26d_au.gds.gz", opt);
}
TEST(26e)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 100;
run_test (_this, "t26.dxf.gz", "t26e_au.gds.gz", opt);
}
TEST(27a)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 0;
opt.circle_points = 10;
run_test (_this, "t27.dxf.gz", "t27a_au.gds.gz", opt);
}
TEST(27b)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 1;
opt.circle_points = 10;
run_test (_this, "t27.dxf.gz", "t27b_au.gds.gz", opt);
}
TEST(27c)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 2;
opt.circle_points = 10;
run_test (_this, "t27.dxf.gz", "t27c_au.gds.gz", opt);
}
TEST(27d)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 3;
opt.circle_points = 10;
run_test (_this, "t27.dxf.gz", "t27d_au.gds.gz", opt);
}
TEST(27e)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 10;
run_test (_this, "t27.dxf.gz", "t27e_au.gds.gz", opt);
}
TEST(28)
{
run_test (_this, "t28.dxf.gz", "t28_au.gds.gz");
}
TEST(29)
{
run_test (_this, "t29.dxf.gz", "t29_au.gds.gz");
}
TEST(29a)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 1000;
opt.circle_accuracy = 1;
run_test (_this, "t29.dxf.gz", "t29a_au.gds.gz", opt);
}
TEST(29b)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 1000;
opt.circle_accuracy = 0.1;
run_test (_this, "t29.dxf.gz", "t29b_au.gds.gz", opt);
}
TEST(29c)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 1000;
opt.circle_accuracy = 0.01;
run_test (_this, "t29.dxf.gz", "t29c_au.gds.gz", opt);
}
TEST(29d)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1;
opt.polyline_mode = 4;
opt.circle_points = 1000;
opt.circle_accuracy = 0.001;
run_test (_this, "t29.dxf.gz", "t29d_au.gds.gz", opt);
}
TEST(30)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1000;
opt.polyline_mode = 4;
opt.circle_points = 1000;
opt.circle_accuracy = 0.001;
run_test (_this, "t30.dxf.gz", "t30d_au.gds.gz", opt);
}
// accuracy
TEST(31)
{
db::DXFReaderOptions opt;
opt.dbu = 0.001;
opt.unit = 1000;
opt.contour_accuracy = 0;
run_test (_this, "t31.dxf.gz", "t31a_au.gds.gz", opt);
opt.contour_accuracy = 0.005;
run_test (_this, "t31.dxf.gz", "t31b_au.gds.gz", opt);
opt.contour_accuracy = 0.01;
run_test (_this, "t31.dxf.gz", "t31c_au.gds.gz", opt);
opt.contour_accuracy = 0.02;
run_test (_this, "t31.dxf.gz", "t31d_au.gds.gz", opt);
}
// issue #198
TEST(32)
{
db::DXFReaderOptions opt;
opt.layer_map = string2lm ("L11D0:1,L12D0:2");
opt.create_other_layers = false;
opt.polyline_mode = 3;
opt.contour_accuracy = 0.0;
run_test_public (_this, "round_path.dxf.gz", "t32a_au.gds.gz", opt);
opt.contour_accuracy = 0.1;
run_test_public (_this, "round_path.dxf.gz", "t32b_au.gds.gz", opt);
opt.contour_accuracy = 1.0;
run_test_public (_this, "round_path.dxf.gz", "t32c_au.gds.gz", opt);
opt.polyline_mode = 4;
run_test_public (_this, "round_path.dxf.gz", "t32d_au.gds.gz", opt);
opt.polyline_mode = 2;
run_test_public (_this, "round_path.dxf.gz", "t32e_au.gds.gz", opt);
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

@ -2,5 +2,5 @@
TEMPLATE = subdirs
!equals(HAVE_QT, "0") {
SUBDIRS = lay_plugin
SUBDIRS = lay_plugin unit_tests
}