rdp 0.1.1

A Rust implementation of the Ramer–Douglas–Peucker algorithm
Documentation
#!/usr/bin/env python
import os
from sys import platform
from ctypes import Structure, POINTER, c_void_p, c_size_t, c_double, cast, cdll
import numpy as np

file_path = os.path.dirname(__file__)

if platform == "darwin":
    prefix = 'lib'
    ext = "dylib"
elif "linux" in platform:
    prefix = 'lib'
    ext = "so"
    fpath = os.path.join(file_path, ".libs")

elif "win32" in platform:
    prefix = ''
    ext = 'dll'

prefix = {'win32': ''}.get(platform, 'lib')
extension = {'darwin': '.dylib', 'win32': '.dll'}.get(platform, '.so')



lib = cdll.LoadLibrary(os.path.join(file_path, "target/release", prefix + "rdp" + extension))

class _FFIArray(Structure):
    """
    Convert sequence of float lists to a C-compatible void array
    example: [[1.0, 2.0], [3.0, 4.0]]

    """
    _fields_ = [("data", c_void_p),
                ("len", c_size_t)]

    @classmethod
    def from_param(cls, seq):
        """  Allow implicit conversions """
        return seq if isinstance(seq, cls) else cls(seq)

    def __init__(self, seq, data_type = c_double):
        self.data = cast(
            np.array(seq, dtype=np.float64).ctypes.data_as(POINTER(data_type)),
            c_void_p
        )
        self.len = len(seq)


class _CoordResult(Structure):
    """ Container for returned FFI coordinate data """
    _fields_ = [("coords", _FFIArray)]

def _void_array_to_nested_list(res, _func, _args):
    """ Dereference the FFI result to a list of coordinates """
    try:
        shape = res.coords.len, 2
        ptr = cast(res.coords.data, POINTER(c_double))
        array = np.ctypeslib.as_array(ptr, shape)
        return array.tolist()
    finally:
        drop_array(res.coords)

simplify_coords = lib.simplify_linestring_ffi
simplify_coords.argtypes = (_FFIArray, c_double)
simplify_coords.restype = _CoordResult
simplify_coords.errcheck = _void_array_to_nested_list

drop_array = lib.drop_float_array
drop_array.argtypes = (_FFIArray,)
drop_array.restype = None

if __name__ == "__main__":
    print(simplify_coords(
        [[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [17.3, 3.2], [27.8, 0.1]],
        1.0
    ))