mirror of https://github.com/KLayout/klayout.git
WIP, more testcases, debugging
This commit is contained in:
parent
88a1ccbcfb
commit
f71210c64a
|
|
@ -300,8 +300,14 @@ Edge::crosses (const db::DEdge &e, const db::DEdge &other)
|
|||
bool
|
||||
Edge::crosses_including (const db::DEdge &e, const db::DEdge &other)
|
||||
{
|
||||
return e.side_of (other.p1 ()) * e.side_of (other.p2 ()) <= 0 &&
|
||||
other.side_of (e.p1 ()) * other.side_of (e.p2 ()) <= 0;
|
||||
int sa = e.side_of (other.p1 ());
|
||||
int sb = e.side_of (other.p2 ());
|
||||
int s1 = sa * sb;
|
||||
|
||||
int s2 = other.side_of (e.p1 ()) * other.side_of (e.p2 ());
|
||||
|
||||
// e can end on other and so can other end on e, but both may not be coincident
|
||||
return s1 <= 0 && s2 <= 0 && ! (sa == 0 && sb == 0);
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
|
|
|
|||
|
|
@ -1099,14 +1099,19 @@ Triangulation::find_vertexes_along_line (const db::DPoint &p1, const db::DPoint
|
|||
}
|
||||
|
||||
std::vector<Vertex *> result;
|
||||
result.push_back (v);
|
||||
|
||||
while (v) {
|
||||
Vertex *vn = 0;
|
||||
for (auto e = v->begin_edges (); e != v->end_edges (); ++e) {
|
||||
Vertex *vv = (*e)->other (v);
|
||||
if (db::vprod_sign (e12.d (), *vv - *v) == 0 && db::sprod_sign (e12.d (), *vv - *v) > 0 && db::sprod_sign (e12.d (), *vv - e12.p2 ()) < 0) {
|
||||
int cs = 0;
|
||||
if (db::vprod_sign (e12.d (), *vv - *v) == 0 && db::sprod_sign (e12.d (), *vv - *v) > 0 && (cs = db::sprod_sign (e12.d (), *vv - e12.p2 ())) <= 0) {
|
||||
result.push_back (vv);
|
||||
vn = vv;
|
||||
if (cs < 0) {
|
||||
// continue searching
|
||||
vn = vv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1377,8 +1382,6 @@ Triangulation::make_contours (const Poly &poly, const Trans &trans, std::vector<
|
|||
void
|
||||
Triangulation::create_constrained_delaunay (const db::Region ®ion, const CplxTrans &trans)
|
||||
{
|
||||
clear ();
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
|
||||
for (auto p = region.begin_merged (); ! p.at_end (); ++p) {
|
||||
|
|
@ -1389,15 +1392,8 @@ Triangulation::create_constrained_delaunay (const db::Region ®ion, const Cplx
|
|||
}
|
||||
|
||||
void
|
||||
Triangulation::create_constrained_delaunay (const db::Polygon &p, const std::vector<Point> &vertexes, const CplxTrans &trans)
|
||||
Triangulation::create_constrained_delaunay (const db::Polygon &p, const CplxTrans &trans)
|
||||
{
|
||||
clear ();
|
||||
|
||||
unsigned int id = 0;
|
||||
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
|
||||
insert_point (trans * *v)->set_is_precious (true, id++);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (p, trans, edge_contours);
|
||||
|
||||
|
|
@ -1405,15 +1401,8 @@ Triangulation::create_constrained_delaunay (const db::Polygon &p, const std::vec
|
|||
}
|
||||
|
||||
void
|
||||
Triangulation::create_constrained_delaunay (const db::DPolygon &p, const std::vector<DPoint> &vertexes, const DCplxTrans &trans)
|
||||
Triangulation::create_constrained_delaunay (const db::DPolygon &p, const DCplxTrans &trans)
|
||||
{
|
||||
clear ();
|
||||
|
||||
unsigned int id = 0;
|
||||
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
|
||||
insert_point (trans * *v)->set_is_precious (true, id++);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (p, trans, edge_contours);
|
||||
|
||||
|
|
@ -1458,6 +1447,8 @@ Triangulation::triangulate (const db::Region ®ion, const TriangulationParamet
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
clear ();
|
||||
|
||||
create_constrained_delaunay (region, db::CplxTrans (dbu));
|
||||
refine (parameters);
|
||||
}
|
||||
|
|
@ -1467,6 +1458,24 @@ Triangulation::triangulate (const db::Region ®ion, const TriangulationParamet
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
clear ();
|
||||
|
||||
create_constrained_delaunay (region, trans);
|
||||
refine (parameters);
|
||||
}
|
||||
|
||||
void
|
||||
Triangulation::triangulate (const db::Region ®ion, const std::vector<db::Point> &vertexes, const TriangulationParameters ¶meters, const db::CplxTrans &trans)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
clear ();
|
||||
|
||||
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);
|
||||
refine (parameters);
|
||||
}
|
||||
|
|
@ -1482,7 +1491,16 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
create_constrained_delaunay (poly, vertexes, db::CplxTrans (dbu));
|
||||
db::CplxTrans trans (dbu);
|
||||
|
||||
clear ();
|
||||
|
||||
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);
|
||||
refine (parameters);
|
||||
}
|
||||
|
||||
|
|
@ -1497,7 +1515,14 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
create_constrained_delaunay (poly, vertexes, trans);
|
||||
clear ();
|
||||
|
||||
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);
|
||||
refine (parameters);
|
||||
}
|
||||
|
||||
|
|
@ -1512,7 +1537,14 @@ Triangulation::triangulate (const db::DPolygon &poly, const std::vector<db::DPoi
|
|||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate");
|
||||
|
||||
create_constrained_delaunay (poly, vertexes, trans);
|
||||
clear ();
|
||||
|
||||
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);
|
||||
refine (parameters);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ public:
|
|||
|
||||
// more versions
|
||||
void triangulate (const db::Region ®ion, const TriangulationParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
void triangulate (const db::Region ®ion, const std::vector<db::Point> &vertexes, const TriangulationParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
void triangulate (const db::Polygon &poly, const TriangulationParameters ¶meters, double dbu = 1.0);
|
||||
void triangulate (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const TriangulationParameters ¶meters, double dbu = 1.0);
|
||||
void triangulate (const db::Polygon &poly, const TriangulationParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
|
|
@ -181,6 +182,17 @@ public:
|
|||
*/
|
||||
std::vector<Vertex *> find_vertexes_along_line (const db::DPoint &p1, const db::DPoint &p2) const;
|
||||
|
||||
/**
|
||||
* @brief Removes the outside triangles.
|
||||
*
|
||||
* This method is useful in combination with the "remove_outside_triangles = false" triangulation
|
||||
* parameter. In this mode, outside triangles are not removed after triangulation (the
|
||||
* triangulated area is convex). This enables use of the "find" functions.
|
||||
*
|
||||
* This method can be used to finally remove the outside triangles if no longer needed.
|
||||
*/
|
||||
void remove_outside_triangles ();
|
||||
|
||||
/**
|
||||
* @brief Statistics: number of flips (fixing)
|
||||
*/
|
||||
|
|
@ -197,6 +209,37 @@ public:
|
|||
return m_hops;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given Region
|
||||
*
|
||||
* This method is used internally by the "triangulation" method to create the basic triangulation,
|
||||
* followed by a "refine" step.
|
||||
*/
|
||||
void create_constrained_delaunay (const db::Region ®ion, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given Polygon
|
||||
*
|
||||
* This method is used internally by the "triangulation" method to create the basic triangulation,
|
||||
* followed by a "refine" step.
|
||||
*/
|
||||
void create_constrained_delaunay (const db::Polygon &poly, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given DPolygon
|
||||
*
|
||||
* This method is used internally by the "triangulation" method to create the basic triangulation,
|
||||
* followed by a "refine" step.
|
||||
*/
|
||||
void create_constrained_delaunay (const db::DPolygon &poly, const DCplxTrans &trans = db::DCplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Refines the triangulation using the given parameters
|
||||
*
|
||||
* This method is used internally by the "triangulation" method after creating the basic triangulation.
|
||||
*/
|
||||
void refine (const TriangulationParameters ¶m);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Checks the polygon graph for consistency
|
||||
|
|
@ -254,26 +297,6 @@ protected:
|
|||
*/
|
||||
void constrain (const std::vector<std::vector<Vertex *> > &contours);
|
||||
|
||||
/**
|
||||
* @brief Removes the outside triangles.
|
||||
*/
|
||||
void remove_outside_triangles ();
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given Region
|
||||
*/
|
||||
void create_constrained_delaunay (const db::Region ®ion, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given Polygon
|
||||
*/
|
||||
void create_constrained_delaunay (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const db::CplxTrans &trans = db::CplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Creates a constrained Delaunay triangulation from the given DPolygon
|
||||
*/
|
||||
void create_constrained_delaunay (const db::DPolygon &poly, const std::vector<DPoint> &vertexes, const DCplxTrans &trans);
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether the edge is "illegal" (violates the Delaunay criterion)
|
||||
*/
|
||||
|
|
@ -308,7 +331,6 @@ private:
|
|||
void insert_new_vertex(Vertex *vertex, std::list<tl::weak_ptr<Polygon> > *new_triangles_out);
|
||||
std::vector<Edge *> ensure_edge_inner (Vertex *from, Vertex *to);
|
||||
void join_edges (std::vector<Edge *> &edges);
|
||||
void refine (const TriangulationParameters ¶m);
|
||||
};
|
||||
|
||||
} // namespace plc
|
||||
|
|
|
|||
|
|
@ -155,24 +155,28 @@ TEST(collect_vertexes)
|
|||
tris.insert_point (0.5, 0.5);
|
||||
|
||||
std::vector<db::plc::Vertex *> vertexes = tris.find_vertexes_along_line (db::DPoint (0, 0), db::DPoint (1.5, 1.5));
|
||||
EXPECT_EQ (vertexes.size (), size_t (3));
|
||||
if (vertexes.size () >= size_t (3)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(0.2, 0.2)");
|
||||
EXPECT_EQ (vertexes [1]->to_string (), "(0.5, 0.5)");
|
||||
EXPECT_EQ (vertexes [2]->to_string (), "(1, 1)");
|
||||
EXPECT_EQ (vertexes.size (), size_t (4));
|
||||
if (vertexes.size () >= size_t (4)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(0, 0)");
|
||||
EXPECT_EQ (vertexes [1]->to_string (), "(0.2, 0.2)");
|
||||
EXPECT_EQ (vertexes [2]->to_string (), "(0.5, 0.5)");
|
||||
EXPECT_EQ (vertexes [3]->to_string (), "(1, 1)");
|
||||
}
|
||||
|
||||
vertexes = tris.find_vertexes_along_line (db::DPoint (0, 0), db::DPoint (1.0, 1.0));
|
||||
EXPECT_EQ (vertexes.size (), size_t (2));
|
||||
if (vertexes.size () >= size_t (2)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(0.2, 0.2)");
|
||||
EXPECT_EQ (vertexes [1]->to_string (), "(0.5, 0.5)");
|
||||
EXPECT_EQ (vertexes.size (), size_t (4));
|
||||
if (vertexes.size () >= size_t (4)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(0, 0)");
|
||||
EXPECT_EQ (vertexes [1]->to_string (), "(0.2, 0.2)");
|
||||
EXPECT_EQ (vertexes [2]->to_string (), "(0.5, 0.5)");
|
||||
EXPECT_EQ (vertexes [3]->to_string (), "(1, 1)");
|
||||
}
|
||||
|
||||
vertexes = tris.find_vertexes_along_line (db::DPoint (1, 1), db::DPoint (0.25, 0.25));
|
||||
EXPECT_EQ (vertexes.size (), size_t (1));
|
||||
if (vertexes.size () >= size_t (1)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(0.5, 0.5)");
|
||||
EXPECT_EQ (vertexes.size (), size_t (2));
|
||||
if (vertexes.size () >= size_t (2)) {
|
||||
EXPECT_EQ (vertexes [0]->to_string (), "(1, 1)");
|
||||
EXPECT_EQ (vertexes [1]->to_string (), "(0.5, 0.5)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,24 +43,74 @@ TriangulationRExtractor::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 ()));
|
||||
auto inv_trans = trans.inverted ();
|
||||
|
||||
// NOTE: currently we treat polygon ports and points where the location is the center of the bounding box
|
||||
std::vector<db::Point> vp = vertex_ports;
|
||||
vp.reserve (vertex_ports.size () + polygon_ports.size ());
|
||||
for (auto pp = polygon_ports.begin (); pp != polygon_ports.end (); ++pp) {
|
||||
vp.push_back (pp->box ().center ());
|
||||
}
|
||||
|
||||
|
||||
db::plc::Graph plc;
|
||||
db::plc::Triangulation tri (&plc);
|
||||
|
||||
tri.triangulate (polygon, vp, m_tri_param, trans);
|
||||
std::unordered_map <const db::plc::Vertex *, size_t> pp_vertexes;
|
||||
|
||||
// create a network node for each triangle node
|
||||
if (polygon_ports.empty ()) {
|
||||
|
||||
tri.triangulate (polygon, vertex_ports, m_tri_param, trans);
|
||||
|
||||
} else {
|
||||
|
||||
// Subtract the polygon ports from the original polygon and compute the intersection.
|
||||
// Hence we have coincident edges that we can use to identify the nodes that are
|
||||
// connected for the polygon ports
|
||||
|
||||
db::Region org (polygon);
|
||||
db::Region pp (polygon_ports.begin (), polygon_ports.end ());
|
||||
|
||||
db::Region residual_poly = org - pp;
|
||||
|
||||
// We must not remove outside triangles yet, as we need them for "find_vertexes_along_line"
|
||||
db::plc::TriangulationParameters param = m_tri_param;
|
||||
param.remove_outside_triangles = false;
|
||||
|
||||
tri.clear ();
|
||||
|
||||
unsigned int id = 0;
|
||||
for (auto v = vertex_ports.begin (); v != vertex_ports.end (); ++v) {
|
||||
tri.insert_point (trans * *v)->set_is_precious (true, id++);
|
||||
}
|
||||
|
||||
for (auto p = polygon_ports.begin (); p != polygon_ports.end (); ++p) {
|
||||
// create vertexes for the port polygon vertexes - this ensures we will find vertexes
|
||||
// on the edges of the polygons - yet, they may be outside of the original polygon.
|
||||
// In that case they will not be considered
|
||||
for (auto e = p->begin_edge (); !e.at_end (); ++e) {
|
||||
tri.insert_point (trans * (*e).p1 ())->set_is_precious (true, id);
|
||||
}
|
||||
}
|
||||
|
||||
// perform the triangulation
|
||||
|
||||
tri.create_constrained_delaunay (residual_poly, trans);
|
||||
tri.refine (param);
|
||||
|
||||
// identify the vertexes present for the polygon port -> store them inside pp_vertexes
|
||||
|
||||
for (auto p = polygon_ports.begin (); p != polygon_ports.end (); ++p) {
|
||||
for (auto e = p->begin_edge (); !e.at_end (); ++e) {
|
||||
// NOTE: this currently only works if one of the end points is an actual
|
||||
// vertex.
|
||||
auto vport = tri.find_vertexes_along_line (trans * (*e).p1 (), trans * (*e).p2 ());
|
||||
for (auto v = vport.begin (); v != vport.end (); ++v) {
|
||||
pp_vertexes.insert (std::make_pair (*v, p - polygon_ports.begin ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tri.remove_outside_triangles ();
|
||||
|
||||
}
|
||||
|
||||
// Create a network node for each triangle node.
|
||||
|
||||
std::unordered_map<const db::plc::Vertex *, pex::RNode *> vertex2node;
|
||||
std::unordered_set<size_t> vports_present;
|
||||
std::map<size_t, pex::RNode *> pport_nodes;
|
||||
|
||||
size_t internal_node_id = 0;
|
||||
|
||||
|
|
@ -73,28 +123,71 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector<
|
|||
continue;
|
||||
}
|
||||
|
||||
pex::RNode::node_type type = pex::RNode::Internal;
|
||||
size_t port_index = 0;
|
||||
pex::RNode *n = 0;
|
||||
|
||||
if (vertex->is_precious ()) {
|
||||
size_t idx = vertex->id ();
|
||||
if (idx >= vertex_ports.size ()) {
|
||||
type = pex::RNode::PolygonPort;
|
||||
port_index = size_t (idx) - vertex_ports.size ();
|
||||
auto ipp = pp_vertexes.find (vertex);
|
||||
if (ipp != pp_vertexes.end ()) {
|
||||
|
||||
size_t port_index = ipp->second;
|
||||
auto pn = pport_nodes.find (port_index);
|
||||
if (pn != pport_nodes.end ()) {
|
||||
n = pn->second;
|
||||
} else {
|
||||
type = pex::RNode::VertexPort;
|
||||
port_index = size_t (idx);
|
||||
n = rnetwork.create_node (pex::RNode::PolygonPort, port_index);
|
||||
pport_nodes.insert (std::make_pair (port_index, n));
|
||||
n->location = trans * polygon_ports [port_index].box ();
|
||||
}
|
||||
|
||||
} else if (vertex->is_precious ()) {
|
||||
|
||||
size_t port_index = size_t (vertex->id ());
|
||||
if (port_index < vertex_ports.size ()) {
|
||||
n = rnetwork.create_node (pex::RNode::VertexPort, port_index);
|
||||
n->location = db::DBox (*vertex, *vertex);
|
||||
vports_present.insert (port_index);
|
||||
}
|
||||
|
||||
} else {
|
||||
port_index = internal_node_id++;
|
||||
|
||||
n = rnetwork.create_node (pex::RNode::Internal, internal_node_id++);
|
||||
n->location = db::DBox (*vertex, *vertex);
|
||||
|
||||
}
|
||||
|
||||
pex::RNode *n = rnetwork.create_node (type, port_index);
|
||||
db::DPoint loc = *vertex;
|
||||
n->location = db::DBox (loc, loc);
|
||||
if (n) {
|
||||
vertex2node.insert (std::make_pair (vertex, n));
|
||||
}
|
||||
|
||||
vertex2node.insert (std::make_pair (vertex, n));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check for vertex ports not assigned to a node
|
||||
// -> this may be an indication for a vertex port inside a polygon port
|
||||
|
||||
for (size_t iv = 0; iv < vertex_ports.size (); ++iv) {
|
||||
|
||||
if (vports_present.find (iv) != vports_present.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
db::Point vp = vertex_ports [iv];
|
||||
|
||||
for (auto p = polygon_ports.begin (); p != polygon_ports.end (); ++p) {
|
||||
|
||||
if (p->box ().contains (vp) && db::inside_poly_test<db::Polygon> (*p) (vp) >= 0) {
|
||||
|
||||
auto ip = pport_nodes.find (p - polygon_ports.begin ());
|
||||
if (ip != pport_nodes.end ()) {
|
||||
|
||||
// create a new vertex port and short it to the polygon port
|
||||
auto n = rnetwork.create_node (pex::RNode::VertexPort, iv);
|
||||
n->location = db::DBox (trans * vp, trans * vp);
|
||||
rnetwork.create_element (pex::RElement::short_value (), n, ip->second);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -121,17 +214,22 @@ TriangulationRExtractor::create_conductances (const db::plc::Polygon &tri, const
|
|||
const db::plc::Vertex *p0 = tri.vertex (i + 1);
|
||||
const db::plc::Vertex *p1 = tri.vertex (i + 2);
|
||||
|
||||
double a = fabs (db::vprod (*pm1 - *p0, *p1 - *p0) * 0.5);
|
||||
|
||||
double lm1 = (*p0 - *pm1).sq_length ();
|
||||
double l0 = (*p1 - *p0).sq_length ();
|
||||
double l1 = (*pm1 - *p1).sq_length ();
|
||||
|
||||
double s = (l0 + l1 - lm1) / (8.0 * a);
|
||||
|
||||
auto i0 = vertex2node.find (p0);
|
||||
auto im1 = vertex2node.find (pm1);
|
||||
rnetwork.create_element (s, i0->second, im1->second);
|
||||
|
||||
if (i0->second != im1->second) {
|
||||
|
||||
double a = fabs (db::vprod (*pm1 - *p0, *p1 - *p0) * 0.5);
|
||||
|
||||
double lm1 = (*p0 - *pm1).sq_length ();
|
||||
double l0 = (*p1 - *p0).sq_length ();
|
||||
double l1 = (*pm1 - *p1).sq_length ();
|
||||
|
||||
double s = (l0 + l1 - lm1) / (8.0 * a);
|
||||
|
||||
rnetwork.create_element (s, i0->second, im1->second);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,3 +67,191 @@ TEST(extraction)
|
|||
"R V1 V0 10.0938"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_with_polygon_ports)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (0, 0),
|
||||
db::Point (0, 100),
|
||||
db::Point (1000, 100),
|
||||
db::Point (1000, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1000, 0, 1100, 100)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P1 P0 10"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_with_polygon_ports_inside)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (-100, 0),
|
||||
db::Point (-100, 100),
|
||||
db::Point (1100, 100),
|
||||
db::Point (1100, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1000, 0, 1100, 100)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P1 P0 10"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_split_by_ports)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (-100, 0),
|
||||
db::Point (-100, 100),
|
||||
db::Point (1100, 100),
|
||||
db::Point (1100, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1100, 0, 1200, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (500, 0, 600, 100)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P2 P0 5\n"
|
||||
"R P1 P2 5"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_split_by_butting_port)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (-100, 0),
|
||||
db::Point (-100, 100),
|
||||
db::Point (1100, 100),
|
||||
db::Point (1100, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1100, 0, 1200, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (500, 100, 600, 200)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P2 P0 4.84211\n"
|
||||
"R P1 P2 4.84211\n"
|
||||
"R P0 P1 281.111"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_with_outside_polygon_port)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (-100, 0),
|
||||
db::Point (-100, 100),
|
||||
db::Point (1100, 100),
|
||||
db::Point (1100, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1100, 0, 1200, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (500, 200, 600, 300)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R P1 P0 11"
|
||||
)
|
||||
}
|
||||
|
||||
TEST(extraction_with_polygon_ports_and_vertex_port_inside)
|
||||
{
|
||||
db::Point contour[] = {
|
||||
db::Point (-100, 0),
|
||||
db::Point (-100, 100),
|
||||
db::Point (1100, 100),
|
||||
db::Point (1100, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0]));
|
||||
|
||||
double dbu = 0.001;
|
||||
|
||||
pex::RNetwork rn;
|
||||
pex::TriangulationRExtractor rex (dbu);
|
||||
|
||||
std::vector<db::Point> vertex_ports;
|
||||
vertex_ports.push_back (db::Point (-50, 50));
|
||||
|
||||
std::vector<db::Polygon> polygon_ports;
|
||||
polygon_ports.push_back (db::Polygon (db::Box (-100, 0, 0, 100)));
|
||||
polygon_ports.push_back (db::Polygon (db::Box (1000, 0, 1100, 100)));
|
||||
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R V0 P0 0\n" // shorted because V0 is inside P0
|
||||
"R P1 P0 10"
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue