diff --git a/setup.py b/setup.py index 21c9611..4fc2af9 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ setuptools.setup( name="upolygon", - version="0.1.5", + version="0.1.6", author="V7", author_email="simon@v7labs.com", description="Collection of fast polygon operations for DL", diff --git a/upolygon/simplify_polygon.c b/upolygon/simplify_polygon.c index dc1ffff..b8ea12c 100644 --- a/upolygon/simplify_polygon.c +++ b/upolygon/simplify_polygon.c @@ -6,7 +6,7 @@ "depends": [], "name": "upolygon.simplify_polygon", "sources": [ - "/Users/simedw/Projects/v7/upolygon/upolygon/simplify_polygon.pyx" + "/home/simedw/upolygon/upolygon/simplify_polygon.pyx" ] }, "module_name": "upolygon.simplify_polygon" @@ -927,6 +927,29 @@ static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *nam /* None.proto */ static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t, Py_ssize_t); +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif + /* PyObjectCall.proto */ #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); @@ -934,41 +957,128 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) #endif -/* GetItemInt.proto */ -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - -/* ObjectGetItem.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectGetMethod.proto */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); + +/* PyObjectCallMethod0.proto */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); + +/* pop.proto */ +static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); +#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ?\ + __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) +#else +#define __Pyx_PyList_Pop(L) __Pyx__PyObject_Pop(L) +#define __Pyx_PyObject_Pop(L) __Pyx__PyObject_Pop(L) +#endif + +/* UnpackUnboundCMethod.proto */ +typedef struct { + PyObject *type; + PyObject **method_name; + PyCFunction func; + PyObject *method; + int flag; +} __Pyx_CachedCFunction; + +/* CallUnboundCMethod0.proto */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CallUnboundCMethod0(cfunc, self)\ + (likely((cfunc)->func) ?\ + (likely((cfunc)->flag == METH_NOARGS) ? (*((cfunc)->func))(self, NULL) :\ + (PY_VERSION_HEX >= 0x030600B1 && likely((cfunc)->flag == METH_FASTCALL) ?\ + (PY_VERSION_HEX >= 0x030700A0 ?\ + (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0) :\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL)) :\ + (PY_VERSION_HEX >= 0x030700A0 && (cfunc)->flag == (METH_FASTCALL | METH_KEYWORDS) ?\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL) :\ + (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ? ((*(PyCFunctionWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, __pyx_empty_tuple, NULL)) :\ + ((cfunc)->flag == METH_VARARGS ? (*((cfunc)->func))(self, __pyx_empty_tuple) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)))))) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)) +#else +#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) +#endif + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* IterFinish.proto */ +static CYTHON_INLINE int __Pyx_IterFinish(void); + +/* UnpackItemEndCheck.proto */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); + +/* ListAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { + Py_INCREF(x); + PyList_SET_ITEM(list, len, x); + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} #else -#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) #endif -/* PyIntBinop.proto */ -#if !CYTHON_COMPILING_IN_PYPY -static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); +/* SetItemInt.proto */ +#define __Pyx_SetItemInt(o, i, v, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_SetItemInt_Fast(o, (Py_ssize_t)i, v, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list assignment index out of range"), -1) :\ + __Pyx_SetItemInt_Generic(o, to_py_func(i), v))) +static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v); +static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, + int is_list, int wraparound, int boundscheck); + +/* ListCompAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len)) { + Py_INCREF(x); + PyList_SET_ITEM(list, len, x); + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} #else -#define __Pyx_PyInt_AddObjC(op1, op2, intval, inplace, zerodivision_check)\ - (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2)) +#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) #endif /* PyDictVersioning.proto */ @@ -1018,68 +1128,6 @@ static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_ve static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); #endif -/* SliceTupleAndList.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); -static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); -#else -#define __Pyx_PyList_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) -#define __Pyx_PyTuple_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif - -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* SliceObject.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( - PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, - PyObject** py_start, PyObject** py_stop, PyObject** py_slice, - int has_cstart, int has_cstop, int wraparound); - -/* ListCompAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len)) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - __Pyx_SET_SIZE(list, len + 1); - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) -#endif - /* PyThreadStateGet.proto */ #if CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; @@ -1187,18 +1235,22 @@ int __pyx_module_is_main_upolygon__simplify_polygon = 0; /* Implementation of 'upolygon.simplify_polygon' */ static PyObject *__pyx_builtin_range; static const char __pyx_k_i[] = "i"; -static const char __pyx_k_end[] = "end"; +static const char __pyx_k_pop[] = "pop"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_path[] = "path"; -static const char __pyx_k_res1[] = "res1"; -static const char __pyx_k_res2[] = "res2"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_index[] = "index"; static const char __pyx_k_paths[] = "paths"; static const char __pyx_k_range[] = "range"; +static const char __pyx_k_stack[] = "stack"; +static const char __pyx_k_length[] = "length"; +static const char __pyx_k_result[] = "result"; +static const char __pyx_k_deleted[] = "deleted"; static const char __pyx_k_epsilon[] = "epsilon"; static const char __pyx_k_distance[] = "distance"; +static const char __pyx_k_endIndex[] = "endIndex"; +static const char __pyx_k_startIndex[] = "startIndex"; static const char __pyx_k_max_distance[] = "max_distance"; static const char __pyx_k_simplify_polygon[] = "simplify_polygon"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; @@ -1206,28 +1258,31 @@ static const char __pyx_k_simplify_single_polygon[] = "simplify_single_polygon"; static const char __pyx_k_upolygon_simplify_polygon[] = "upolygon.simplify_polygon"; static const char __pyx_k_upolygon_simplify_polygon_pyx[] = "upolygon/simplify_polygon.pyx"; static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_deleted; static PyObject *__pyx_n_s_distance; -static PyObject *__pyx_n_s_end; +static PyObject *__pyx_n_s_endIndex; static PyObject *__pyx_n_s_epsilon; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_index; +static PyObject *__pyx_n_s_length; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_max_distance; static PyObject *__pyx_n_s_name; static PyObject *__pyx_n_s_path; static PyObject *__pyx_n_s_paths; +static PyObject *__pyx_n_s_pop; static PyObject *__pyx_n_s_range; -static PyObject *__pyx_n_s_res1; -static PyObject *__pyx_n_s_res2; +static PyObject *__pyx_n_s_result; static PyObject *__pyx_n_s_simplify_polygon; static PyObject *__pyx_n_s_simplify_single_polygon; +static PyObject *__pyx_n_s_stack; +static PyObject *__pyx_n_s_startIndex; static PyObject *__pyx_n_s_test; static PyObject *__pyx_n_s_upolygon_simplify_polygon; static PyObject *__pyx_kp_s_upolygon_simplify_polygon_pyx; static PyObject *__pyx_pf_8upolygon_16simplify_polygon_simplify_single_polygon(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_path, float __pyx_v_epsilon); /* proto */ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_paths, float __pyx_v_epsilon); /* proto */ -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_2; +static __Pyx_CachedCFunction __pyx_umethod_PyList_Type_pop = {0, &__pyx_n_s_pop, 0, 0, 0}; static PyObject *__pyx_tuple_; static PyObject *__pyx_tuple__3; static PyObject *__pyx_codeobj__2; @@ -1338,8 +1393,8 @@ static PyObject *__pyx_f_8upolygon_16simplify_polygon_perpendicular_distance(flo * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_single_polygon(list path, float epsilon): # <<<<<<<<<<<<<< - * if len(path) <= 1: - * return path + * # Note that we are using an iterative version of this algorithm + * # instread of the classical recursive to prevent reaching python's */ /* Python wrapper */ @@ -1413,532 +1468,591 @@ static PyObject *__pyx_pw_8upolygon_16simplify_polygon_1simplify_single_polygon( } static PyObject *__pyx_pf_8upolygon_16simplify_polygon_simplify_single_polygon(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_path, float __pyx_v_epsilon) { + int __pyx_v_length; + int __pyx_v_startIndex; + int __pyx_v_endIndex; float __pyx_v_max_distance; int __pyx_v_index; - int __pyx_v_end; - PyObject *__pyx_v_i = NULL; + int __pyx_v_i; + PyObject *__pyx_v_deleted = NULL; + PyObject *__pyx_v_stack = NULL; PyObject *__pyx_v_distance = NULL; - PyObject *__pyx_v_res1 = NULL; - PyObject *__pyx_v_res2 = NULL; + PyObject *__pyx_v_result = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations Py_ssize_t __pyx_t_1; - int __pyx_t_2; + PyObject *__pyx_t_2 = NULL; PyObject *__pyx_t_3 = NULL; PyObject *__pyx_t_4 = NULL; - PyObject *(*__pyx_t_5)(PyObject *); + int __pyx_t_5; PyObject *__pyx_t_6 = NULL; - float __pyx_t_7; - float __pyx_t_8; - float __pyx_t_9; - float __pyx_t_10; + PyObject *(*__pyx_t_7)(PyObject *); + int __pyx_t_8; + int __pyx_t_9; + int __pyx_t_10; long __pyx_t_11; float __pyx_t_12; float __pyx_t_13; - int __pyx_t_14; - PyObject *__pyx_t_15 = NULL; - PyObject *__pyx_t_16 = NULL; - PyObject *__pyx_t_17 = NULL; - long __pyx_t_18; + float __pyx_t_14; + float __pyx_t_15; + float __pyx_t_16; + float __pyx_t_17; + int __pyx_t_18; + long __pyx_t_19; + int __pyx_t_20; int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; __Pyx_RefNannySetupContext("simplify_single_polygon", 0); - /* "upolygon/simplify_polygon.pyx":17 - * @cython.nonecheck(False) - * def simplify_single_polygon(list path, float epsilon): - * if len(path) <= 1: # <<<<<<<<<<<<<< - * return path - * cdef float max_distance = 0 + /* "upolygon/simplify_polygon.pyx":20 + * # instread of the classical recursive to prevent reaching python's + * # max recursion. + * cdef int length = len(path) // 2 # <<<<<<<<<<<<<< + * cdef int startIndex = 0 + * cdef int endIndex = length */ if (unlikely(__pyx_v_path == Py_None)) { PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 17, __pyx_L1_error) + __PYX_ERR(0, 20, __pyx_L1_error) } - __pyx_t_1 = PyList_GET_SIZE(__pyx_v_path); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 17, __pyx_L1_error) - __pyx_t_2 = ((__pyx_t_1 <= 1) != 0); - if (__pyx_t_2) { - - /* "upolygon/simplify_polygon.pyx":18 - * def simplify_single_polygon(list path, float epsilon): - * if len(path) <= 1: - * return path # <<<<<<<<<<<<<< + __pyx_t_1 = PyList_GET_SIZE(__pyx_v_path); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 20, __pyx_L1_error) + __pyx_v_length = __Pyx_div_Py_ssize_t(__pyx_t_1, 2); + + /* "upolygon/simplify_polygon.pyx":21 + * # max recursion. + * cdef int length = len(path) // 2 + * cdef int startIndex = 0 # <<<<<<<<<<<<<< + * cdef int endIndex = length * cdef float max_distance = 0 - * cdef int index = 0 */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_path); - __pyx_r = __pyx_v_path; - goto __pyx_L0; + __pyx_v_startIndex = 0; - /* "upolygon/simplify_polygon.pyx":17 - * @cython.nonecheck(False) - * def simplify_single_polygon(list path, float epsilon): - * if len(path) <= 1: # <<<<<<<<<<<<<< - * return path + /* "upolygon/simplify_polygon.pyx":22 + * cdef int length = len(path) // 2 + * cdef int startIndex = 0 + * cdef int endIndex = length # <<<<<<<<<<<<<< * cdef float max_distance = 0 + * cdef int index = 0 */ - } + __pyx_v_endIndex = __pyx_v_length; - /* "upolygon/simplify_polygon.pyx":19 - * if len(path) <= 1: - * return path + /* "upolygon/simplify_polygon.pyx":23 + * cdef int startIndex = 0 + * cdef int endIndex = length * cdef float max_distance = 0 # <<<<<<<<<<<<<< * cdef int index = 0 - * cdef int end = len(path) // 2 - 1 + * cdef int i */ __pyx_v_max_distance = 0.0; - /* "upolygon/simplify_polygon.pyx":20 - * return path + /* "upolygon/simplify_polygon.pyx":24 + * cdef int endIndex = length * cdef float max_distance = 0 * cdef int index = 0 # <<<<<<<<<<<<<< - * cdef int end = len(path) // 2 - 1 - * for i in range(1, end): + * cdef int i + * deleted = [False] * length */ __pyx_v_index = 0; - /* "upolygon/simplify_polygon.pyx":21 - * cdef float max_distance = 0 + /* "upolygon/simplify_polygon.pyx":26 * cdef int index = 0 - * cdef int end = len(path) // 2 - 1 # <<<<<<<<<<<<<< - * for i in range(1, end): - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) + * cdef int i + * deleted = [False] * length # <<<<<<<<<<<<<< + * stack = [(startIndex,endIndex)] + * while stack: */ - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 21, __pyx_L1_error) + __pyx_t_2 = PyList_New(1 * ((__pyx_v_length<0) ? 0:__pyx_v_length)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 26, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + { Py_ssize_t __pyx_temp; + for (__pyx_temp=0; __pyx_temp < __pyx_v_length; __pyx_temp++) { + __Pyx_INCREF(Py_False); + __Pyx_GIVEREF(Py_False); + PyList_SET_ITEM(__pyx_t_2, __pyx_temp, Py_False); + } } - __pyx_t_1 = PyList_GET_SIZE(__pyx_v_path); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 21, __pyx_L1_error) - __pyx_v_end = (__Pyx_div_Py_ssize_t(__pyx_t_1, 2) - 1); + __pyx_v_deleted = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; - /* "upolygon/simplify_polygon.pyx":22 - * cdef int index = 0 - * cdef int end = len(path) // 2 - 1 - * for i in range(1, end): # <<<<<<<<<<<<<< - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - * if distance > max_distance: + /* "upolygon/simplify_polygon.pyx":27 + * cdef int i + * deleted = [False] * length + * stack = [(startIndex,endIndex)] # <<<<<<<<<<<<<< + * while stack: + * startIndex, endIndex = stack.pop() */ - __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_end); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_startIndex); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_endIndex); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 27, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 27, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_int_1); - __Pyx_GIVEREF(__pyx_int_1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_int_1); + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); + __pyx_t_2 = 0; __pyx_t_3 = 0; - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 27, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) { - __pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_1 = 0; - __pyx_t_5 = NULL; - } else { - __pyx_t_1 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 22, __pyx_L1_error) - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - for (;;) { - if (likely(!__pyx_t_5)) { - if (likely(PyList_CheckExact(__pyx_t_4))) { - if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 22, __pyx_L1_error) - #else - __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif + __Pyx_GIVEREF(__pyx_t_4); + PyList_SET_ITEM(__pyx_t_3, 0, __pyx_t_4); + __pyx_t_4 = 0; + __pyx_v_stack = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "upolygon/simplify_polygon.pyx":28 + * deleted = [False] * length + * stack = [(startIndex,endIndex)] + * while stack: # <<<<<<<<<<<<<< + * startIndex, endIndex = stack.pop() + * if startIndex == endIndex: + */ + while (1) { + __pyx_t_5 = (PyList_GET_SIZE(__pyx_v_stack) != 0); + if (!__pyx_t_5) break; + + /* "upolygon/simplify_polygon.pyx":29 + * stack = [(startIndex,endIndex)] + * while stack: + * startIndex, endIndex = stack.pop() # <<<<<<<<<<<<<< + * if startIndex == endIndex: + * continue + */ + __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 29, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); } else { - if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 22, __pyx_L1_error) - #else - __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_2 = PyList_GET_ITEM(sequence, 1); } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_2); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_2 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } else { - __pyx_t_3 = __pyx_t_5(__pyx_t_4); - if (unlikely(!__pyx_t_3)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(0, 22, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_3); + Py_ssize_t index = -1; + __pyx_t_6 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_7 = Py_TYPE(__pyx_t_6)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_4)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + index = 1; __pyx_t_2 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_2); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 2) < 0) __PYX_ERR(0, 29, __pyx_L1_error) + __pyx_t_7 = NULL; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L6_unpacking_done; + __pyx_L5_unpacking_failed:; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __pyx_t_7 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 29, __pyx_L1_error) + __pyx_L6_unpacking_done:; } - __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_3); - __pyx_t_3 = 0; - - /* "upolygon/simplify_polygon.pyx":23 - * cdef int end = len(path) // 2 - 1 - * for i in range(1, end): - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) # <<<<<<<<<<<<<< - * if distance > max_distance: - * max_distance = distance + __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_4); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_9 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_startIndex = __pyx_t_8; + __pyx_v_endIndex = __pyx_t_9; + + /* "upolygon/simplify_polygon.pyx":30 + * while stack: + * startIndex, endIndex = stack.pop() + * if startIndex == endIndex: # <<<<<<<<<<<<<< + * continue + * max_distance = 0 */ - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_3 = PyNumber_Multiply(__pyx_int_2, __pyx_v_i); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_path, __pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_7 = __pyx_PyFloat_AsFloat(__pyx_t_6); if (unlikely((__pyx_t_7 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_6 = PyNumber_Multiply(__pyx_int_2, __pyx_v_i); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_3 = __Pyx_PyInt_AddObjC(__pyx_t_6, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_path, __pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_8 = __pyx_PyFloat_AsFloat(__pyx_t_6); if (unlikely((__pyx_t_8 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_9 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, 0)); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_10 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, 1)); if (unlikely((__pyx_t_10 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_11 = (2 * __pyx_v_end); - __pyx_t_12 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_12 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 23, __pyx_L1_error) - } - __pyx_t_11 = ((2 * __pyx_v_end) + 1); - __pyx_t_13 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_13 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error) - __pyx_t_6 = __pyx_f_8upolygon_16simplify_polygon_perpendicular_distance(__pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10, __pyx_t_12, __pyx_t_13); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_XDECREF_SET(__pyx_v_distance, __pyx_t_6); - __pyx_t_6 = 0; - - /* "upolygon/simplify_polygon.pyx":24 - * for i in range(1, end): - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - * if distance > max_distance: # <<<<<<<<<<<<<< - * max_distance = distance - * index = i + __pyx_t_5 = ((__pyx_v_startIndex == __pyx_v_endIndex) != 0); + if (__pyx_t_5) { + + /* "upolygon/simplify_polygon.pyx":31 + * startIndex, endIndex = stack.pop() + * if startIndex == endIndex: + * continue # <<<<<<<<<<<<<< + * max_distance = 0 + * for i in range(startIndex,endIndex): */ - __pyx_t_6 = PyFloat_FromDouble(__pyx_v_max_distance); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_3 = PyObject_RichCompare(__pyx_v_distance, __pyx_t_6, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 24, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "upolygon/simplify_polygon.pyx":25 - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - * if distance > max_distance: - * max_distance = distance # <<<<<<<<<<<<<< - * index = i - * + goto __pyx_L3_continue; + + /* "upolygon/simplify_polygon.pyx":30 + * while stack: + * startIndex, endIndex = stack.pop() + * if startIndex == endIndex: # <<<<<<<<<<<<<< + * continue + * max_distance = 0 */ - __pyx_t_13 = __pyx_PyFloat_AsFloat(__pyx_v_distance); if (unlikely((__pyx_t_13 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 25, __pyx_L1_error) - __pyx_v_max_distance = __pyx_t_13; + } - /* "upolygon/simplify_polygon.pyx":26 - * if distance > max_distance: - * max_distance = distance - * index = i # <<<<<<<<<<<<<< - * - * if max_distance > epsilon: + /* "upolygon/simplify_polygon.pyx":32 + * if startIndex == endIndex: + * continue + * max_distance = 0 # <<<<<<<<<<<<<< + * for i in range(startIndex,endIndex): + * if deleted[i]: */ - __pyx_t_14 = __Pyx_PyInt_As_int(__pyx_v_i); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 26, __pyx_L1_error) - __pyx_v_index = __pyx_t_14; - - /* "upolygon/simplify_polygon.pyx":24 - * for i in range(1, end): - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - * if distance > max_distance: # <<<<<<<<<<<<<< - * max_distance = distance - * index = i + __pyx_v_max_distance = 0.0; + + /* "upolygon/simplify_polygon.pyx":33 + * continue + * max_distance = 0 + * for i in range(startIndex,endIndex): # <<<<<<<<<<<<<< + * if deleted[i]: + * continue */ - } - - /* "upolygon/simplify_polygon.pyx":22 - * cdef int index = 0 - * cdef int end = len(path) // 2 - 1 - * for i in range(1, end): # <<<<<<<<<<<<<< - * distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - * if distance > max_distance: + __pyx_t_9 = __pyx_v_endIndex; + __pyx_t_8 = __pyx_t_9; + for (__pyx_t_10 = __pyx_v_startIndex; __pyx_t_10 < __pyx_t_8; __pyx_t_10+=1) { + __pyx_v_i = __pyx_t_10; + + /* "upolygon/simplify_polygon.pyx":34 + * max_distance = 0 + * for i in range(startIndex,endIndex): + * if deleted[i]: # <<<<<<<<<<<<<< + * continue + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) */ - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "upolygon/simplify_polygon.pyx":28 - * index = i - * - * if max_distance > epsilon: # <<<<<<<<<<<<<< - * res1 = simplify_single_polygon(path[:2*index+2], epsilon) - * res2 = simplify_single_polygon(path[2*index:], epsilon) + __pyx_t_5 = __Pyx_PyObject_IsTrue(PyList_GET_ITEM(__pyx_v_deleted, __pyx_v_i)); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 34, __pyx_L1_error) + if (__pyx_t_5) { + + /* "upolygon/simplify_polygon.pyx":35 + * for i in range(startIndex,endIndex): + * if deleted[i]: + * continue # <<<<<<<<<<<<<< + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) + * if distance > max_distance: + */ + goto __pyx_L8_continue; + + /* "upolygon/simplify_polygon.pyx":34 + * max_distance = 0 + * for i in range(startIndex,endIndex): + * if deleted[i]: # <<<<<<<<<<<<<< + * continue + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) */ - __pyx_t_2 = ((__pyx_v_max_distance > __pyx_v_epsilon) != 0); - if (__pyx_t_2) { + } - /* "upolygon/simplify_polygon.pyx":29 - * - * if max_distance > epsilon: - * res1 = simplify_single_polygon(path[:2*index+2], epsilon) # <<<<<<<<<<<<<< - * res2 = simplify_single_polygon(path[2*index:], epsilon) - * return res1[0:len(res1)-2] + res2 + /* "upolygon/simplify_polygon.pyx":36 + * if deleted[i]: + * continue + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) # <<<<<<<<<<<<<< + * if distance > max_distance: + * max_distance = distance + */ + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = (2 * __pyx_v_i); + __pyx_t_12 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_12 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = ((2 * __pyx_v_i) + 1); + __pyx_t_13 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_13 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = (__pyx_v_startIndex * 2); + __pyx_t_14 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_14 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = ((__pyx_v_startIndex * 2) + 1); + __pyx_t_15 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_15 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = (2 * (__pyx_v_endIndex - 1)); + __pyx_t_16 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_16 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 36, __pyx_L1_error) + } + __pyx_t_11 = ((2 * (__pyx_v_endIndex - 1)) + 1); + __pyx_t_17 = __pyx_PyFloat_AsFloat(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); if (unlikely((__pyx_t_17 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 36, __pyx_L1_error) + __pyx_t_3 = __pyx_f_8upolygon_16simplify_polygon_perpendicular_distance(__pyx_t_12, __pyx_t_13, __pyx_t_14, __pyx_t_15, __pyx_t_16, __pyx_t_17); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 36, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_XDECREF_SET(__pyx_v_distance, __pyx_t_3); + __pyx_t_3 = 0; + + /* "upolygon/simplify_polygon.pyx":37 + * continue + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) + * if distance > max_distance: # <<<<<<<<<<<<<< + * max_distance = distance + * index = i + */ + __pyx_t_3 = PyFloat_FromDouble(__pyx_v_max_distance); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 37, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_RichCompare(__pyx_v_distance, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 37, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (__pyx_t_5) { + + /* "upolygon/simplify_polygon.pyx":38 + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) + * if distance > max_distance: + * max_distance = distance # <<<<<<<<<<<<<< + * index = i + * if max_distance > epsilon: + */ + __pyx_t_17 = __pyx_PyFloat_AsFloat(__pyx_v_distance); if (unlikely((__pyx_t_17 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L1_error) + __pyx_v_max_distance = __pyx_t_17; + + /* "upolygon/simplify_polygon.pyx":39 + * if distance > max_distance: + * max_distance = distance + * index = i # <<<<<<<<<<<<<< + * if max_distance > epsilon: + * stack.append((startIndex,index)) + */ + __pyx_v_index = __pyx_v_i; + + /* "upolygon/simplify_polygon.pyx":37 + * continue + * distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) + * if distance > max_distance: # <<<<<<<<<<<<<< + * max_distance = distance + * index = i */ - __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_simplify_single_polygon); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 29, __pyx_L1_error) - } - __pyx_t_6 = __Pyx_PyList_GetSlice(__pyx_v_path, 0, ((2 * __pyx_v_index) + 2)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_15 = PyFloat_FromDouble(__pyx_v_epsilon); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_15); - __pyx_t_16 = NULL; - __pyx_t_14 = 0; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_16)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_16); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - __pyx_t_14 = 1; } + __pyx_L8_continue:; } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_6, __pyx_t_15}; - __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_14, 2+__pyx_t_14); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_6, __pyx_t_15}; - __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_14, 2+__pyx_t_14); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0; + + /* "upolygon/simplify_polygon.pyx":40 + * max_distance = distance + * index = i + * if max_distance > epsilon: # <<<<<<<<<<<<<< + * stack.append((startIndex,index)) + * stack.append((index, endIndex)) + */ + __pyx_t_5 = ((__pyx_v_max_distance > __pyx_v_epsilon) != 0); + if (__pyx_t_5) { + + /* "upolygon/simplify_polygon.pyx":41 + * index = i + * if max_distance > epsilon: + * stack.append((startIndex,index)) # <<<<<<<<<<<<<< + * stack.append((index, endIndex)) + * else: + */ + __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_startIndex); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 41, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_index); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 41, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 41, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; - } else - #endif - { - __pyx_t_17 = PyTuple_New(2+__pyx_t_14); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 29, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_17); - if (__pyx_t_16) { - __Pyx_GIVEREF(__pyx_t_16); PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_16); __pyx_t_16 = NULL; - } - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_17, 0+__pyx_t_14, __pyx_t_6); - __Pyx_GIVEREF(__pyx_t_15); - PyTuple_SET_ITEM(__pyx_t_17, 1+__pyx_t_14, __pyx_t_15); - __pyx_t_6 = 0; - __pyx_t_15 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_17, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_2); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3); + __pyx_t_2 = 0; + __pyx_t_3 = 0; + __pyx_t_18 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_t_4); if (unlikely(__pyx_t_18 == ((int)-1))) __PYX_ERR(0, 41, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "upolygon/simplify_polygon.pyx":42 + * if max_distance > epsilon: + * stack.append((startIndex,index)) + * stack.append((index, endIndex)) # <<<<<<<<<<<<<< + * else: + * for i in range(startIndex+1,endIndex-1): + */ + __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_index); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 42, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_endIndex); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 42, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 42, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3); + __pyx_t_4 = 0; + __pyx_t_3 = 0; + __pyx_t_18 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_t_2); if (unlikely(__pyx_t_18 == ((int)-1))) __PYX_ERR(0, 42, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "upolygon/simplify_polygon.pyx":40 + * max_distance = distance + * index = i + * if max_distance > epsilon: # <<<<<<<<<<<<<< + * stack.append((startIndex,index)) + * stack.append((index, endIndex)) + */ + goto __pyx_L12; } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_res1 = __pyx_t_4; - __pyx_t_4 = 0; - /* "upolygon/simplify_polygon.pyx":30 - * if max_distance > epsilon: - * res1 = simplify_single_polygon(path[:2*index+2], epsilon) - * res2 = simplify_single_polygon(path[2*index:], epsilon) # <<<<<<<<<<<<<< - * return res1[0:len(res1)-2] + res2 - * else: + /* "upolygon/simplify_polygon.pyx":44 + * stack.append((index, endIndex)) + * else: + * for i in range(startIndex+1,endIndex-1): # <<<<<<<<<<<<<< + * deleted[i] = True + * result = [] */ - __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_simplify_single_polygon); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 30, __pyx_L1_error) - } - __pyx_t_17 = __Pyx_PyList_GetSlice(__pyx_v_path, (2 * __pyx_v_index), PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_17); - __pyx_t_15 = PyFloat_FromDouble(__pyx_v_epsilon); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_15); - __pyx_t_6 = NULL; - __pyx_t_14 = 0; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_6)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_6); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - __pyx_t_14 = 1; + /*else*/ { + __pyx_t_11 = (__pyx_v_endIndex - 1); + __pyx_t_19 = __pyx_t_11; + for (__pyx_t_9 = (__pyx_v_startIndex + 1); __pyx_t_9 < __pyx_t_19; __pyx_t_9+=1) { + __pyx_v_i = __pyx_t_9; + + /* "upolygon/simplify_polygon.pyx":45 + * else: + * for i in range(startIndex+1,endIndex-1): + * deleted[i] = True # <<<<<<<<<<<<<< + * result = [] + * for i in range(0, length): + */ + if (unlikely(__Pyx_SetItemInt(__pyx_v_deleted, __pyx_v_i, Py_True, int, 1, __Pyx_PyInt_From_int, 1, 0, 0) < 0)) __PYX_ERR(0, 45, __pyx_L1_error) } } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_17, __pyx_t_15}; - __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_14, 2+__pyx_t_14); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; - __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_17, __pyx_t_15}; - __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_14, 2+__pyx_t_14); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; - __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; - } else - #endif - { - __pyx_t_16 = PyTuple_New(2+__pyx_t_14); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_16); - if (__pyx_t_6) { - __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_16, 0, __pyx_t_6); __pyx_t_6 = NULL; - } - __Pyx_GIVEREF(__pyx_t_17); - PyTuple_SET_ITEM(__pyx_t_16, 0+__pyx_t_14, __pyx_t_17); - __Pyx_GIVEREF(__pyx_t_15); - PyTuple_SET_ITEM(__pyx_t_16, 1+__pyx_t_14, __pyx_t_15); - __pyx_t_17 = 0; - __pyx_t_15 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_16, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0; - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_res2 = __pyx_t_4; - __pyx_t_4 = 0; - - /* "upolygon/simplify_polygon.pyx":31 - * res1 = simplify_single_polygon(path[:2*index+2], epsilon) - * res2 = simplify_single_polygon(path[2*index:], epsilon) - * return res1[0:len(res1)-2] + res2 # <<<<<<<<<<<<<< - * else: - * return [path[0], path[1], path[end*2], path[end*2+1]] + __pyx_L12:; + __pyx_L3_continue:; + } + + /* "upolygon/simplify_polygon.pyx":46 + * for i in range(startIndex+1,endIndex-1): + * deleted[i] = True + * result = [] # <<<<<<<<<<<<<< + * for i in range(0, length): + * if not deleted[i]: */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyObject_Length(__pyx_v_res1); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 31, __pyx_L1_error) - __pyx_t_4 = __Pyx_PyObject_GetSlice(__pyx_v_res1, 0, (__pyx_t_1 - 2), NULL, NULL, NULL, 1, 1, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 31, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_res2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; + __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 46, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_v_result = ((PyObject*)__pyx_t_2); + __pyx_t_2 = 0; - /* "upolygon/simplify_polygon.pyx":28 - * index = i + /* "upolygon/simplify_polygon.pyx":47 + * deleted[i] = True + * result = [] + * for i in range(0, length): # <<<<<<<<<<<<<< + * if not deleted[i]: + * result.append(path[2*i]) + */ + __pyx_t_9 = __pyx_v_length; + __pyx_t_8 = __pyx_t_9; + for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_8; __pyx_t_10+=1) { + __pyx_v_i = __pyx_t_10; + + /* "upolygon/simplify_polygon.pyx":48 + * result = [] + * for i in range(0, length): + * if not deleted[i]: # <<<<<<<<<<<<<< + * result.append(path[2*i]) + * result.append(path[2*i+1]) + */ + __pyx_t_5 = __Pyx_PyObject_IsTrue(PyList_GET_ITEM(__pyx_v_deleted, __pyx_v_i)); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 48, __pyx_L1_error) + __pyx_t_20 = ((!__pyx_t_5) != 0); + if (__pyx_t_20) { + + /* "upolygon/simplify_polygon.pyx":49 + * for i in range(0, length): + * if not deleted[i]: + * result.append(path[2*i]) # <<<<<<<<<<<<<< + * result.append(path[2*i+1]) + * return result + */ + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 49, __pyx_L1_error) + } + __pyx_t_11 = (2 * __pyx_v_i); + __pyx_t_2 = PyList_GET_ITEM(__pyx_v_path, __pyx_t_11); + __Pyx_INCREF(__pyx_t_2); + __pyx_t_18 = __Pyx_PyList_Append(__pyx_v_result, __pyx_t_2); if (unlikely(__pyx_t_18 == ((int)-1))) __PYX_ERR(0, 49, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "upolygon/simplify_polygon.pyx":50 + * if not deleted[i]: + * result.append(path[2*i]) + * result.append(path[2*i+1]) # <<<<<<<<<<<<<< + * return result * - * if max_distance > epsilon: # <<<<<<<<<<<<<< - * res1 = simplify_single_polygon(path[:2*index+2], epsilon) - * res2 = simplify_single_polygon(path[2*index:], epsilon) */ + if (unlikely(__pyx_v_path == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 50, __pyx_L1_error) + } + __pyx_t_11 = ((2 * __pyx_v_i) + 1); + __pyx_t_2 = PyList_GET_ITEM(__pyx_v_path, __pyx_t_11); + __Pyx_INCREF(__pyx_t_2); + __pyx_t_18 = __Pyx_PyList_Append(__pyx_v_result, __pyx_t_2); if (unlikely(__pyx_t_18 == ((int)-1))) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "upolygon/simplify_polygon.pyx":48 + * result = [] + * for i in range(0, length): + * if not deleted[i]: # <<<<<<<<<<<<<< + * result.append(path[2*i]) + * result.append(path[2*i+1]) + */ + } } - /* "upolygon/simplify_polygon.pyx":33 - * return res1[0:len(res1)-2] + res2 - * else: - * return [path[0], path[1], path[end*2], path[end*2+1]] # <<<<<<<<<<<<<< + /* "upolygon/simplify_polygon.pyx":51 + * result.append(path[2*i]) + * result.append(path[2*i+1]) + * return result # <<<<<<<<<<<<<< * * # Basic RamerDouglasPeucker algorithm */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 33, __pyx_L1_error) - } - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 33, __pyx_L1_error) - } - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 33, __pyx_L1_error) - } - __pyx_t_11 = (__pyx_v_end * 2); - if (unlikely(__pyx_v_path == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 33, __pyx_L1_error) - } - __pyx_t_18 = ((__pyx_v_end * 2) + 1); - __pyx_t_3 = PyList_New(4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 33, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(PyList_GET_ITEM(__pyx_v_path, 0)); - __Pyx_GIVEREF(PyList_GET_ITEM(__pyx_v_path, 0)); - PyList_SET_ITEM(__pyx_t_3, 0, PyList_GET_ITEM(__pyx_v_path, 0)); - __Pyx_INCREF(PyList_GET_ITEM(__pyx_v_path, 1)); - __Pyx_GIVEREF(PyList_GET_ITEM(__pyx_v_path, 1)); - PyList_SET_ITEM(__pyx_t_3, 1, PyList_GET_ITEM(__pyx_v_path, 1)); - __Pyx_INCREF(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); - __Pyx_GIVEREF(PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); - PyList_SET_ITEM(__pyx_t_3, 2, PyList_GET_ITEM(__pyx_v_path, __pyx_t_11)); - __Pyx_INCREF(PyList_GET_ITEM(__pyx_v_path, __pyx_t_18)); - __Pyx_GIVEREF(PyList_GET_ITEM(__pyx_v_path, __pyx_t_18)); - PyList_SET_ITEM(__pyx_t_3, 3, PyList_GET_ITEM(__pyx_v_path, __pyx_t_18)); - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - } + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_result); + __pyx_r = __pyx_v_result; + goto __pyx_L0; /* "upolygon/simplify_polygon.pyx":16 * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_single_polygon(list path, float epsilon): # <<<<<<<<<<<<<< - * if len(path) <= 1: - * return path + * # Note that we are using an iterative version of this algorithm + * # instread of the classical recursive to prevent reaching python's */ /* function exit code */ __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_15); - __Pyx_XDECREF(__pyx_t_16); - __Pyx_XDECREF(__pyx_t_17); __Pyx_AddTraceback("upolygon.simplify_polygon.simplify_single_polygon", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_XDECREF(__pyx_v_i); + __Pyx_XDECREF(__pyx_v_deleted); + __Pyx_XDECREF(__pyx_v_stack); __Pyx_XDECREF(__pyx_v_distance); - __Pyx_XDECREF(__pyx_v_res1); - __Pyx_XDECREF(__pyx_v_res2); + __Pyx_XDECREF(__pyx_v_result); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "upolygon/simplify_polygon.pyx":39 +/* "upolygon/simplify_polygon.pyx":57 * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_polygon(list paths, float epsilon): # <<<<<<<<<<<<<< @@ -1980,11 +2094,11 @@ static PyObject *__pyx_pw_8upolygon_16simplify_polygon_3simplify_polygon(PyObjec case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_epsilon)) != 0)) kw_args--; else { - __Pyx_RaiseArgtupleInvalid("simplify_polygon", 1, 2, 2, 1); __PYX_ERR(0, 39, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("simplify_polygon", 1, 2, 2, 1); __PYX_ERR(0, 57, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "simplify_polygon") < 0)) __PYX_ERR(0, 39, __pyx_L3_error) + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "simplify_polygon") < 0)) __PYX_ERR(0, 57, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { goto __pyx_L5_argtuple_error; @@ -1993,17 +2107,17 @@ static PyObject *__pyx_pw_8upolygon_16simplify_polygon_3simplify_polygon(PyObjec values[1] = PyTuple_GET_ITEM(__pyx_args, 1); } __pyx_v_paths = ((PyObject*)values[0]); - __pyx_v_epsilon = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_epsilon == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L3_error) + __pyx_v_epsilon = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_epsilon == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 57, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("simplify_polygon", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 39, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("simplify_polygon", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 57, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("upolygon.simplify_polygon.simplify_polygon", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_paths), (&PyList_Type), 1, "paths", 1))) __PYX_ERR(0, 39, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_paths), (&PyList_Type), 1, "paths", 1))) __PYX_ERR(0, 57, __pyx_L1_error) __pyx_r = __pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(__pyx_self, __pyx_v_paths, __pyx_v_epsilon); /* function exit code */ @@ -2033,33 +2147,33 @@ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("simplify_polygon", 0); - /* "upolygon/simplify_polygon.pyx":40 + /* "upolygon/simplify_polygon.pyx":58 * @cython.nonecheck(False) * def simplify_polygon(list paths, float epsilon): * return [simplify_single_polygon(path, epsilon) for path in paths] # <<<<<<<<<<<<<< */ __Pyx_XDECREF(__pyx_r); { /* enter inner scope */ - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_1); if (unlikely(__pyx_v_paths == Py_None)) { PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); - __PYX_ERR(0, 40, __pyx_L5_error) + __PYX_ERR(0, 58, __pyx_L5_error) } __pyx_t_2 = __pyx_v_paths; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0; for (;;) { if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break; #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 58, __pyx_L5_error) #else - __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_4); #endif __Pyx_XDECREF_SET(__pyx_7genexpr__pyx_v_path, __pyx_t_4); __pyx_t_4 = 0; - __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_simplify_single_polygon); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 40, __pyx_L5_error) + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_simplify_single_polygon); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PyFloat_FromDouble(__pyx_v_epsilon); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_6 = PyFloat_FromDouble(__pyx_v_epsilon); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_6); __pyx_t_7 = NULL; __pyx_t_8 = 0; @@ -2076,7 +2190,7 @@ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_ #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_5)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_7genexpr__pyx_v_path, __pyx_t_6}; - __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; @@ -2085,14 +2199,14 @@ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_ #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) { PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_7genexpr__pyx_v_path, __pyx_t_6}; - __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; } else #endif { - __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_9); if (__pyx_t_7) { __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL; @@ -2103,12 +2217,12 @@ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_ __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_6); __pyx_t_6 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L5_error) + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; } __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) __PYX_ERR(0, 40, __pyx_L5_error) + if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) __PYX_ERR(0, 58, __pyx_L5_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; } __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; @@ -2123,7 +2237,7 @@ static PyObject *__pyx_pf_8upolygon_16simplify_polygon_2simplify_polygon(CYTHON_ __pyx_t_1 = 0; goto __pyx_L0; - /* "upolygon/simplify_polygon.pyx":39 + /* "upolygon/simplify_polygon.pyx":57 * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_polygon(list paths, float epsilon): # <<<<<<<<<<<<<< @@ -2195,28 +2309,32 @@ static struct PyModuleDef __pyx_moduledef = { static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_deleted, __pyx_k_deleted, sizeof(__pyx_k_deleted), 0, 0, 1, 1}, {&__pyx_n_s_distance, __pyx_k_distance, sizeof(__pyx_k_distance), 0, 0, 1, 1}, - {&__pyx_n_s_end, __pyx_k_end, sizeof(__pyx_k_end), 0, 0, 1, 1}, + {&__pyx_n_s_endIndex, __pyx_k_endIndex, sizeof(__pyx_k_endIndex), 0, 0, 1, 1}, {&__pyx_n_s_epsilon, __pyx_k_epsilon, sizeof(__pyx_k_epsilon), 0, 0, 1, 1}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1}, + {&__pyx_n_s_length, __pyx_k_length, sizeof(__pyx_k_length), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_max_distance, __pyx_k_max_distance, sizeof(__pyx_k_max_distance), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_n_s_path, __pyx_k_path, sizeof(__pyx_k_path), 0, 0, 1, 1}, {&__pyx_n_s_paths, __pyx_k_paths, sizeof(__pyx_k_paths), 0, 0, 1, 1}, + {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, - {&__pyx_n_s_res1, __pyx_k_res1, sizeof(__pyx_k_res1), 0, 0, 1, 1}, - {&__pyx_n_s_res2, __pyx_k_res2, sizeof(__pyx_k_res2), 0, 0, 1, 1}, + {&__pyx_n_s_result, __pyx_k_result, sizeof(__pyx_k_result), 0, 0, 1, 1}, {&__pyx_n_s_simplify_polygon, __pyx_k_simplify_polygon, sizeof(__pyx_k_simplify_polygon), 0, 0, 1, 1}, {&__pyx_n_s_simplify_single_polygon, __pyx_k_simplify_single_polygon, sizeof(__pyx_k_simplify_single_polygon), 0, 0, 1, 1}, + {&__pyx_n_s_stack, __pyx_k_stack, sizeof(__pyx_k_stack), 0, 0, 1, 1}, + {&__pyx_n_s_startIndex, __pyx_k_startIndex, sizeof(__pyx_k_startIndex), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_n_s_upolygon_simplify_polygon, __pyx_k_upolygon_simplify_polygon, sizeof(__pyx_k_upolygon_simplify_polygon), 0, 0, 1, 1}, {&__pyx_kp_s_upolygon_simplify_polygon_pyx, __pyx_k_upolygon_simplify_polygon_pyx, sizeof(__pyx_k_upolygon_simplify_polygon_pyx), 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0} }; static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 33, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -2230,24 +2348,24 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_single_polygon(list path, float epsilon): # <<<<<<<<<<<<<< - * if len(path) <= 1: - * return path + * # Note that we are using an iterative version of this algorithm + * # instread of the classical recursive to prevent reaching python's */ - __pyx_tuple_ = PyTuple_Pack(9, __pyx_n_s_path, __pyx_n_s_epsilon, __pyx_n_s_max_distance, __pyx_n_s_index, __pyx_n_s_end, __pyx_n_s_i, __pyx_n_s_distance, __pyx_n_s_res1, __pyx_n_s_res2); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 16, __pyx_L1_error) + __pyx_tuple_ = PyTuple_Pack(12, __pyx_n_s_path, __pyx_n_s_epsilon, __pyx_n_s_length, __pyx_n_s_startIndex, __pyx_n_s_endIndex, __pyx_n_s_max_distance, __pyx_n_s_index, __pyx_n_s_i, __pyx_n_s_deleted, __pyx_n_s_stack, __pyx_n_s_distance, __pyx_n_s_result); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); - __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 9, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_upolygon_simplify_polygon_pyx, __pyx_n_s_simplify_single_polygon, 16, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 16, __pyx_L1_error) + __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 12, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_upolygon_simplify_polygon_pyx, __pyx_n_s_simplify_single_polygon, 16, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 16, __pyx_L1_error) - /* "upolygon/simplify_polygon.pyx":39 + /* "upolygon/simplify_polygon.pyx":57 * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_polygon(list paths, float epsilon): # <<<<<<<<<<<<<< * return [simplify_single_polygon(path, epsilon) for path in paths] */ - __pyx_tuple__3 = PyTuple_Pack(3, __pyx_n_s_paths, __pyx_n_s_epsilon, __pyx_n_s_path); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 39, __pyx_L1_error) + __pyx_tuple__3 = PyTuple_Pack(3, __pyx_n_s_paths, __pyx_n_s_epsilon, __pyx_n_s_path); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 57, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3); - __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_upolygon_simplify_polygon_pyx, __pyx_n_s_simplify_polygon, 39, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 39, __pyx_L1_error) + __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_upolygon_simplify_polygon_pyx, __pyx_n_s_simplify_polygon, 57, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 57, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -2256,9 +2374,8 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { } static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + __pyx_umethod_PyList_Type_pop.type = (PyObject*)&PyList_Type; if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; @@ -2534,23 +2651,23 @@ if (!__Pyx_RefNanny) { * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_single_polygon(list path, float epsilon): # <<<<<<<<<<<<<< - * if len(path) <= 1: - * return path + * # Note that we are using an iterative version of this algorithm + * # instread of the classical recursive to prevent reaching python's */ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8upolygon_16simplify_polygon_1simplify_single_polygon, NULL, __pyx_n_s_upolygon_simplify_polygon); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_simplify_single_polygon, __pyx_t_1) < 0) __PYX_ERR(0, 16, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "upolygon/simplify_polygon.pyx":39 + /* "upolygon/simplify_polygon.pyx":57 * @cython.wraparound(False) * @cython.nonecheck(False) * def simplify_polygon(list paths, float epsilon): # <<<<<<<<<<<<<< * return [simplify_single_polygon(path, epsilon) for path in paths] */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8upolygon_16simplify_polygon_3simplify_polygon, NULL, __pyx_n_s_upolygon_simplify_polygon); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 39, __pyx_L1_error) + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8upolygon_16simplify_polygon_3simplify_polygon, NULL, __pyx_n_s_upolygon_simplify_polygon); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_simplify_polygon, __pyx_t_1) < 0) __PYX_ERR(0, 39, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_simplify_polygon, __pyx_t_1) < 0) __PYX_ERR(0, 57, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "upolygon/simplify_polygon.pyx":1 @@ -2804,386 +2921,6 @@ static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t a, Py_ssize_t b) return q; } -/* PyObjectCall */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = func->ob_type->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* GetItemInt */ -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyList_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyTuple_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - } - return m->sq_item(o, i); - } - } -#else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); - } -#endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -} - -/* ObjectGetItem */ -#if CYTHON_USE_TYPE_SLOTS -static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { - PyObject *runerr; - Py_ssize_t key_value; - PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; - if (unlikely(!(m && m->sq_item))) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); - return NULL; - } - key_value = __Pyx_PyIndex_AsSsize_t(index); - if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { - return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); - } - if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { - PyErr_Clear(); - PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); - } - return NULL; -} -static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { - PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; - if (likely(m && m->mp_subscript)) { - return m->mp_subscript(obj, key); - } - return __Pyx_PyObject_GetIndex(obj, key); -} -#endif - -/* PyIntBinop */ -#if !CYTHON_COMPILING_IN_PYPY -static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) { - (void)inplace; - (void)zerodivision_check; - #if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(op1))) { - const long b = intval; - long x; - long a = PyInt_AS_LONG(op1); - x = (long)((unsigned long)a + b); - if (likely((x^a) >= 0 || (x^b) >= 0)) - return PyInt_FromLong(x); - return PyLong_Type.tp_as_number->nb_add(op1, op2); - } - #endif - #if CYTHON_USE_PYLONG_INTERNALS - if (likely(PyLong_CheckExact(op1))) { - const long b = intval; - long a, x; -#ifdef HAVE_LONG_LONG - const PY_LONG_LONG llb = intval; - PY_LONG_LONG lla, llx; -#endif - const digit* digits = ((PyLongObject*)op1)->ob_digit; - const Py_ssize_t size = Py_SIZE(op1); - if (likely(__Pyx_sst_abs(size) <= 1)) { - a = likely(size) ? digits[0] : 0; - if (size == -1) a = -a; - } else { - switch (size) { - case -2: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 2: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case -3: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 3: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case -4: - if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 4: - if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - default: return PyLong_Type.tp_as_number->nb_add(op1, op2); - } - } - x = a + b; - return PyLong_FromLong(x); -#ifdef HAVE_LONG_LONG - long_long: - llx = lla + llb; - return PyLong_FromLongLong(llx); -#endif - - - } - #endif - if (PyFloat_CheckExact(op1)) { - const long b = intval; - double a = PyFloat_AS_DOUBLE(op1); - double result; - PyFPE_START_PROTECT("add", return NULL) - result = ((double)a) + (double)b; - PyFPE_END_PROTECT(result) - return PyFloat_FromDouble(result); - } - return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2); -} -#endif - -/* PyDictVersioning */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; -} -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) - return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* GetModuleGlobalName */ -#if CYTHON_USE_DICT_VERSIONS -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) -#else -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) -#endif -{ - PyObject *result; -#if !CYTHON_AVOID_BORROWED_REFS -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 - result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } else if (unlikely(PyErr_Occurred())) { - return NULL; - } -#else - result = PyDict_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } -#endif -#else - result = PyObject_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } - PyErr_Clear(); -#endif - return __Pyx_GetBuiltinName(name); -} - -/* SliceTupleAndList */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) { - Py_ssize_t start = *_start, stop = *_stop, length = *_length; - if (start < 0) { - start += length; - if (start < 0) - start = 0; - } - if (stop < 0) - stop += length; - else if (stop > length) - stop = length; - *_length = stop - start; - *_start = start; - *_stop = stop; -} -static CYTHON_INLINE void __Pyx_copy_object_array(PyObject** CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { - PyObject *v; - Py_ssize_t i; - for (i = 0; i < length; i++) { - v = dest[i] = src[i]; - Py_INCREF(v); - } -} -static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice( - PyObject* src, Py_ssize_t start, Py_ssize_t stop) { - PyObject* dest; - Py_ssize_t length = PyList_GET_SIZE(src); - __Pyx_crop_slice(&start, &stop, &length); - if (unlikely(length <= 0)) - return PyList_New(0); - dest = PyList_New(length); - if (unlikely(!dest)) - return NULL; - __Pyx_copy_object_array( - ((PyListObject*)src)->ob_item + start, - ((PyListObject*)dest)->ob_item, - length); - return dest; -} -static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice( - PyObject* src, Py_ssize_t start, Py_ssize_t stop) { - PyObject* dest; - Py_ssize_t length = PyTuple_GET_SIZE(src); - __Pyx_crop_slice(&start, &stop, &length); - if (unlikely(length <= 0)) - return PyTuple_New(0); - dest = PyTuple_New(length); - if (unlikely(!dest)) - return NULL; - __Pyx_copy_object_array( - ((PyTupleObject*)src)->ob_item + start, - ((PyTupleObject*)dest)->ob_item, - length); - return dest; -} -#endif - /* PyFunctionFastCall */ #if CYTHON_FAST_PYCALL static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, @@ -3303,6 +3040,68 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #endif #endif +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = func->ob_type->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + /* PyCFunctionFastCall */ #if CYTHON_FAST_PYCCALL static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { @@ -3326,101 +3125,382 @@ static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, P } #endif -/* SliceObject */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, - Py_ssize_t cstart, Py_ssize_t cstop, - PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, - int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { -#if CYTHON_USE_TYPE_SLOTS - PyMappingMethods* mp; -#if PY_MAJOR_VERSION < 3 - PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; - if (likely(ms && ms->sq_slice)) { - if (!has_cstart) { - if (_py_start && (*_py_start != Py_None)) { - cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); - if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; - } else - cstart = 0; - } - if (!has_cstop) { - if (_py_stop && (*_py_stop != Py_None)) { - cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); - if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; - } else - cstop = PY_SSIZE_T_MAX; +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif } - if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { - Py_ssize_t l = ms->sq_length(obj); - if (likely(l >= 0)) { - if (cstop < 0) { - cstop += l; - if (cstop < 0) cstop = 0; - } - if (cstart < 0) { - cstart += l; - if (cstart < 0) cstart = 0; - } - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - goto bad; - PyErr_Clear(); + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectGetMethod */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { + PyObject *attr; +#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + int meth_found = 0; + assert (*method == NULL); + if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; + } + if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { + return 0; + } + descr = _PyType_Lookup(tp, name); + if (likely(descr != NULL)) { + Py_INCREF(descr); +#if PY_MAJOR_VERSION >= 3 + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) + #endif +#else + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr))) + #endif +#endif + { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; } } - return ms->sq_slice(obj, cstart, cstop); } + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = __Pyx_PyDict_GetItemStr(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + goto try_unpack; + } + Py_DECREF(dict); + } + if (meth_found) { + *method = descr; + return 1; + } + if (f != NULL) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + if (descr != NULL) { + *method = descr; + return 0; + } + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(name)); #endif - mp = Py_TYPE(obj)->tp_as_mapping; - if (likely(mp && mp->mp_subscript)) + return 0; +#else + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; +#endif +try_unpack: +#if CYTHON_UNPACK_METHODS + if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { + PyObject *function = PyMethod_GET_FUNCTION(attr); + Py_INCREF(function); + Py_DECREF(attr); + *method = function; + return 1; + } #endif + *method = attr; + return 0; +} + +/* PyObjectCallMethod0 */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { + PyObject *method = NULL, *result = NULL; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_CallOneArg(method, obj); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) goto bad; + result = __Pyx_PyObject_CallNoArg(method); + Py_DECREF(method); +bad: + return result; +} + +/* UnpackUnboundCMethod */ +static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { + PyObject *method; + method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); + if (unlikely(!method)) + return -1; + target->method = method; +#if CYTHON_COMPILING_IN_CPYTHON + #if PY_MAJOR_VERSION >= 3 + if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) + #endif { - PyObject* result; - PyObject *py_slice, *py_start, *py_stop; - if (_py_slice) { - py_slice = *_py_slice; + PyMethodDescrObject *descr = (PyMethodDescrObject*) method; + target->func = descr->d_method->ml_meth; + target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); + } +#endif + return 0; +} + +/* CallUnboundCMethod0 */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + PyObject *args, *result = NULL; + if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_ASSUME_SAFE_MACROS + args = PyTuple_New(1); + if (unlikely(!args)) goto bad; + Py_INCREF(self); + PyTuple_SET_ITEM(args, 0, self); +#else + args = PyTuple_Pack(1, self); + if (unlikely(!args)) goto bad; +#endif + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); + Py_DECREF(args); +bad: + return result; +} + +/* pop */ +static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { + if (Py_TYPE(L) == &PySet_Type) { + return PySet_Pop(L); + } + return __Pyx_PyObject_CallMethod0(L, __pyx_n_s_pop); +} +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { + if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) { + __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); + return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); + } + return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyList_Type_pop, L); +} +#endif + +/* RaiseTooManyValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* IterFinish */ +static CYTHON_INLINE int __Pyx_IterFinish(void) { +#if CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* exc_type = tstate->curexc_type; + if (unlikely(exc_type)) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) { + PyObject *exc_value, *exc_tb; + exc_value = tstate->curexc_value; + exc_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + Py_DECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; } else { - PyObject* owned_start = NULL; - PyObject* owned_stop = NULL; - if (_py_start) { - py_start = *_py_start; - } else { - if (has_cstart) { - owned_start = py_start = PyInt_FromSsize_t(cstart); - if (unlikely(!py_start)) goto bad; - } else - py_start = Py_None; - } - if (_py_stop) { - py_stop = *_py_stop; - } else { - if (has_cstop) { - owned_stop = py_stop = PyInt_FromSsize_t(cstop); - if (unlikely(!py_stop)) { - Py_XDECREF(owned_start); - goto bad; - } - } else - py_stop = Py_None; - } - py_slice = PySlice_New(py_start, py_stop, Py_None); - Py_XDECREF(owned_start); - Py_XDECREF(owned_stop); - if (unlikely(!py_slice)) goto bad; + return -1; } -#if CYTHON_USE_TYPE_SLOTS - result = mp->mp_subscript(obj, py_slice); + } + return 0; #else - result = PyObject_GetItem(obj, py_slice); + if (unlikely(PyErr_Occurred())) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } + } + return 0; #endif - if (!_py_slice) { - Py_DECREF(py_slice); +} + +/* UnpackItemEndCheck */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); + __Pyx_RaiseTooManyValuesError(expected); + return -1; + } else { + return __Pyx_IterFinish(); + } + return 0; +} + +/* SetItemInt */ +static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) { + int r; + if (!j) return -1; + r = PyObject_SetItem(o, j, v); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int is_list, + CYTHON_NCP_UNUSED int wraparound, CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = (!wraparound) ? i : ((likely(i >= 0)) ? i : i + PyList_GET_SIZE(o)); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o)))) { + PyObject* old = PyList_GET_ITEM(o, n); + Py_INCREF(v); + PyList_SET_ITEM(o, n, v); + Py_DECREF(old); + return 1; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_ass_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return -1; + PyErr_Clear(); + } + } + return m->sq_ass_item(o, i, v); } - return result; } - PyErr_Format(PyExc_TypeError, - "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); -bad: - return NULL; +#else +#if CYTHON_COMPILING_IN_PYPY + if (is_list || (PySequence_Check(o) && !PyDict_Check(o))) +#else + if (is_list || PySequence_Check(o)) +#endif + { + return PySequence_SetItem(o, i, v); + } +#endif + return __Pyx_SetItemInt_Generic(o, PyInt_FromSsize_t(i), v); +} + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); } /* PyErrFetchRestore */ @@ -3685,6 +3765,28 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { } } +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; @@ -3716,28 +3818,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { } } -/* CIntFromPyVerify */ -#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) -#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) -#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ - {\ - func_type value = func_value;\ - if (sizeof(target_type) < sizeof(func_type)) {\ - if (unlikely(value != (func_type) (target_type) value)) {\ - func_type zero = 0;\ - if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ - return (target_type) -1;\ - if (is_unsigned && unlikely(value < zero))\ - goto raise_neg_overflow;\ - else\ - goto raise_overflow;\ - }\ - }\ - return (target_type) value;\ - } - /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; diff --git a/upolygon/simplify_polygon.pyx b/upolygon/simplify_polygon.pyx index a0ee9eb..51dbf3a 100644 --- a/upolygon/simplify_polygon.pyx +++ b/upolygon/simplify_polygon.pyx @@ -14,23 +14,41 @@ cdef perpendicular_distance(float px, float py, float ax, float ay, float bx, fl @cython.wraparound(False) @cython.nonecheck(False) def simplify_single_polygon(list path, float epsilon): - if len(path) <= 1: - return path + # Note that we are using an iterative version of this algorithm + # instead of the classical recursive to prevent reaching python's + # max recursion. + cdef int length = len(path) // 2 + cdef int startIndex = 0 + cdef int endIndex = length cdef float max_distance = 0 cdef int index = 0 - cdef int end = len(path) // 2 - 1 - for i in range(1, end): - distance = perpendicular_distance(path[2*i], path[2*i+1], path[0], path[1], path[2*end], path[2*end+1]) - if distance > max_distance: - max_distance = distance - index = i - - if max_distance > epsilon: - res1 = simplify_single_polygon(path[:2*index+2], epsilon) - res2 = simplify_single_polygon(path[2*index:], epsilon) - return res1[0:len(res1)-2] + res2 - else: - return [path[0], path[1], path[end*2], path[end*2+1]] + cdef int i + deleted = [False] * length + stack = [(startIndex,endIndex)] + while stack: + startIndex, endIndex = stack.pop() + if startIndex == endIndex: + continue + max_distance = 0 + for i in range(startIndex,endIndex): + if deleted[i]: + continue + distance = perpendicular_distance(path[2*i], path[2*i+1], path[startIndex*2], path[startIndex*2+1], path[2*(endIndex-1)], path[2*(endIndex-1)+1]) + if distance > max_distance: + max_distance = distance + index = i + if max_distance > epsilon: + stack.append((startIndex,index)) + stack.append((index, endIndex)) + else: + for i in range(startIndex+1,endIndex-1): + deleted[i] = True + result = [] + for i in range(0, length): + if not deleted[i]: + result.append(path[2*i]) + result.append(path[2*i+1]) + return result # Basic Ramer–Douglas–Peucker algorithm @cython.boundscheck(False)