OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::MinimumSpanningTree Class Reference

Implements Prim's algorithm to compute Minimum Spanning Trees (MST). More...

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/MinimumSpanningTree.hpp>

Collaboration diagram for Slic3r::MinimumSpanningTree:

Classes

struct  Edge
 Represents an edge of the tree. More...

Public Member Functions

 MinimumSpanningTree ()=default
 MinimumSpanningTree (std::vector< Point > vertices)
 Constructs a minimum spanning tree that spans all given vertices.
std::vector< Point > adjacent_nodes (Point node) const
 Gets the nodes that are adjacent to the specified node.
std::vector< Point > leaves () const
 Gets the leaves of the tree.
std::vector< Point > vertices () const
 Gets all vertices of the tree.

Private Types

using AdjacencyGraph_t = std::unordered_map<Point, std::vector<Edge>, PointHash>

Private Member Functions

AdjacencyGraph_t prim (std::vector< Point > vertices) const
 Computes the edges of a minimum spanning tree using Prim's algorithm.

Private Attributes

AdjacencyGraph_t adjacency_graph

Detailed Description

Implements Prim's algorithm to compute Minimum Spanning Trees (MST).

The minimum spanning tree is always computed from a clique of vertices.


Class Documentation

◆ Slic3r::MinimumSpanningTree::Edge

struct Slic3r::MinimumSpanningTree::Edge

Represents an edge of the tree.

While edges are meant to be undirected, these do have a start and end point.

Collaboration diagram for Slic3r::MinimumSpanningTree::Edge:
Class Members
const Point end

The point at which this edge ends.

const Point start

The point at which this edge starts.

Member Typedef Documentation

◆ AdjacencyGraph_t

using Slic3r::MinimumSpanningTree::AdjacencyGraph_t = std::unordered_map<Point, std::vector<Edge>, PointHash>
private

Constructor & Destructor Documentation

◆ MinimumSpanningTree() [1/2]

Slic3r::MinimumSpanningTree::MinimumSpanningTree ( )
default

References vertices().

Here is the call graph for this function:

◆ MinimumSpanningTree() [2/2]

Slic3r::MinimumSpanningTree::MinimumSpanningTree ( std::vector< Point > vertices)

Constructs a minimum spanning tree that spans all given vertices.

28{
29 //Just copy over the fields.
30}
AdjacencyGraph_t adjacency_graph
Definition MinimumSpanningTree.hpp:64
AdjacencyGraph_t prim(std::vector< Point > vertices) const
Computes the edges of a minimum spanning tree using Prim's algorithm.
Definition MinimumSpanningTree.cpp:32
std::vector< Point > vertices() const
Gets all vertices of the tree.
Definition MinimumSpanningTree.cpp:137

References adjacency_graph, prim(), and vertices().

Here is the call graph for this function:

Member Function Documentation

◆ adjacent_nodes()

std::vector< Point > Slic3r::MinimumSpanningTree::adjacent_nodes ( Point node) const

Gets the nodes that are adjacent to the specified node.

Returns
A list of nodes that are adjacent.
112{
113 std::vector<Point> result;
114 AdjacencyGraph_t::const_iterator adjacency_entry = adjacency_graph.find(node);
115 if (adjacency_entry != adjacency_graph.end())
116 {
117 const auto& edges = adjacency_entry->second;
118 std::transform(edges.begin(), edges.end(), std::back_inserter(result),
119 [&node](const Edge& e) { return (e.start == node) ? e.end : e.start; });
120 }
121 return result;
122}
Represents an edge of the tree.
Definition MinimumSpanningTree.hpp:26

References adjacency_graph.

◆ leaves()

std::vector< Point > Slic3r::MinimumSpanningTree::leaves ( ) const

Gets the leaves of the tree.

Returns
A list of nodes that are all leaves of the tree.
125{
126 std::vector<Point> result;
127 for (std::pair<Point, std::vector<Edge>> node : adjacency_graph)
128 {
129 if (node.second.size() <= 1) //Leaves are nodes that have only one adjacent edge, or just the one node if the tree contains one node.
130 {
131 result.push_back(node.first);
132 }
133 }
134 return result;
135}

References adjacency_graph.

◆ prim()

auto Slic3r::MinimumSpanningTree::prim ( std::vector< Point > vertices) const
private

Computes the edges of a minimum spanning tree using Prim's algorithm.

Parameters
verticesThe vertices to span.
Returns
An adjacency graph with for each point one or more edges.
33{
34 AdjacencyGraph_t result;
35 if (vertices.empty())
36 {
37 return result; //No vertices, so we can't create edges either.
38 }
39 // If there's only one vertex, we can't go creating any edges so just add the point to the adjacency list with no
40 // edges
41 if (vertices.size() == 1)
42 {
43 // unordered_map::operator[]() will construct an empty vector in place for us when we try and access an element
44 // that doesnt exist
45 result[*vertices.begin()];
46 return result;
47 }
48 result.reserve(vertices.size());
49 std::vector<Point> vertices_list(vertices.begin(), vertices.end());
50
51 std::unordered_map<const Point*, coordf_t> smallest_distance; //The shortest distance to the current tree.
52 std::unordered_map<const Point*, const Point*> smallest_distance_to; //Which point the shortest distance goes towards.
53 smallest_distance.reserve(vertices_list.size());
54 smallest_distance_to.reserve(vertices_list.size());
55 for (size_t vertex_index = 1; vertex_index < vertices_list.size(); vertex_index++)
56 {
57 const auto& vert = vertices_list[vertex_index];
58 smallest_distance[&vert] = vsize2_with_unscale(vert - vertices_list[0]);
59 smallest_distance_to[&vert] = &vertices_list[0];
60 }
61
62 while (result.size() < vertices_list.size()) //All of the vertices need to be in the tree at the end.
63 {
64 //Choose the closest vertex to connect to that is not yet in the tree.
65 //This search is O(V) right now, which can be made down to O(log(V)). This reduces the overall time complexity from O(V*V) to O(V*log(E)).
66 //However that requires an implementation of a heap that supports the decreaseKey operation, which is not in the std library.
67 //TODO: Implement this?
68 // Break equal-distance ties on coordinates: the map is keyed by address, so its
69 // iteration order (and therefore the first minimum) would otherwise depend on where
70 // the vertices were allocated.
71 using MapValue = std::pair<const Point*, coordf_t>;
72 const auto closest = std::min_element(smallest_distance.begin(), smallest_distance.end(),
73 [](const MapValue& a, const MapValue& b) {
74 if (a.second != b.second)
75 return a.second < b.second;
76 return *a.first < *b.first;
77 });
78
79 //Add this point to the graph and remove it from the candidates.
80 const Point* closest_point = closest->first;
81 const Point other_end = *smallest_distance_to[closest_point];
82 if (result.find(*closest_point) == result.end())
83 {
84 result[*closest_point] = std::vector<Edge>();
85 }
86 result[*closest_point].push_back({*closest_point, other_end});
87 if (result.find(other_end) == result.end())
88 {
89 result[other_end] = std::vector<Edge>();
90 }
91 result[other_end].push_back({other_end, *closest_point});
92 smallest_distance.erase(closest_point); //Remove it so we don't check for these points again.
93 smallest_distance_to.erase(closest_point);
94
95 //Update the distances of all points that are not in the graph.
96 for (std::pair<const Point*, coordf_t> point_and_distance : smallest_distance)
97 {
98 const coordf_t new_distance = vsize2_with_unscale(*closest_point - *point_and_distance.first);
99 const coordf_t old_distance = point_and_distance.second;
100 if (new_distance < old_distance) //New point is closer.
101 {
102 smallest_distance[point_and_distance.first] = new_distance;
103 smallest_distance_to[point_and_distance.first] = closest_point;
104 }
105 }
106 }
107
108 return result;
109}
std::unordered_map< Point, std::vector< Edge >, PointHash > AdjacencyGraph_t
Definition MinimumSpanningTree.hpp:63
Foot closest(const Contour &c, const Vec2d &p, double stop=-1.0, const std::vector< Vec2d > *source_normals=nullptr, double normal_cosine=0.0)
Definition SeamContour.cpp:36
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
double coordf_t
Definition GUI_ObjectList.hpp:46
double vsize2_with_unscale(const Point pt)
Definition MinimumSpanningTree.cpp:22

References vertices(), and Slic3r::vsize2_with_unscale().

Referenced by MinimumSpanningTree().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vertices()

std::vector< Point > Slic3r::MinimumSpanningTree::vertices ( ) const

Gets all vertices of the tree.

Returns
A list of vertices of the tree.
138{
139 std::vector<Point> result;
140 using MapValue = std::pair<Point, std::vector<Edge>>;
141 std::transform(adjacency_graph.begin(), adjacency_graph.end(), std::back_inserter(result),
142 [](const MapValue& node) { return node.first; });
143 return result;
144}

References adjacency_graph.

Referenced by MinimumSpanningTree(), MinimumSpanningTree(), and prim().

Here is the caller graph for this function:

Member Data Documentation

◆ adjacency_graph

AdjacencyGraph_t Slic3r::MinimumSpanningTree::adjacency_graph
private

The documentation for this class was generated from the following files: