diff --git a/src/db/db/dbPLC.cc b/src/db/db/dbPLC.cc index 7fbb26b44..8f7c650a5 100644 --- a/src/db/db/dbPLC.cc +++ b/src/db/db/dbPLC.cc @@ -43,47 +43,58 @@ namespace plc // Vertex implementation Vertex::Vertex (Graph *graph) - : DPoint (), mp_graph (graph), m_is_precious (false) + : DPoint (), mp_graph (graph), mp_ids (0) { // .. nothing yet .. } Vertex::Vertex (Graph *graph, const db::DPoint &p) - : DPoint (p), mp_graph (graph), m_is_precious (false) + : DPoint (p), mp_graph (graph), mp_ids (0) { // .. nothing yet .. } Vertex::Vertex (Graph *graph, const Vertex &v) - : DPoint (), mp_graph (graph), m_is_precious (false), m_id (0) + : DPoint (), mp_graph (graph), mp_ids (0) { operator= (v); } Vertex::Vertex (Graph *graph, db::DCoord x, db::DCoord y) - : DPoint (x, y), mp_graph (graph), m_is_precious (false), m_id (0) + : DPoint (x, y), mp_graph (graph), mp_ids (0) { // .. nothing yet .. } Vertex::Vertex (const Vertex &v) - : DPoint (v), mp_graph (v.mp_graph), m_is_precious (v.m_is_precious), m_id (v.m_id) + : DPoint (), mp_graph (v.mp_graph), mp_ids (0) { - // NOTE: edges are not copied! + operator= (v); } Vertex::~Vertex () { - // .. nothing yet .. + if (mp_ids) { + delete mp_ids; + mp_ids = 0; + } } Vertex &Vertex::operator= (const Vertex &v) { if (this != &v) { + // NOTE: edges are not copied! db::DPoint::operator= (v); - m_is_precious = v.m_is_precious; - m_id = v.m_id; + + if (mp_ids) { + delete mp_ids; + mp_ids = 0; + } + if (v.mp_ids) { + mp_ids = new std::set (*v.mp_ids); + } + } return *this; } @@ -99,6 +110,39 @@ Vertex::is_outside () const return false; } +void +Vertex::set_is_precious (bool f, unsigned int id) +{ + if (f) { + if (! mp_ids) { + mp_ids = new std::set (); + } + mp_ids->insert (id); + } else { + if (mp_ids) { + delete mp_ids; + mp_ids = 0; + } + } +} + +bool +Vertex::is_precious () const +{ + return mp_ids != 0; +} + +const std::set & +Vertex::ids () const +{ + if (mp_ids != 0) { + return *mp_ids; + } else { + static std::set empty; + return empty; + } +} + std::vector Vertex::polygons () const { diff --git a/src/db/db/dbPLC.h b/src/db/db/dbPLC.h index ea5ed4e38..6a65e61d1 100644 --- a/src/db/db/dbPLC.h +++ b/src/db/db/dbPLC.h @@ -131,16 +131,12 @@ public: * * "precious" vertexes are not removed during triangulation for example. */ - void set_is_precious (bool f, unsigned int id) - { - m_is_precious = f; - m_id = id; - } + void set_is_precious (bool f, unsigned int id); /** * @brief Gets a value indicating whether the vertex is precious */ - bool is_precious () const { return m_is_precious; } + bool is_precious () const; /** * @brief Gets the ID passed to "set_is_precious" @@ -148,7 +144,7 @@ public: * This ID can be used to identify the vertex in the context it came from (e.g. * index in point vector). */ - unsigned int id () const { return m_id; } + const std::set &ids () const; /** * @brief Returns a string representation of the vertex @@ -187,8 +183,7 @@ private: Graph *mp_graph; edges_type mp_edges; - bool m_is_precious : 1; - unsigned int m_id : 31; + std::set *mp_ids; }; /** diff --git a/src/db/db/dbPLCTriangulation.h b/src/db/db/dbPLCTriangulation.h index db97f9651..3d3f30d4d 100644 --- a/src/db/db/dbPLCTriangulation.h +++ b/src/db/db/dbPLCTriangulation.h @@ -236,10 +236,38 @@ public: /** * @brief Refines the triangulation using the given parameters * - * This method is used internally by the "triangulation" method after creating the basic triangulation. + * This method is used internally by the "triangulate" method after creating the basic triangulation. + * + * This method is provided as a partial solution of a triangulation for special cases. */ void refine (const TriangulationParameters ¶m); + /** + * @brief Given a set of contours with edges, mark outer triangles + * + * The edges must be made from existing vertexes. Edge orientation is + * clockwise. + * + * This will also mark triangles as outside ones. + * This method is used internally by the "triangulate" method after creating the basic triangulation. + * + * This method is provided as a partial solution of a triangulation for special cases. + */ + void constrain (const std::vector > &contours); + + /** + * @brief Inserts a contours of a polygon + * + * This method fills the contours of the given polygon by doint an "insert_point" + * on all points and logging the outer edges ("segments") into the "contours" + * array. The latter can be passed to "constrain" to create a constrained + * triangulation. + * + * This method is used internally by the "triangulate" method to create the basic triangulation. + * This method is provided as a partial solution of a triangulation for special cases. + */ + template void make_contours (const Poly &poly, const Trans &trans, std::vector > &contours); + protected: /** * @brief Checks the polygon graph for consistency @@ -287,16 +315,6 @@ protected: */ std::vector ensure_edge (Vertex *from, Vertex *to); - /** - * @brief Given a set of contours with edges, mark outer triangles - * - * The edges must be made from existing vertexes. Edge orientation is - * clockwise. - * - * This will also mark triangles as outside ones. - */ - void constrain (const std::vector > &contours); - /** * @brief Returns a value indicating whether the edge is "illegal" (violates the Delaunay criterion) */ @@ -313,8 +331,6 @@ private: size_t m_id; mutable size_t m_flips, m_hops; - template void make_contours (const Poly &poly, const Trans &trans, std::vector > &contours); - void remove_outside_vertex (Vertex *vertex, std::list > *new_triangles = 0); void remove_inside_vertex (Vertex *vertex, std::list > *new_triangles_out = 0); std::vector fill_concave_corners (const std::vector &edges); diff --git a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc index 5ab556ab8..6b57ef505 100644 --- a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc +++ b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc @@ -145,7 +145,7 @@ TEST(internal_vertex) std::vector ip; for (size_t i = 0; i < p->internal_vertexes (); ++i) { - ip.push_back (p->internal_vertex (i)->to_string () + "#" + tl::to_string (p->internal_vertex (i)->id ())); + ip.push_back (p->internal_vertex (i)->to_string () + "#" + tl::to_string (p->internal_vertex (i)->ids ())); } std::sort (ip.begin (), ip.end ()); EXPECT_EQ (tl::join (ip, "/"), "(0, 0)#2/(0, 0.05)#0/(0.2, 0.07)#1"); diff --git a/src/db/unit_tests/dbPLCGraphTests.cc b/src/db/unit_tests/dbPLCGraphTests.cc index 29b7d9597..9a907a1c6 100644 --- a/src/db/unit_tests/dbPLCGraphTests.cc +++ b/src/db/unit_tests/dbPLCGraphTests.cc @@ -56,7 +56,12 @@ TEST(basic) EXPECT_EQ (v1->is_precious (), false); v1->set_is_precious (true, 17); EXPECT_EQ (v1->is_precious (), true); - EXPECT_EQ (v1->id (), 17u); + EXPECT_EQ (v1->ids ().size (), 1u); + EXPECT_EQ (*v1->ids ().begin (), 17u); + v1->set_is_precious (true, 1); + EXPECT_EQ (v1->is_precious (), true); + EXPECT_EQ (v1->ids ().size (), 2u); + EXPECT_EQ (*v1->ids ().begin (), 2u); } TEST(edge) diff --git a/src/pex/pex/pexRNetExtractor.cc b/src/pex/pex/pexRNetExtractor.cc index 5894ac356..3ce59e3ba 100644 --- a/src/pex/pex/pexRNetExtractor.cc +++ b/src/pex/pex/pexRNetExtractor.cc @@ -468,14 +468,14 @@ RNetExtractor::extract_conductor (const RExtractorTechConductor &cond, // type 0 objects (vertex ports) for (auto i = vertex_ports.begin (); i != vertex_ports.end (); ++i) { - // @@@ could be without enlarge? + // TODO: could be without enlarge? box_heap.push_back (db::Box (*i, *i).enlarged (db::Vector (1, 1))); scanner.insert2 (&box_heap.back (), make_id (i - vertex_ports.begin (), 0)); } // type 1 objects (via ports) for (auto i = via_ports.begin (); i != via_ports.end (); ++i) { - // @@@ could be without enlarge? + // TODO: could be without enlarge? box_heap.push_back (db::Box (i->position, i->position).enlarged (db::Vector (1, 1))); scanner.insert2 (&box_heap.back (), make_id (i - via_ports.begin (), 1)); } diff --git a/src/pex/pex/pexSquareCountingRExtractor.cc b/src/pex/pex/pexSquareCountingRExtractor.cc index acf9689d1..1abf32d95 100644 --- a/src/pex/pex/pexSquareCountingRExtractor.cc +++ b/src/pex/pex/pexSquareCountingRExtractor.cc @@ -269,7 +269,9 @@ SquareCountingRExtractor::extract (const db::Polygon &polygon, const std::vector for (size_t i = 0; i < plc_poly->internal_vertexes (); ++i) { auto v = plc_poly->internal_vertex (i); db::Point loc = inv_trans * *v; - ports.push_back (std::make_pair (PortDefinition (pex::RNode::VertexPort, loc, v->id ()), (pex::RNode *) 0)); + for (auto pi = v->ids ().begin (); pi != v->ids ().end (); ++pi) { + ports.push_back (std::make_pair (PortDefinition (pex::RNode::VertexPort, loc, *pi), (pex::RNode *) 0)); + } } // 3. polygon ports diff --git a/src/pex/pex/pexTriangulationRExtractor.cc b/src/pex/pex/pexTriangulationRExtractor.cc index b39a6a37d..18f2e70da 100644 --- a/src/pex/pex/pexTriangulationRExtractor.cc +++ b/src/pex/pex/pexTriangulationRExtractor.cc @@ -77,6 +77,14 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< tri.clear (); + std::vector > edge_contours; + + // first step of the triangulation + + for (auto p = residual_poly.begin_merged (); ! p.at_end (); ++p) { + tri.make_contours (*p, trans, edge_contours); + } + 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++); @@ -91,9 +99,9 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< } } - // perform the triangulation + // constrain and refine the triangulation - tri.create_constrained_delaunay (residual_poly, trans); + tri.constrain (edge_contours); tri.refine (param); // identify the vertexes present for the polygon port -> store them inside pp_vertexes @@ -147,11 +155,19 @@ TriangulationRExtractor::extract (const db::Polygon &polygon, const std::vector< } 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); + for (auto pi = vertex->ids ().begin (); pi != vertex->ids ().end (); ++pi) { + size_t port_index = size_t (*pi); + if (port_index < vertex_ports.size ()) { + RNode *nn = rnetwork.create_node (pex::RNode::VertexPort, port_index); + nn->location = db::DBox (*vertex, *vertex); + if (n) { + // in case of multiple vertexes on the same spot, short them + rnetwork.create_element (RElement::short_value (), n, nn); + } else { + n = nn; + } + vports_present.insert (port_index); + } } } else { diff --git a/src/pex/unit_tests/pexRNetExtractorTests.cc b/src/pex/unit_tests/pexRNetExtractorTests.cc index 5227a323b..fac83d200 100644 --- a/src/pex/unit_tests/pexRNetExtractorTests.cc +++ b/src/pex/unit_tests/pexRNetExtractorTests.cc @@ -215,6 +215,18 @@ TEST(netex_2layer) rex.extract (tech, geo, vertex_ports, polygon_ports, network); EXPECT_EQ (network.to_string (true), - "" + "R $0(0.3,-5.7;0.5,-5.5) $1(0.3,-5.7;0.5,-5.5) 50\n" + "R $2(9.3,-5.9;9.9,-5.3) $3(9.3,-5.9;9.9,-5.3) 12.5\n" + "R $4(9.3,0.1;9.9,0.3) $5(9.3,0.1;9.9,0.3) 25\n" + "R $6(0.1,0.1;0.7,0.7) $7(0.1,0.1;0.7,0.7) 12.5\n" + "R $0(0.3,-5.7;0.5,-5.5) $2(9.3,-5.9;9.9,-5.3) 5.75\n" + "R $2(9.3,-5.9;9.9,-5.3) P0(12.9,-5.9;13.5,-5.3) 2.25\n" + "R $6(0.1,0.1;0.7,0.7) V0(5.2,0.4;5.2,0.4) 3\n" + "R $4(9.3,0.1;9.9,0.3) V0(5.2,0.4;5.2,0.4) 2.75\n" + "R $5(9.3,0.1;9.9,0.3) $8(10,-3.5;10,-2.7) 1.03125\n" + "R $3(9.3,-5.9;9.9,-5.3) $8(10,-3.5;10,-2.7) 0.78125\n" + "R $8(10,-3.5;10,-2.7) P1(12.9,-3.4;13.5,-2.8) 1\n" + "R $7(0.1,0.1;0.7,0.7) V1(0.4,-5.6;0.4,-5.6) 1.875\n" + "R $1(0.3,-5.7;0.5,-5.5) V1(0.4,-5.6;0.4,-5.6) 0" ); } diff --git a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc index 09f1fce8f..ab485e7cb 100644 --- a/src/pex/unit_tests/pexTriangulationRExtractorTests.cc +++ b/src/pex/unit_tests/pexTriangulationRExtractorTests.cc @@ -301,7 +301,7 @@ TEST(extraction_analytic_disc) rex.extract (disc, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P0 P1 0.245379" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 + "R P0 P1 0.245558" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 ) rex.triangulation_parameters ().max_area = 100000 * dbu * dbu; @@ -309,7 +309,7 @@ TEST(extraction_analytic_disc) rex.extract (disc, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R P0 P1 0.255614" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 + "R P0 P1 0.255609" // theoretical: 1/(2*PI)*log(r2/r1) = 0.25615 with r2=10000, r1=2000 ) } @@ -357,7 +357,7 @@ TEST(extraction_meander) rex.extract (poly, vertex_ports, polygon_ports, rn); EXPECT_EQ (rn.to_string (), - "R V0 V1 8.75751" // what is the "real" value? + "R V0 V1 8.61417" // what is the "real" value? ) }