This commit is contained in:
Matthias Koefferlein 2025-04-17 23:20:37 +02:00
parent 94396da117
commit a2ef7a28f8
8 changed files with 174 additions and 52 deletions

View File

@ -72,6 +72,11 @@ Vertex::Vertex (const Vertex &v)
// NOTE: edges are not copied!
}
Vertex::~Vertex ()
{
// .. nothing yet ..
}
Vertex &Vertex::operator= (const Vertex &v)
{
if (this != &v) {
@ -176,6 +181,11 @@ Edge::Edge (Graph *graph, Vertex *v1, Vertex *v2)
// .. nothing yet ..
}
Edge::~Edge ()
{
// .. nothing yet ..
}
void
Edge::set_left (Polygon *t)
{

View File

@ -161,10 +161,12 @@ protected:
Vertex (Graph *graph, const DPoint &p);
Vertex (Graph *graph, const Vertex &v);
Vertex (Graph *graph, db::DCoord x, db::DCoord y);
~Vertex ();
private:
friend class Edge;
friend class Graph;
friend class tl::stable_vector<Vertex>;
void remove_edge (const edges_iterator_non_const &ec)
{
@ -499,12 +501,14 @@ protected:
Edge (Graph *graph);
Edge (Graph *graph, Vertex *v1, Vertex *v2);
~Edge ();
private:
friend class Polygon;
friend class Graph;
friend class Triangulation;
friend class ConvexDecomposition;
friend class tl::stable_vector<Edge>;
Graph *mp_graph;
Vertex *mp_v1, *mp_v2;
@ -538,23 +542,34 @@ class DB_PUBLIC Polygon
: public tl::list_node<Polygon>, public tl::Object
{
public:
template<class Iter>
Polygon (Graph *graph, Iter from, Iter to)
: mp_graph (graph), mp_e (from, to)
{
init ();
}
/**
* @brief Destructor
*
* It is legal to delete a polygon object to remove it.
*/
~Polygon ();
/**
* @brief Detaches a polygon object from the edges
*/
void unlink ();
void set_id (size_t id) { m_id = id; }
/**
* @brief Gets the polygon's unique ID
*/
size_t id () const { return m_id; }
/**
* @brief Gets a value indicating whether the polygon is an outside polygon
*
* Outside polygons are polygons that fill concave parts in a triangulation for example.
*/
bool is_outside () const { return m_is_outside; }
void set_outside (bool o) { m_is_outside = o; }
/**
* @brief Returns a string representation
*/
std::string to_string (bool with_id = false) const;
/**
@ -727,8 +742,19 @@ protected:
Polygon (Graph *graph);
Polygon (Graph *graph, Edge *e1, Edge *e2, Edge *e3);
template<class Iter>
Polygon (Graph *graph, Iter from, Iter to)
: mp_graph (graph), mp_e (from, to)
{
init ();
}
void set_outside (bool o) { m_is_outside = o; }
void set_id (size_t id) { m_id = id; }
private:
friend class Graph;
friend class Triangulation;
Graph *mp_graph;
bool m_is_outside;
@ -764,6 +790,7 @@ struct PolygonLessFunc
* hold triangles (polygons with 3 vertexes).
*/
class DB_PUBLIC Graph
: public tl::Object
{
public:
typedef tl::list<Polygon> polygons_type;

View File

@ -85,24 +85,6 @@ struct equal_compare_func
}
};
struct ConcaveCorner
{
ConcaveCorner ()
: corner (0), incoming (0), outgoing (0)
{
// .. nothing yet ..
}
ConcaveCorner (Vertex *_corner, Edge *_incoming, Edge *_outgoing)
: corner (_corner), incoming (_incoming), outgoing (_outgoing)
{
// .. nothing yet ..
}
Vertex *corner;
Edge *incoming, *outgoing;
};
Edge *find_outgoing_segment (Vertex *vertex, Edge *incoming, int &vp_max_sign)
{
Vertex *vfrom = incoming->other (vertex);
@ -141,20 +123,16 @@ Edge *find_outgoing_segment (Vertex *vertex, Edge *incoming, int &vp_max_sign)
return outgoing;
}
void collect_concave_vertexes (Graph &tris, std::vector<ConcaveCorner> &concave_vertexes)
void
ConvexDecomposition::collect_concave_vertexes (std::vector<ConcaveCorner> &concave_vertexes)
{
concave_vertexes.clear ();
// @@@ use edge "level"
// @@@ use edges from heap
std::unordered_set<Edge *> left;
for (auto it = tris.begin (); it != tris.end (); ++it) {
for (unsigned int i = 0; i < 3; ++i) {
Edge *e = it->edge (i);
if (e->is_segment ()) {
left.insert (e);
}
for (auto e = mp_graph->edges ().begin (); e != mp_graph->edges ().end (); ++e) {
if (e->is_segment () && (e->left () != 0 || e->right () != 0)) {
left.insert (e.operator-> ());
}
}
@ -191,7 +169,7 @@ void collect_concave_vertexes (Graph &tris, std::vector<ConcaveCorner> &concave_
}
std::pair<bool, db::DPoint>
search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction)
ConvexDecomposition::search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction)
{
auto vtri = v0->polygons (); // TODO: slow?
std::vector<const Vertex *> nvv, nvv_next;
@ -253,7 +231,7 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C
bool split_edges = param.split_edges;
std::vector<ConcaveCorner> concave_vertexes;
collect_concave_vertexes (*mp_graph, concave_vertexes);
collect_concave_vertexes (concave_vertexes);
// @@@ return if no concave corners
@ -302,7 +280,7 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C
}
// As the insertion invalidates the edges, we need to collect the concave vertexes again
collect_concave_vertexes (*mp_graph, concave_vertexes);
collect_concave_vertexes (concave_vertexes);
}

View File

@ -121,7 +121,27 @@ public:
private:
Graph *mp_graph;
struct ConcaveCorner
{
ConcaveCorner ()
: corner (0), incoming (0), outgoing (0)
{
// .. nothing yet ..
}
ConcaveCorner (Vertex *_corner, Edge *_incoming, Edge *_outgoing)
: corner (_corner), incoming (_incoming), outgoing (_outgoing)
{
// .. nothing yet ..
}
Vertex *corner;
Edge *incoming, *outgoing;
};
void hertel_mehlhorn_decomposition (Triangulation &tris, const ConvexDecompositionParameters &param);
void collect_concave_vertexes (std::vector<ConcaveCorner> &concave_vertexes);
std::pair<bool, db::DPoint> search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction);
};
} // namespace plc

View File

@ -1133,12 +1133,10 @@ Triangulation::ensure_edge_inner (Vertex *from, Vertex *to)
}
Vertex *split_vertex;
if (dedge.side_of (split_point) == 0) {
if (dedge.side_of (*split_edge->v1 ()) == 0) {
split_vertex = split_edge->v1 ();
} else {
split_vertex = split_edge->v2 ();
}
if (dedge.side_of (*split_edge->v1 ()) == 0) {
split_vertex = split_edge->v1 ();
} else if (dedge.side_of (*split_edge->v2 ()) == 0) {
split_vertex = split_edge->v2 ();
} else {
split_vertex = insert_point (split_point);
}

View File

@ -27,15 +27,97 @@
#include <list>
#include <memory>
TEST(basic)
namespace
{
db::DBox box (0, 0, 100.0, 200.0);
db::plc::Graph plc;
// @@@ pg.insert_polygon (db::DSimplePolygon (box));
class TestableGraph
: public db::plc::Graph
{
public:
using db::plc::Graph::Graph;
using db::plc::Graph::create_vertex;
using db::plc::Graph::create_edge;
using db::plc::Graph::create_triangle;
using db::plc::Graph::create_polygon;
};
// @@@
tl::info << plc.to_string ();
plc.dump ("debug.gds"); // @@@
}
TEST(basic)
{
TestableGraph plc;
db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2));
EXPECT_EQ (v1->to_string (), "(1, 2)");
v1 = plc.create_vertex (db::DPoint (2, 1));
EXPECT_EQ (v1->to_string (), "(2, 1)");
EXPECT_EQ (v1->is_precious (), false);
v1->set_is_precious (true);
EXPECT_EQ (v1->is_precious (), true);
}
TEST(edge)
{
TestableGraph plc;
db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2));
db::plc::Vertex *v2 = plc.create_vertex (db::DPoint (3, 4));
db::plc::Edge *e = plc.create_edge (v1, v2);
EXPECT_EQ (e->to_string (), "((1, 2), (3, 4))");
EXPECT_EQ (v1->num_edges (), size_t (1));
EXPECT_EQ (v2->num_edges (), size_t (1));
EXPECT_EQ ((*v1->begin_edges ())->edge ().to_string (), "(1,2;3,4)");
EXPECT_EQ ((*v2->begin_edges ())->edge ().to_string (), "(1,2;3,4)");
}
TEST(polygon)
{
TestableGraph plc;
EXPECT_EQ (plc.num_polygons (), size_t (0));
EXPECT_EQ (plc.bbox ().to_string (), "()");
db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2));
db::plc::Vertex *v2 = plc.create_vertex (db::DPoint (3, 4));
db::plc::Vertex *v3 = plc.create_vertex (db::DPoint (3, 2));
db::plc::Edge *e1 = plc.create_edge (v1, v2);
db::plc::Edge *e2 = plc.create_edge (v1, v3);
db::plc::Edge *e3 = plc.create_edge (v2, v3);
db::plc::Polygon *tri = plc.create_triangle (e1, e2, e3);
EXPECT_EQ (tri->to_string (), "((1, 2), (3, 4), (3, 2))");
EXPECT_EQ (tri->polygon ().to_string (), "(1,2;3,4;3,2)");
EXPECT_EQ (plc.bbox ().to_string (), "(1,2;3,4)");
EXPECT_EQ (plc.num_polygons (), size_t (1));
EXPECT_EQ (v1->num_edges (), size_t (2));
EXPECT_EQ (v2->num_edges (), size_t (2));
EXPECT_EQ (v3->num_edges (), size_t (2));
EXPECT_EQ (tri->edge (0) == e1, true);
EXPECT_EQ (tri->edge (3) == e1, true);
EXPECT_EQ (tri->edge (1) == e3, true);
EXPECT_EQ (tri->edge (2) == e2, true);
EXPECT_EQ (tri->edge (-1) == e2, true);
EXPECT_EQ (e1->left () == 0, true);
EXPECT_EQ (e1->right () == tri, true);
EXPECT_EQ (e2->left () == tri, true);
EXPECT_EQ (e2->right () == 0, true);
EXPECT_EQ (e3->left () == 0, true);
EXPECT_EQ (e3->right () == tri, true);
delete tri;
EXPECT_EQ (e1->left () == 0, true);
EXPECT_EQ (e1->right () == 0, true);
EXPECT_EQ (e2->left () == 0, true);
EXPECT_EQ (e2->right () == 0, true);
EXPECT_EQ (e3->left () == 0, true);
EXPECT_EQ (e3->right () == 0, true);
}

View File

@ -71,6 +71,8 @@ public:
TestablePolygon (db::plc::Edge *e1, db::plc::Edge *e2, db::plc::Edge *e3)
: db::plc::Polygon (0, e1, e2, e3)
{ }
using db::plc::Polygon::set_outside;
};
// Tests for Vertex class

View File

@ -33,6 +33,9 @@
#include <cstdlib>
#include <cmath>
namespace
{
class TestableTriangulation
: public db::plc::Triangulation
{
@ -64,6 +67,8 @@ public:
using db::plc::Graph::create_triangle;
};
}
TEST(basic)
{
db::plc::Graph plc;
@ -343,7 +348,7 @@ TEST(heavy_insert)
double y = round (flt_rand () * res) * (1.0 / res);
db::plc::Vertex *v = tris.insert_point (x, y);
bbox += db::DPoint (x, y);
vmap.insert (std::make_pair (*v, false));
vmap.insert (std::pair<db::DPoint, bool> (*v, false));
}
// not strictly true, but very likely with at least 10 vertexes: