aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/matplotlib/py2/src/_path_wrapper.cpp
diff options
context:
space:
mode:
authorshumkovnd <shumkovnd@yandex-team.com>2023-11-10 14:39:34 +0300
committershumkovnd <shumkovnd@yandex-team.com>2023-11-10 16:42:24 +0300
commit77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch)
treec51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/matplotlib/py2/src/_path_wrapper.cpp
parentdd6d20cadb65582270ac23f4b3b14ae189704b9d (diff)
downloadydb-77eb2d3fdcec5c978c64e025ced2764c57c00285.tar.gz
KIKIMR-19287: add task_stats_drawing script
Diffstat (limited to 'contrib/python/matplotlib/py2/src/_path_wrapper.cpp')
-rw-r--r--contrib/python/matplotlib/py2/src/_path_wrapper.cpp900
1 files changed, 900 insertions, 0 deletions
diff --git a/contrib/python/matplotlib/py2/src/_path_wrapper.cpp b/contrib/python/matplotlib/py2/src/_path_wrapper.cpp
new file mode 100644
index 0000000000..08a595e7c4
--- /dev/null
+++ b/contrib/python/matplotlib/py2/src/_path_wrapper.cpp
@@ -0,0 +1,900 @@
+#include "numpy_cpp.h"
+
+#include "_path.h"
+
+#include "py_converters.h"
+#include "py_adaptors.h"
+
+PyObject *convert_polygon_vector(std::vector<Polygon> &polygons)
+{
+ PyObject *pyresult = PyList_New(polygons.size());
+
+ for (size_t i = 0; i < polygons.size(); ++i) {
+ Polygon poly = polygons[i];
+ npy_intp dims[2];
+ dims[1] = 2;
+
+ dims[0] = (npy_intp)poly.size();
+
+ numpy::array_view<double, 2> subresult(dims);
+ memcpy(subresult.data(), &poly[0], sizeof(double) * poly.size() * 2);
+
+ if (PyList_SetItem(pyresult, i, subresult.pyobj())) {
+ Py_DECREF(pyresult);
+ return NULL;
+ }
+ }
+
+ return pyresult;
+}
+
+const char *Py_point_in_path__doc__ = "point_in_path(x, y, radius, path, trans)";
+
+static PyObject *Py_point_in_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ double x, y, r;
+ py::PathIterator path;
+ agg::trans_affine trans;
+ bool result;
+
+ if (!PyArg_ParseTuple(args,
+ "dddO&O&:point_in_path",
+ &x,
+ &y,
+ &r,
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans)) {
+ return NULL;
+ }
+
+ CALL_CPP("point_in_path", (result = point_in_path(x, y, r, path, trans)));
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+const char *Py_points_in_path__doc__ = "points_in_path(points, radius, path, trans)";
+
+static PyObject *Py_points_in_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ numpy::array_view<const double, 2> points;
+ double r;
+ py::PathIterator path;
+ agg::trans_affine trans;
+
+ if (!PyArg_ParseTuple(args,
+ "O&dO&O&:points_in_path",
+ &convert_points,
+ &points,
+ &r,
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans)) {
+ return NULL;
+ }
+
+ npy_intp dims[] = { (npy_intp)points.size() };
+ numpy::array_view<uint8_t, 1> results(dims);
+
+ CALL_CPP("points_in_path", (points_in_path(points, r, path, trans, results)));
+
+ return results.pyobj();
+}
+
+const char *Py_point_on_path__doc__ = "point_on_path(x, y, radius, path, trans)";
+
+static PyObject *Py_point_on_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ double x, y, r;
+ py::PathIterator path;
+ agg::trans_affine trans;
+ bool result;
+
+ if (!PyArg_ParseTuple(args,
+ "dddO&O&:point_on_path",
+ &x,
+ &y,
+ &r,
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans)) {
+ return NULL;
+ }
+
+ CALL_CPP("point_on_path", (result = point_on_path(x, y, r, path, trans)));
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+const char *Py_points_on_path__doc__ = "points_on_path(points, radius, path, trans)";
+
+static PyObject *Py_points_on_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ numpy::array_view<const double, 2> points;
+ double r;
+ py::PathIterator path;
+ agg::trans_affine trans;
+
+ if (!PyArg_ParseTuple(args,
+ "O&dO&O&:points_on_path",
+ &convert_points,
+ &points,
+ &r,
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans)) {
+ return NULL;
+ }
+
+ npy_intp dims[] = { (npy_intp)points.size() };
+ numpy::array_view<uint8_t, 1> results(dims);
+
+ CALL_CPP("points_on_path", (points_on_path(points, r, path, trans, results)));
+
+ return results.pyobj();
+}
+
+const char *Py_get_path_extents__doc__ = "get_path_extents(path, trans)";
+
+static PyObject *Py_get_path_extents(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::trans_affine trans;
+
+ if (!PyArg_ParseTuple(
+ args, "O&O&:get_path_extents", &convert_path, &path, &convert_trans_affine, &trans)) {
+ return NULL;
+ }
+
+ extent_limits e;
+
+ CALL_CPP("get_path_extents", (reset_limits(e)));
+ CALL_CPP("get_path_extents", (update_path_extents(path, trans, e)));
+
+ npy_intp dims[] = { 2, 2 };
+ numpy::array_view<double, 2> extents(dims);
+ extents(0, 0) = e.x0;
+ extents(0, 1) = e.y0;
+ extents(1, 0) = e.x1;
+ extents(1, 1) = e.y1;
+
+ return extents.pyobj();
+}
+
+const char *Py_update_path_extents__doc__ =
+ "update_path_extents(path, trans, rect, minpos, ignore)";
+
+static PyObject *Py_update_path_extents(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::trans_affine trans;
+ agg::rect_d rect;
+ numpy::array_view<double, 1> minpos;
+ int ignore;
+ int changed;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&O&O&i:update_path_extents",
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans,
+ &convert_rect,
+ &rect,
+ &minpos.converter,
+ &minpos,
+ &ignore)) {
+ return NULL;
+ }
+
+ if (minpos.dim(0) != 2) {
+ PyErr_Format(PyExc_ValueError,
+ "minpos must be of length 2, got %" NPY_INTP_FMT,
+ minpos.dim(0));
+ return NULL;
+ }
+
+ extent_limits e;
+
+ if (ignore) {
+ CALL_CPP("update_path_extents", reset_limits(e));
+ } else {
+ if (rect.x1 > rect.x2) {
+ e.x0 = std::numeric_limits<double>::infinity();
+ e.x1 = -std::numeric_limits<double>::infinity();
+ } else {
+ e.x0 = rect.x1;
+ e.x1 = rect.x2;
+ }
+ if (rect.y1 > rect.y2) {
+ e.y0 = std::numeric_limits<double>::infinity();
+ e.y1 = -std::numeric_limits<double>::infinity();
+ } else {
+ e.y0 = rect.y1;
+ e.y1 = rect.y2;
+ }
+ e.xm = minpos(0);
+ e.ym = minpos(1);
+ }
+
+ CALL_CPP("update_path_extents", (update_path_extents(path, trans, e)));
+
+ changed = (e.x0 != rect.x1 || e.y0 != rect.y1 || e.x1 != rect.x2 || e.y1 != rect.y2 ||
+ e.xm != minpos(0) || e.ym != minpos(1));
+
+ npy_intp extentsdims[] = { 2, 2 };
+ numpy::array_view<double, 2> outextents(extentsdims);
+ outextents(0, 0) = e.x0;
+ outextents(0, 1) = e.y0;
+ outextents(1, 0) = e.x1;
+ outextents(1, 1) = e.y1;
+
+ npy_intp minposdims[] = { 2 };
+ numpy::array_view<double, 1> outminpos(minposdims);
+ outminpos(0) = e.xm;
+ outminpos(1) = e.ym;
+
+ return Py_BuildValue(
+ "NNi", outextents.pyobj(), outminpos.pyobj(), changed);
+}
+
+const char *Py_get_path_collection_extents__doc__ = "get_path_collection_extents(";
+
+static PyObject *Py_get_path_collection_extents(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ agg::trans_affine master_transform;
+ PyObject *pathsobj;
+ numpy::array_view<const double, 3> transforms;
+ numpy::array_view<const double, 2> offsets;
+ agg::trans_affine offset_trans;
+ extent_limits e;
+
+ if (!PyArg_ParseTuple(args,
+ "O&OO&O&O&:get_path_collection_extents",
+ &convert_trans_affine,
+ &master_transform,
+ &pathsobj,
+ &convert_transforms,
+ &transforms,
+ &convert_points,
+ &offsets,
+ &convert_trans_affine,
+ &offset_trans)) {
+ return NULL;
+ }
+
+ try
+ {
+ py::PathGenerator paths(pathsobj);
+
+ CALL_CPP("get_path_collection_extents",
+ (get_path_collection_extents(
+ master_transform, paths, transforms, offsets, offset_trans, e)));
+ }
+ catch (const py::exception &)
+ {
+ return NULL;
+ }
+
+ npy_intp dims[] = { 2, 2 };
+ numpy::array_view<double, 2> extents(dims);
+ extents(0, 0) = e.x0;
+ extents(0, 1) = e.y0;
+ extents(1, 0) = e.x1;
+ extents(1, 1) = e.y1;
+
+ return extents.pyobj();
+}
+
+const char *Py_point_in_path_collection__doc__ =
+ "point_in_path_collection(x, y, radius, master_transform, paths, transforms, offsets, "
+ "offset_trans, filled, offset_position)";
+
+static PyObject *Py_point_in_path_collection(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ double x, y, radius;
+ agg::trans_affine master_transform;
+ PyObject *pathsobj;
+ numpy::array_view<const double, 3> transforms;
+ numpy::array_view<const double, 2> offsets;
+ agg::trans_affine offset_trans;
+ int filled;
+ e_offset_position offset_position;
+ std::vector<int> result;
+
+ if (!PyArg_ParseTuple(args,
+ "dddO&OO&O&O&iO&:point_in_path_collection",
+ &x,
+ &y,
+ &radius,
+ &convert_trans_affine,
+ &master_transform,
+ &pathsobj,
+ &convert_transforms,
+ &transforms,
+ &convert_points,
+ &offsets,
+ &convert_trans_affine,
+ &offset_trans,
+ &filled,
+ &convert_offset_position,
+ &offset_position)) {
+ return NULL;
+ }
+
+ try
+ {
+ py::PathGenerator paths(pathsobj);
+
+ CALL_CPP("point_in_path_collection",
+ (point_in_path_collection(x,
+ y,
+ radius,
+ master_transform,
+ paths,
+ transforms,
+ offsets,
+ offset_trans,
+ filled,
+ offset_position,
+ result)));
+ }
+ catch (const py::exception &)
+ {
+ return NULL;
+ }
+
+ npy_intp dims[] = {(npy_intp)result.size() };
+ numpy::array_view<int, 1> pyresult(dims);
+ if (result.size() > 0) {
+ memcpy(pyresult.data(), &result[0], result.size() * sizeof(int));
+ }
+ return pyresult.pyobj();
+}
+
+const char *Py_path_in_path__doc__ = "path_in_path(path_a, trans_a, path_b, trans_b)";
+
+static PyObject *Py_path_in_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator a;
+ agg::trans_affine atrans;
+ py::PathIterator b;
+ agg::trans_affine btrans;
+ bool result;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&O&O&:path_in_path",
+ &convert_path,
+ &a,
+ &convert_trans_affine,
+ &atrans,
+ &convert_path,
+ &b,
+ &convert_trans_affine,
+ &btrans)) {
+ return NULL;
+ }
+
+ CALL_CPP("path_in_path", (result = path_in_path(a, atrans, b, btrans)));
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+const char *Py_clip_path_to_rect__doc__ = "clip_path_to_rect(path, rect, inside)";
+
+static PyObject *Py_clip_path_to_rect(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::rect_d rect;
+ int inside;
+ std::vector<Polygon> result;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&i:clip_path_to_rect",
+ &convert_path,
+ &path,
+ &convert_rect,
+ &rect,
+ &inside)) {
+ return NULL;
+ }
+
+ CALL_CPP("clip_path_to_rect", (clip_path_to_rect(path, rect, inside, result)));
+
+ return convert_polygon_vector(result);
+}
+
+const char *Py_affine_transform__doc__ = "affine_transform(points, trans)";
+
+static PyObject *Py_affine_transform(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *vertices_obj;
+ agg::trans_affine trans;
+
+ if (!PyArg_ParseTuple(args,
+ "OO&:affine_transform",
+ &vertices_obj,
+ &convert_trans_affine,
+ &trans)) {
+ return NULL;
+ }
+
+ try {
+ numpy::array_view<double, 2> vertices(vertices_obj);
+ npy_intp dims[] = { (npy_intp)vertices.size(), 2 };
+ numpy::array_view<double, 2> result(dims);
+ CALL_CPP("affine_transform", (affine_transform_2d(vertices, trans, result)));
+ return result.pyobj();
+ } catch (py::exception &) {
+ PyErr_Clear();
+ try {
+ numpy::array_view<double, 1> vertices(vertices_obj);
+ npy_intp dims[] = { (npy_intp)vertices.size() };
+ numpy::array_view<double, 1> result(dims);
+ CALL_CPP("affine_transform", (affine_transform_1d(vertices, trans, result)));
+ return result.pyobj();
+ } catch (py::exception &) {
+ return NULL;
+ }
+ }
+}
+
+const char *Py_count_bboxes_overlapping_bbox__doc__ = "count_bboxes_overlapping_bbox(bbox, bboxes)";
+
+static PyObject *Py_count_bboxes_overlapping_bbox(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ agg::rect_d bbox;
+ numpy::array_view<const double, 3> bboxes;
+ int result;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&:count_bboxes_overlapping_bbox",
+ &convert_rect,
+ &bbox,
+ &convert_bboxes,
+ &bboxes)) {
+ return NULL;
+ }
+
+ CALL_CPP("count_bboxes_overlapping_bbox",
+ (result = count_bboxes_overlapping_bbox(bbox, bboxes)));
+
+ return PyLong_FromLong(result);
+}
+
+const char *Py_path_intersects_path__doc__ = "path_intersects_path(path1, path2, filled=False)";
+
+static PyObject *Py_path_intersects_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator p1;
+ py::PathIterator p2;
+ agg::trans_affine t1;
+ agg::trans_affine t2;
+ int filled = 0;
+ const char *names[] = { "p1", "p2", "filled", NULL };
+ bool result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwds,
+ "O&O&i:path_intersects_path",
+ (char **)names,
+ &convert_path,
+ &p1,
+ &convert_path,
+ &p2,
+ &filled)) {
+ return NULL;
+ }
+
+ CALL_CPP("path_intersects_path", (result = path_intersects_path(p1, p2)));
+ if (filled) {
+ if (!result) {
+ CALL_CPP("path_intersects_path",
+ (result = path_in_path(p1, t1, p2, t2)));
+ }
+ if (!result) {
+ CALL_CPP("path_intersects_path",
+ (result = path_in_path(p2, t1, p1, t2)));
+ }
+ }
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+const char *Py_path_intersects_rectangle__doc__ = "path_intersects_rectangle(path, rect_x1, rect_y1, rect_x2, rect_y2, filled=False)";
+
+static PyObject *Py_path_intersects_rectangle(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ double rect_x1, rect_y1, rect_x2, rect_y2;
+ int filled = 0;
+ const char *names[] = { "path", "rect_x1", "rect_y1", "rect_x2", "rect_y2", "filled", NULL };
+ bool result;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwds,
+ "O&dddd|i:path_intersects_rectangle",
+ (char **)names,
+ &convert_path,
+ &path,
+ &rect_x1,
+ &rect_y1,
+ &rect_x2,
+ &rect_y2,
+ &filled)) {
+ return NULL;
+ }
+
+ CALL_CPP("path_intersects_rectangle", (result = path_intersects_rectangle(path, rect_x1, rect_y1, rect_x2, rect_y2, filled)));
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+const char *Py_convert_path_to_polygons__doc__ =
+ "convert_path_to_polygons(path, trans, width=0, height=0)";
+
+static PyObject *Py_convert_path_to_polygons(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::trans_affine trans;
+ double width = 0.0, height = 0.0;
+ int closed_only = 1;
+ std::vector<Polygon> result;
+ const char *names[] = { "path", "transform", "width", "height", "closed_only", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwds,
+ "O&O&|ddi:convert_path_to_polygons",
+ (char **)names,
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans,
+ &width,
+ &height,
+ &closed_only)) {
+ return NULL;
+ }
+
+ CALL_CPP("convert_path_to_polygons",
+ (convert_path_to_polygons(path, trans, width, height, closed_only, result)));
+
+ return convert_polygon_vector(result);
+}
+
+const char *Py_cleanup_path__doc__ =
+ "cleanup_path(path, trans, remove_nans, clip_rect, snap_mode, stroke_width, simplify, "
+ "return_curves, sketch)";
+
+static PyObject *Py_cleanup_path(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::trans_affine trans;
+ int remove_nans;
+ agg::rect_d clip_rect;
+ e_snap_mode snap_mode;
+ double stroke_width;
+ PyObject *simplifyobj;
+ bool simplify = false;
+ int return_curves;
+ SketchParams sketch;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&iO&O&dOiO&:cleanup_path",
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans,
+ &remove_nans,
+ &convert_rect,
+ &clip_rect,
+ &convert_snap,
+ &snap_mode,
+ &stroke_width,
+ &simplifyobj,
+ &return_curves,
+ &convert_sketch_params,
+ &sketch)) {
+ return NULL;
+ }
+
+ if (simplifyobj == Py_None) {
+ simplify = path.should_simplify();
+ } else if (PyObject_IsTrue(simplifyobj)) {
+ simplify = true;
+ }
+
+ bool do_clip = (clip_rect.x1 < clip_rect.x2 && clip_rect.y1 < clip_rect.y2);
+
+ std::vector<double> vertices;
+ std::vector<npy_uint8> codes;
+
+ CALL_CPP("cleanup_path",
+ (cleanup_path(path,
+ trans,
+ remove_nans,
+ do_clip,
+ clip_rect,
+ snap_mode,
+ stroke_width,
+ simplify,
+ return_curves,
+ sketch,
+ vertices,
+ codes)));
+
+ size_t length = codes.size();
+
+ npy_intp vertices_dims[] = {(npy_intp)length, 2 };
+ numpy::array_view<double, 2> pyvertices(vertices_dims);
+
+ npy_intp codes_dims[] = {(npy_intp)length };
+ numpy::array_view<unsigned char, 1> pycodes(codes_dims);
+
+ memcpy(pyvertices.data(), &vertices[0], sizeof(double) * 2 * length);
+ memcpy(pycodes.data(), &codes[0], sizeof(unsigned char) * length);
+
+ return Py_BuildValue("NN", pyvertices.pyobj(), pycodes.pyobj());
+}
+
+const char *Py_convert_to_string__doc__ = "convert_to_string(path, trans, "
+ "clip_rect, simplify, sketch, precision, codes, postfix)";
+
+static PyObject *Py_convert_to_string(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ py::PathIterator path;
+ agg::trans_affine trans;
+ agg::rect_d cliprect;
+ PyObject *simplifyobj;
+ bool simplify = false;
+ SketchParams sketch;
+ int precision;
+ PyObject *codesobj;
+ char *codes[5];
+ int postfix;
+ char *buffer = NULL;
+ size_t buffersize;
+ PyObject *result;
+ int status;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&O&OO&iOi:convert_to_string",
+ &convert_path,
+ &path,
+ &convert_trans_affine,
+ &trans,
+ &convert_rect,
+ &cliprect,
+ &simplifyobj,
+ &convert_sketch_params,
+ &sketch,
+ &precision,
+ &codesobj,
+ &postfix)) {
+ return NULL;
+ }
+
+ if (simplifyobj == Py_None) {
+ simplify = path.should_simplify();
+ } else if (PyObject_IsTrue(simplifyobj)) {
+ simplify = true;
+ }
+
+ if (!PySequence_Check(codesobj)) {
+ return NULL;
+ }
+ if (PySequence_Size(codesobj) != 5) {
+ PyErr_SetString(
+ PyExc_ValueError,
+ "codes must be a 5-length sequence of byte strings");
+ return NULL;
+ }
+ for (int i = 0; i < 5; ++i) {
+ PyObject *item = PySequence_GetItem(codesobj, i);
+ if (item == NULL) {
+ return NULL;
+ }
+ codes[i] = PyBytes_AsString(item);
+ if (codes[i] == NULL) {
+ return NULL;
+ }
+ }
+
+ CALL_CPP("convert_to_string",
+ (status = convert_to_string(
+ path, trans, cliprect, simplify, sketch,
+ precision, codes, (bool)postfix, &buffer,
+ &buffersize)));
+
+ if (status) {
+ free(buffer);
+ if (status == 1) {
+ PyErr_SetString(PyExc_MemoryError, "Memory error");
+ } else if (status == 2) {
+ PyErr_SetString(PyExc_ValueError, "Malformed path codes");
+ }
+ return NULL;
+ }
+
+ if (buffersize == 0) {
+ result = PyBytes_FromString("");
+ } else {
+ result = PyBytes_FromStringAndSize(buffer, buffersize);
+ }
+
+ free(buffer);
+
+ return result;
+}
+
+
+const char *Py_is_sorted__doc__ = "is_sorted(array)\n\n"
+ "Returns True if 1-D array is monotonically increasing, ignoring NaNs\n";
+
+static PyObject *Py_is_sorted(PyObject *self, PyObject *obj)
+{
+ npy_intp size;
+ bool result;
+
+ PyArrayObject *array = (PyArrayObject *)PyArray_FromAny(
+ obj, NULL, 1, 1, 0, NULL);
+
+ if (array == NULL) {
+ return NULL;
+ }
+
+ size = PyArray_DIM(array, 0);
+
+ if (size < 2) {
+ Py_DECREF(array);
+ Py_RETURN_TRUE;
+ }
+
+ /* Handle just the most common types here, otherwise coerce to
+ double */
+ switch(PyArray_TYPE(array)) {
+ case NPY_INT:
+ {
+ _is_sorted_int<npy_int> is_sorted;
+ result = is_sorted(array);
+ }
+ break;
+
+ case NPY_LONG:
+ {
+ _is_sorted_int<npy_long> is_sorted;
+ result = is_sorted(array);
+ }
+ break;
+
+ case NPY_LONGLONG:
+ {
+ _is_sorted_int<npy_longlong> is_sorted;
+ result = is_sorted(array);
+ }
+ break;
+
+ case NPY_FLOAT:
+ {
+ _is_sorted<npy_float> is_sorted;
+ result = is_sorted(array);
+ }
+ break;
+
+ case NPY_DOUBLE:
+ {
+ _is_sorted<npy_double> is_sorted;
+ result = is_sorted(array);
+ }
+ break;
+
+ default:
+ {
+ Py_DECREF(array);
+ array = (PyArrayObject *)PyArray_FromObject(obj, NPY_DOUBLE, 1, 1);
+
+ if (array == NULL) {
+ return NULL;
+ }
+
+ _is_sorted<npy_double> is_sorted;
+ result = is_sorted(array);
+ }
+ }
+
+ Py_DECREF(array);
+
+ if (result) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+
+extern "C" {
+
+ static PyMethodDef module_functions[] = {
+ {"point_in_path", (PyCFunction)Py_point_in_path, METH_VARARGS, Py_point_in_path__doc__},
+ {"points_in_path", (PyCFunction)Py_points_in_path, METH_VARARGS, Py_points_in_path__doc__},
+ {"point_on_path", (PyCFunction)Py_point_on_path, METH_VARARGS, Py_point_on_path__doc__},
+ {"points_on_path", (PyCFunction)Py_points_on_path, METH_VARARGS, Py_points_on_path__doc__},
+ {"get_path_extents", (PyCFunction)Py_get_path_extents, METH_VARARGS, Py_get_path_extents__doc__},
+ {"update_path_extents", (PyCFunction)Py_update_path_extents, METH_VARARGS, Py_update_path_extents__doc__},
+ {"get_path_collection_extents", (PyCFunction)Py_get_path_collection_extents, METH_VARARGS, Py_get_path_collection_extents__doc__},
+ {"point_in_path_collection", (PyCFunction)Py_point_in_path_collection, METH_VARARGS, Py_point_in_path_collection__doc__},
+ {"path_in_path", (PyCFunction)Py_path_in_path, METH_VARARGS, Py_path_in_path__doc__},
+ {"clip_path_to_rect", (PyCFunction)Py_clip_path_to_rect, METH_VARARGS, Py_clip_path_to_rect__doc__},
+ {"affine_transform", (PyCFunction)Py_affine_transform, METH_VARARGS, Py_affine_transform__doc__},
+ {"count_bboxes_overlapping_bbox", (PyCFunction)Py_count_bboxes_overlapping_bbox, METH_VARARGS, Py_count_bboxes_overlapping_bbox__doc__},
+ {"path_intersects_path", (PyCFunction)Py_path_intersects_path, METH_VARARGS|METH_KEYWORDS, Py_path_intersects_path__doc__},
+ {"path_intersects_rectangle", (PyCFunction)Py_path_intersects_rectangle, METH_VARARGS|METH_KEYWORDS, Py_path_intersects_rectangle__doc__},
+ {"convert_path_to_polygons", (PyCFunction)Py_convert_path_to_polygons, METH_VARARGS|METH_KEYWORDS, Py_convert_path_to_polygons__doc__},
+ {"cleanup_path", (PyCFunction)Py_cleanup_path, METH_VARARGS, Py_cleanup_path__doc__},
+ {"convert_to_string", (PyCFunction)Py_convert_to_string, METH_VARARGS, Py_convert_to_string__doc__},
+ {"is_sorted", (PyCFunction)Py_is_sorted, METH_O, Py_is_sorted__doc__},
+ {NULL}
+ };
+
+#if PY3K
+ static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_path",
+ NULL,
+ 0,
+ module_functions,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+#define INITERROR return NULL
+ PyMODINIT_FUNC PyInit__path(void)
+#else
+#define INITERROR return
+ PyMODINIT_FUNC init_path(void)
+#endif
+ {
+ PyObject *m;
+#if PY3K
+ m = PyModule_Create(&moduledef);
+#else
+ m = Py_InitModule3("_path", module_functions, NULL);
+#endif
+
+ if (m == NULL) {
+ INITERROR;
+ }
+
+ import_array();
+
+#if PY3K
+ return m;
+#endif
+ }
+}