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 <stack>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_set>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -522,9 +521,11 @@ static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
|
using PointMap = SkeletalTrapezoidation::PointMap;
|
||||||
const double fix_angle,
|
|
||||||
const std::unordered_map<Point, Point, PointHash> &vertex_mapping)
|
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) {
|
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.
|
// 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;
|
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,
|
Geometry::VoronoiDiagram &voronoi_diagram,
|
||||||
const Polygons &polys,
|
const Polygons &polys,
|
||||||
Polygons &polys_rotated,
|
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;
|
const Polygons polys_rotated_original = polys_rotated;
|
||||||
double fixed_by_angle = fix_angles.front();
|
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) {
|
for (const double &fix_angle : fix_angles) {
|
||||||
vertex_mapping.clear();
|
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};
|
const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11};
|
||||||
double fixed_by_angle = fix_angles.front();
|
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.
|
// polys_copy is referenced through items stored in the std::vector segments.
|
||||||
Polygons polys_copy = polys;
|
Polygons polys_copy = polys;
|
||||||
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
|
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
|
||||||
@ -813,9 +814,11 @@ process_voronoi_diagram:
|
|||||||
edge.from->incident_edge = &edge;
|
edge.from->incident_edge = &edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using NodeSet = SkeletalTrapezoidation::NodeSet;
|
||||||
|
|
||||||
void SkeletalTrapezoidation::separatePointyQuadEndNodes()
|
void SkeletalTrapezoidation::separatePointyQuadEndNodes()
|
||||||
{
|
{
|
||||||
std::unordered_set<node_t*> visited_nodes;
|
NodeSet visited_nodes;
|
||||||
for (edge_t& edge : graph.edges)
|
for (edge_t& edge : graph.edges)
|
||||||
{
|
{
|
||||||
if (edge.prev)
|
if (edge.prev)
|
||||||
@ -2285,16 +2288,18 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c
|
|||||||
|
|
||||||
void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_junctions)
|
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)
|
for (edge_t& edge : graph.edges)
|
||||||
{
|
{
|
||||||
if (!edge.prev)
|
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())
|
while (!unprocessed_quad_starts.empty())
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,10 @@
|
|||||||
#include <boost/polygon/voronoi.hpp>
|
#include <boost/polygon/voronoi.hpp>
|
||||||
|
|
||||||
#include <memory> // smart pointers
|
#include <memory> // smart pointers
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility> // pair
|
#include <utility> // pair
|
||||||
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include <Arachne/utils/VoronoiUtils.hpp>
|
#include <Arachne/utils/VoronoiUtils.hpp>
|
||||||
|
|
||||||
#include "utils/HalfEdgeGraph.hpp"
|
#include "utils/HalfEdgeGraph.hpp"
|
||||||
@ -80,7 +82,9 @@ class SkeletalTrapezoidation
|
|||||||
const BeadingStrategy& beading_strategy;
|
const BeadingStrategy& beading_strategy;
|
||||||
|
|
||||||
public:
|
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.
|
* Construct a new trapezoidation problem to solve.
|
||||||
@ -164,8 +168,8 @@ protected:
|
|||||||
* mapping each voronoi VD edge to the corresponding halfedge HE edge
|
* 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
|
* 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;
|
ankerl::unordered_dense::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::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.
|
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.
|
//CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
#include "SkeletalTrapezoidationGraph.hpp"
|
#include "SkeletalTrapezoidationGraph.hpp"
|
||||||
#include <unordered_map>
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
@ -180,8 +181,8 @@ bool STHalfEdgeNode::isLocalMaximum(bool strict) const
|
|||||||
|
|
||||||
void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
|
void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
|
||||||
{
|
{
|
||||||
std::unordered_map<edge_t*, std::list<edge_t>::iterator> edge_locator;
|
ankerl::unordered_dense::map<edge_t*, Edges::iterator> edge_locator;
|
||||||
std::unordered_map<node_t*, std::list<node_t>::iterator> node_locator;
|
ankerl::unordered_dense::map<node_t*, Nodes::iterator> node_locator;
|
||||||
|
|
||||||
for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it)
|
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);
|
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()
|
if (current_edge_it != edges.end()
|
||||||
&& to_be_removed == &*current_edge_it)
|
&& to_be_removed == &*current_edge_it)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// CuraEngine is released under the terms of the AGPLv3 or higher.
|
// CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
#include <algorithm> //For std::partition_copy and std::min_element.
|
#include <algorithm> //For std::partition_copy and std::min_element.
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "WallToolPaths.hpp"
|
#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.
|
* \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,
|
// 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,
|
// so that we can easily find which two toolpaths are next to each other,
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#define CURAENGINE_WALLTOOLPATHS_H
|
#define CURAENGINE_WALLTOOLPATHS_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_set>
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include "BeadingStrategy/BeadingStrategyFactory.hpp"
|
#include "BeadingStrategy/BeadingStrategyFactory.hpp"
|
||||||
#include "utils/ExtrusionLine.hpp"
|
#include "utils/ExtrusionLine.hpp"
|
||||||
@ -73,6 +74,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
static bool removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths);
|
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.
|
* 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.
|
* 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.
|
* \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:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
|
@ -21,8 +21,10 @@ class HalfEdgeGraph
|
|||||||
public:
|
public:
|
||||||
using edge_t = derived_edge_t;
|
using edge_t = derived_edge_t;
|
||||||
using node_t = derived_node_t;
|
using node_t = derived_node_t;
|
||||||
std::list<edge_t> edges;
|
using Edges = std::list<edge_t>;
|
||||||
std::list<node_t> nodes;
|
using Nodes = std::list<node_t>;
|
||||||
|
Edges edges;
|
||||||
|
Nodes nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::Arachne
|
} // namespace Slic3r::Arachne
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "SparsePointGrid.hpp"
|
#include "SparsePointGrid.hpp"
|
||||||
#include "PolygonsPointIndex.hpp"
|
#include "PolygonsPointIndex.hpp"
|
||||||
#include "../../Polygon.hpp"
|
#include "../../Polygon.hpp"
|
||||||
#include <unordered_set>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace Slic3r::Arachne
|
namespace Slic3r::Arachne
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define UTILS_SPARSE_GRID_H
|
#define UTILS_SPARSE_GRID_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define UTILS_SPARSE_LINE_GRID_H
|
#define UTILS_SPARSE_LINE_GRID_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define UTILS_SPARSE_POINT_GRID_H
|
#define UTILS_SPARSE_POINT_GRID_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "SparseGrid.hpp"
|
#include "SparseGrid.hpp"
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "../../Point.hpp"
|
#include "../../Point.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -39,11 +39,11 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
// #define ARACHNE_DEBUG
|
// #define ARACHNE_DEBUG
|
||||||
|
|
||||||
#ifdef ARACHNE_DEBUG
|
#ifdef ARACHNE_DEBUG
|
||||||
@ -569,7 +569,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P
|
|||||||
size_t occurrence = 0;
|
size_t occurrence = 0;
|
||||||
bool is_overhang = false;
|
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) {
|
for (const ExtrusionPath &path : paths) {
|
||||||
++point_occurrence[path.polyline.first_point()].occurrence;
|
++point_occurrence[path.polyline.first_point()].occurrence;
|
||||||
++point_occurrence[path.polyline.last_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())
|
if (polylines.empty())
|
||||||
return polylines;
|
return polylines;
|
||||||
|
|
||||||
std::unordered_map<size_t, Polyline> connected;
|
ankerl::unordered_dense::map<size_t, Polyline> connected;
|
||||||
connected.reserve(polylines.size());
|
connected.reserve(polylines.size());
|
||||||
for (size_t i = 0; i < polylines.size(); i++) {
|
for (size_t i = 0; i < polylines.size(); i++) {
|
||||||
if (!polylines[i].empty()) {
|
if (!polylines[i].empty()) {
|
||||||
@ -731,7 +731,7 @@ ExtrusionPaths sort_extra_perimeters(ExtrusionPaths extra_perims, int index_of_f
|
|||||||
{
|
{
|
||||||
if (extra_perims.empty()) return {};
|
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 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++) {
|
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)) {
|
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.
|
// 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<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::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++)
|
for (size_t idx = 0; idx < all_extrusions.size(); idx++)
|
||||||
map_extrusion_to_idx.emplace(all_extrusions[idx], 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) {
|
for (auto [before, after] : extrusions_constrains) {
|
||||||
auto after_it = map_extrusion_to_idx.find(after);
|
auto after_it = map_extrusion_to_idx.find(after);
|
||||||
++blocked[after_it->second];
|
++blocked[after_it->second];
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_count) {
|
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
|
//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<Vec3f> final_vertices;
|
||||||
std::vector<Vec3i> final_indices;
|
std::vector<Vec3i> final_indices;
|
||||||
final_indices.reserve(face_indices.size());
|
final_indices.reserve(face_indices.size());
|
||||||
|
Loading…
Reference in New Issue
Block a user