mirror of https://github.com/KLayout/klayout.git
WIP: tagged area collector
This commit is contained in:
parent
b74e9567fd
commit
863d835ff7
|
|
@ -7,6 +7,7 @@ include($$PWD/../../lib.pri)
|
||||||
DEFINES += MAKE_DB_LIBRARY
|
DEFINES += MAKE_DB_LIBRARY
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
|
dbAreaCollector.cc \
|
||||||
dbArray.cc \
|
dbArray.cc \
|
||||||
dbBox.cc \
|
dbBox.cc \
|
||||||
dbBoxConvert.cc \
|
dbBoxConvert.cc \
|
||||||
|
|
@ -232,6 +233,7 @@ SOURCES = \
|
||||||
dbShapeCollectionUtils.cc
|
dbShapeCollectionUtils.cc
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
|
dbAreaCollector.h \
|
||||||
dbArray.h \
|
dbArray.h \
|
||||||
dbBoxConvert.h \
|
dbBoxConvert.h \
|
||||||
dbBox.h \
|
dbBox.h \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2024 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 "dbAreaCollector.h"
|
||||||
|
|
||||||
|
namespace db
|
||||||
|
{
|
||||||
|
|
||||||
|
// .. nothing yet ..
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2024 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_dbAreaCollector
|
||||||
|
#define HDR_dbAreaCollector
|
||||||
|
|
||||||
|
#include "dbCommon.h"
|
||||||
|
|
||||||
|
#include "dbEdgeProcessor.h"
|
||||||
|
#include "tlBitSetMap.h"
|
||||||
|
|
||||||
|
namespace db {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The receiver for the tagged partial areas
|
||||||
|
*
|
||||||
|
* See description of tagged_area_collector for details.
|
||||||
|
*/
|
||||||
|
template <class Value>
|
||||||
|
class DB_PUBLIC tagged_area_receiver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
tagged_area_receiver<Value> () { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~tagged_area_receiver () { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This method gets called when the scanline process starts
|
||||||
|
*/
|
||||||
|
virtual void start () { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This method gets called when the scanline process finishes
|
||||||
|
*/
|
||||||
|
virtual void finish () { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds some partial area with the given value
|
||||||
|
*/
|
||||||
|
virtual void add_area (area_type /*area*/, const Value & /*value*/) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A helper class providing an inserter that is the connection between the receiver and the provider
|
||||||
|
*/
|
||||||
|
template <class Value>
|
||||||
|
class DB_PUBLIC tagged_area_inserter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
tagged_area_inserter<Value> (area_type area, tagged_area_receiver<Value> *receiver)
|
||||||
|
: m_area (area), mp_receiver (receiver)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
// methods necessary, so this object can act as an inserter
|
||||||
|
tagged_area_inserter<Value> &operator* () { return *this; }
|
||||||
|
tagged_area_inserter<Value> &operator++ (int) { return *this; }
|
||||||
|
|
||||||
|
tagged_area_inserter<Value> &operator= (const Value &value)
|
||||||
|
{
|
||||||
|
mp_receiver->add_area (m_area, value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
area_type m_area;
|
||||||
|
tagged_area_receiver<Value> *mp_receiver;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Provides the operation and edge receiver part of the tagged area collector
|
||||||
|
*
|
||||||
|
* Use this object both as the edge operator and as an edge collector.
|
||||||
|
* After running the edge processor, use "area" to obtain the area.
|
||||||
|
*
|
||||||
|
* This method collects "tagged areas". That is, each field of the area divided by
|
||||||
|
* the edges carries a bit set which is made from the combinations of overlapping
|
||||||
|
* layers. The layers are given by the property number where the number is the
|
||||||
|
* bit set in the bit field. Hence, every field is associated with a bit set.
|
||||||
|
*
|
||||||
|
* The Area collector will now report the field's areas for accumulation together with
|
||||||
|
* a field value that is obtained from the bit set map. As the bit set map
|
||||||
|
* may deliver multiple fields, multiple such values can be present for each field.
|
||||||
|
* The areas are reported through the tagged_area_receiver object. This object
|
||||||
|
* is supposed to add up the areas in an application specific fashion.
|
||||||
|
*/
|
||||||
|
template <class Value>
|
||||||
|
class DB_PUBLIC tagged_area_collector
|
||||||
|
: public EdgeEvaluatorBase,
|
||||||
|
public EdgeSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
tagged_area_collector<Value> (const tl::bit_set_map<Value> &bsm, tagged_area_receiver<Value> &receiver)
|
||||||
|
: mp_bsm (&bsm), mp_receiver (&receiver)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation of EdgeEvaluatorBase
|
||||||
|
virtual void reset ()
|
||||||
|
{
|
||||||
|
m_prev = tl::BitSet ();
|
||||||
|
m_state = tl::BitSet ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void begin_group ()
|
||||||
|
{
|
||||||
|
m_prev = m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int edge (bool north, bool enter, property_type p)
|
||||||
|
{
|
||||||
|
if (north) {
|
||||||
|
|
||||||
|
m_counts.resize (p + 1, 0);
|
||||||
|
|
||||||
|
int &count = m_counts [p];
|
||||||
|
if (enter) {
|
||||||
|
if (count == 0) {
|
||||||
|
m_state.set (p);
|
||||||
|
}
|
||||||
|
++count;
|
||||||
|
} else {
|
||||||
|
--count;
|
||||||
|
if (count == 0) {
|
||||||
|
m_state.reset (p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this will call "put" when the group is finished
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool is_reset () const
|
||||||
|
{
|
||||||
|
// that is a dummy
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool prefer_touch () const
|
||||||
|
{
|
||||||
|
// leave events come before enter events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool selects_edges () const
|
||||||
|
{
|
||||||
|
// select_edge is not needed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation of EdgeSink
|
||||||
|
|
||||||
|
virtual void start ()
|
||||||
|
{
|
||||||
|
mp_receiver->start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush ()
|
||||||
|
{
|
||||||
|
mp_receiver->finish ();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void put (const db::Edge &edge)
|
||||||
|
{
|
||||||
|
area_type partial_area = area_type (edge.p1 ().x () + edge.p2 ().x ()) * area_type (edge.dy ()) * 0.5;
|
||||||
|
mp_bsm->lookup (m_prev, tagged_area_inserter<Value> (partial_area, mp_receiver));
|
||||||
|
mp_bsm->lookup (m_state, tagged_area_inserter<Value> (-partial_area, mp_receiver));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
area_type m_area_sum;
|
||||||
|
const tl::bit_set_map<Value> *mp_bsm;
|
||||||
|
tagged_area_receiver<Value> *mp_receiver;
|
||||||
|
tl::BitSet m_prev, m_state;
|
||||||
|
std::vector<int> m_counts;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -1694,6 +1694,7 @@ public:
|
||||||
void next_coincident ()
|
void next_coincident ()
|
||||||
{
|
{
|
||||||
m_pn = m_ps = 0;
|
m_pn = m_ps = 0;
|
||||||
|
mp_op->begin_group ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_coincident ()
|
void end_coincident ()
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,7 @@ public:
|
||||||
|
|
||||||
virtual void reset () { }
|
virtual void reset () { }
|
||||||
virtual void reserve (size_t /*n*/) { }
|
virtual void reserve (size_t /*n*/) { }
|
||||||
|
virtual void begin_group () { }
|
||||||
virtual int edge (bool /*north*/, bool /*enter*/, property_type /*p*/) { return 0; }
|
virtual int edge (bool /*north*/, bool /*enter*/, property_type /*p*/) { return 0; }
|
||||||
virtual int select_edge (bool /*horizontal*/, property_type /*p*/) { return 0; }
|
virtual int select_edge (bool /*horizontal*/, property_type /*p*/) { return 0; }
|
||||||
virtual int compare_ns () const { return 0; }
|
virtual int compare_ns () const { return 0; }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
KLayout Layout Viewer
|
||||||
|
Copyright (C) 2006-2024 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 "dbAreaCollector.h"
|
||||||
|
#include "dbEdgeProcessor.h"
|
||||||
|
#include "tlUnitTest.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class AreaReceiver
|
||||||
|
: public db::tagged_area_receiver<double>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
AreaReceiver () : m_sum (0.0) { }
|
||||||
|
virtual void add_area (area_type area, const double &value) { m_sum += value * area; }
|
||||||
|
|
||||||
|
double get () const { return m_sum; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(1)
|
||||||
|
{
|
||||||
|
db::EdgeProcessor ep;
|
||||||
|
|
||||||
|
ep.insert (db::SimplePolygon (db::Box (0, 0, 1000, 2000)), 0);
|
||||||
|
ep.insert (db::SimplePolygon (db::Box (500, 1000, 1500, 3000)), 1);
|
||||||
|
|
||||||
|
// set up an XOR mask where 1-vs-0 is counted twice
|
||||||
|
tl::bit_set_map<double> bsm;
|
||||||
|
tl::BitSetMask bs0;
|
||||||
|
bs0.set (0, tl::BitSetMask::True);
|
||||||
|
bs0.set (1, tl::BitSetMask::False);
|
||||||
|
tl::BitSetMask bs1;
|
||||||
|
bs0.set (0, tl::BitSetMask::False);
|
||||||
|
bs0.set (1, tl::BitSetMask::True);
|
||||||
|
bsm.insert (bs0, 1.0);
|
||||||
|
bsm.insert (bs1, 2.0);
|
||||||
|
bsm.sort ();
|
||||||
|
|
||||||
|
AreaReceiver rec;
|
||||||
|
db::tagged_area_collector<double> coll (bsm, rec);
|
||||||
|
ep.process (coll, coll);
|
||||||
|
|
||||||
|
EXPECT_EQ (rec.get (), 0.0); // @@@
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ TARGET = db_tests
|
||||||
include($$PWD/../../lib_ut.pri)
|
include($$PWD/../../lib_ut.pri)
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
|
dbAreaCollectorTests.cc \
|
||||||
dbCompoundOperationTests.cc \
|
dbCompoundOperationTests.cc \
|
||||||
dbFillToolTests.cc \
|
dbFillToolTests.cc \
|
||||||
dbLogTests.cc \
|
dbLogTests.cc \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue