Refactored Arachne to use ankerl::unordered_dense hash tables
instead of std::unordered_set/map The code is now generic enough to enable experiments with various hash maps in the future.
This commit is contained in:
parent
29719a7ab9
commit
0d1522791d
@ -5,7 +5,6 @@
|
||||
|
||||
#include <stack>
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
@ -522,9 +521,11 @@ static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
|
||||
const double fix_angle,
|
||||
const std::unordered_map<Point, Point, PointHash> &vertex_mapping)
|
||||
using PointMap = SkeletalTrapezoidation::PointMap;
|
||||
|
||||
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
|
||||
const double fix_angle,
|
||||
const PointMap &vertex_mapping)
|
||||
{
|
||||
for (STHalfEdgeNode &node : graph.nodes) {
|
||||
// If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction.
|
||||
@ -588,7 +589,7 @@ VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::Voronoi
|
||||
return VoronoiDiagramStatus::NO_ISSUE_DETECTED;
|
||||
}
|
||||
|
||||
inline static std::pair<std::unordered_map<Point, Point, PointHash>, double> try_to_fix_degenerated_voronoi_diagram_by_rotation(
|
||||
inline static std::pair<PointMap, double> try_to_fix_degenerated_voronoi_diagram_by_rotation(
|
||||
Geometry::VoronoiDiagram &voronoi_diagram,
|
||||
const Polygons &polys,
|
||||
Polygons &polys_rotated,
|
||||
@ -597,7 +598,7 @@ inline static std::pair<std::unordered_map<Point, Point, PointHash>, double> try
|
||||
{
|
||||
const Polygons polys_rotated_original = polys_rotated;
|
||||
double fixed_by_angle = fix_angles.front();
|
||||
std::unordered_map<Point, Point, PointHash> vertex_mapping;
|
||||
PointMap vertex_mapping;
|
||||
|
||||
for (const double &fix_angle : fix_angles) {
|
||||
vertex_mapping.clear();
|
||||
@ -685,7 +686,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
||||
const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11};
|
||||
double fixed_by_angle = fix_angles.front();
|
||||
|
||||
std::unordered_map<Point, Point, PointHash> vertex_mapping;
|
||||
PointMap vertex_mapping;
|
||||
// polys_copy is referenced through items stored in the std::vector segments.
|
||||
Polygons polys_copy = polys;
|
||||
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
|
||||
@ -813,9 +814,11 @@ process_voronoi_diagram:
|
||||
edge.from->incident_edge = &edge;
|
||||
}
|
||||
|
||||
using NodeSet = SkeletalTrapezoidation::NodeSet;
|
||||
|
||||
void SkeletalTrapezoidation::separatePointyQuadEndNodes()
|
||||
{
|
||||
std::unordered_set<node_t*> visited_nodes;
|
||||
NodeSet visited_nodes;
|
||||
for (edge_t& edge : graph.edges)
|
||||
{
|
||||
if (edge.prev)
|
||||
@ -2285,16 +2288,18 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c
|
||||
|
||||
void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_junctions)
|
||||
{
|
||||
std::unordered_set<edge_t*> unprocessed_quad_starts(graph.edges.size() * 5 / 2);
|
||||
using EdgeSet = ankerl::unordered_dense::set<edge_t*>;
|
||||
|
||||
EdgeSet unprocessed_quad_starts(graph.edges.size() * 5 / 2);
|
||||
for (edge_t& edge : graph.edges)
|
||||
{
|
||||
if (!edge.prev)
|
||||
{
|
||||
unprocessed_quad_starts.insert(&edge);
|
||||
unprocessed_quad_starts.emplace(&edge);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<edge_t*> passed_odd_edges;
|
||||
EdgeSet passed_odd_edges;
|
||||
|
||||
while (!unprocessed_quad_starts.empty())
|
||||
{
|
||||
|
@ -7,8 +7,10 @@
|
||||
#include <boost/polygon/voronoi.hpp>
|
||||
|
||||
#include <memory> // smart pointers
|
||||
#include <unordered_map>
|
||||
#include <utility> // pair
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include <Arachne/utils/VoronoiUtils.hpp>
|
||||
|
||||
#include "utils/HalfEdgeGraph.hpp"
|
||||
@ -80,7 +82,9 @@ class SkeletalTrapezoidation
|
||||
const BeadingStrategy& beading_strategy;
|
||||
|
||||
public:
|
||||
using Segment = PolygonsSegmentIndex;
|
||||
using Segment = PolygonsSegmentIndex;
|
||||
using PointMap = ankerl::unordered_dense::map<Point, Point, PointHash>;
|
||||
using NodeSet = ankerl::unordered_dense::set<node_t*>;
|
||||
|
||||
/*!
|
||||
* Construct a new trapezoidation problem to solve.
|
||||
@ -164,8 +168,8 @@ protected:
|
||||
* mapping each voronoi VD edge to the corresponding halfedge HE edge
|
||||
* In case the result segment is discretized, we map the VD edge to the *last* HE edge
|
||||
*/
|
||||
std::unordered_map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
|
||||
std::unordered_map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
|
||||
ankerl::unordered_dense::map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
|
||||
ankerl::unordered_dense::map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
|
||||
node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
|
||||
|
||||
/*!
|
||||
|
@ -2,7 +2,8 @@
|
||||
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include "SkeletalTrapezoidationGraph.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
@ -180,8 +181,8 @@ bool STHalfEdgeNode::isLocalMaximum(bool strict) const
|
||||
|
||||
void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
|
||||
{
|
||||
std::unordered_map<edge_t*, std::list<edge_t>::iterator> edge_locator;
|
||||
std::unordered_map<node_t*, std::list<node_t>::iterator> node_locator;
|
||||
ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
|
||||
ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
|
||||
|
||||
for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it)
|
||||
{
|
||||
@ -193,7 +194,7 @@ void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
|
||||
node_locator.emplace(&*node_it, node_it);
|
||||
}
|
||||
|
||||
auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, std::list<edge_t>::iterator& current_edge_it, bool& edge_it_is_updated)
|
||||
auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, Edges::iterator& current_edge_it, bool& edge_it_is_updated)
|
||||
{
|
||||
if (current_edge_it != edges.end()
|
||||
&& to_be_removed == &*current_edge_it)
|
||||
|
@ -2,7 +2,6 @@
|
||||
// CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#include <algorithm> //For std::partition_copy and std::min_element.
|
||||
#include <unordered_set>
|
||||
|
||||
#include "WallToolPaths.hpp"
|
||||
|
||||
@ -767,9 +766,9 @@ bool WallToolPaths::removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpa
|
||||
*
|
||||
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
|
||||
*/
|
||||
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner)
|
||||
WallToolPaths::ExtrusionLineSet WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner)
|
||||
{
|
||||
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> order_requirements;
|
||||
ExtrusionLineSet order_requirements;
|
||||
|
||||
// We build a grid where we map toolpath vertex locations to toolpaths,
|
||||
// so that we can easily find which two toolpaths are next to each other,
|
||||
|
@ -5,7 +5,8 @@
|
||||
#define CURAENGINE_WALLTOOLPATHS_H
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include "BeadingStrategy/BeadingStrategyFactory.hpp"
|
||||
#include "utils/ExtrusionLine.hpp"
|
||||
@ -73,6 +74,7 @@ public:
|
||||
*/
|
||||
static bool removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths);
|
||||
|
||||
using ExtrusionLineSet = ankerl::unordered_dense::set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>>;
|
||||
/*!
|
||||
* Get the order constraints of the insets when printing walls per region / hole.
|
||||
* Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right.
|
||||
@ -81,7 +83,7 @@ public:
|
||||
*
|
||||
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
|
||||
*/
|
||||
static std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner);
|
||||
static ExtrusionLineSet getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
|
@ -21,8 +21,10 @@ class HalfEdgeGraph
|
||||
public:
|
||||
using edge_t = derived_edge_t;
|
||||
using node_t = derived_node_t;
|
||||
std::list<edge_t> edges;
|
||||
std::list<node_t> nodes;
|
||||
using Edges = std::list<edge_t>;
|
||||
using Nodes = std::list<node_t>;
|
||||
Edges edges;
|
||||
Nodes nodes;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::Arachne
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "SparsePointGrid.hpp"
|
||||
#include "PolygonsPointIndex.hpp"
|
||||
#include "../../Polygon.hpp"
|
||||
#include <unordered_set>
|
||||
#include <cassert>
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define UTILS_SPARSE_GRID_H
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define UTILS_SPARSE_LINE_GRID_H
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define UTILS_SPARSE_POINT_GRID_H
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "SparseGrid.hpp"
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "../../Point.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
|
@ -39,11 +39,11 @@
|
||||
#include <ostream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
// #define ARACHNE_DEBUG
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
@ -569,7 +569,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
|
||||
size_t occurrence = 0;
|
||||
bool is_overhang = false;
|
||||
};
|
||||
std::unordered_map<Point, PointInfo, PointHash> point_occurrence;
|
||||
ankerl::unordered_dense::map<Point, PointInfo, PointHash> point_occurrence;
|
||||
for (const ExtrusionPath &path : paths) {
|
||||
++point_occurrence[path.polyline.first_point()].occurrence;
|
||||
++point_occurrence[path.polyline.last_point()].occurrence;
|
||||
@ -681,7 +681,7 @@ Polylines reconnect_polylines(const Polylines &polylines, double limit_distance)
|
||||
if (polylines.empty())
|
||||
return polylines;
|
||||
|
||||
std::unordered_map<size_t, Polyline> connected;
|
||||
ankerl::unordered_dense::map<size_t, Polyline> connected;
|
||||
connected.reserve(polylines.size());
|
||||
for (size_t i = 0; i < polylines.size(); i++) {
|
||||
if (!polylines[i].empty()) {
|
||||
@ -731,7 +731,7 @@ ExtrusionPaths sort_extra_perimeters(ExtrusionPaths extra_perims, int index_of_f
|
||||
{
|
||||
if (extra_perims.empty()) return {};
|
||||
|
||||
std::vector<std::unordered_set<size_t>> dependencies(extra_perims.size());
|
||||
std::vector<ankerl::unordered_dense::set<size_t>> dependencies(extra_perims.size());
|
||||
for (size_t path_idx = 0; path_idx < extra_perims.size(); path_idx++) {
|
||||
for (size_t prev_path_idx = 0; prev_path_idx < path_idx; prev_path_idx++) {
|
||||
if (paths_touch(extra_perims[path_idx], extra_perims[prev_path_idx], extrusion_spacing * 1.5f)) {
|
||||
@ -1153,11 +1153,11 @@ void PerimeterGenerator::process_arachne(
|
||||
// Find topological order with constraints from extrusions_constrains.
|
||||
std::vector<size_t> blocked(all_extrusions.size(), 0); // Value indicating how many extrusions it is blocking (preceding extrusions) an extrusion.
|
||||
std::vector<std::vector<size_t>> blocking(all_extrusions.size()); // Each extrusion contains a vector of extrusions that are blocked by this extrusion.
|
||||
std::unordered_map<const Arachne::ExtrusionLine *, size_t> map_extrusion_to_idx;
|
||||
ankerl::unordered_dense::map<const Arachne::ExtrusionLine *, size_t> map_extrusion_to_idx;
|
||||
for (size_t idx = 0; idx < all_extrusions.size(); idx++)
|
||||
map_extrusion_to_idx.emplace(all_extrusions[idx], idx);
|
||||
|
||||
auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, params.config.external_perimeters_first);
|
||||
Arachne::WallToolPaths::ExtrusionLineSet extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, params.config.external_perimeters_first);
|
||||
for (auto [before, after] : extrusions_constrains) {
|
||||
auto after_it = map_extrusion_to_idx.find(after);
|
||||
++blocked[after_it->second];
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_count) {
|
||||
@ -155,7 +157,7 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_
|
||||
}
|
||||
|
||||
//Extract the result mesh
|
||||
std::unordered_map<size_t, size_t> final_vertices_mapping;
|
||||
ankerl::unordered_dense::map<size_t, size_t> final_vertices_mapping;
|
||||
std::vector<Vec3f> final_vertices;
|
||||
std::vector<Vec3i> final_indices;
|
||||
final_indices.reserve(face_indices.size());
|
||||
|
Loading…
Reference in New Issue
Block a user