2013-08-29 22:06:10 +00:00
|
|
|
#include "PolylineCollection.hpp"
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
2016-04-10 17:32:39 +00:00
|
|
|
struct Chaining
|
2013-08-29 22:06:10 +00:00
|
|
|
{
|
2016-04-10 17:32:39 +00:00
|
|
|
Point first;
|
|
|
|
Point last;
|
|
|
|
size_t idx;
|
|
|
|
};
|
2013-08-29 22:06:10 +00:00
|
|
|
|
2016-04-10 17:32:39 +00:00
|
|
|
template<typename T>
|
|
|
|
inline int nearest_point_index(const std::vector<Chaining> &pairs, const Point &start_near, bool no_reverse)
|
|
|
|
{
|
|
|
|
T dmin = std::numeric_limits<T>::max();
|
|
|
|
int idx = 0;
|
|
|
|
for (std::vector<Chaining>::const_iterator it = pairs.begin(); it != pairs.end(); ++it) {
|
|
|
|
T d = sqr(T(start_near.x - it->first.x));
|
|
|
|
if (d <= dmin) {
|
|
|
|
d += sqr(T(start_near.y - it->first.y));
|
|
|
|
if (d < dmin) {
|
|
|
|
idx = (it - pairs.begin()) * 2;
|
|
|
|
dmin = d;
|
|
|
|
if (dmin < EPSILON)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (! no_reverse) {
|
|
|
|
d = sqr(T(start_near.x - it->last.x));
|
|
|
|
if (d <= dmin) {
|
|
|
|
d += sqr(T(start_near.y - it->last.y));
|
|
|
|
if (d < dmin) {
|
|
|
|
idx = (it - pairs.begin()) * 2 + 1;
|
|
|
|
dmin = d;
|
|
|
|
if (dmin < EPSILON)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-08-29 22:06:10 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-10 17:32:39 +00:00
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2016-11-02 20:31:03 +00:00
|
|
|
Polylines PolylineCollection::_chained_path_from(
|
2016-04-10 17:32:39 +00:00
|
|
|
const Polylines &src,
|
2016-11-02 20:31:03 +00:00
|
|
|
Point start_near,
|
2017-07-27 08:39:43 +00:00
|
|
|
bool no_reverse,
|
|
|
|
bool move_from_src)
|
2016-04-10 17:32:39 +00:00
|
|
|
{
|
|
|
|
std::vector<Chaining> endpoints;
|
|
|
|
endpoints.reserve(src.size());
|
|
|
|
for (size_t i = 0; i < src.size(); ++ i) {
|
|
|
|
Chaining c;
|
|
|
|
c.first = src[i].first_point();
|
|
|
|
if (! no_reverse)
|
|
|
|
c.last = src[i].last_point();
|
|
|
|
c.idx = i;
|
2016-04-11 15:05:58 +00:00
|
|
|
endpoints.push_back(c);
|
2016-04-10 17:32:39 +00:00
|
|
|
}
|
|
|
|
Polylines retval;
|
|
|
|
while (! endpoints.empty()) {
|
2013-08-29 22:06:10 +00:00
|
|
|
// find nearest point
|
2016-04-10 17:32:39 +00:00
|
|
|
int endpoint_index = nearest_point_index<double>(endpoints, start_near, no_reverse);
|
2016-04-11 15:05:58 +00:00
|
|
|
assert(endpoint_index >= 0 && endpoint_index < endpoints.size() * 2);
|
2016-11-02 20:31:03 +00:00
|
|
|
if (move_from_src) {
|
|
|
|
retval.push_back(std::move(src[endpoints[endpoint_index/2].idx]));
|
|
|
|
} else {
|
|
|
|
retval.push_back(src[endpoints[endpoint_index/2].idx]);
|
|
|
|
}
|
2016-04-10 17:32:39 +00:00
|
|
|
if (endpoint_index & 1)
|
|
|
|
retval.back().reverse();
|
|
|
|
endpoints.erase(endpoints.begin() + endpoint_index/2);
|
|
|
|
start_near = retval.back().last_point();
|
2013-08-29 22:06:10 +00:00
|
|
|
}
|
2016-04-11 15:05:58 +00:00
|
|
|
return retval;
|
2013-08-29 22:06:10 +00:00
|
|
|
}
|
|
|
|
|
2016-04-10 17:32:39 +00:00
|
|
|
Point PolylineCollection::leftmost_point(const Polylines &polylines)
|
|
|
|
{
|
|
|
|
if (polylines.empty()) CONFESS("leftmost_point() called on empty PolylineCollection");
|
|
|
|
Polylines::const_iterator it = polylines.begin();
|
|
|
|
Point p = it->leftmost_point();
|
|
|
|
for (++ it; it != polylines.end(); ++it) {
|
2014-04-24 14:40:10 +00:00
|
|
|
Point p2 = it->leftmost_point();
|
2016-04-10 17:32:39 +00:00
|
|
|
if (p2.x < p.x)
|
|
|
|
p = p2;
|
2013-11-21 13:15:38 +00:00
|
|
|
}
|
2014-04-24 14:40:10 +00:00
|
|
|
return p;
|
2013-11-21 13:15:38 +00:00
|
|
|
}
|
|
|
|
|
2016-04-10 17:32:39 +00:00
|
|
|
} // namespace Slic3r
|