mirror of https://github.com/KLayout/klayout.git
parent
4bd2672134
commit
dcd0476efc
|
|
@ -301,6 +301,30 @@ public:
|
|||
return m_instances.transform_into (ref, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transforms the cell by the given transformation.
|
||||
*
|
||||
* The transformation is applied to all instances and shapes. Magnified transformations will
|
||||
* render magnified instances. See \transform_into for a version which avoids this.
|
||||
*
|
||||
* @param t The transformation to apply
|
||||
*/
|
||||
template <class Trans>
|
||||
void transform (const Trans &t)
|
||||
{
|
||||
m_instances.transform (t);
|
||||
for (typename shapes_map::iterator s = m_shapes_map.begin (); s != m_shapes_map.end (); ++s) {
|
||||
if (! s->second.empty ()) {
|
||||
// Note: don't use the copy ctor here - it will copy the attachment to the manager
|
||||
// and create problems when destroyed. Plus: swap would be more efficient. But by using
|
||||
// assign_transformed we get undo support for free.
|
||||
shapes_type d;
|
||||
d = s->second;
|
||||
s->second.assign_transformed (d, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transforms the cell into a new coordinate system.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,28 @@ static db::Instance cell_inst_dtransform_into_cplx (db::Cell *cell, const db::In
|
|||
return cell->transform_into (inst, dbu_trans.inverted () * t * dbu_trans);
|
||||
}
|
||||
|
||||
static void cell_dtransform_simple (db::Cell *cell, const db::DTrans &t)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer-unit transformation")));
|
||||
}
|
||||
|
||||
db::CplxTrans dbu_trans (layout->dbu ());
|
||||
cell->transform (db::Trans (dbu_trans.inverted () * db::DCplxTrans (t) * dbu_trans));
|
||||
}
|
||||
|
||||
static void cell_dtransform_cplx (db::Cell *cell, const db::DCplxTrans &t)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
if (! layout) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cell does not reside inside a layout - cannot use a micrometer-unit transformation")));
|
||||
}
|
||||
|
||||
db::CplxTrans dbu_trans (layout->dbu ());
|
||||
cell->transform (dbu_trans.inverted () * t * dbu_trans);
|
||||
}
|
||||
|
||||
static void cell_dtransform_into_simple (db::Cell *cell, const db::DTrans &t)
|
||||
{
|
||||
const db::Layout *layout = cell->layout ();
|
||||
|
|
@ -2347,6 +2369,46 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This variant has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("transform", (void (db::Cell::*)(const db::Trans &)) &db::Cell::transform, gsi::arg ("trans"),
|
||||
"@brief Transforms the cell by the given integer transformation\n"
|
||||
"\n"
|
||||
"This method transforms all instances and all shapes by the given transformation. "
|
||||
"There is a variant called \\transform_into which applies the transformation to instances "
|
||||
"in a way such that it can be applied recursively to the child cells.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.7."
|
||||
) +
|
||||
gsi::method ("transform", (void (db::Cell::*)(const db::ICplxTrans &)) &db::Cell::transform, gsi::arg ("trans"),
|
||||
"@brief Transforms the cell by the given complex integer transformation\n"
|
||||
"\n"
|
||||
"This method transforms all instances and all shapes by the given transformation. "
|
||||
"There is a variant called \\transform_into which applies the transformation to instances "
|
||||
"in a way such that it can be applied recursively to the child cells. The difference is important in "
|
||||
"the presence of magnifications: \"transform\" will leave magnified instances while \"transform_into\" "
|
||||
"will not do so but expect the magnification to be applied inside the called cells too.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.7."
|
||||
) +
|
||||
gsi::method_ext ("transform", &cell_dtransform_simple, gsi::arg ("trans"),
|
||||
"@brief Transforms the cell by the given, micrometer-unit transformation\n"
|
||||
"\n"
|
||||
"This method transforms all instances and all shapes by the given transformation. "
|
||||
"There is a variant called \\transform_into which applies the transformation to instances "
|
||||
"in a way such that it can be applied recursively to the child cells.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.7."
|
||||
) +
|
||||
gsi::method_ext ("transform", &cell_dtransform_cplx, gsi::arg ("trans"),
|
||||
"@brief Transforms the cell by the given, micrometer-unit transformation\n"
|
||||
"\n"
|
||||
"This method transforms all instances and all shapes by the given transformation. "
|
||||
"There is a variant called \\transform_into which applies the transformation to instances "
|
||||
"in a way such that it can be applied recursively to the child cells. The difference is important in "
|
||||
"the presence of magnifications: \"transform\" will leave magnified instances while \"transform_into\" "
|
||||
"will not do so but expect the magnification to be applied inside the called cells too.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.7."
|
||||
) +
|
||||
gsi::method_ext ("transform_into", &cell_dtransform_into_simple, gsi::arg ("trans"),
|
||||
"@brief Transforms the cell into a new coordinate system with the given transformation where the transformation is in micrometer units\n"
|
||||
"This method is identical to the corresponding \\transform_into method with a \\Trans argument. For this variant "
|
||||
|
|
|
|||
|
|
@ -722,6 +722,14 @@ TEST(3a)
|
|||
c0.transform_into (db::ICplxTrans (ti));
|
||||
inst = *c0.begin ();
|
||||
EXPECT_EQ (inst.to_string (), "cell_index=1 m90 -334,0");
|
||||
|
||||
c0.transform (db::Trans (5));
|
||||
inst = *c0.begin ();
|
||||
EXPECT_EQ (inst.to_string (), "cell_index=1 r270 0,-334");
|
||||
|
||||
c0.transform (db::ICplxTrans (ti));
|
||||
inst = *c0.begin ();
|
||||
EXPECT_EQ (inst.to_string (), "cell_index=1 r315 *2.5 600,-570");
|
||||
}
|
||||
|
||||
TEST(3b)
|
||||
|
|
@ -791,6 +799,73 @@ TEST(3b)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(3c)
|
||||
{
|
||||
::pi = 0;
|
||||
|
||||
db::Manager m (true);
|
||||
db::Layout g (&m);
|
||||
db::Cell &c0 (g.cell (g.add_cell ()));
|
||||
db::Cell &c1 (g.cell (g.add_cell ()));
|
||||
|
||||
db::Trans t (db::Vector (100, -100));
|
||||
c0.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (c1.cell_index ()), t), 5));
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c0.shapes (0).insert (db::BoxWithProperties (b, 17));
|
||||
c1.shapes (1).insert (b);
|
||||
|
||||
// Note: this requires editable mode since db::Shapes::erase is permitted in editable mode only
|
||||
// (erase is triggered by undo)
|
||||
if (db::default_editable_mode ()) {
|
||||
|
||||
m.transaction ("t");
|
||||
c0.transform (db::ICplxTrans (2.5));
|
||||
m.commit ();
|
||||
|
||||
EXPECT_EQ (c1.cell_instances (), size_t (0));
|
||||
EXPECT_EQ (c0.cell_instances (), size_t (1));
|
||||
EXPECT_EQ (c0.begin ()->to_string (), "cell_index=1 r0 *2.5 250,-250 prop_id=5");
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).size (), size_t (1));
|
||||
EXPECT_EQ (c0.shapes (1).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (0).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (1).size (), size_t (1));
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).begin (db::ShapeIterator::All)->to_string (), "box (0,250;2500,3000) prop_id=17");
|
||||
EXPECT_EQ (c1.shapes (1).begin (db::ShapeIterator::All)->to_string (), "box (0,100;1000,1200)");
|
||||
|
||||
m.undo ();
|
||||
|
||||
EXPECT_EQ (c1.cell_instances (), size_t (0));
|
||||
EXPECT_EQ (c0.cell_instances (), size_t (1));
|
||||
EXPECT_EQ (c0.begin ()->to_string (), "cell_index=1 r0 100,-100 prop_id=5");
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).size (), size_t (1));
|
||||
EXPECT_EQ (c0.shapes (1).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (0).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (1).size (), size_t (1));
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).begin (db::ShapeIterator::All)->to_string (), "box (0,100;1000,1200) prop_id=17");
|
||||
EXPECT_EQ (c1.shapes (1).begin (db::ShapeIterator::All)->to_string (), "box (0,100;1000,1200)");
|
||||
|
||||
m.redo ();
|
||||
|
||||
EXPECT_EQ (c1.cell_instances (), size_t (0));
|
||||
EXPECT_EQ (c0.cell_instances (), size_t (1));
|
||||
EXPECT_EQ (c0.begin ()->to_string (), "cell_index=1 r0 *2.5 250,-250 prop_id=5");
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).size (), size_t (1));
|
||||
EXPECT_EQ (c0.shapes (1).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (0).size (), size_t (0));
|
||||
EXPECT_EQ (c1.shapes (1).size (), size_t (1));
|
||||
|
||||
EXPECT_EQ (c0.shapes (0).begin (db::ShapeIterator::All)->to_string (), "box (0,250;2500,3000) prop_id=17");
|
||||
EXPECT_EQ (c1.shapes (1).begin (db::ShapeIterator::All)->to_string (), "box (0,100;1000,1200)");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct map1
|
||||
{
|
||||
db::cell_index_type operator() (db::cell_index_type i) const { return 3-i; }
|
||||
|
|
|
|||
|
|
@ -1122,6 +1122,59 @@ class DBLayout_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Cell#transform and Cell#transform_into
|
||||
def test_14
|
||||
|
||||
g = RBA::Layout::new
|
||||
c0 = g.create_cell("c0")
|
||||
c1 = g.create_cell("c1")
|
||||
|
||||
t = RBA::Trans::new(RBA::Vector::new(100, -100))
|
||||
inst = c0.insert(RBA::CellInstArray::new(c1.cell_index, t))
|
||||
|
||||
ti = RBA::ICplxTrans::new(2.5, 45.0, false, RBA::Vector::new(10, 20))
|
||||
t = RBA::Trans::new(1)
|
||||
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 100,-100")
|
||||
|
||||
c0.transform_into(t)
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 100,100")
|
||||
|
||||
c0.transform_into(ti)
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 0,354")
|
||||
|
||||
c0.transform(t)
|
||||
assert_equal(inst.to_s, "cell_index=1 r90 -354,0")
|
||||
|
||||
c0.transform(ti)
|
||||
assert_equal(inst.to_s, "cell_index=1 r135 *2.5 -616,-606")
|
||||
|
||||
g = RBA::Layout::new
|
||||
c0 = g.create_cell("c0")
|
||||
c1 = g.create_cell("c1")
|
||||
|
||||
t = RBA::Trans::new(RBA::Vector::new(100, -100))
|
||||
inst = c0.insert(RBA::CellInstArray::new(c1.cell_index, t))
|
||||
|
||||
ti = RBA::DCplxTrans::new(2.5, 45.0, false, RBA::DVector::new(0.01, 0.02))
|
||||
t = RBA::DTrans::new(1)
|
||||
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 100,-100")
|
||||
|
||||
c0.transform_into(t)
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 100,100")
|
||||
|
||||
c0.transform_into(ti)
|
||||
assert_equal(inst.to_s, "cell_index=1 r0 0,354")
|
||||
|
||||
c0.transform(t)
|
||||
assert_equal(inst.to_s, "cell_index=1 r90 -354,0")
|
||||
|
||||
c0.transform(ti)
|
||||
assert_equal(inst.to_s, "cell_index=1 r135 *2.5 -616,-606")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue