Turn ExtrusionLoop into a collection of polylines. Includes some changes to the Polygon API to avoid returning newly allocatd objects

This commit is contained in:
Alessandro Ranellucci 2014-05-07 12:02:09 +02:00
parent c72dc13d7e
commit d2d885fc53
11 changed files with 107 additions and 72 deletions

View File

@ -157,56 +157,85 @@ ExtrusionPath::gcode(Extruder* extruder, double e, double F,
}
#endif
ExtrusionLoop::ExtrusionLoop(const Polygon &polygon, ExtrusionRole role)
{
this->role = role;
this->set_polygon(polygon);
}
ExtrusionLoop*
ExtrusionLoop::clone() const
{
return new ExtrusionLoop (*this);
}
ExtrusionPath*
ExtrusionLoop::split_at_index(int index) const
void
ExtrusionLoop::split_at_index(int index, ExtrusionPath* path) const
{
Polyline* poly = this->polygon.split_at_index(index);
Polygon polygon;
this->polygon(&polygon);
polygon.split_at_index(index, &path->polyline);
ExtrusionPath* path = new ExtrusionPath();
path->polyline = *poly;
path->role = this->role;
path->mm3_per_mm = this->mm3_per_mm;
path->width = this->width;
path->height = this->height;
delete poly;
return path;
}
ExtrusionPath*
ExtrusionLoop::split_at_first_point() const
void
ExtrusionLoop::split_at_first_point(ExtrusionPath* path) const
{
return this->split_at_index(0);
return this->split_at_index(0, path);
}
bool
ExtrusionLoop::make_counter_clockwise()
{
return this->polygon.make_counter_clockwise();
Polygon polygon;
this->polygon(&polygon);
bool was_cw = polygon.is_clockwise();
if (was_cw) this->reverse();
return was_cw;
}
void
ExtrusionLoop::reverse()
{
// no-op
for (Polylines::iterator polyline = this->polylines.begin(); polyline != this->polylines.end(); ++polyline)
polyline->reverse();
std::reverse(this->polylines.begin(), this->polylines.end());
}
Point
ExtrusionLoop::first_point() const
{
return this->polygon.points.front();
return this->polylines.front().points.front();
}
Point
ExtrusionLoop::last_point() const
{
return this->polygon.points.front(); // in polygons, first == last
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);
}
}
#ifdef SLIC3RXS

View File

@ -73,14 +73,18 @@ class ExtrusionPath : public ExtrusionEntity
class ExtrusionLoop : public ExtrusionEntity
{
public:
Polylines polylines;
ExtrusionLoop(const Polygon &polygon, ExtrusionRole role);
ExtrusionLoop* clone() const;
Polygon polygon;
ExtrusionPath* split_at_index(int index) const;
ExtrusionPath* split_at_first_point() const;
void split_at_index(int index, ExtrusionPath* path) const;
void split_at_first_point(ExtrusionPath* path) const;
bool make_counter_clockwise();
void reverse();
Point first_point() const;
Point last_point() const;
void set_polygon(const Polygon &polygon);
void polygon(Polygon* polygon) const;
};
}

View File

@ -51,43 +51,41 @@ Polygon::lines(Lines* lines) const
lines->push_back(Line(this->points.back(), this->points.front()));
}
Polyline*
Polygon::split_at(const Point &point) const
void
Polygon::split_at(const Point &point, Polyline* polyline) const
{
// find index of point
for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {
if (it->coincides_with(point))
return this->split_at_index(it - this->points.begin());
if (it->coincides_with(point)) {
this->split_at_index(it - this->points.begin(), polyline);
return;
}
}
CONFESS("Point not found");
return NULL;
}
Polyline*
Polygon::split_at_index(int index) const
void
Polygon::split_at_index(int index, Polyline* polyline) const
{
Polyline* poly = new Polyline;
poly->points.reserve(this->points.size() + 1);
polyline->points.reserve(this->points.size() + 1);
for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
poly->points.push_back(*it);
polyline->points.push_back(*it);
for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
poly->points.push_back(*it);
return poly;
polyline->points.push_back(*it);
}
Polyline*
Polygon::split_at_first_point() const
void
Polygon::split_at_first_point(Polyline* polyline) const
{
return this->split_at_index(0);
this->split_at_index(0, polyline);
}
Points
Polygon::equally_spaced_points(double distance) const
void
Polygon::equally_spaced_points(double distance, Points* points) const
{
Polyline* polyline = this->split_at_first_point();
Points pts = polyline->equally_spaced_points(distance);
delete polyline;
return pts;
Polyline polyline;
this->split_at_first_point(&polyline);
polyline.equally_spaced_points(distance, points);
}
double

View File

@ -20,10 +20,10 @@ class Polygon : public MultiPoint {
Point last_point() const;
Lines lines() const;
void lines(Lines* lines) const;
Polyline* split_at(const Point &point) const;
Polyline* split_at_index(int index) const;
Polyline* split_at_first_point() const;
Points equally_spaced_points(double distance) const;
void split_at(const Point &point, Polyline* polyline) const;
void split_at_index(int index, Polyline* polyline) const;
void split_at_first_point(Polyline* polyline) const;
void equally_spaced_points(double distance, Points* points) const;
double area() const;
bool is_counter_clockwise() const;
bool is_clockwise() const;

View File

@ -89,11 +89,10 @@ Polyline::extend_start(double distance)
/* this method returns a collection of points picked on the polygon contour
so that they are evenly spaced according to the input distance */
Points
Polyline::equally_spaced_points(double distance) const
void
Polyline::equally_spaced_points(double distance, Points* points) const
{
Points pts;
pts.push_back(this->first_point());
points->push_back(this->first_point());
double len = 0;
for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) {
@ -102,19 +101,17 @@ Polyline::equally_spaced_points(double distance) const
if (len < distance) continue;
if (len == distance) {
pts.push_back(*it);
points->push_back(*it);
len = 0;
continue;
}
double take = segment_length - (len - distance); // how much we take of this segment
Line segment(*(it-1), *it);
pts.push_back(segment.point_at(take));
points->push_back(segment.point_at(take));
it--;
len = -take;
}
return pts;
}
void

View File

@ -19,7 +19,7 @@ class Polyline : public MultiPoint {
void clip_start(double distance);
void extend_end(double distance);
void extend_start(double distance);
Points equally_spaced_points(double distance) const;
void equally_spaced_points(double distance, Points* points) const;
void simplify(double tolerance);
#ifdef SLIC3RXS

View File

@ -33,7 +33,7 @@ template <class T>
class Clone {
T* val;
public:
Clone() {}
Clone() : val() {}
Clone(T* t) : val(new T(*t)) {}
Clone(const T& t) : val(new T(t)) {}
operator T*() const {return val; }

View File

@ -4,7 +4,7 @@ use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 7;
use Test::More tests => 8;
my $square = [
[100, 100],
@ -18,7 +18,8 @@ my $loop = Slic3r::ExtrusionLoop->new(
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
mm3_per_mm => 1,
);
isa_ok $loop->polygon, 'Slic3r::Polygon::Ref', 'loop polygon';
isa_ok $loop, 'Slic3r::ExtrusionLoop';
isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon';
is_deeply $loop->polygon->pp, $square, 'polygon points roundtrip';
$loop = $loop->clone;

View File

@ -9,13 +9,14 @@
%name{Slic3r::ExtrusionLoop} class ExtrusionLoop {
~ExtrusionLoop();
SV* arrayref()
%code{% RETVAL = THIS->polygon.to_AV(); %};
%code{% Polygon polygon; THIS->polygon(&polygon); RETVAL = polygon.to_AV(); %};
SV* pp()
%code{% RETVAL = THIS->polygon.to_SV_pureperl(); %};
void reverse()
%code{% THIS->polygon.reverse(); %};
ExtrusionPath* split_at_index(int index);
ExtrusionPath* split_at_first_point();
%code{% Polygon polygon; THIS->polygon(&polygon); RETVAL = polygon.to_SV_pureperl(); %};
void reverse();
ExtrusionPath* split_at_index(int index)
%code{% RETVAL = new ExtrusionPath (); THIS->split_at_index(index, RETVAL); %};
ExtrusionPath* split_at_first_point()
%code{% RETVAL = new ExtrusionPath (); THIS->split_at_first_point(RETVAL); %};
bool make_counter_clockwise();
Clone<Point> first_point();
Clone<Point> last_point();
@ -33,22 +34,25 @@ _new(CLASS, polygon_sv, role, mm3_per_mm, width, height)
float width;
float height;
CODE:
RETVAL = new ExtrusionLoop ();
RETVAL->polygon.from_SV_check(polygon_sv);
RETVAL->role = role;
Polygon polygon;
polygon.from_SV_check(polygon_sv);
RETVAL = new ExtrusionLoop (polygon, role);
RETVAL->mm3_per_mm = mm3_per_mm;
RETVAL->width = width;
RETVAL->height = height;
OUTPUT:
RETVAL
Ref<Polygon>
Polygon*
ExtrusionLoop::polygon(...)
CODE:
if (items > 1) {
THIS->polygon.from_SV_check( ST(1) );
Polygon polygon;
polygon.from_SV_check( ST(1) );
THIS->set_polygon(polygon);
}
RETVAL = &(THIS->polygon);
RETVAL = new Polygon ();
THIS->polygon(RETVAL);
OUTPUT:
RETVAL

View File

@ -19,12 +19,13 @@
void reverse();
Lines lines();
Polyline* split_at(Point* point)
%code{% RETVAL = THIS->split_at(*point); %};
%code{% RETVAL = new Polyline(); THIS->split_at(*point, RETVAL); %};
Polyline* split_at_index(int index)
%code{% RETVAL = THIS->split_at_index(index); %};
%code{% RETVAL = new Polyline(); THIS->split_at_index(index, RETVAL); %};
Polyline* split_at_first_point()
%code{% RETVAL = THIS->split_at_first_point(); %};
Points equally_spaced_points(double distance);
%code{% RETVAL = new Polyline(); THIS->split_at_first_point(RETVAL); %};
Points equally_spaced_points(double distance)
%code{% THIS->equally_spaced_points(distance, &RETVAL); %};
double length();
double area();
bool is_counter_clockwise();

View File

@ -23,7 +23,8 @@
Lines lines();
Clone<Point> first_point();
Clone<Point> last_point();
Points equally_spaced_points(double distance);
Points equally_spaced_points(double distance)
%code{% THIS->equally_spaced_points(distance, &RETVAL); %};
double length();
bool is_valid();
void clip_end(double distance);