mirror of https://github.com/KLayout/klayout.git
WIP: properties for regions, tests for flat and original layer regions
This commit is contained in:
parent
1dfa5abc9a
commit
0ba719ad84
|
|
@ -279,7 +279,7 @@ void AsIfFlatRegion::merge_polygons_to (db::Shapes &output, bool min_coherence,
|
||||||
|
|
||||||
if (need_split_props) {
|
if (need_split_props) {
|
||||||
|
|
||||||
db::Shapes result;
|
db::Shapes result (output.is_editable ());
|
||||||
|
|
||||||
std::vector<std::pair<db::properties_id_type, const db::Polygon *> > polygons_by_prop_id;
|
std::vector<std::pair<db::properties_id_type, const db::Polygon *> > polygons_by_prop_id;
|
||||||
polygons_by_prop_id.reserve (n);
|
polygons_by_prop_id.reserve (n);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ namespace
|
||||||
if (! m_rec_iter.at_end ()) {
|
if (! m_rec_iter.at_end ()) {
|
||||||
m_rec_iter->edge_pair (m_shape);
|
m_rec_iter->edge_pair (m_shape);
|
||||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||||
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::Properties) != 0 ? m_rec_iter->prop_id () : 0;
|
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ namespace
|
||||||
if (! m_rec_iter.at_end ()) {
|
if (! m_rec_iter.at_end ()) {
|
||||||
m_rec_iter->edge (m_shape);
|
m_rec_iter->edge (m_shape);
|
||||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||||
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::Properties) != 0 ? m_rec_iter->prop_id () : 0;
|
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ namespace
|
||||||
if (! m_rec_iter.at_end ()) {
|
if (! m_rec_iter.at_end ()) {
|
||||||
m_rec_iter->polygon (m_polygon);
|
m_rec_iter->polygon (m_polygon);
|
||||||
m_polygon.transform (m_iter_trans * m_rec_iter.trans (), false);
|
m_polygon.transform (m_iter_trans * m_rec_iter.trans (), false);
|
||||||
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::Properties) != 0 ? m_rec_iter->prop_id () : 0;
|
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,10 +240,10 @@ OriginalLayerRegion::count () const
|
||||||
size_t nn = 0;
|
size_t nn = 0;
|
||||||
if (iter.multiple_layers ()) {
|
if (iter.multiple_layers ()) {
|
||||||
for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
|
for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
|
||||||
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & db::ShapeIterator::Regions);
|
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
|
||||||
}
|
}
|
||||||
} else if (iter.layer () < layout.layers ()) {
|
} else if (iter.layer () < layout.layers ()) {
|
||||||
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & db::ShapeIterator::Regions);
|
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
|
||||||
}
|
}
|
||||||
n += cc.weight (*c) * nn;
|
n += cc.weight (*c) * nn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ namespace
|
||||||
if (! m_rec_iter.at_end ()) {
|
if (! m_rec_iter.at_end ()) {
|
||||||
m_rec_iter->text (m_shape);
|
m_rec_iter->text (m_shape);
|
||||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||||
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::Properties) != 0 ? m_rec_iter->prop_id () : 0;
|
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ public:
|
||||||
Properties = (1 << Null),
|
Properties = (1 << Null),
|
||||||
All = (1 << Null) - 1,
|
All = (1 << Null) - 1,
|
||||||
AllWithProperties = (1 << (Null + 1)) - 1,
|
AllWithProperties = (1 << (Null + 1)) - 1,
|
||||||
|
RegardProperties = (1 << (Null + 1)), // special flag, not evaluated on query but in receiver (indicates to regard shapes with different properties as different entities)
|
||||||
Nothing = 0
|
Nothing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1266,7 +1267,8 @@ public:
|
||||||
{
|
{
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||||
if ((flags & (*l)->type_mask ()) != 0) {
|
unsigned int tm = (*l)->type_mask ();
|
||||||
|
if (((flags & db::ShapeIterator::Properties) == 0 || (tm & db::ShapeIterator::Properties) != 0) && (flags & tm) != 0) {
|
||||||
n += (*l)->size ();
|
n += (*l)->size ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1465,6 +1467,25 @@ public:
|
||||||
return (db::Cell *) (size_t (mp_cell) & ~3);
|
return (db::Cell *) (size_t (mp_cell) & ~3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a flag indicating whether an update is needed
|
||||||
|
*
|
||||||
|
* This flag means that the shape collection has been modified and the bounding box
|
||||||
|
* and the quad trees will be recomputed (internally).
|
||||||
|
*/
|
||||||
|
bool is_dirty () const
|
||||||
|
{
|
||||||
|
return (size_t (mp_cell) & 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a value indicating that the shape collection is constructed with editable scope
|
||||||
|
*/
|
||||||
|
bool is_editable () const
|
||||||
|
{
|
||||||
|
return (size_t (mp_cell) & 2) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the pointer to layout that the shapes container belongs to
|
* @brief Gets the pointer to layout that the shapes container belongs to
|
||||||
*
|
*
|
||||||
|
|
@ -1472,7 +1493,7 @@ public:
|
||||||
*/
|
*/
|
||||||
db::Layout *layout () const;
|
db::Layout *layout () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the redo method
|
* @brief Implementation of the redo method
|
||||||
*/
|
*/
|
||||||
void redo (db::Op *op);
|
void redo (db::Op *op);
|
||||||
|
|
@ -1504,18 +1525,6 @@ private:
|
||||||
return m_layers;
|
return m_layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract dirty flag from mp_cell
|
|
||||||
bool is_dirty () const
|
|
||||||
{
|
|
||||||
return (size_t (mp_cell) & 1) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract editable flag from mp_cell
|
|
||||||
bool is_editable () const
|
|
||||||
{
|
|
||||||
return (size_t (mp_cell) & 2) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the shape repository associated with this container
|
// get the shape repository associated with this container
|
||||||
db::GenericRepository &shape_repository () const;
|
db::GenericRepository &shape_repository () const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -755,7 +755,7 @@ inline unsigned int iterator_type_mask (ShapeIterator::user_object_type::tag)
|
||||||
template <class Sh>
|
template <class Sh>
|
||||||
inline unsigned int iterator_type_mask (db::object_tag< db::object_with_properties<Sh> >)
|
inline unsigned int iterator_type_mask (db::object_tag< db::object_with_properties<Sh> >)
|
||||||
{
|
{
|
||||||
return iterator_type_mask (typename Sh::tag ());
|
return iterator_type_mask (typename Sh::tag ()) | ShapeIterator::Properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Sh, class StableTag>
|
template <class Sh, class StableTag>
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,7 @@ static db::Layout *layout (db::Shapes *sh)
|
||||||
|
|
||||||
static unsigned int s_all () { return db::ShapeIterator::All; }
|
static unsigned int s_all () { return db::ShapeIterator::All; }
|
||||||
static unsigned int s_all_with_properties () { return db::ShapeIterator::AllWithProperties; }
|
static unsigned int s_all_with_properties () { return db::ShapeIterator::AllWithProperties; }
|
||||||
|
static unsigned int s_regard_properties () { return db::ShapeIterator::RegardProperties; }
|
||||||
static unsigned int s_properties () { return db::ShapeIterator::Properties; }
|
static unsigned int s_properties () { return db::ShapeIterator::Properties; }
|
||||||
static unsigned int s_polygons () { return db::ShapeIterator::Polygons; }
|
static unsigned int s_polygons () { return db::ShapeIterator::Polygons; }
|
||||||
static unsigned int s_regions () { return db::ShapeIterator::Regions; }
|
static unsigned int s_regions () { return db::ShapeIterator::Regions; }
|
||||||
|
|
@ -1335,6 +1336,10 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
|
||||||
gsi::method ("SProperties|#s_properties", &s_properties,
|
gsi::method ("SProperties|#s_properties", &s_properties,
|
||||||
"@brief Indicates that only shapes with properties shall be retrieved"
|
"@brief Indicates that only shapes with properties shall be retrieved"
|
||||||
) +
|
) +
|
||||||
|
gsi::method ("SRegardProperties|#s_regard_properties", &s_regard_properties,
|
||||||
|
"@brief Special option to regard shapes with different properties as different entities (used by \\Region for example).\n"
|
||||||
|
"This option has been introduced in version 0.28.4.\n"
|
||||||
|
) +
|
||||||
gsi::method_ext ("dump_mem_statistics", &dump_mem_statistics, gsi::arg<bool> ("detailed", false),
|
gsi::method_ext ("dump_mem_statistics", &dump_mem_statistics, gsi::arg<bool> ("detailed", false),
|
||||||
"@hide"
|
"@hide"
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2026,6 +2026,179 @@ TEST(40_with_holes)
|
||||||
EXPECT_EQ (r.filtered (db::HoleCountFilter (3, 5, true)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
EXPECT_EQ (r.filtered (db::HoleCountFilter (3, 5, true)).to_string (), "(0,0;0,200;100,200;100,0/10,10;20,10;20,20;10,20/30,30;40,30;40,40;30,40)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(50_PropertiesFlat)
|
||||||
|
{
|
||||||
|
db::Region r;
|
||||||
|
|
||||||
|
// Fill flat region with parts with properties
|
||||||
|
|
||||||
|
r.insert (db::Box (0, 0, 100, 200));
|
||||||
|
r.insert (db::BoxWithProperties (db::Box (1, 2, 101, 202), 1));
|
||||||
|
r.insert (db::Box (10, 20, 110, 220));
|
||||||
|
r.insert (db::BoxWithProperties (db::Box (11, 12, 111, 212), 42));
|
||||||
|
|
||||||
|
EXPECT_EQ (r.count (), size_t (4));
|
||||||
|
|
||||||
|
db::Region::const_iterator s = r.begin ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;100,200;100,0)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(10,20;10,220;110,220;110,20)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
|
||||||
|
s = r.begin_merged ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
// property #0 elements are merged
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
|
||||||
|
// a single property #1 element
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
|
||||||
|
// a single property #42 element
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(51_PropertiesFlatFromLayout)
|
||||||
|
{
|
||||||
|
db::Layout ly;
|
||||||
|
unsigned int li = ly.insert_layer ();
|
||||||
|
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||||
|
|
||||||
|
db::Shapes &si = top.shapes (li);
|
||||||
|
si.insert (db::Box (0, 0, 100, 200));
|
||||||
|
si.insert (db::BoxWithProperties (db::Box (1, 2, 101, 202), 1));
|
||||||
|
si.insert (db::Box (10, 20, 110, 220));
|
||||||
|
si.insert (db::BoxWithProperties (db::Box (11, 12, 111, 212), 42));
|
||||||
|
|
||||||
|
// NOTE: without specific "property only" selector -> properties are ignored.
|
||||||
|
|
||||||
|
db::Region r (db::RecursiveShapeIterator (ly, top, li));
|
||||||
|
|
||||||
|
EXPECT_EQ (r.count (), size_t (4));
|
||||||
|
|
||||||
|
db::Region::const_iterator s = r.begin ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;100,200;100,0)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(10,20;10,220;110,220;110,20)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
|
||||||
|
s = r.begin_merged ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
// property #0 elements are merged
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;1,200;1,202;10,202;10,220;110,220;110,212;111,212;111,12;101,12;101,2;100,2;100,0)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
|
||||||
|
// NOTE: now with explicit propertly-only source
|
||||||
|
db::RecursiveShapeIterator rsi (ly, top, li);
|
||||||
|
rsi.shape_flags (db::ShapeIterator::AllWithProperties);
|
||||||
|
r = db::Region (rsi);
|
||||||
|
|
||||||
|
EXPECT_EQ (r.count (), size_t (2));
|
||||||
|
|
||||||
|
s = r.begin ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
|
||||||
|
s = r.begin_merged ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
// property #0 elements are merged
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;11,202;11,212;111,212;111,12;101,12;101,2)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
// NOTE: now with regarding properties
|
||||||
|
rsi = db::RecursiveShapeIterator (ly, top, li);
|
||||||
|
rsi.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
|
||||||
|
r = db::Region (rsi);
|
||||||
|
|
||||||
|
EXPECT_EQ (r.count (), size_t (4));
|
||||||
|
|
||||||
|
s = r.begin ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;100,200;100,0)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
EXPECT_EQ (s->to_string (), "(10,20;10,220;110,220;110,20)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
|
||||||
|
s = r.begin_merged ();
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
|
||||||
|
// property #0 elements are merged
|
||||||
|
EXPECT_EQ (s->to_string (), "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
|
||||||
|
// a single property #1 element
|
||||||
|
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), false);
|
||||||
|
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
|
||||||
|
// a single property #42 element
|
||||||
|
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
|
||||||
|
++s;
|
||||||
|
|
||||||
|
EXPECT_EQ (s.at_end (), true);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(100_Processors)
|
TEST(100_Processors)
|
||||||
{
|
{
|
||||||
db::Region r;
|
db::Region r;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue