From 5309e3ef223730d16948021fd6a4677d3e1baae4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 22 Nov 2013 22:38:30 +0100 Subject: [PATCH] More files for convex_hull --- xs/src/Geometry.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ xs/src/Geometry.hpp | 12 ++++++++++++ xs/t/14_geometry.t | 22 ++++++++++++++++++++++ xs/xsp/Geometry.xsp | 23 +++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 xs/src/Geometry.cpp create mode 100644 xs/src/Geometry.hpp create mode 100644 xs/t/14_geometry.t create mode 100644 xs/xsp/Geometry.xsp diff --git a/xs/src/Geometry.cpp b/xs/src/Geometry.cpp new file mode 100644 index 000000000..d6526619c --- /dev/null +++ b/xs/src/Geometry.cpp @@ -0,0 +1,46 @@ +#include "Geometry.hpp" +#include + +namespace Slic3r { + +static bool +sort_points (Point a, Point b) +{ + return (a.x < b.x) || (a.x == b.x && a.y < b.y); +} + +void +convex_hull(Points points, Polygon &hull) +{ + assert(points.size() >= 2); + // sort input points + std::sort(points.begin(), points.end(), sort_points); + + typedef const Point* PointPtr; + PointPtr* out_hull = (PointPtr*)malloc(points.size()*2*sizeof(PointPtr)); + + /* lower hull */ + size_t k = 0; + for (Points::const_iterator it = points.begin(); it != points.end(); ++it) { + while (k >= 2 && it->ccw(out_hull[k-2], out_hull[k-1]) <= 0) --k; + Point pz = *&*it; + out_hull[k++] = &*it; + } + + /* upper hull */ + size_t t = k+1; + for (Points::const_iterator it = points.end() - 2; it != points.begin(); --it) { + while (k >= t && it->ccw(out_hull[k-2], out_hull[k-1]) <= 0) --k; + out_hull[k++] = &*it; + } + + // we assume hull is empty + hull.points.reserve(k); + for (size_t i = 0; i < k; ++i) { + hull.points.push_back(*(out_hull[i])); + } + + free(out_hull); +} + +} diff --git a/xs/src/Geometry.hpp b/xs/src/Geometry.hpp new file mode 100644 index 000000000..8085d7f2b --- /dev/null +++ b/xs/src/Geometry.hpp @@ -0,0 +1,12 @@ +#ifndef slic3r_Geometry_hpp_ +#define slic3r_Geometry_hpp_ + +#include "Polygon.hpp" + +namespace Slic3r { + +void convex_hull(Points points, Polygon &hull); + +} + +#endif diff --git a/xs/t/14_geometry.t b/xs/t/14_geometry.t new file mode 100644 index 000000000..4324da818 --- /dev/null +++ b/xs/t/14_geometry.t @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Slic3r::XS; +use Test::More tests => 2; + +{ + my @points = ( + Slic3r::Point->new(100,100), + Slic3r::Point->new(100,200), + Slic3r::Point->new(200,200), + Slic3r::Point->new(200,100), + Slic3r::Point->new(150,150), + ); + my $hull = Slic3r::Geometry::convex_hull(\@points); + isa_ok $hull, 'Slic3r::Polygon', 'convex_hull returns a Polygon'; + is scalar(@$hull), 4, 'convex_hull returns the correct number of points'; +} + +__END__ diff --git a/xs/xsp/Geometry.xsp b/xs/xsp/Geometry.xsp new file mode 100644 index 000000000..52750c8f2 --- /dev/null +++ b/xs/xsp/Geometry.xsp @@ -0,0 +1,23 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "Geometry.hpp" +%} + +%package{Slic3r::Geometry}; + +%{ + +Polygon* +convex_hull(points) + Points points + PREINIT: + const char* CLASS = "Slic3r::Polygon"; + CODE: + RETVAL = new Polygon (); + convex_hull(points, *RETVAL); + OUTPUT: + RETVAL + +%}