From 74c55a6b78fa2da638fc5d730f7d7eecc9df2596 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 1 Mar 2012 14:28:06 +0000 Subject: [PATCH 1/5] Fix lasso example. --- examples/event_handling/lasso_demo.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/examples/event_handling/lasso_demo.py b/examples/event_handling/lasso_demo.py index d441a203fa3f..59722b2c87d8 100644 --- a/examples/event_handling/lasso_demo.py +++ b/examples/event_handling/lasso_demo.py @@ -4,11 +4,11 @@ selected points This is currently a proof-of-concept implementation (though it is -usable as is). There will be some refinement of the API and the -inside polygon detection routine. +usable as is). There will be some refinement of the API. """ from matplotlib.widgets import Lasso -from matplotlib.nxutils import points_inside_poly +import matplotlib.mlab +from matplotlib.path import Path from matplotlib.colors import colorConverter from matplotlib.collections import RegularPolyCollection @@ -18,7 +18,7 @@ class Datum: colorin = colorConverter.to_rgba('red') - colorout = colorConverter.to_rgba('green') + colorout = colorConverter.to_rgba('blue') def __init__(self, x, y, include=False): self.x = x self.y = y @@ -46,13 +46,12 @@ def __init__(self, ax, data): ax.add_collection(self.collection) self.cid = self.canvas.mpl_connect('button_press_event', self.onpress) - self.ind = None def callback(self, verts): facecolors = self.collection.get_facecolors() - ind = nonzero(points_inside_poly(self.xys, verts))[0] + p = Path(verts) for i in range(self.Nxy): - if i in ind: + if p.contains_point(self.xys[i]): facecolors[i] = Datum.colorin else: facecolors[i] = Datum.colorout @@ -60,7 +59,7 @@ def callback(self, verts): self.canvas.draw_idle() self.canvas.widgetlock.release(self.lasso) del self.lasso - self.ind = ind + def onpress(self, event): if self.canvas.widgetlock.locked(): return if event.inaxes is None: return From c5558109299463226be516691c0e357f19c43009 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 1 Mar 2012 14:32:29 +0000 Subject: [PATCH 2/5] Spurious import, tidied subplot call. --- examples/event_handling/lasso_demo.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/event_handling/lasso_demo.py b/examples/event_handling/lasso_demo.py index 59722b2c87d8..5b317ebdc586 100644 --- a/examples/event_handling/lasso_demo.py +++ b/examples/event_handling/lasso_demo.py @@ -7,16 +7,15 @@ usable as is). There will be some refinement of the API. """ from matplotlib.widgets import Lasso -import matplotlib.mlab from matplotlib.path import Path from matplotlib.colors import colorConverter from matplotlib.collections import RegularPolyCollection -from matplotlib.pyplot import figure, show +import matplotlib.pyplot as plt from numpy import nonzero from numpy.random import rand -class Datum: +class Datum(object): colorin = colorConverter.to_rgba('red') colorout = colorConverter.to_rgba('blue') def __init__(self, x, y, include=False): @@ -26,7 +25,7 @@ def __init__(self, x, y, include=False): else: self.color = self.colorout -class LassoManager: +class LassoManager(object): def __init__(self, ax, data): self.axes = ax self.canvas = ax.figure.canvas @@ -71,8 +70,7 @@ def onpress(self, event): data = [Datum(*xy) for xy in rand(100, 2)] - fig = figure() - ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False) + ax = plt.axes(xlim=(0,1), ylim=(0,1), autoscale_on=False) lman = LassoManager(ax, data) - show() + plt.show() From 67352c8fe8f7b83e9f5c6774fd8f677aed6e158a Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 8 Mar 2012 18:49:12 -0500 Subject: [PATCH 3/5] Creates a backward compatibility layer for nxutils. nxutils is now implemented in terms of the methods in _path.cpp. A "points_in_path" method has been added to support "nxutils.points_in_poly". --- examples/event_handling/lasso_demo.py | 5 +- lib/matplotlib/nxutils.py | 46 +++++ lib/matplotlib/path.py | 21 ++- src/_path.cpp | 251 ++++++++++++++++++-------- 4 files changed, 248 insertions(+), 75 deletions(-) create mode 100644 lib/matplotlib/nxutils.py diff --git a/examples/event_handling/lasso_demo.py b/examples/event_handling/lasso_demo.py index d441a203fa3f..4659123c7008 100644 --- a/examples/event_handling/lasso_demo.py +++ b/examples/event_handling/lasso_demo.py @@ -8,9 +8,9 @@ inside polygon detection routine. """ from matplotlib.widgets import Lasso -from matplotlib.nxutils import points_inside_poly from matplotlib.colors import colorConverter from matplotlib.collections import RegularPolyCollection +from matplotlib import path from matplotlib.pyplot import figure, show from numpy import nonzero @@ -50,7 +50,8 @@ def __init__(self, ax, data): def callback(self, verts): facecolors = self.collection.get_facecolors() - ind = nonzero(points_inside_poly(self.xys, verts))[0] + p = path.Path(verts) + ind = nonzero(p.contains_points(self.xys))[0] for i in range(self.Nxy): if i in ind: facecolors[i] = Datum.colorin diff --git a/lib/matplotlib/nxutils.py b/lib/matplotlib/nxutils.py new file mode 100644 index 000000000000..2b1bff51cae3 --- /dev/null +++ b/lib/matplotlib/nxutils.py @@ -0,0 +1,46 @@ +import warnings + +from matplotlib import path + +def pnpoly(x, y, xyverts): + """ + inside = pnpoly(x, y, xyverts) + + Return 1 if x,y is inside the polygon, 0 otherwise. + + *xyverts* + a sequence of x,y vertices. + + A point on the boundary may be treated as inside or outside. + + Deprecated: Use `matplotlib.path.Path.contains_point` instead. + """ + warings.warn( + DeprecationWarning, + "nxutils is deprecated. Use matplotlib.path.Path.contains_point instead.") + + p = path.Path(xyverts) + return p.contains_point(x, y) + +def points_inside_poly(xypoints, xyverts): + """ + mask = points_inside_poly(xypoints, xyverts) + + Returns a boolean ndarray, True for points inside the polygon. + + *xypoints* + a sequence of N x,y pairs. + + *xyverts* + sequence of x,y vertices of the polygon. + + A point on the boundary may be treated as inside or outside. + + Deprecated: Use `matplotlib.path.Path.contains_points` instead. + """ + warnings.warn( + DeprecationWarning, + "nxutils is deprecated. Use matplotlib.path.Path.contains_points instead.") + + p = path.Path(xyverts) + return p.contains_points(xypoints) diff --git a/lib/matplotlib/path.py b/lib/matplotlib/path.py index 8ebdfe99127f..a4a3d811e394 100644 --- a/lib/matplotlib/path.py +++ b/lib/matplotlib/path.py @@ -12,7 +12,7 @@ from matplotlib._path import point_in_path, get_path_extents, \ point_in_path_collection, get_path_collection_extents, \ path_in_path, path_intersects_path, convert_path_to_polygons, \ - cleanup_path + cleanup_path, points_in_path from matplotlib.cbook import simple_linear_interpolation, maxdict from matplotlib import rcParams @@ -280,12 +280,31 @@ def contains_point(self, point, transform=None, radius=0.0): If *transform* is not *None*, the path will be transformed before performing the test. + + *radius* allows the path to be made slightly larger or + smaller. """ if transform is not None: transform = transform.frozen() result = point_in_path(point[0], point[1], radius, self, transform) return result + def contains_points(self, points, transform=None, radius=0.0): + """ + Returns a bool array which is *True* if the path contains the + corresponding point. + + If *transform* is not *None*, the path will be transformed + before performing the test. + + *radius* allows the path to be made slightly larger or + smaller. + """ + if transform is not None: + transform = transform.frozen() + result = points_in_path(points, radius, self, transform) + return result + def contains_path(self, path, transform=None): """ Returns *True* if this path completely contains the given path. diff --git a/src/_path.cpp b/src/_path.cpp index 2729b3b1042a..114b6a48cc13 100644 --- a/src/_path.cpp +++ b/src/_path.cpp @@ -33,6 +33,8 @@ class _path_module : public Py::ExtensionModule<_path_module> { add_varargs_method("point_in_path", &_path_module::point_in_path, "point_in_path(x, y, path, trans)"); + add_varargs_method("points_in_path", &_path_module::points_in_path, + "points_in_path(points, path, trans)"); add_varargs_method("point_on_path", &_path_module::point_on_path, "point_on_path(x, y, r, path, trans)"); add_varargs_method("get_path_extents", &_path_module::get_path_extents, @@ -66,6 +68,7 @@ class _path_module : public Py::ExtensionModule<_path_module> private: Py::Object point_in_path(const Py::Tuple& args); + Py::Object points_in_path(const Py::Tuple& args); Py::Object point_on_path(const Py::Tuple& args); Py::Object get_path_extents(const Py::Tuple& args); Py::Object update_path_extents(const Py::Tuple& args); @@ -119,16 +122,32 @@ class _path_module : public Py::ExtensionModule<_path_module> // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point // _point_, returns 1 if inside, 0 if outside. template -bool -point_in_path_impl(const double tx, const double ty, T& path) +static void +point_in_path_impl(const void* const points_, const size_t s0, + const size_t s1, const size_t n, T& path, + npy_bool* const inside_flag) { - int yflag0, yflag1, inside_flag; - double vtx0, vty0, vtx1, vty1, sx, sy; + int *yflag0, *yflag1; + double *vtx0, *vty0, *vtx1, *vty1; + double tx, ty; + double sx, sy; double x, y; + size_t i; + int all_done; + const char *const points = (const char * const)points_; + + yflag0 = (int *)malloc(n * sizeof(int)); + yflag1 = (int *)malloc(n * sizeof(int)); + vtx0 = (double *)malloc(n * sizeof(double)); + vty0 = (double *)malloc(n * sizeof(double)); + vtx1 = (double *)malloc(n * sizeof(double)); + vty1 = (double *)malloc(n * sizeof(double)); path.rewind(0); - inside_flag = 0; + for (i = 0; i < n; ++i) { + inside_flag[i] = 0; + } unsigned code = 0; do @@ -138,23 +157,28 @@ point_in_path_impl(const double tx, const double ty, T& path) code = path.vertex(&x, &y); } - sx = vtx0 = x; - sy = vty0 = y; + sx = x; + sy = y; - // get test bit for above/below X axis - yflag0 = (vty0 >= ty); + for (i = 0; i < n; ++i) { + vtx0[i] = vtx1[i] = x; + vty0[i] = vty1[i] = y; - vtx1 = x; - vty1 = y; + ty = *(double *)(points + s0 * i + s1); + + // get test bit for above/below X axis + yflag0[i] = (vty0[i] >= ty); + + inside_flag[i] = 0; + } - inside_flag = 0; do { code = path.vertex(&x, &y); // The following cases denote the beginning on a new subpath if (code == agg::path_cmd_stop || - (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) + (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { x = sx; y = sy; @@ -164,79 +188,105 @@ point_in_path_impl(const double tx, const double ty, T& path) break; } - yflag1 = (vty1 >= ty); - // Check if endpoints straddle (are on opposite sides) of - // X axis (i.e. the Y's differ); if so, +X ray could - // intersect this edge. The old test also checked whether - // the endpoints are both to the right or to the left of - // the test point. However, given the faster intersection - // point computation used below, this test was found to be - // a break-even proposition for most polygons and a loser - // for triangles (where 50% or more of the edges which - // survive this test will cross quadrants and so have to - // have the X intersection computed anyway). I credit - // Joseph Samosky with inspiring me to try dropping the - // "both left or both right" part of my code. - if (yflag0 != yflag1) - { - // Check intersection of pgon segment with +X ray. - // Note if >= point's X; if so, the ray hits it. The - // division operation is avoided for the ">=" test by - // checking the sign of the first vertex wrto the test - // point; idea inspired by Joseph Samosky's and Mark - // Haigh-Hutchinson's different polygon inclusion - // tests. - if (((vty1 - ty) * (vtx0 - vtx1) >= - (vtx1 - tx) * (vty0 - vty1)) == yflag1) - { - inside_flag ^= 1; + for (i = 0; i < n; ++i) { + tx = *(double *)(points + s0 * i); + ty = *(double *)(points + s0 * i + s1); + + yflag1[i] = (vty1[i] >= ty); + // Check if endpoints straddle (are on opposite sides) of + // X axis (i.e. the Y's differ); if so, +X ray could + // intersect this edge. The old test also checked whether + // the endpoints are both to the right or to the left of + // the test point. However, given the faster intersection + // point computation used below, this test was found to be + // a break-even proposition for most polygons and a loser + // for triangles (where 50% or more of the edges which + // survive this test will cross quadrants and so have to + // have the X intersection computed anyway). I credit + // Joseph Samosky with inspiring me to try dropping the + // "both left or both right" part of my code. + if (yflag0[i] != yflag1[i]) { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. The + // division operation is avoided for the ">=" test by + // checking the sign of the first vertex wrto the test + // point; idea inspired by Joseph Samosky's and Mark + // Haigh-Hutchinson's different polygon inclusion + // tests. + if (((vty1[i] - ty) * (vtx0[i] - vtx1[i]) >= + (vtx1[i] - tx) * (vty0[i] - vty1[i])) == yflag1[i]) { + inside_flag[i] ^= 1; + } } - } - // Move to the next pair of vertices, retaining info as - // possible. - yflag0 = yflag1; - vtx0 = vtx1; - vty0 = vty1; - vtx1 = x; - vty1 = y; + // Move to the next pair of vertices, retaining info as + // possible. + yflag0[i] = yflag1[i]; + vtx0[i] = vtx1[i]; + vty0[i] = vty1[i]; + + vtx1[i] = x; + vty1[i] = y; + } } while (code != agg::path_cmd_stop && (code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); - yflag1 = (vty1 >= ty); - if (yflag0 != yflag1) - { - if (((vty1 - ty) * (vtx0 - vtx1) >= - (vtx1 - tx) * (vty0 - vty1)) == yflag1) - { - inside_flag ^= 1; + all_done = 1; + for (i = 0; i < n; ++i) { + tx = *(double *)(points + s0 * i); + ty = *(double *)(points + s0 * i + s1); + + yflag1[i] = (vty1[i] >= ty); + if (yflag0[i] != yflag1[i]) { + if (((vty1[i] - ty) * (vtx0[i] - vtx1[i]) >= + (vtx1[i] - tx) * (vty0[i] - vty1[i])) == yflag1[i]) { + inside_flag[i] ^= 1; + } + } + + if (inside_flag[i] == 0) { + all_done = 0; } } - if (inside_flag != 0) - { - return true; + if (all_done) { + goto exit; } } while (code != agg::path_cmd_stop); - return (inside_flag != 0); + exit: + + free(yflag0); + free(yflag1); + free(vtx0); + free(vty0); + free(vtx1); + free(vty1); } -inline bool -point_in_path(double x, double y, double r, PathIterator& path, - const agg::trans_affine& trans) +inline void +points_in_path(const void* const points, const size_t s0, + const size_t s1, const size_t n, + const double r, PathIterator& path, + const agg::trans_affine& trans, + npy_bool* result) { typedef agg::conv_transform transformed_path_t; typedef PathNanRemover no_nans_t; typedef agg::conv_curve curve_t; typedef agg::conv_contour contour_t; + size_t i; + for (i = 0; i < n; ++i) { + result[i] = 0; + } + if (path.total_vertices() < 3) { - return false; + return; } transformed_path_t trans_path(path, trans); @@ -244,12 +294,29 @@ point_in_path(double x, double y, double r, PathIterator& path, curve_t curved_path(no_nans_path); contour_t contoured_path(curved_path); contoured_path.width(fabs(r)); - return point_in_path_impl(x, y, contoured_path); + point_in_path_impl(points, s0, s1, n, contoured_path, result); } inline bool -point_on_path(double x, double y, double r, PathIterator& path, - const agg::trans_affine& trans) +point_in_path(const double x, const double y, const double r, + PathIterator& path, const agg::trans_affine& trans) +{ + double points[2]; + npy_bool result; + + points[0] = x; + points[1] = y; + + points_in_path(points, 0, sizeof(double), 1, r, path, trans, &result); + return result; +} + +inline void +points_on_path(const void* const points, const size_t s0, + const size_t s1, const size_t n, + const double r, PathIterator& path, + const agg::trans_affine& trans, + npy_bool* result) { typedef agg::conv_transform transformed_path_t; typedef PathNanRemover no_nans_t; @@ -261,32 +328,72 @@ point_on_path(double x, double y, double r, PathIterator& path, curve_t curved_path(nan_removed_path); stroke_t stroked_path(curved_path); stroked_path.width(r * 2.0); - return point_in_path_impl(x, y, stroked_path); + point_in_path_impl(points, s0, s1, n, stroked_path, result); +} + +inline bool +point_on_path(const double x, const double y, const double r, + PathIterator& path, const agg::trans_affine& trans) +{ + double points[2]; + npy_bool result; + + points[0] = x; + points[1] = y; + + points_on_path(points, 0, sizeof(double), 1, r, path, trans, &result); + return result; } Py::Object _path_module::point_in_path(const Py::Tuple& args) { - args.verify_length(5); - double x = Py::Float(args[0]); double y = Py::Float(args[1]); double r = Py::Float(args[2]); PathIterator path(args[3]); agg::trans_affine trans = py_to_agg_transformation_matrix(args[4].ptr(), false); - if (::point_in_path(x, y, r, path, trans)) - { + if (::point_in_path(x, y, r, path, trans)) { return Py::Int(1); } return Py::Int(0); } Py::Object -_path_module::point_on_path(const Py::Tuple& args) +_path_module::points_in_path(const Py::Tuple& args) { - args.verify_length(5); + args.verify_length(4); + + npy_intp n; + PyArrayObject* points_array; + points_array = (PyArrayObject*)PyArray_FromObject(args[0].ptr(), PyArray_DOUBLE, 2, 2); + if (points_array == NULL || PyArray_DIM(points_array, 1) != 2) { + throw Py::TypeError( + "Argument 0 to points_in_path must be an Nx2 numpy array"); + + } + double r = Py::Float(args[1]); + PathIterator path(args[2]); + agg::trans_affine trans = py_to_agg_transformation_matrix(args[3].ptr(), false); + + n = PyArray_DIM(points_array, 0); + PyObject* result = PyArray_ZEROS(1, &n, PyArray_BOOL, 0); + if (result == NULL) { + throw Py::MemoryError("Could not allocate memory for result"); + } + + ::points_in_path(PyArray_DATA(points_array), + PyArray_STRIDE(points_array, 0), + PyArray_STRIDE(points_array, 1), + n, r, path, trans, + (npy_bool *)PyArray_DATA(result)); + return Py::Object(result, true);; +} +Py::Object +_path_module::point_on_path(const Py::Tuple& args) +{ double x = Py::Float(args[0]); double y = Py::Float(args[1]); double r = Py::Float(args[2]); From 36f7a6e80f55077e35498fd13a10b959a391ff5a Mon Sep 17 00:00:00 2001 From: Ben Root Date: Fri, 9 Mar 2012 13:11:37 -0600 Subject: [PATCH 4/5] nxutils shim work * Fixed usage error with deprecation warnings * Used deprecation directive in docstrings * Made point_in_path_impl more memory efficient --- lib/matplotlib/nxutils.py | 16 +++++++----- src/_path.cpp | 54 +++++++++++++++------------------------ 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/lib/matplotlib/nxutils.py b/lib/matplotlib/nxutils.py index 2b1bff51cae3..078cb6afa690 100644 --- a/lib/matplotlib/nxutils.py +++ b/lib/matplotlib/nxutils.py @@ -13,11 +13,13 @@ def pnpoly(x, y, xyverts): A point on the boundary may be treated as inside or outside. - Deprecated: Use `matplotlib.path.Path.contains_point` instead. + .. deprecated:: 1.2.0 + Use :meth:`~matplotlib.path.Path.contains_point` instead. """ warings.warn( - DeprecationWarning, - "nxutils is deprecated. Use matplotlib.path.Path.contains_point instead.") + "nxutils is deprecated. Use matplotlib.path.Path.contains_point" + " instead.", + DeprecationWarning) p = path.Path(xyverts) return p.contains_point(x, y) @@ -36,11 +38,13 @@ def points_inside_poly(xypoints, xyverts): A point on the boundary may be treated as inside or outside. - Deprecated: Use `matplotlib.path.Path.contains_points` instead. + .. deprecated:: 1.2.0 + Use :meth:`~matplotlib.path.Path.contains_points` instead. """ warnings.warn( - DeprecationWarning, - "nxutils is deprecated. Use matplotlib.path.Path.contains_points instead.") + "nxutils is deprecated. Use matplotlib.path.Path.contains_points" + " instead.", + DeprecationWarning) p = path.Path(xyverts) return p.contains_points(xypoints) diff --git a/src/_path.cpp b/src/_path.cpp index 114b6a48cc13..d9171fd8fe16 100644 --- a/src/_path.cpp +++ b/src/_path.cpp @@ -127,8 +127,9 @@ point_in_path_impl(const void* const points_, const size_t s0, const size_t s1, const size_t n, T& path, npy_bool* const inside_flag) { - int *yflag0, *yflag1; - double *vtx0, *vty0, *vtx1, *vty1; + int *yflag0; + int yflag1; + double vtx0, vty0, vtx1, vty1; double tx, ty; double sx, sy; double x, y; @@ -137,11 +138,6 @@ point_in_path_impl(const void* const points_, const size_t s0, const char *const points = (const char * const)points_; yflag0 = (int *)malloc(n * sizeof(int)); - yflag1 = (int *)malloc(n * sizeof(int)); - vtx0 = (double *)malloc(n * sizeof(double)); - vty0 = (double *)malloc(n * sizeof(double)); - vtx1 = (double *)malloc(n * sizeof(double)); - vty1 = (double *)malloc(n * sizeof(double)); path.rewind(0); @@ -157,17 +153,14 @@ point_in_path_impl(const void* const points_, const size_t s0, code = path.vertex(&x, &y); } - sx = x; - sy = y; + sx = vtx0 = vtx1 = x; + sy = vty0 = vty1 = y; for (i = 0; i < n; ++i) { - vtx0[i] = vtx1[i] = x; - vty0[i] = vty1[i] = y; - ty = *(double *)(points + s0 * i + s1); // get test bit for above/below X axis - yflag0[i] = (vty0[i] >= ty); + yflag0[i] = (vty0 >= ty); inside_flag[i] = 0; } @@ -192,7 +185,7 @@ point_in_path_impl(const void* const points_, const size_t s0, tx = *(double *)(points + s0 * i); ty = *(double *)(points + s0 * i + s1); - yflag1[i] = (vty1[i] >= ty); + yflag1 = (vty1 >= ty); // Check if endpoints straddle (are on opposite sides) of // X axis (i.e. the Y's differ); if so, +X ray could // intersect this edge. The old test also checked whether @@ -205,7 +198,7 @@ point_in_path_impl(const void* const points_, const size_t s0, // have the X intersection computed anyway). I credit // Joseph Samosky with inspiring me to try dropping the // "both left or both right" part of my code. - if (yflag0[i] != yflag1[i]) { + if (yflag0[i] != yflag1) { // Check intersection of pgon segment with +X ray. // Note if >= point's X; if so, the ray hits it. The // division operation is avoided for the ">=" test by @@ -213,22 +206,22 @@ point_in_path_impl(const void* const points_, const size_t s0, // point; idea inspired by Joseph Samosky's and Mark // Haigh-Hutchinson's different polygon inclusion // tests. - if (((vty1[i] - ty) * (vtx0[i] - vtx1[i]) >= - (vtx1[i] - tx) * (vty0[i] - vty1[i])) == yflag1[i]) { + if (((vty1 - ty) * (vtx0 - vtx1) >= + (vtx1 - tx) * (vty0 - vty1)) == yflag1) { inside_flag[i] ^= 1; } } - // Move to the next pair of vertices, retaining info as // possible. - yflag0[i] = yflag1[i]; - vtx0[i] = vtx1[i]; - vty0[i] = vty1[i]; - - vtx1[i] = x; - vty1[i] = y; + yflag0[i] = yflag1; } + + vtx0 = vtx1; + vty0 = vty1; + + vtx1 = x; + vty1 = y; } while (code != agg::path_cmd_stop && (code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); @@ -238,10 +231,10 @@ point_in_path_impl(const void* const points_, const size_t s0, tx = *(double *)(points + s0 * i); ty = *(double *)(points + s0 * i + s1); - yflag1[i] = (vty1[i] >= ty); - if (yflag0[i] != yflag1[i]) { - if (((vty1[i] - ty) * (vtx0[i] - vtx1[i]) >= - (vtx1[i] - tx) * (vty0[i] - vty1[i])) == yflag1[i]) { + yflag1 = (vty1 >= ty); + if (yflag0[i] != yflag1) { + if (((vty1 - ty) * (vtx0 - vtx1) >= + (vtx1 - tx) * (vty0 - vty1)) == yflag1) { inside_flag[i] ^= 1; } } @@ -260,11 +253,6 @@ point_in_path_impl(const void* const points_, const size_t s0, exit: free(yflag0); - free(yflag1); - free(vtx0); - free(vty0); - free(vtx1); - free(vty1); } inline void From abb1dc94dd2f558d9558ba29972326b0ef0c5ba9 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 9 Mar 2012 15:07:49 -0500 Subject: [PATCH 5/5] Add missing DECREF --- src/_path.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_path.cpp b/src/_path.cpp index d9171fd8fe16..4a39788fd1eb 100644 --- a/src/_path.cpp +++ b/src/_path.cpp @@ -376,6 +376,8 @@ _path_module::points_in_path(const Py::Tuple& args) PyArray_STRIDE(points_array, 1), n, r, path, trans, (npy_bool *)PyArray_DATA(result)); + Py_DECREF(points_array); + return Py::Object(result, true);; }