WIP: Consolidation of shortest path calculations,

various chaining algorithms are replaced with the improved TSP
algorithm.
This commit is contained in:
bubnikv 2019-09-26 17:30:03 +02:00
parent 10eecb2cab
commit d06831076d
8 changed files with 43 additions and 78 deletions

View File

@ -1,5 +1,6 @@
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
#include "ShortestPath.hpp"
// #define CLIPPER_UTILS_DEBUG
@ -671,21 +672,19 @@ void traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval)
// collect ordering points
Points ordering_points;
ordering_points.reserve(nodes.size());
for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
Point p((*it)->Contour.front().X, (*it)->Contour.front().Y);
ordering_points.emplace_back(p);
}
for (ClipperLib::PolyNode *pn : nodes)
ordering_points.emplace_back(Point(pn->Contour.front().X, pn->Contour.front().Y));
// perform the ordering
ClipperLib::PolyNodes ordered_nodes;
Slic3r::Geometry::chained_path_items(ordering_points, nodes, ordered_nodes);
ClipperLib::PolyNodes ordered_nodes = chain_clipper_polynodes(ordering_points, nodes);
// push results recursively
for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) {
for (ClipperLib::PolyNode *pn : ordered_nodes) {
// traverse the next depth
traverse_pt((*it)->Childs, retval);
retval->emplace_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
if ((*it)->IsHole()) retval->back().reverse(); // ccw
traverse_pt(pn->Childs, retval);
retval->emplace_back(ClipperPath_to_Slic3rPolygon(pn->Contour));
if (pn->IsHole())
retval->back().reverse(); // ccw
}
}

View File

@ -309,49 +309,7 @@ convex_hull(const Polygons &polygons)
return convex_hull(std::move(pp));
}
/* accepts an arrayref of points and returns a list of indices
according to a nearest-neighbor walk */
void
chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near)
{
PointConstPtrs my_points;
std::map<const Point*,Points::size_type> indices;
my_points.reserve(points.size());
for (Points::const_iterator it = points.begin(); it != points.end(); ++it) {
my_points.push_back(&*it);
indices[&*it] = it - points.begin();
}
retval.reserve(points.size());
while (!my_points.empty()) {
Points::size_type idx = start_near.nearest_point_index(my_points);
start_near = *my_points[idx];
retval.push_back(indices[ my_points[idx] ]);
my_points.erase(my_points.begin() + idx);
}
}
void
chained_path(const Points &points, std::vector<Points::size_type> &retval)
{
if (points.empty()) return; // can't call front() on empty vector
chained_path(points, retval, points.front());
}
/* retval and items must be different containers */
template<class T>
void
chained_path_items(Points &points, T &items, T &retval)
{
std::vector<Points::size_type> indices;
chained_path(points, indices);
for (std::vector<Points::size_type>::const_iterator it = indices.begin(); it != indices.end(); ++it)
retval.push_back(items[*it]);
}
template void chained_path_items(Points &points, ClipperLib::PolyNodes &items, ClipperLib::PolyNodes &retval);
bool
directions_parallel(double angle1, double angle2, double max_diff)
bool directions_parallel(double angle1, double angle2, double max_diff)
{
double diff = fabs(angle1 - angle2);
max_diff += EPSILON;
@ -359,8 +317,7 @@ directions_parallel(double angle1, double angle2, double max_diff)
}
template<class T>
bool
contains(const std::vector<T> &vector, const Point &point)
bool contains(const std::vector<T> &vector, const Point &point)
{
for (typename std::vector<T>::const_iterator it = vector.begin(); it != vector.end(); ++it) {
if (it->contains(point)) return true;
@ -369,16 +326,14 @@ contains(const std::vector<T> &vector, const Point &point)
}
template bool contains(const ExPolygons &vector, const Point &point);
double
rad2deg_dir(double angle)
double rad2deg_dir(double angle)
{
angle = (angle < PI) ? (-angle + PI/2.0) : (angle + PI/2.0);
if (angle < 0) angle += PI;
return rad2deg(angle);
}
void
simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
{
Polygons pp;
for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) {
@ -391,8 +346,7 @@ simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
*retval = Slic3r::simplify_polygons(pp);
}
double
linint(double value, double oldmin, double oldmax, double newmin, double newmax)
double linint(double value, double oldmin, double oldmax, double newmin, double newmax)
{
return (value - oldmin) * (newmax - newmin) / (oldmax - oldmin) + newmin;
}

View File

@ -138,9 +138,6 @@ Pointf3s convex_hull(Pointf3s points);
Polygon convex_hull(Points points);
Polygon convex_hull(const Polygons &polygons);
void chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near);
void chained_path(const Points &points, std::vector<Points::size_type> &retval);
template<class T> void chained_path_items(Points &points, T &items, T &retval);
bool directions_parallel(double angle1, double angle2, double max_diff = 0);
template<class T> bool contains(const std::vector<T> &vector, const Point &point);
template<typename T> T rad2deg(T angle) { return T(180.0) * angle / T(PI); }

View File

@ -1,8 +1,8 @@
#include "Layer.hpp"
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
#include "Print.hpp"
#include "Fill/Fill.hpp"
#include "ShortestPath.hpp"
#include "SVG.hpp"
#include <boost/log/trivial.hpp>
@ -57,8 +57,7 @@ void Layer::make_slices()
ordering_points.push_back(ex.contour.first_point());
// sort slices
std::vector<Points::size_type> order;
Slic3r::Geometry::chained_path(ordering_points, order);
std::vector<Points::size_type> order = chain_points(ordering_points);
// populate slices vector
for (size_t i : order)

View File

@ -12,7 +12,6 @@
#include <boost/log/trivial.hpp>
#include <float.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/parallel_for.h>
#include <tbb/atomic.h>
@ -75,13 +74,9 @@ PrintBase::ApplyStatus PrintObject::set_copies(const Points &points)
{
// Order copies with a nearest-neighbor search.
std::vector<Point> copies;
{
std::vector<Points::size_type> ordered_copies;
Slic3r::Geometry::chained_path(points, ordered_copies);
copies.reserve(ordered_copies.size());
for (size_t point_idx : ordered_copies)
copies.emplace_back(points[point_idx] + m_copies_shift);
}
copies.reserve(points.size());
for (const Point &pt : points)
copies.emplace_back(pt + m_copies_shift);
// Invalidate and set copies.
PrintBase::ApplyStatus status = PrintBase::APPLY_STATUS_UNCHANGED;
if (copies != m_copies) {

View File

@ -339,6 +339,22 @@ std::vector<size_t> chain_points(const Points &points, Point *start_near)
return out;
}
template<class T> static inline T chain_path_items(const Points &points, const T &items)
{
auto segment_end_point = [&points](size_t idx, bool /* first_point */) -> const Point& { return points[idx]; };
std::vector<std::pair<size_t, bool>> ordered = chain_segments<Point, decltype(segment_end_point)>(segment_end_point, points.size(), nullptr);
T out;
out.reserve(items.size());
for (auto &segment_and_reversal : ordered)
out.emplace_back(items[segment_and_reversal.first]);
return out;
}
ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items)
{
return chain_path_items(points, items);
}
std::vector<std::pair<size_t, size_t>> chain_print_object_instances(const Print &print)
{
// Order objects using a nearest neighbor search.

View File

@ -8,6 +8,8 @@
#include <utility>
#include <vector>
namespace ClipperLib { class PolyNode; }
namespace Slic3r {
std::vector<size_t> chain_points(const Points &points, Point *start_near = nullptr);
@ -16,6 +18,8 @@ std::vector<std::pair<size_t, bool>> chain_extrusion_entities(std::vector<Extrus
void reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, std::vector<std::pair<size_t, bool>> &chain);
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near = nullptr);
std::vector<ClipperLib::PolyNode*> chain_clipper_polynodes(const Points &points, const std::vector<ClipperLib::PolyNode*> &items);
// Chain instances of print objects by an approximate shortest path.
// Returns pairs of PrintObject idx and instance of that PrintObject.
class Print;

View File

@ -3,6 +3,7 @@
%{
#include <xsinit.h>
#include "libslic3r/Geometry.hpp"
#include "libslic3r/ShortestPath.hpp"
%}
@ -49,7 +50,7 @@ std::vector<Points::size_type>
chained_path(points)
Points points
CODE:
Slic3r::Geometry::chained_path(points, RETVAL);
RETVAL = chain_points(points);
OUTPUT:
RETVAL
@ -58,7 +59,7 @@ chained_path_from(points, start_from)
Points points
Point* start_from
CODE:
Slic3r::Geometry::chained_path(points, RETVAL, *start_from);
RETVAL = chain_points(points, start_from);
OUTPUT:
RETVAL