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 #endif
ExtrusionLoop::ExtrusionLoop(const Polygon &polygon, ExtrusionRole role)
{
this->role = role;
this->set_polygon(polygon);
}
ExtrusionLoop* ExtrusionLoop*
ExtrusionLoop::clone() const ExtrusionLoop::clone() const
{ {
return new ExtrusionLoop (*this); return new ExtrusionLoop (*this);
} }
ExtrusionPath* void
ExtrusionLoop::split_at_index(int index) const 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->role = this->role;
path->mm3_per_mm = this->mm3_per_mm; path->mm3_per_mm = this->mm3_per_mm;
path->width = this->width; path->width = this->width;
path->height = this->height; path->height = this->height;
delete poly;
return path;
} }
ExtrusionPath* void
ExtrusionLoop::split_at_first_point() const ExtrusionLoop::split_at_first_point(ExtrusionPath* path) const
{ {
return this->split_at_index(0); return this->split_at_index(0, path);
} }
bool bool
ExtrusionLoop::make_counter_clockwise() 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 void
ExtrusionLoop::reverse() 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 Point
ExtrusionLoop::first_point() const ExtrusionLoop::first_point() const
{ {
return this->polygon.points.front(); return this->polylines.front().points.front();
} }
Point Point
ExtrusionLoop::last_point() const 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 #ifdef SLIC3RXS

View File

@ -73,14 +73,18 @@ class ExtrusionPath : public ExtrusionEntity
class ExtrusionLoop : public ExtrusionEntity class ExtrusionLoop : public ExtrusionEntity
{ {
public: public:
Polylines polylines;
ExtrusionLoop(const Polygon &polygon, ExtrusionRole role);
ExtrusionLoop* clone() const; ExtrusionLoop* clone() const;
Polygon polygon; void split_at_index(int index, ExtrusionPath* path) const;
ExtrusionPath* split_at_index(int index) const; void split_at_first_point(ExtrusionPath* path) const;
ExtrusionPath* split_at_first_point() const;
bool make_counter_clockwise(); bool make_counter_clockwise();
void reverse(); void reverse();
Point first_point() const; Point first_point() const;
Point last_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())); lines->push_back(Line(this->points.back(), this->points.front()));
} }
Polyline* void
Polygon::split_at(const Point &point) const Polygon::split_at(const Point &point, Polyline* polyline) const
{ {
// find index of point // find index of point
for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) { for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {
if (it->coincides_with(point)) if (it->coincides_with(point)) {
return this->split_at_index(it - this->points.begin()); this->split_at_index(it - this->points.begin(), polyline);
return;
}
} }
CONFESS("Point not found"); CONFESS("Point not found");
return NULL;
} }
Polyline* void
Polygon::split_at_index(int index) const Polygon::split_at_index(int index, Polyline* polyline) const
{ {
Polyline* poly = new Polyline; polyline->points.reserve(this->points.size() + 1);
poly->points.reserve(this->points.size() + 1);
for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it) 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) for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
poly->points.push_back(*it); polyline->points.push_back(*it);
return poly;
} }
Polyline* void
Polygon::split_at_first_point() const Polygon::split_at_first_point(Polyline* polyline) const
{ {
return this->split_at_index(0); this->split_at_index(0, polyline);
} }
Points void
Polygon::equally_spaced_points(double distance) const Polygon::equally_spaced_points(double distance, Points* points) const
{ {
Polyline* polyline = this->split_at_first_point(); Polyline polyline;
Points pts = polyline->equally_spaced_points(distance); this->split_at_first_point(&polyline);
delete polyline; polyline.equally_spaced_points(distance, points);
return pts;
} }
double double

View File

@ -20,10 +20,10 @@ class Polygon : public MultiPoint {
Point last_point() const; Point last_point() const;
Lines lines() const; Lines lines() const;
void lines(Lines* lines) const; void lines(Lines* lines) const;
Polyline* split_at(const Point &point) const; void split_at(const Point &point, Polyline* polyline) const;
Polyline* split_at_index(int index) const; void split_at_index(int index, Polyline* polyline) const;
Polyline* split_at_first_point() const; void split_at_first_point(Polyline* polyline) const;
Points equally_spaced_points(double distance) const; void equally_spaced_points(double distance, Points* points) const;
double area() const; double area() const;
bool is_counter_clockwise() const; bool is_counter_clockwise() const;
bool is_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 /* this method returns a collection of points picked on the polygon contour
so that they are evenly spaced according to the input distance */ so that they are evenly spaced according to the input distance */
Points void
Polyline::equally_spaced_points(double distance) const Polyline::equally_spaced_points(double distance, Points* points) const
{ {
Points pts; points->push_back(this->first_point());
pts.push_back(this->first_point());
double len = 0; double len = 0;
for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) { 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) continue;
if (len == distance) { if (len == distance) {
pts.push_back(*it); points->push_back(*it);
len = 0; len = 0;
continue; continue;
} }
double take = segment_length - (len - distance); // how much we take of this segment double take = segment_length - (len - distance); // how much we take of this segment
Line segment(*(it-1), *it); Line segment(*(it-1), *it);
pts.push_back(segment.point_at(take)); points->push_back(segment.point_at(take));
it--; it--;
len = -take; len = -take;
} }
return pts;
} }
void void

View File

@ -19,7 +19,7 @@ class Polyline : public MultiPoint {
void clip_start(double distance); void clip_start(double distance);
void extend_end(double distance); void extend_end(double distance);
void extend_start(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); void simplify(double tolerance);
#ifdef SLIC3RXS #ifdef SLIC3RXS

View File

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

View File

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

View File

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

View File

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

View File

@ -23,7 +23,8 @@
Lines lines(); Lines lines();
Clone<Point> first_point(); Clone<Point> first_point();
Clone<Point> last_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(); double length();
bool is_valid(); bool is_valid();
void clip_end(double distance); void clip_end(double distance);