WIP: debugging, tests. Triangulation should be safer now against linear chains of vertexes.

This commit is contained in:
Matthias Koefferlein 2025-05-04 14:36:34 +02:00
parent f83cd61843
commit 80ad38f81b
6 changed files with 134 additions and 12 deletions

View File

@ -1471,12 +1471,17 @@ Triangulation::triangulate (const db::Region &region, const std::vector<db::Poin
clear ();
std::vector<std::vector<Vertex *> > edge_contours;
for (auto p = region.begin_merged (); ! p.at_end (); ++p) {
make_contours (*p, trans, edge_contours);
}
unsigned int id = 0;
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v)->set_is_precious (true, id++);
}
create_constrained_delaunay (region, trans);
constrain (edge_contours);
refine (parameters);
}
@ -1495,12 +1500,15 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
clear ();
std::vector<std::vector<Vertex *> > edge_contours;
make_contours (poly, trans, edge_contours);
unsigned int id = 0;
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v)->set_is_precious (true, id++);
}
create_constrained_delaunay (poly, trans);
constrain (edge_contours);
refine (parameters);
}
@ -1517,12 +1525,15 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
clear ();
std::vector<std::vector<Vertex *> > edge_contours;
make_contours (poly, trans, edge_contours);
unsigned int id = 0;
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v)->set_is_precious (true, id++);
}
create_constrained_delaunay (poly, trans);
constrain (edge_contours);
refine (parameters);
}
@ -1539,12 +1550,15 @@ Triangulation::triangulate (const db::DPolygon &poly, const std::vector<db::DPoi
clear ();
std::vector<std::vector<Vertex *> > edge_contours;
make_contours (poly, trans, edge_contours);
unsigned int id = 0;
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v)->set_is_precious (true, id++);
}
create_constrained_delaunay (poly, trans);
constrain (edge_contours);
refine (parameters);
}

View File

@ -1118,11 +1118,29 @@ TEST(triangulate_with_vertexes)
EXPECT_EQ (vp, 0);
}
// normal triangulation
vertexes.clear ();
vertexes.push_back (db::Point (50, 50));
tri.triangulate (poly, vertexes, param, trans);
EXPECT_EQ (plc.to_string (), "((-0.45, 0), (-0.5, -0.05), (-0.5, 0.05)), ((0.5, 0.05), (-0.45, 0), (-0.5, 0.05)), ((-0.45, 0), (0.5, -0.05), (-0.5, -0.05)), ((-0.45, 0), (0.5, 0.05), (0.5, -0.05))");
EXPECT_EQ (plc.to_string (), "((-0.5, -0.05), (-0.5, 0.05), (-0.45, 0)), ((-0.5, 0.05), (0.5, 0.05), (-0.45, 0)), ((0.5, -0.05), (-0.45, 0), (0.5, 0.05)), ((0.5, -0.05), (-0.5, -0.05), (-0.45, 0))");
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
auto *vp = tri.find_vertex_for_point (trans * *v);
if (! vp) {
tl::warn << "Vertex not present in output: " << v->to_string ();
EXPECT_EQ (1, 0);
}
}
// linear chain of vertexes must not break triangulation
vertexes.clear ();
vertexes.push_back (db::Point (50, 50));
vertexes.push_back (db::Point (100, 50));
vertexes.push_back (db::Point (150, 50));
tri.triangulate (poly, vertexes, param, trans);
EXPECT_EQ (plc.to_string (), "((-0.5, -0.05), (-0.5, 0.05), (-0.45, 0)), ((-0.4, 0), (-0.45, 0), (-0.5, 0.05)), ((-0.5, -0.05), (-0.45, 0), (-0.4, 0)), ((0.5, -0.05), (-0.35, 0), (0.5, 0.05)), ((-0.5, -0.05), (-0.35, 0), (0.5, -0.05)), ((-0.5, -0.05), (-0.4, 0), (-0.35, 0)), ((-0.35, 0), (-0.5, 0.05), (0.5, 0.05)), ((-0.35, 0), (-0.4, 0), (-0.5, 0.05))");
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
auto *vp = tri.find_vertex_for_point (trans * *v);
@ -1139,7 +1157,7 @@ TEST(triangulate_with_vertexes)
tri.triangulate (poly, vertexes, param, trans);
EXPECT_GT (plc.num_polygons (), size_t (380));
EXPECT_LT (plc.num_polygons (), size_t (400));
EXPECT_LT (plc.num_polygons (), size_t (420));
for (auto t = plc.begin (); t != plc.end (); ++t) {
EXPECT_LE (t->area (), param.max_area);

View File

@ -79,7 +79,7 @@ RNetExtractor::extract (const RExtractorTech &tech,
vp_offset += p->second.size ();
}
for (auto p = polygon_ports.begin (); p != polygon_ports.end () && p->first < g->first; ++p) {
vp_offset += p->second.size ();
pp_offset += p->second.size ();
}
// fetch the port list for vertex ports
@ -377,6 +377,7 @@ private:
// for internal nodes always create a node in the target network
global = mp_rnetwork->create_node (local->type, ++m_next_internal_port_index);
global->location = local->location;
} else if (local->type == RNode::VertexPort) {
@ -409,7 +410,7 @@ private:
if (i2n != m_id_to_node.end ()) {
global = i2n->second;
} else {
global = mp_rnetwork->create_node (RNode::VertexPort, index_from_id (id) + m_polygon_port_index_offset);
global = mp_rnetwork->create_node (RNode::PolygonPort, index_from_id (id) + m_polygon_port_index_offset);
global->location = local->location;
m_id_to_node.insert (std::make_pair (id, global));
}
@ -422,7 +423,7 @@ private:
}
// create the R elements in the target network
for (auto e = local_network.begin_elements (); e != local_network.begin_elements (); ++e) {
for (auto e = local_network.begin_elements (); e != local_network.end_elements (); ++e) {
const RElement *local = e.operator-> ();
@ -431,7 +432,14 @@ private:
tl_assert (ia != n2n.end ());
tl_assert (ia != n2n.end ());
mp_rnetwork->create_element (local->conductance, ia->second, ib->second);
double c;
if (mp_cond->resistance < 1e-10) {
c = RElement::short_value ();
} else {
c = local->conductance / mp_cond->resistance;
}
mp_rnetwork->create_element (c, ia->second, ib->second);
}
}

View File

@ -181,7 +181,8 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector
{
rnetwork.clear ();
db::CplxTrans trans = db::CplxTrans (m_dbu) * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ()));
db::CplxTrans to_um (m_dbu);
db::CplxTrans trans = to_um * db::ICplxTrans (db::Trans (db::Point () - polygon.box ().center ()));
auto inv_trans = trans.inverted ();
db::plc::Graph plc;
@ -285,7 +286,7 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector
auto n4p = nodes_for_ports.find (p->first);
if (n4p == nodes_for_ports.end ()) {
pex::RNode *node = rnetwork.create_node (p->first.type, p->first.port_index);
node->location = trans * p->first.location;
node->location = to_um * p->first.location;
n4p = nodes_for_ports.insert (std::make_pair (p->first, node)).first;
}
p->second = n4p->second;

View File

@ -137,3 +137,84 @@ TEST(netex_viagen2)
"R $10(0.6,4.9;1.2,5.1) $11(0.6,4.9;1.2,5.1) 25"
);
}
TEST(netex_2layer)
{
db::Layout ly;
{
std::string fn = tl::testdata () + "/pex/netex_test1.gds";
tl::InputStream is (fn);
db::Reader reader (is);
reader.read (ly);
}
TestableRNetExtractor rex (ly.dbu ());
auto tc = ly.cell_by_name ("TOP");
tl_assert (tc.first);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l1p = ly.get_layer (db::LayerProperties (1, 1));
unsigned int l1v = ly.get_layer (db::LayerProperties (1, 2));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
unsigned int l3p = ly.get_layer (db::LayerProperties (3, 1));
unsigned int l3v = ly.get_layer (db::LayerProperties (3, 2));
std::map<unsigned int, db::Region> geo;
geo.insert (std::make_pair (l1, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1))));
geo.insert (std::make_pair (l2, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l2))));
geo.insert (std::make_pair (l3, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3))));
pex::RNetwork network;
pex::RExtractorTech tech;
pex::RExtractorTechVia via1;
via1.bottom_conductor = l1;
via1.cut_layer = l2;
via1.top_conductor = l3;
via1.resistance = 2.0;
via1.merge_distance = 0.2;
tech.vias.push_back (via1);
pex::RExtractorTechConductor cond1;
cond1.layer = l1;
cond1.resistance = 0.5;
tech.conductors.push_back (cond1);
pex::RExtractorTechConductor cond2;
cond2.layer = l3;
cond2.resistance = 0.25;
tech.conductors.push_back (cond2);
std::map<unsigned int, std::vector<db::Point> > vertex_ports;
std::map<unsigned int, std::vector<db::Polygon> > polygon_ports;
db::Region l1p_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1p));
for (auto p = l1p_region.begin_merged (); ! p.at_end (); ++p) {
polygon_ports[l1].push_back (*p);
}
db::Region l3p_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3p));
for (auto p = l3p_region.begin_merged (); ! p.at_end (); ++p) {
polygon_ports[l3].push_back (*p);
}
db::Region l1v_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l1v));
for (auto p = l1v_region.begin_merged (); ! p.at_end (); ++p) {
vertex_ports[l1].push_back (p->box ().center ());
}
db::Region l3v_region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l3v));
for (auto p = l3v_region.begin_merged (); ! p.at_end (); ++p) {
vertex_ports[l3].push_back (p->box ().center ());
}
rex.extract (tech, geo, vertex_ports, polygon_ports, network);
EXPECT_EQ (network.to_string (true),
""
);
}

BIN
testdata/pex/netex_test1.gds vendored Normal file

Binary file not shown.