mirror of https://github.com/KLayout/klayout.git
Polygon neighborhood compound operation
This commit is contained in:
parent
aa67448401
commit
1f44a951f4
|
|
@ -231,11 +231,11 @@ static db::CompoundRegionOperationNode *new_edge_neighborhood (const std::vector
|
|||
return new db::EdgeNeighborhoodCompoundOperationNode (children, visitor, bext, eext, din, dout);
|
||||
}
|
||||
|
||||
gsi::ClassExt<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode_ext (
|
||||
gsi::ClassExt<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode_ext_EdgeNeighborhood (
|
||||
gsi::constructor ("new_edge_neighborhood", &new_edge_neighborhood, gsi::arg ("children"), gsi::arg ("visitor"), gsi::arg ("bext", 0), gsi::arg ("eext", 0), gsi::arg ("din", 0), gsi::arg ("dout", 0),
|
||||
"@brief Creates a new edge neighborhood collector\n"
|
||||
"\n"
|
||||
"@param children The inputs to use. The inputs are enumrated by base zero indexes in the visitor callback.\n"
|
||||
"@param children The inputs to use. The inputs are enumerated by base zero indexes in the visitor callback.\n"
|
||||
"@param visitor The visitor object (see \\EdgeNeighborhoodVisitor) receiving the edge events.\n"
|
||||
"@param bext The search window extension to use at the edge beginning.\n"
|
||||
"@param eext The search window extension to use at the edge end.\n"
|
||||
|
|
|
|||
|
|
@ -123,17 +123,17 @@ Class<gsi::PolygonNeighborhoodVisitorImpl> decl_PolygonNeighborhoodVisitorImpl (
|
|||
// ---------------------------------------------------------------------------------
|
||||
// PolygonNeighborhoodCompoundOperationNode binding
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_neighborhood (const std::vector<db::CompoundRegionOperationNode *> &children, db::PolygonNeighborhoodVisitor *visitor, const db::Coord dist)
|
||||
static db::CompoundRegionOperationNode *new_polygon_neighborhood (const std::vector<db::CompoundRegionOperationNode *> &children, db::PolygonNeighborhoodVisitor *visitor, const db::Coord dist)
|
||||
{
|
||||
return new db::PolygonNeighborhoodCompoundOperationNode (children, visitor, dist);
|
||||
}
|
||||
|
||||
gsi::ClassExt<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode_ext (
|
||||
gsi::constructor ("new_polygon_neighborhood", &new_edge_neighborhood, gsi::arg ("children"), gsi::arg ("visitor"), gsi::arg ("dist", 0),
|
||||
"@brief Creates a new edge neighborhood collector\n"
|
||||
gsi::ClassExt<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode_ext_PolygonNeighborhood (
|
||||
gsi::constructor ("new_polygon_neighborhood", &new_polygon_neighborhood, gsi::arg ("children"), gsi::arg ("visitor"), gsi::arg ("dist", 0),
|
||||
"@brief Creates a new polygon neighborhood collector\n"
|
||||
"\n"
|
||||
"@param children The inputs to use. The inputs are enumrated by base zero indexes in the visitor callback.\n"
|
||||
"@param visitor The visitor object (see \\PolygonNeighborhoodVisitor) receiving the edge events.\n"
|
||||
"@param children The inputs to use. The inputs are enumerated by base zero indexes in the visitor callback.\n"
|
||||
"@param visitor The visitor object (see \\PolygonNeighborhoodVisitor) receiving the polygon events.\n"
|
||||
"@param dist The search distance in which to look up neighbors.\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.30.0.\n"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include "dbRegion.h"
|
||||
#include "dbPolygonNeighborhood.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbTestSupport.h"
|
||||
|
||||
#include "tlStream.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class PNPrimaryCopyVisitor
|
||||
: public db::PolygonNeighborhoodVisitor
|
||||
{
|
||||
public:
|
||||
PNPrimaryCopyVisitor ()
|
||||
{
|
||||
set_result_type (db::CompoundRegionOperationNode::ResultType::Region);
|
||||
}
|
||||
|
||||
void neighbors (const db::Layout *, const db::Cell *, const db::PolygonWithProperties &polygon, const neighbors_type &)
|
||||
{
|
||||
output_polygon (polygon);
|
||||
}
|
||||
};
|
||||
|
||||
class PNPrimaryCopyIntruderVisitor
|
||||
: public db::PolygonNeighborhoodVisitor
|
||||
{
|
||||
public:
|
||||
PNPrimaryCopyIntruderVisitor (unsigned int input)
|
||||
{
|
||||
set_result_type (db::CompoundRegionOperationNode::ResultType::Edges);
|
||||
m_input = input;
|
||||
}
|
||||
|
||||
void neighbors (const db::Layout *, const db::Cell *, const db::PolygonWithProperties &polygon, const neighbors_type &neighbors)
|
||||
{
|
||||
for (auto n = neighbors.begin (); n != neighbors.end (); ++n) {
|
||||
if (n->first == m_input) {
|
||||
for (auto p = n->second.begin (); p != n->second.end (); ++p) {
|
||||
output_edge (db::Edge (polygon.box ().center (), p->box ().center ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_input;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static void prep_layer (db::Layout &ly, int gds_layer, db::Region &r, db::DeepShapeStore &dss, bool deep)
|
||||
{
|
||||
unsigned int li = ly.get_layer (db::LayerProperties (gds_layer, 0));
|
||||
if (deep) {
|
||||
r = db::Region (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), li), dss);
|
||||
} else {
|
||||
r = db::Region (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), li));
|
||||
}
|
||||
}
|
||||
|
||||
static void run_test (tl::TestBase *_this, db::PolygonNeighborhoodVisitor &visitor, const std::string &au_name, bool deep = true, db::Coord dist = 0)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testdata ());
|
||||
fn += "/algo/polygon_neighborhood.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Region r1, r2, r3;
|
||||
prep_layer (ly, 1, r1, dss, deep);
|
||||
prep_layer (ly, 2, r2, dss, deep);
|
||||
prep_layer (ly, 3, r3, dss, deep);
|
||||
|
||||
std::vector<db::CompoundRegionOperationNode *> children;
|
||||
children.push_back (new db::CompoundRegionOperationPrimaryNode ());
|
||||
children.push_back (new db::CompoundRegionOperationForeignNode ());
|
||||
children.push_back (new db::CompoundRegionOperationSecondaryNode (&r2));
|
||||
children.push_back (new db::CompoundRegionOperationSecondaryNode (&r3));
|
||||
|
||||
db::PolygonNeighborhoodCompoundOperationNode en_node (children, &visitor, dist);
|
||||
|
||||
unsigned int l100 = ly.get_layer (db::LayerProperties (100, 0));
|
||||
|
||||
if (en_node.result_type () == db::CompoundRegionOperationNode::ResultType::Region) {
|
||||
auto res = r1.cop_to_region (en_node);
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l100);
|
||||
} else if (en_node.result_type () == db::CompoundRegionOperationNode::ResultType::Edges) {
|
||||
auto res = r1.cop_to_edges (en_node);
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l100);
|
||||
} else if (en_node.result_type () == db::CompoundRegionOperationNode::ResultType::EdgePairs) {
|
||||
auto res = r1.cop_to_edge_pairs (en_node);
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l100);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, ly, tl::testdata () + au_name);
|
||||
}
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
PNPrimaryCopyVisitor visitor;
|
||||
run_test (_this, visitor, "/algo/polygon_neighborhood_au1.gds");
|
||||
}
|
||||
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
PNPrimaryCopyIntruderVisitor visitor (0);
|
||||
run_test (_this, visitor, "/algo/polygon_neighborhood_au2.gds", true, 2000);
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
PNPrimaryCopyIntruderVisitor visitor (1);
|
||||
run_test (_this, visitor, "/algo/polygon_neighborhood_au3.gds", true, 2000);
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
PNPrimaryCopyIntruderVisitor visitor (2);
|
||||
run_test (_this, visitor, "/algo/polygon_neighborhood_au4.gds", true, 2000);
|
||||
}
|
||||
|
||||
TEST(5)
|
||||
{
|
||||
PNPrimaryCopyIntruderVisitor visitor (3);
|
||||
run_test (_this, visitor, "/algo/polygon_neighborhood_au5.gds", true, 2000);
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ SOURCES = \
|
|||
dbFillToolTests.cc \
|
||||
dbLogTests.cc \
|
||||
dbObjectWithPropertiesTests.cc \
|
||||
dbPolygonNeighborhoodTests.cc \
|
||||
dbRecursiveInstanceIteratorTests.cc \
|
||||
dbRegionCheckUtilsTests.cc \
|
||||
dbTriangleTests.cc \
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ RUBYTEST (dbEdgePairTest, "dbEdgePairTest.rb")
|
|||
RUBYTEST (dbEdgesTest, "dbEdgesTest.rb")
|
||||
RUBYTEST (dbEdgeTest, "dbEdgeTest.rb")
|
||||
RUBYTEST (dbEdgeNeighborhood, "dbEdgeNeighborhood.rb")
|
||||
RUBYTEST (dbPolygonNeighborhood, "dbPolygonNeighborhood.rb")
|
||||
RUBYTEST (dbGlyphs, "dbGlyphs.rb")
|
||||
RUBYTEST (dbHierNetworkProcessorTests, "dbHierNetworkProcessorTests.rb")
|
||||
RUBYTEST (dbInstanceTest, "dbInstanceTest.rb")
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,142 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2025 Matthias Koefferlein
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if !$:.member?(File::dirname($0))
|
||||
$:.push(File::dirname($0))
|
||||
end
|
||||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class MyVisitor < RBA::PolygonNeighborhoodVisitor
|
||||
|
||||
def initialize
|
||||
@log = {}
|
||||
@current_log = nil
|
||||
end
|
||||
|
||||
def log
|
||||
@log.keys.sort { |a,b| a < b ? -1 : (a == b ? 0 : 1) }.collect { |k| @log[k].join("") }.join("")
|
||||
end
|
||||
|
||||
def neighbors(layout, cell, polygon, neighborhood)
|
||||
polygon = polygon.dup
|
||||
output(polygon)
|
||||
@log[polygon] ||= []
|
||||
@current_log = @log[polygon]
|
||||
@current_log << "Polygon: #{polygon}\n"
|
||||
neighborhood.each do |inp, poly|
|
||||
poly_str = poly.collect { |p| p.to_s }.join("/")
|
||||
@current_log << " #{inp}: #{poly_str}\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class MyVisitor2 < RBA::PolygonNeighborhoodVisitor
|
||||
|
||||
def initialize
|
||||
self.result_type = RBA::CompoundRegionOperationNode::ResultType::Edges
|
||||
end
|
||||
|
||||
def neighbors(layout, cell, polygon, neighborhood)
|
||||
neighborhood.each do |inp, poly|
|
||||
poly.each do |p|
|
||||
e = RBA::Edge::new(polygon.bbox.center, p.bbox.center)
|
||||
output(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DBPolygonNeighborhood_TestClass < TestBase
|
||||
|
||||
# basic events
|
||||
def test_1
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
l1 = ly.layer(1, 0)
|
||||
cell = ly.create_cell("TOP")
|
||||
|
||||
pid1 = RBA::Layout::properties_id({ 1 => "one" })
|
||||
|
||||
cell.shapes(l1).insert(RBA::Box::new(0, 0, 1000, 1000), pid1)
|
||||
cell.shapes(l1).insert(RBA::Box::new(-1100, 0, -100, 1000))
|
||||
|
||||
prim = RBA::Region::new(cell.begin_shapes_rec(l1))
|
||||
prim.enable_properties
|
||||
|
||||
visitor = MyVisitor::new
|
||||
|
||||
visitor.result_type = RBA::CompoundRegionOperationNode::ResultType::Region
|
||||
assert_equal(visitor.result_type, RBA::CompoundRegionOperationNode::ResultType::Region)
|
||||
|
||||
dist = 101
|
||||
|
||||
children = [
|
||||
RBA::CompoundRegionOperationNode::new_foreign
|
||||
]
|
||||
|
||||
node = RBA::CompoundRegionOperationNode::new_polygon_neighborhood(children, visitor, dist)
|
||||
res = prim.complex_op(node)
|
||||
|
||||
assert_equal(visitor.log,
|
||||
"Polygon: (-1100,0;-1100,1000;-100,1000;-100,0) props={}\n" +
|
||||
" 0: (0,0;0,1000;1000,1000;1000,0) props={1=>one}\n" +
|
||||
"Polygon: (0,0;0,1000;1000,1000;1000,0) props={1=>one}\n" +
|
||||
" 0: (-1100,0;-1100,1000;-100,1000;-100,0) props={}\n"
|
||||
)
|
||||
|
||||
assert_equal(res.to_s, "(-1100,0;-1100,1000;-100,1000;-100,0);(0,0;0,1000;1000,1000;1000,0){1=>one}")
|
||||
|
||||
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
|
||||
|
||||
dist = 101
|
||||
|
||||
children = [
|
||||
RBA::CompoundRegionOperationNode::new_foreign
|
||||
]
|
||||
|
||||
node = RBA::CompoundRegionOperationNode::new_polygon_neighborhood(children, visitor, dist)
|
||||
res = prim.complex_op(node)
|
||||
|
||||
assert_equal(res.to_s, "(-600,500;500,500);(500,500;-600,500)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
||||
Loading…
Reference in New Issue