diff --git a/xs/src/ExtrusionEntity.cpp b/xs/src/ExtrusionEntity.cpp index 060c914bb..965c086f9 100644 --- a/xs/src/ExtrusionEntity.cpp +++ b/xs/src/ExtrusionEntity.cpp @@ -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 diff --git a/xs/src/ExtrusionEntity.hpp b/xs/src/ExtrusionEntity.hpp index 347a7ce23..ac57e26b5 100644 --- a/xs/src/ExtrusionEntity.hpp +++ b/xs/src/ExtrusionEntity.hpp @@ -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; }; } diff --git a/xs/src/Polygon.cpp b/xs/src/Polygon.cpp index ca062958c..72514b0dd 100644 --- a/xs/src/Polygon.cpp +++ b/xs/src/Polygon.cpp @@ -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 diff --git a/xs/src/Polygon.hpp b/xs/src/Polygon.hpp index 2dfe0ed09..c8570d763 100644 --- a/xs/src/Polygon.hpp +++ b/xs/src/Polygon.hpp @@ -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; diff --git a/xs/src/Polyline.cpp b/xs/src/Polyline.cpp index 4c49435ae..10dfb0ad2 100644 --- a/xs/src/Polyline.cpp +++ b/xs/src/Polyline.cpp @@ -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 diff --git a/xs/src/Polyline.hpp b/xs/src/Polyline.hpp index b2648ba48..f41d9132b 100644 --- a/xs/src/Polyline.hpp +++ b/xs/src/Polyline.hpp @@ -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 diff --git a/xs/src/perlglue.hpp b/xs/src/perlglue.hpp index d950dd256..ed767ef3e 100644 --- a/xs/src/perlglue.hpp +++ b/xs/src/perlglue.hpp @@ -33,7 +33,7 @@ template 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; } diff --git a/xs/t/08_extrusionloop.t b/xs/t/08_extrusionloop.t index 54ef72ca7..aad73dbb1 100644 --- a/xs/t/08_extrusionloop.t +++ b/xs/t/08_extrusionloop.t @@ -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; diff --git a/xs/xsp/ExtrusionLoop.xsp b/xs/xsp/ExtrusionLoop.xsp index c1c6e4a97..b53eca32b 100644 --- a/xs/xsp/ExtrusionLoop.xsp +++ b/xs/xsp/ExtrusionLoop.xsp @@ -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 first_point(); Clone 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* 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 diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index d27a9d1b0..e5d415d6b 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -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(); diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 752962a6a..848bd3f51 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -23,7 +23,8 @@ Lines lines(); Clone first_point(); Clone 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);