2013-07-16 19:04:14 +00:00
|
|
|
#include "ExtrusionEntity.hpp"
|
2013-11-21 16:53:50 +00:00
|
|
|
#include "ExtrusionEntityCollection.hpp"
|
|
|
|
#include "ExPolygonCollection.hpp"
|
|
|
|
#include "ClipperUtils.hpp"
|
2014-04-07 23:43:02 +00:00
|
|
|
#include "Extruder.hpp"
|
2014-04-27 17:18:53 +00:00
|
|
|
#include <sstream>
|
|
|
|
#ifdef SLIC3RXS
|
|
|
|
#include "perlglue.hpp"
|
|
|
|
#endif
|
2013-07-16 19:04:14 +00:00
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
2013-11-21 17:03:40 +00:00
|
|
|
bool
|
|
|
|
ExtrusionEntity::is_perimeter() const
|
|
|
|
{
|
|
|
|
return this->role == erPerimeter
|
|
|
|
|| this->role == erExternalPerimeter
|
|
|
|
|| this->role == erOverhangPerimeter
|
|
|
|
|| this->role == erContourInternalPerimeter;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ExtrusionEntity::is_fill() const
|
|
|
|
{
|
|
|
|
return this->role == erFill
|
|
|
|
|| this->role == erSolidFill
|
|
|
|
|| this->role == erTopSolidFill;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ExtrusionEntity::is_bridge() const
|
|
|
|
{
|
|
|
|
return this->role == erBrige
|
|
|
|
|| this->role == erInternalBridge
|
|
|
|
|| this->role == erOverhangPerimeter;
|
|
|
|
}
|
|
|
|
|
2013-08-29 09:47:59 +00:00
|
|
|
ExtrusionPath*
|
|
|
|
ExtrusionPath::clone() const
|
|
|
|
{
|
|
|
|
return new ExtrusionPath (*this);
|
|
|
|
}
|
|
|
|
|
2013-07-16 19:04:14 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::reverse()
|
|
|
|
{
|
|
|
|
this->polyline.reverse();
|
|
|
|
}
|
|
|
|
|
2014-04-24 14:40:10 +00:00
|
|
|
Point
|
2013-09-02 20:33:03 +00:00
|
|
|
ExtrusionPath::first_point() const
|
2013-08-26 21:42:00 +00:00
|
|
|
{
|
2014-04-24 14:40:10 +00:00
|
|
|
return this->polyline.points.front();
|
2013-08-26 21:42:00 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 14:40:10 +00:00
|
|
|
Point
|
2013-09-02 20:33:03 +00:00
|
|
|
ExtrusionPath::last_point() const
|
2013-08-28 23:36:42 +00:00
|
|
|
{
|
2014-04-24 14:40:10 +00:00
|
|
|
return this->polyline.points.back();
|
2013-08-28 23:36:42 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 19:19:30 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
2013-11-21 16:53:50 +00:00
|
|
|
{
|
|
|
|
// perform clipping
|
|
|
|
Polylines clipped;
|
2014-03-09 19:19:30 +00:00
|
|
|
intersection(this->polyline, collection, clipped);
|
|
|
|
return this->_inflate_collection(clipped, retval);
|
2013-11-21 16:53:50 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 19:19:30 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
|
2013-11-21 16:53:50 +00:00
|
|
|
{
|
|
|
|
// perform clipping
|
|
|
|
Polylines clipped;
|
2014-03-09 19:19:30 +00:00
|
|
|
diff(this->polyline, collection, clipped);
|
|
|
|
return this->_inflate_collection(clipped, retval);
|
2013-11-21 16:53:50 +00:00
|
|
|
}
|
|
|
|
|
2013-11-21 17:03:40 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::clip_end(double distance)
|
|
|
|
{
|
|
|
|
this->polyline.clip_end(distance);
|
|
|
|
}
|
|
|
|
|
2013-11-21 19:25:24 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::simplify(double tolerance)
|
|
|
|
{
|
|
|
|
this->polyline.simplify(tolerance);
|
|
|
|
}
|
|
|
|
|
2013-11-21 17:03:40 +00:00
|
|
|
double
|
|
|
|
ExtrusionPath::length() const
|
|
|
|
{
|
|
|
|
return this->polyline.length();
|
|
|
|
}
|
|
|
|
|
2014-03-09 19:19:30 +00:00
|
|
|
void
|
|
|
|
ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
|
2013-11-21 16:53:50 +00:00
|
|
|
{
|
|
|
|
for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it) {
|
|
|
|
ExtrusionPath* path = this->clone();
|
|
|
|
path->polyline = *it;
|
2014-03-09 19:19:30 +00:00
|
|
|
collection->entities.push_back(path);
|
2013-11-21 16:53:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-01 13:54:57 +00:00
|
|
|
#ifdef SLIC3RXS
|
2014-04-27 17:18:53 +00:00
|
|
|
|
|
|
|
REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
|
|
|
|
|
2014-04-01 13:54:57 +00:00
|
|
|
std::string
|
2014-04-07 23:43:02 +00:00
|
|
|
ExtrusionPath::gcode(Extruder* extruder, double e, double F,
|
2014-04-01 13:54:57 +00:00
|
|
|
double xofs, double yofs, std::string extrusion_axis,
|
|
|
|
std::string gcode_line_suffix) const
|
|
|
|
{
|
|
|
|
dSP;
|
|
|
|
|
|
|
|
std::stringstream stream;
|
|
|
|
stream.setf(std::ios::fixed);
|
|
|
|
|
|
|
|
double local_F = F;
|
|
|
|
|
|
|
|
Lines lines = this->polyline.lines();
|
|
|
|
for (Lines::const_iterator line_it = lines.begin();
|
|
|
|
line_it != lines.end(); ++line_it)
|
|
|
|
{
|
|
|
|
const double line_length = line_it->length() * SCALING_FACTOR;
|
|
|
|
|
|
|
|
// calculate extrusion length for this line
|
2014-04-07 23:43:02 +00:00
|
|
|
double E = (e == 0) ? 0 : extruder->extrude(e * line_length);
|
2014-04-01 13:54:57 +00:00
|
|
|
|
|
|
|
// compose G-code line
|
|
|
|
|
|
|
|
Point point = line_it->b;
|
|
|
|
const double x = point.x * SCALING_FACTOR + xofs;
|
|
|
|
const double y = point.y * SCALING_FACTOR + yofs;
|
|
|
|
stream.precision(3);
|
|
|
|
stream << "G1 X" << x << " Y" << y;
|
|
|
|
|
|
|
|
if (E != 0) {
|
|
|
|
stream.precision(5);
|
|
|
|
stream << " " << extrusion_axis << E;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (local_F != 0) {
|
|
|
|
stream.precision(3);
|
|
|
|
stream << " F" << local_F;
|
|
|
|
local_F = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream << gcode_line_suffix;
|
|
|
|
stream << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream.str();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 10:02:09 +00:00
|
|
|
ExtrusionLoop::ExtrusionLoop(const Polygon &polygon, ExtrusionRole role)
|
|
|
|
{
|
|
|
|
this->role = role;
|
|
|
|
this->set_polygon(polygon);
|
|
|
|
}
|
|
|
|
|
2013-08-29 09:47:59 +00:00
|
|
|
ExtrusionLoop*
|
|
|
|
ExtrusionLoop::clone() const
|
|
|
|
{
|
|
|
|
return new ExtrusionLoop (*this);
|
|
|
|
}
|
|
|
|
|
2014-05-07 10:02:09 +00:00
|
|
|
void
|
|
|
|
ExtrusionLoop::split_at_index(int index, ExtrusionPath* path) const
|
2013-07-16 19:04:14 +00:00
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
Polygon polygon;
|
|
|
|
this->polygon(&polygon);
|
|
|
|
|
|
|
|
polygon.split_at_index(index, &path->polyline);
|
2013-07-16 19:04:14 +00:00
|
|
|
|
|
|
|
path->role = this->role;
|
2014-01-03 17:27:46 +00:00
|
|
|
path->mm3_per_mm = this->mm3_per_mm;
|
2014-04-29 21:15:36 +00:00
|
|
|
path->width = this->width;
|
|
|
|
path->height = this->height;
|
2013-07-16 19:04:14 +00:00
|
|
|
}
|
|
|
|
|
2014-05-07 10:02:09 +00:00
|
|
|
void
|
|
|
|
ExtrusionLoop::split_at_first_point(ExtrusionPath* path) const
|
2013-07-16 19:04:14 +00:00
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
return this->split_at_index(0, path);
|
2013-07-16 19:04:14 +00:00
|
|
|
}
|
|
|
|
|
2013-08-28 23:40:42 +00:00
|
|
|
bool
|
|
|
|
ExtrusionLoop::make_counter_clockwise()
|
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
Polygon polygon;
|
|
|
|
this->polygon(&polygon);
|
|
|
|
|
|
|
|
bool was_cw = polygon.is_clockwise();
|
|
|
|
if (was_cw) this->reverse();
|
|
|
|
return was_cw;
|
2013-08-28 23:40:42 +00:00
|
|
|
}
|
|
|
|
|
2013-08-29 09:47:59 +00:00
|
|
|
void
|
|
|
|
ExtrusionLoop::reverse()
|
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
for (Polylines::iterator polyline = this->polylines.begin(); polyline != this->polylines.end(); ++polyline)
|
|
|
|
polyline->reverse();
|
|
|
|
std::reverse(this->polylines.begin(), this->polylines.end());
|
2013-08-29 09:47:59 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 14:40:10 +00:00
|
|
|
Point
|
2013-09-02 20:33:03 +00:00
|
|
|
ExtrusionLoop::first_point() const
|
2013-08-29 09:47:59 +00:00
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
return this->polylines.front().points.front();
|
2013-08-29 09:47:59 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 14:40:10 +00:00
|
|
|
Point
|
2013-09-02 20:33:03 +00:00
|
|
|
ExtrusionLoop::last_point() const
|
2013-08-29 09:47:59 +00:00
|
|
|
{
|
2014-05-07 10:02:09 +00:00
|
|
|
return this->polylines.back().points.back(); // which coincides with first_point(), by the way
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ExtrusionLoop::set_polygon(const Polygon &polygon)
|
|
|
|
{
|
|
|
|
Polyline polyline;
|
|
|
|
polygon.split_at_first_point(&polyline);
|
|
|
|
this->polylines.clear();
|
|
|
|
this->polylines.push_back(polyline);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ExtrusionLoop::polygon(Polygon* polygon) const
|
|
|
|
{
|
|
|
|
for (Polylines::const_iterator polyline = this->polylines.begin(); polyline != this->polylines.end(); ++polyline) {
|
|
|
|
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
|
|
|
|
polygon->points.insert(polygon->points.end(), polyline->points.begin(), polyline->points.end()-1);
|
|
|
|
}
|
2013-08-29 09:47:59 +00:00
|
|
|
}
|
|
|
|
|
2014-04-27 17:18:53 +00:00
|
|
|
#ifdef SLIC3RXS
|
|
|
|
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
|
|
|
|
#endif
|
|
|
|
|
2013-07-16 19:04:14 +00:00
|
|
|
}
|