Some convenience features: transformations in EdgeNeighborhood, added Matrix transformation support for edge pairs.

This commit is contained in:
Matthias Koefferlein 2024-11-01 17:34:46 +01:00
parent 2629700566
commit dd0949867f
7 changed files with 140 additions and 20 deletions

View File

@ -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;
}

View File

@ -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
*/

View File

@ -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"

View File

@ -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"

View File

@ -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);
}
}
}

View File

@ -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")

View File

@ -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