mirror of https://github.com/KLayout/klayout.git
Some convenience features: transformations in EdgeNeighborhood, added Matrix transformation support for edge pairs.
This commit is contained in:
parent
2629700566
commit
dd0949867f
|
|
@ -27,6 +27,17 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
static db::IMatrix3d to_original_trans (const db::Edge &edge)
|
||||
{
|
||||
// compute normal and unit vector along edge
|
||||
db::DVector e = db::DVector (edge.d ());
|
||||
e = e * (1.0 / e.double_length ());
|
||||
db::DVector ne (-e.y (), e.x ());
|
||||
|
||||
// transform on the edge
|
||||
return db::IMatrix3d (e.x (), ne.x (), e.y (), ne.y (), edge.p1 ().x (), edge.p1 ().y (), 0.0, 0.0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
EdgeNeighborhoodVisitor::EdgeNeighborhoodVisitor ()
|
||||
|
|
@ -105,6 +116,18 @@ EdgeNeighborhoodVisitor::output_edge_pair (const db::EdgePair &edge_pair)
|
|||
mp_edge_pairs->insert (edge_pair);
|
||||
}
|
||||
|
||||
db::IMatrix3d
|
||||
EdgeNeighborhoodVisitor::to_original_trans (const db::Edge &edge)
|
||||
{
|
||||
return db::to_original_trans (edge);
|
||||
}
|
||||
|
||||
db::IMatrix3d
|
||||
EdgeNeighborhoodVisitor::to_edge_local_trans (const db::Edge &edge)
|
||||
{
|
||||
return db::to_original_trans (edge).inverted ();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
EdgeNeighborhoodCompoundOperationNode::EdgeNeighborhoodCompoundOperationNode (const std::vector<CompoundRegionOperationNode *> &children, EdgeNeighborhoodVisitor *visitor, db::Coord bext, db::Coord eext, db::Coord din, db::Coord dout)
|
||||
|
|
@ -181,17 +204,9 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
// compute normal and unit vector along edge
|
||||
db::DVector e = db::DVector (edge.d ());
|
||||
e = e * (1.0 / e.double_length ());
|
||||
db::DVector ne (-e.y (), e.x ());
|
||||
db::IMatrix3d from_original_trans = db::to_original_trans (edge).inverted ();
|
||||
|
||||
// transform on the edge
|
||||
db::IMatrix2d trans (e.x (), ne.x (), e.y (), ne.y ());
|
||||
db::IMatrix2d itrans = trans.inverted ();
|
||||
db::Disp move (db::Point () - edge.p1 ());
|
||||
|
||||
db::Edge ref_edge = itrans * (move * edge);
|
||||
db::Edge ref_edge = from_original_trans * edge;
|
||||
tl_assert (ref_edge.dy () == 0);
|
||||
tl_assert (ref_edge.dx () > 0);
|
||||
|
||||
|
|
@ -212,7 +227,7 @@ private:
|
|||
size_t id = 0;
|
||||
for (auto nn = n->second.begin (); nn != n->second.end (); ++nn) {
|
||||
for (auto e = (*nn)->begin_edge (); ! e.at_end (); ++e) {
|
||||
ep.insert (itrans * (move * *e), id);
|
||||
ep.insert (from_original_trans * *e, id);
|
||||
}
|
||||
id += 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbCompoundOperation.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbMatrix.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -97,6 +98,16 @@ public:
|
|||
*/
|
||||
virtual void on_edge (const db::Layout * /*layout*/, const db::Cell * /*cell*/, const db::Edge & /*edge*/, const neighbors_type & /*neighbors*/) { }
|
||||
|
||||
/**
|
||||
* @brief Gets a transformation to transform from edge-local space to original space
|
||||
*/
|
||||
static db::IMatrix3d to_original_trans (const db::Edge &edge);
|
||||
|
||||
/**
|
||||
* @brief Gets a transformation to transform from original space into edge-local space
|
||||
*/
|
||||
static db::IMatrix3d to_edge_local_trans (const db::Edge &edge);
|
||||
|
||||
/**
|
||||
* @brief Sets the result type
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -172,17 +172,34 @@ Class<gsi::EdgeNeighborhoodVisitorImpl> decl_EdgeNeighborhoodVisitorImpl (decl_E
|
|||
gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_polygon, gsi::arg ("polygon"),
|
||||
"@brief Outputs a polygon\n"
|
||||
"Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. "
|
||||
"Note that you have to configure the result type as 'Region' on construction of the visitor before being able to do so."
|
||||
"Note that you have to configure the result type as 'Region' on construction of the visitor before being able to do so.\n"
|
||||
"\n"
|
||||
"'output' expects an object in original space - i.e. of the input edge. \\to_original_trans gives you a suitable "
|
||||
"transformation to bring objects from 'edge is horizontal' space into the original space."
|
||||
) +
|
||||
gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_edge, gsi::arg ("edge"),
|
||||
"@brief Outputs an edge\n"
|
||||
"Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. "
|
||||
"Note that you have to configure the result type as 'Edges' on construction of the visitor before being able to do so."
|
||||
"\n"
|
||||
"'output' expects an object in original space - i.e. of the input edge. \\to_original_trans gives you a suitable "
|
||||
"transformation to bring objects from 'edge is horizontal' space into the original space."
|
||||
) +
|
||||
gsi::method ("output", &EdgeNeighborhoodVisitorImpl::output_edge_pair, gsi::arg ("edge_pair"),
|
||||
"@brief Outputs an edge pair\n"
|
||||
"Use this method from one of the callbacks (\\on_edge, \\begin_polygon, \\end_polygon) to deliver a polygon. "
|
||||
"Note that you have to configure the result type as 'EdgePairs' on construction of the visitor before being able to do so."
|
||||
"\n"
|
||||
"'output' expects an object in original space - i.e. of the input edge. \\to_original_trans gives you a suitable "
|
||||
"transformation to bring objects from 'edge is horizontal' space into the original space."
|
||||
) +
|
||||
gsi::method ("to_original_trans", &EdgeNeighborhoodVisitorImpl::to_original_trans, gsi::arg ("edge"),
|
||||
"@brief For a given edge, computes the transformation that brings objects from the normalized space (edge is horizontal) to the original space of the edge.\n"
|
||||
"Use this method to compute the objects suitable for 'output', after you derived them in edge-local space.\n"
|
||||
) +
|
||||
gsi::method ("to_edge_local_trans", &EdgeNeighborhoodVisitorImpl::to_edge_local_trans, gsi::arg ("edge"),
|
||||
"@brief For a given edge, computes the transformation that brings objects from original space to the edge-local space where the edge is horizontal.\n"
|
||||
"Technically, this transformation is the inverse of \\to_original_trans.\n"
|
||||
) +
|
||||
gsi::method ("result_type=", &EdgeNeighborhoodVisitorImpl::set_result_type, gsi::arg ("result_type"),
|
||||
"@brief Configures the result type\n"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbBox.h"
|
||||
#include "dbPolygon.h"
|
||||
#include "dbEdge.h"
|
||||
#include "dbEdgePair.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
|
@ -130,6 +131,12 @@ static db::edge<C> trans_edge (const db::matrix_2d<C> *m, const db::edge<C> &e)
|
|||
return e.transformed (*m);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
static db::edge_pair<C> trans_edge_pair (const db::matrix_2d<C> *m, const db::edge_pair<C> &e)
|
||||
{
|
||||
return e.transformed (*m);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
static double coeff_m (const db::matrix_2d<C> *m, int i, int j)
|
||||
{
|
||||
|
|
@ -234,6 +241,12 @@ matrix2d_methods ()
|
|||
"@param e The edge to transform.\n"
|
||||
"@return The transformed edge\n"
|
||||
) +
|
||||
gsi::method_ext ("*", &trans_edge_pair<C>, gsi::arg ("ep"),
|
||||
"@brief Transforms an edge pair with this matrix.\n"
|
||||
"@param ep The edge pair to transform.\n"
|
||||
"@return The transformed edge\n"
|
||||
"This variant has been added in version 0.29.9."
|
||||
) +
|
||||
gsi::method_ext ("*", &trans_box<C>, gsi::arg ("box"),
|
||||
"@brief Transforms a box with this matrix.\n"
|
||||
"@param box The box to transform.\n"
|
||||
|
|
@ -445,6 +458,12 @@ static db::edge<C> trans_edge3 (const db::matrix_3d<C> *m, const db::edge<C> &e)
|
|||
return e.transformed (*m);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
static db::edge_pair<C> trans_edge_pair3 (const db::matrix_3d<C> *m, const db::edge_pair<C> &e)
|
||||
{
|
||||
return e.transformed (*m);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
static double coeff_m3 (const db::matrix_3d<C> *m, int i, int j)
|
||||
{
|
||||
|
|
@ -617,6 +636,12 @@ matrix3d_methods ()
|
|||
"@param e The edge to transform.\n"
|
||||
"@return The transformed edge\n"
|
||||
) +
|
||||
gsi::method_ext ("*", &trans_edge_pair3<C>, gsi::arg ("ep"),
|
||||
"@brief Transforms an edge pair with this matrix.\n"
|
||||
"@param ep The edge pair to transform.\n"
|
||||
"@return The transformed edge pair\n"
|
||||
"This variant has been added in version 0.29.9."
|
||||
) +
|
||||
gsi::method_ext ("*", &trans_box3<C>, gsi::arg ("box"),
|
||||
"@brief Transforms a box with this matrix.\n"
|
||||
"@param box The box to transform.\n"
|
||||
|
|
|
|||
|
|
@ -62,19 +62,13 @@ public:
|
|||
|
||||
void on_edge (const db::Layout * /*layout*/, const db::Cell * /*cell*/, const db::Edge &edge, const neighbors_type &neighbors)
|
||||
{
|
||||
// Compute transformation to original edge
|
||||
db::DVector e = db::DVector (edge.d ());
|
||||
e = e * (1.0 / e.double_length ());
|
||||
db::DVector ne (-e.y (), e.x ());
|
||||
|
||||
db::IMatrix2d trans (e.x (), ne.x (), e.y (), ne.y ());
|
||||
db::Disp move (edge.p1 () - db::Point ());
|
||||
db::IMatrix3d trans = to_original_trans (edge);
|
||||
|
||||
for (auto n = neighbors.begin (); n != neighbors.end (); ++n) {
|
||||
for (auto nn = n->second.begin (); nn != n->second.end (); ++nn) {
|
||||
if (nn->first == m_input) {
|
||||
for (auto p = nn->second.begin (); p != nn->second.end (); ++p) {
|
||||
output_polygon (move * (trans * *p));
|
||||
output_polygon (trans * *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,31 @@ class MyVisitor < RBA::EdgeNeighborhoodVisitor
|
|||
|
||||
end
|
||||
|
||||
class MyVisitor2 < RBA::EdgeNeighborhoodVisitor
|
||||
|
||||
def initialize
|
||||
self.result_type = RBA::CompoundRegionOperationNode::ResultType::EdgePairs
|
||||
end
|
||||
|
||||
def on_edge(layout, cell, edge, neighborhood)
|
||||
neighborhood.each do |n|
|
||||
polygons = n[1]
|
||||
polygons.each do |inp, poly|
|
||||
poly.each do |p|
|
||||
bbox = p.bbox
|
||||
t = self.to_original_trans(edge)
|
||||
ep = RBA::EdgePair::new(edge, t * RBA::Edge::new(bbox.p1, RBA::Point::new(bbox.right, bbox.bottom)))
|
||||
output(ep)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DBEdgeNeighborhood_TestClass < TestBase
|
||||
|
||||
# basic events
|
||||
def test_1
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
|
@ -108,6 +131,37 @@ class DBEdgeNeighborhood_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# edge pair output, to_original_trans
|
||||
def test_2
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
l1 = ly.layer(1, 0)
|
||||
cell = ly.create_cell("TOP")
|
||||
|
||||
cell.shapes(l1).insert(RBA::Box::new(0, 0, 1000, 1000))
|
||||
cell.shapes(l1).insert(RBA::Box::new(-1100, 0, -100, 1000))
|
||||
|
||||
prim = RBA::Region::new(cell.begin_shapes_rec(l1))
|
||||
|
||||
visitor = MyVisitor2::new
|
||||
|
||||
bext = 0
|
||||
eext = 0
|
||||
din = 10
|
||||
dout = 100
|
||||
|
||||
children = [
|
||||
RBA::CompoundRegionOperationNode::new_foreign
|
||||
]
|
||||
|
||||
node = RBA::CompoundRegionOperationNode::new_edge_neighborhood(children, visitor, bext, eext, din, dout)
|
||||
res = prim.complex_op(node)
|
||||
|
||||
assert_equal(res.to_s, "(-100,1000;-100,0)/(0,1000;0,0);(0,0;0,1000)/(-100,0;-100,1000)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ class DBMatrix_TestClass < TestBase
|
|||
assert_equal((m * RBA::Polygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-18;5,43;20,35)")
|
||||
assert_equal((m * RBA::SimplePolygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-18;5,43;20,35)")
|
||||
assert_equal((m * RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).to_s, "(-10,-18;20,35)")
|
||||
assert_equal((m * RBA::EdgePair::new(RBA::Edge::new(RBA::Point::new(0, -10), RBA::Point::new(15, 20)), RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20)))).to_s, "(-5,-20;25,33)/(-10,-18;20,35)")
|
||||
assert_equal(RBA::Region::new(RBA::Box::new(-5, -10, 10, 20)).transformed(m).to_s, "(5,-25;-10,-18;5,43;20,35)")
|
||||
r = RBA::Region::new(RBA::Box::new(-5, -10, 10, 20))
|
||||
r.transform(m)
|
||||
|
|
@ -273,6 +274,7 @@ class DBMatrix_TestClass < TestBase
|
|||
assert_equal((m * RBA::DPolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-17.5;5,42.5;20,35)")
|
||||
assert_equal((m * RBA::DSimplePolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(5,-25;-10,-17.5;5,42.5;20,35)")
|
||||
assert_equal((m * RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20))).to_s, "(-10,-17.5;20,35)")
|
||||
assert_equal((m * RBA::DEdgePair::new(RBA::DEdge::new(RBA::DPoint::new(0, -10), RBA::DPoint::new(15, 20)), RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20)))).to_s, "(-5,-20;25,32.5)/(-10,-17.5;20,35)")
|
||||
|
||||
m = RBA::IMatrix3d::new(1.0, 0.5, 1.0, -0.5, 2.0, 0.0, 0.0, 0.0, 1.0)
|
||||
assert_equal((m * RBA::Point::new(10, 20)).to_s, "21,35")
|
||||
|
|
@ -281,6 +283,7 @@ class DBMatrix_TestClass < TestBase
|
|||
assert_equal((m * RBA::Polygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-18;6,43;21,35)")
|
||||
assert_equal((m * RBA::SimplePolygon::new(RBA::Box::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-18;6,43;21,35)")
|
||||
assert_equal((m * RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20))).to_s, "(-9,-18;21,35)")
|
||||
assert_equal((m * RBA::EdgePair::new(RBA::Edge::new(RBA::Point::new(0, -10), RBA::Point::new(15, 20)), RBA::Edge::new(RBA::Point::new(-5, -10), RBA::Point::new(10, 20)))).to_s, "(-4,-20;26,33)/(-9,-18;21,35)")
|
||||
assert_equal(RBA::Region::new(RBA::Box::new(-5, -10, 10, 20)).transformed(m).to_s, "(6,-25;-9,-18;6,43;21,35)")
|
||||
r = RBA::Region::new(RBA::Box::new(-5, -10, 10, 20))
|
||||
r.transform(m)
|
||||
|
|
@ -301,6 +304,7 @@ class DBMatrix_TestClass < TestBase
|
|||
assert_equal((m * RBA::DPolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-17.5;6,42.5;21,35)")
|
||||
assert_equal((m * RBA::DSimplePolygon::new(RBA::DBox::new(-5, -10, 10, 20))).to_s, "(6,-25;-9,-17.5;6,42.5;21,35)")
|
||||
assert_equal((m * RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20))).to_s, "(-9,-17.5;21,35)")
|
||||
assert_equal((m * RBA::DEdgePair::new(RBA::DEdge::new(RBA::DPoint::new(0, -10), RBA::DPoint::new(15, 20)), RBA::DEdge::new(RBA::DPoint::new(-5, -10), RBA::DPoint::new(10, 20)))).to_s, "(-4,-20;26,32.5)/(-9,-17.5;21,35)")
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue