diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 164ee4590..c37b86074 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -126,13 +126,6 @@ sub simplify { return @{ Slic3r::Geometry::Clipper::union_ex([ $self->simplify_as_polygons($tolerance) ]) }; } -sub area { - my $self = shift; - my $area = $self->contour->area; - $area -= $_->area for $self->holes; - return $area; -} - # this method only works for expolygons having only a contour or # a contour and a hole, and not being thicker than the supplied # width. it returns a polyline or a polygon diff --git a/xs/src/ExPolygon.cpp b/xs/src/ExPolygon.cpp index 4805b156e..33d71b497 100644 --- a/xs/src/ExPolygon.cpp +++ b/xs/src/ExPolygon.cpp @@ -30,6 +30,16 @@ ExPolygon::rotate(double angle, Point* center) } } +double +ExPolygon::area() const +{ + double a = this->contour.area(); + for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { + a -= -(*it).area(); // holes have negative area + } + return a; +} + SV* ExPolygon::to_SV() { const unsigned int num_holes = this->holes.size(); diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp index c7431c224..62f919ead 100644 --- a/xs/src/ExPolygon.hpp +++ b/xs/src/ExPolygon.hpp @@ -19,6 +19,7 @@ class ExPolygon void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); + double area() const; }; typedef std::vector ExPolygons; diff --git a/xs/src/Polygon.cpp b/xs/src/Polygon.cpp index bff261c25..fc3f54f57 100644 --- a/xs/src/Polygon.cpp +++ b/xs/src/Polygon.cpp @@ -55,7 +55,7 @@ Polygon::split_at_first_point() } double -Polygon::area() +Polygon::area() const { ClipperLib::Polygon p; Slic3rPolygon_to_ClipperPolygon(*this, p); @@ -63,7 +63,7 @@ Polygon::area() } bool -Polygon::is_counter_clockwise() +Polygon::is_counter_clockwise() const { ClipperLib::Polygon* p = new ClipperLib::Polygon(); Slic3rPolygon_to_ClipperPolygon(*this, *p); diff --git a/xs/src/Polygon.hpp b/xs/src/Polygon.hpp index 7186eb65a..dcab04059 100644 --- a/xs/src/Polygon.hpp +++ b/xs/src/Polygon.hpp @@ -16,8 +16,8 @@ class Polygon : public MultiPoint { Polyline* split_at(const Point* point); Polyline* split_at_index(int index); Polyline* split_at_first_point(); - double area(); - bool is_counter_clockwise(); + double area() const; + bool is_counter_clockwise() const; bool make_counter_clockwise(); bool make_clockwise(); }; diff --git a/xs/t/04_expolygon.t b/xs/t/04_expolygon.t index dd5d23288..aa87bc74b 100644 --- a/xs/t/04_expolygon.t +++ b/xs/t/04_expolygon.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 17; +use Test::More tests => 18; use constant PI => 4 * atan2(1, 1); @@ -40,6 +40,8 @@ is_deeply $expolygon->clone->pp, [$square, $hole_in_square], 'clone'; # The following tests implicitely check that modifying clones # does not modify the original one. +is $expolygon->area, 100*100-20*20, 'area'; + { my $expolygon2 = $expolygon->clone; $expolygon2->scale(2.5); diff --git a/xs/xsp/ExPolygon.xsp b/xs/xsp/ExPolygon.xsp index 224f97fc6..49582642a 100644 --- a/xs/xsp/ExPolygon.xsp +++ b/xs/xsp/ExPolygon.xsp @@ -15,6 +15,7 @@ %code{% RETVAL = THIS->to_SV_pureperl(); %}; void scale(double factor); void translate(double x, double y); + double area(); %{ ExPolygon*