From ed8a2f7330c6056d4acfb15c61b99b33a4c10d06 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 15 Mar 2014 16:53:20 +0100 Subject: [PATCH] Extend medial axis endpoints to fill the entire length. Includes fix for a minor memory leak caused by usage of old signature for Line::point_at() --- xs/src/ExPolygon.cpp | 6 ++++++ xs/src/Line.cpp | 17 ++++++++++++----- xs/src/Line.hpp | 3 ++- xs/src/Polyline.cpp | 21 +++++++++++++++++++-- xs/src/Polyline.hpp | 2 ++ xs/t/09_polyline.t | 11 ++++++++++- xs/xsp/Line.xsp | 2 +- xs/xsp/Polyline.xsp | 2 ++ 8 files changed, 54 insertions(+), 10 deletions(-) diff --git a/xs/src/ExPolygon.cpp b/xs/src/ExPolygon.cpp index 4eefd0b16..bfeb30931 100644 --- a/xs/src/ExPolygon.cpp +++ b/xs/src/ExPolygon.cpp @@ -148,6 +148,12 @@ ExPolygon::medial_axis(double max_width, double min_width, Polylines* polylines) // compute the Voronoi diagram ma.build(polylines); + // extend initial and final segments of each polyline (they will be clipped) + for (Polylines::iterator polyline = polylines->begin(); polyline != polylines->end(); ++polyline) { + polyline->extend_start(max_width); + polyline->extend_end(max_width); + } + // clip segments to our expolygon area intersection(*polylines, *this, *polylines); } diff --git a/xs/src/Line.cpp b/xs/src/Line.cpp index 203d64876..dd6b1eec1 100644 --- a/xs/src/Line.cpp +++ b/xs/src/Line.cpp @@ -62,15 +62,22 @@ Line::midpoint() const return new Point ((this->a.x + this->b.x) / 2.0, (this->a.y + this->b.y) / 2.0); } -Point* -Line::point_at(double distance) const +void +Line::point_at(double distance, Point* point) const { double len = this->length(); - Point* p = new Point(this->a); + *point = this->a; if (this->a.x != this->b.x) - p->x = this->a.x + (this->b.x - this->a.x) * distance / len; + point->x = this->a.x + (this->b.x - this->a.x) * distance / len; if (this->a.y != this->b.y) - p->y = this->a.y + (this->b.y - this->a.y) * distance / len; + point->y = this->a.y + (this->b.y - this->a.y) * distance / len; +} + +Point +Line::point_at(double distance) const +{ + Point p; + this->point_at(distance, &p); return p; } diff --git a/xs/src/Line.hpp b/xs/src/Line.hpp index d3f9914ac..a3a229ce6 100644 --- a/xs/src/Line.hpp +++ b/xs/src/Line.hpp @@ -25,7 +25,8 @@ class Line void reverse(); double length() const; Point* midpoint() const; - Point* point_at(double distance) const; + void point_at(double distance, Point* point) const; + Point point_at(double distance) const; bool coincides_with(const Line* line) const; double distance_to(const Point* point) const; double atan2_() const; diff --git a/xs/src/Polyline.cpp b/xs/src/Polyline.cpp index 5f62b5b47..29c983c28 100644 --- a/xs/src/Polyline.cpp +++ b/xs/src/Polyline.cpp @@ -43,7 +43,7 @@ Polyline::clip_end(double distance) } Line segment(last_point, *this->last_point()); - this->points.push_back(*segment.point_at(distance)); + this->points.push_back(segment.point_at(distance)); distance = 0; } } @@ -57,6 +57,23 @@ Polyline::clip_start(double distance) if (this->points.size() >= 2) this->reverse(); } +void +Polyline::extend_end(double distance) +{ + // relocate last point by extending the last segment by the specified length + Line line(this->points[ this->points.size()-2 ], this->points.back()); + this->points.pop_back(); + this->points.push_back(line.point_at(line.length() + distance)); +} + +void +Polyline::extend_start(double distance) +{ + // relocate first point by extending the first segment by the specified length + Line line(this->points[1], this->points.front()); + this->points[0] = line.point_at(line.length() + 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 @@ -79,7 +96,7 @@ Polyline::equally_spaced_points(double distance) const 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)); + pts.push_back(segment.point_at(take)); it--; len = -take; } diff --git a/xs/src/Polyline.hpp b/xs/src/Polyline.hpp index 394edf4f2..56cadddfc 100644 --- a/xs/src/Polyline.hpp +++ b/xs/src/Polyline.hpp @@ -16,6 +16,8 @@ class Polyline : public MultiPoint { Lines lines() const; void clip_end(double distance); void clip_start(double distance); + void extend_end(double distance); + void extend_start(double distance); Points equally_spaced_points(double distance) const; void simplify(double tolerance); diff --git a/xs/t/09_polyline.t b/xs/t/09_polyline.t index 6d39273e9..4f7c21941 100644 --- a/xs/t/09_polyline.t +++ b/xs/t/09_polyline.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 7; +use Test::More tests => 10; my $points = [ [100, 100], @@ -42,4 +42,13 @@ is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline'; is_deeply $polyline->pp, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker'; } +{ + my $polyline = Slic3r::Polyline->new(@$points); + is $polyline->length, 100*2, 'length'; + $polyline->extend_end(50); + is $polyline->length, 100*2 + 50, 'extend_end'; + $polyline->extend_start(50); + is $polyline->length, 100*2 + 50 + 50, 'extend_start'; +} + __END__ diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index c82f458da..23b0250c8 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -26,7 +26,7 @@ Point* midpoint() %code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->midpoint(); %}; Point* point_at(double distance) - %code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->point_at(distance); %}; + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(THIS->point_at(distance)); %}; Polyline* as_polyline() %code{% const char* CLASS = "Slic3r::Polyline"; RETVAL = new Polyline(*THIS); %}; %{ diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index ab7eb3307..8a7bd780d 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -29,6 +29,8 @@ bool is_valid(); void clip_end(double distance); void clip_start(double distance); + void extend_end(double distance); + void extend_start(double distance); void simplify(double tolerance); %{