mirror of https://github.com/KLayout/klayout.git
WIP: enhanced recursive shape iterator's push mode.
This commit is contained in:
parent
f346e70746
commit
2bfccca462
|
|
@ -763,15 +763,11 @@ RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
|
|||
|
||||
}
|
||||
|
||||
if (receiver && ! receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ())) {
|
||||
if (m_has_layers) {
|
||||
m_current_layer = m_layers.size ();
|
||||
}
|
||||
m_shape = shape_iterator ();
|
||||
m_inst = inst_iterator ();
|
||||
} else {
|
||||
new_cell (receiver);
|
||||
if (receiver) {
|
||||
receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
|
||||
}
|
||||
|
||||
new_cell (receiver);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -880,21 +876,24 @@ RecursiveShapeIterator::new_inst (RecursiveShapeReceiver *receiver) const
|
|||
}
|
||||
}
|
||||
|
||||
bool all_of_instance = true;
|
||||
if (m_local_region_stack.back () != box_type::world () && ! m_inst->cell_inst ().bbox (m_box_convert).inside (m_local_region_stack.back ())) {
|
||||
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region_stack.back (), m_box_convert);
|
||||
all_of_instance = false;
|
||||
if (receiver && ! receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), false)) {
|
||||
m_inst_array = inst_array_iterator ();
|
||||
} else {
|
||||
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region_stack.back (), m_box_convert);
|
||||
}
|
||||
} else {
|
||||
m_inst_array = m_inst->cell_inst ().begin ();
|
||||
// TODO: optimization potential: only report all_of_instance == false, if not entirely within the complex region
|
||||
all_of_instance = m_local_complex_region_stack.empty ();
|
||||
}
|
||||
|
||||
if (receiver) {
|
||||
receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), all_of_instance);
|
||||
bool all_of_instance = m_local_complex_region_stack.empty ();
|
||||
if (receiver && ! receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), all_of_instance)) {
|
||||
m_inst_array = inst_array_iterator ();
|
||||
} else {
|
||||
m_inst_array = m_inst->cell_inst ().begin ();
|
||||
}
|
||||
}
|
||||
|
||||
new_inst_member (receiver);
|
||||
|
||||
if (! m_inst_array.at_end ()) {
|
||||
break;
|
||||
} else {
|
||||
|
|
@ -921,8 +920,12 @@ RecursiveShapeIterator::new_inst_member (RecursiveShapeReceiver *receiver) const
|
|||
|
||||
}
|
||||
|
||||
if (! m_inst_array.at_end () && receiver) {
|
||||
receiver->new_inst_member (this, m_inst->cell_inst (), m_inst->complex_trans (*m_inst_array), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
|
||||
while (! m_inst_array.at_end () && receiver) {
|
||||
if (receiver->new_inst_member (this, m_inst->cell_inst (), m_inst->complex_trans (*m_inst_array), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ())) {
|
||||
break;
|
||||
} else {
|
||||
++m_inst_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -758,10 +758,7 @@ public:
|
|||
* @brief Enters a cell
|
||||
*
|
||||
* This method is called when the recursive shape iterator
|
||||
* enters a new cell. This method can return false. In this
|
||||
* case, the cell is skipped together with it's subcells.
|
||||
*
|
||||
* This method is not called for the top cell. When it is called, "iter->trans()"
|
||||
* enters a new cell. It is not called for the top cell. When it is called, "iter->trans()"
|
||||
* will already be updated.
|
||||
*
|
||||
* @param iter The iterator
|
||||
|
|
@ -769,7 +766,7 @@ public:
|
|||
* @param region The clip box as seen from "cell" or db::Box::world if there is no clip box
|
||||
* @param complex_region A complex clip region if one is supplied together with "region"
|
||||
*/
|
||||
virtual bool enter_cell (const RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { return true; }
|
||||
virtual void enter_cell (const RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { }
|
||||
|
||||
/**
|
||||
* @brief Leaves the current cell
|
||||
|
|
@ -798,8 +795,10 @@ public:
|
|||
* ...
|
||||
*
|
||||
* The "all" parameter is true, if all instances of the array will be addressed.
|
||||
*
|
||||
* If this method returns false, the instance (the whole array) is skipped and the cell is not entered.
|
||||
*/
|
||||
virtual void new_inst (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { }
|
||||
virtual bool new_inst (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { return true; }
|
||||
|
||||
/**
|
||||
* @brief Enters a new array member of the instance
|
||||
|
|
@ -807,8 +806,10 @@ public:
|
|||
* See "new_inst" for a description. This method adds the "trans" parameter
|
||||
* which holds the complex transformation for this particular instance of
|
||||
* the array.
|
||||
*
|
||||
* If this method returns false, this array instance (but not the whole array) is skipped and the cell is not entered.
|
||||
*/
|
||||
virtual void new_inst_member (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { }
|
||||
virtual bool new_inst_member (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { return true; }
|
||||
|
||||
/**
|
||||
* @brief Delivers a shape
|
||||
|
|
|
|||
|
|
@ -908,10 +908,9 @@ public:
|
|||
virtual void begin (const db::RecursiveShapeIterator * /*iter*/) { m_text += "begin\n"; }
|
||||
virtual void end (const db::RecursiveShapeIterator * /*iter*/) { m_text += "end\n"; }
|
||||
|
||||
virtual bool enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
virtual void enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
m_text += std::string ("enter_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void leave_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell)
|
||||
|
|
@ -919,18 +918,20 @@ public:
|
|||
m_text += std::string ("leave_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n";
|
||||
}
|
||||
|
||||
virtual void new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all)
|
||||
virtual bool new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all)
|
||||
{
|
||||
m_text += std::string ("new_inst(") + iter->layout ()->cell_name (inst.object ().cell_index ());
|
||||
if (all) {
|
||||
m_text += ",all";
|
||||
}
|
||||
m_text += ")\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
virtual bool new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
m_text += std::string ("new_inst_member(") + iter->layout ()->cell_name (inst.object ().cell_index ()) + "," + tl::to_string (trans) + ")\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans)
|
||||
|
|
@ -942,22 +943,39 @@ private:
|
|||
std::string m_text;
|
||||
};
|
||||
|
||||
class ReceiverRejectingACell
|
||||
class ReceiverRejectingACellInstanceArray
|
||||
: public LoggingReceiver
|
||||
{
|
||||
public:
|
||||
ReceiverRejectingACell (db::cell_index_type rejected) : m_rejected (rejected) { }
|
||||
ReceiverRejectingACellInstanceArray (db::cell_index_type rejected) : m_rejected (rejected) { }
|
||||
|
||||
virtual bool enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box ®ion, const box_tree_type *complex_region)
|
||||
virtual bool new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box ®ion, const box_tree_type *complex_region, bool all)
|
||||
{
|
||||
LoggingReceiver::enter_cell (iter, cell, region, complex_region);
|
||||
return cell->cell_index () != m_rejected;
|
||||
LoggingReceiver::new_inst (iter, inst, region, complex_region, all);
|
||||
return inst.object ().cell_index () != m_rejected;
|
||||
}
|
||||
|
||||
private:
|
||||
db::cell_index_type m_rejected;
|
||||
};
|
||||
|
||||
class ReceiverRejectingACellInstance
|
||||
: public LoggingReceiver
|
||||
{
|
||||
public:
|
||||
ReceiverRejectingACellInstance (db::cell_index_type rejected, const db::ICplxTrans &trans_rejected) : m_rejected (rejected), m_trans_rejected (trans_rejected) { }
|
||||
|
||||
virtual bool new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box ®ion, const box_tree_type *complex_region)
|
||||
{
|
||||
LoggingReceiver::new_inst_member (iter, inst, trans, region, complex_region);
|
||||
return inst.object ().cell_index () != m_rejected || trans != m_trans_rejected;
|
||||
}
|
||||
|
||||
private:
|
||||
db::cell_index_type m_rejected;
|
||||
db::ICplxTrans m_trans_rejected;
|
||||
};
|
||||
|
||||
// Push mode with cells
|
||||
TEST(10)
|
||||
{
|
||||
|
|
@ -1066,7 +1084,7 @@ TEST(10)
|
|||
"end\n"
|
||||
);
|
||||
|
||||
ReceiverRejectingACell rr1 (c2.cell_index ());
|
||||
ReceiverRejectingACellInstanceArray rr1 (c2.cell_index ());
|
||||
db::RecursiveShapeIterator ir1 (g, c0, 0);
|
||||
ir1.push (&rr1);
|
||||
|
||||
|
|
@ -1076,89 +1094,107 @@ TEST(10)
|
|||
"new_inst_member($2,r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n"
|
||||
"enter_cell($3)\n"
|
||||
"leave_cell($3)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 0,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"leave_cell($2)\n"
|
||||
"end\n"
|
||||
);
|
||||
|
||||
ReceiverRejectingACellInstance rri1 (c2.cell_index (), db::ICplxTrans ());
|
||||
db::RecursiveShapeIterator iri1 (g, c0, 0);
|
||||
iri1.push (&rri1);
|
||||
|
||||
EXPECT_EQ (rri1.text (),
|
||||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n" // -> skipped
|
||||
"new_inst_member($3,r0 *1 0,2000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 0,2000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,1000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 3000,1000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,3000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 3000,3000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 0,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n"
|
||||
"enter_cell($3)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 0,2000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 0,8000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,1000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 3000,7000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,3000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 3000,9000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n"
|
||||
"enter_cell($3)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 0,2000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 6000,2000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,1000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 9000,1000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,3000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 9000,3000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"new_inst($3,all)\n"
|
||||
"new_inst_member($3,r0 *1 0,0)\n"
|
||||
"enter_cell($3)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 0,2000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 6000,8000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,1000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 9000,7000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"new_inst_member($3,r0 *1 3000,3000)\n"
|
||||
"enter_cell($3)\n"
|
||||
"shape(box (1000,-500;2000,500),r0 *1 9000,9000)\n"
|
||||
"leave_cell($3)\n"
|
||||
"leave_cell($2)\n"
|
||||
"end\n"
|
||||
);
|
||||
|
||||
ReceiverRejectingACell rr2 (c1.cell_index ());
|
||||
ReceiverRejectingACellInstanceArray rr2 (c1.cell_index ());
|
||||
db::RecursiveShapeIterator ir2 (g, c0, 0);
|
||||
ir2.push (&rr2);
|
||||
|
||||
EXPECT_EQ (rr2.text (),
|
||||
"begin\n"
|
||||
"new_inst($2,all)\n"
|
||||
"new_inst_member($2,r0 *1 0,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 0,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,0)\n"
|
||||
"enter_cell($2)\n"
|
||||
"leave_cell($2)\n"
|
||||
"new_inst_member($2,r0 *1 6000,6000)\n"
|
||||
"enter_cell($2)\n"
|
||||
"leave_cell($2)\n"
|
||||
"end\n"
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue