Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unoptimized for loop #7

Open
kkonevets opened this issue Mar 15, 2017 · 5 comments
Open

unoptimized for loop #7

kkonevets opened this issue Mar 15, 2017 · 5 comments

Comments

@kkonevets
Copy link

kkonevets commented Mar 15, 2017

This code works MUCH faster. It does not use for loop, instead it uses numpy vectorization

import numpy as np


def line_dists(points, start, end):
    if np.all(start == end):
        return np.linalg.norm(points - start, axis=1)

    vec = end - start
    cross = np.cross(vec, start - points)
    return np.divide(abs(cross), np.linalg.norm(vec))


def rdp(M, epsilon=0):
    M = np.array(M)
    start, end = M[0], M[-1]
    dists = line_dists(M, start, end)

    index = np.argmax(dists)
    dmax = dists[index]

    if dmax > epsilon:
        result1 = rdp(M[:index + 1], epsilon)
        result2 = rdp(M[index:], epsilon)

        result = np.vstack((result1[:-1], result2))
    else:
        result = np.array([start, end])

    return result
@kkonevets kkonevets changed the title slow execution time unoptimized algorithm Mar 15, 2017
@kkonevets kkonevets changed the title unoptimized algorithm unoptimized for loop Mar 15, 2017
@JustasB
Copy link

JustasB commented May 5, 2018

I can confirm that it works faster than the pure python version for me as well.

@soichih
Copy link

soichih commented Oct 24, 2018

@kkonevets I can't figure out how to convert your code to work on 3D data.. Is it possible to do something similar with 3D data?

@ivicajan
Copy link

Dear all,

is there a way to limit number of simplified points together with max distance (epsilon)?
Or to be more precise, to pick only subset of N the most relevant points for given dmax.

Thanks in advance!

Cheers,
Ivica

@darwinharianto
Copy link

darwinharianto commented Jun 3, 2022

import numpy as np

def line_dists2D(points, start, end):
    if np.all(start == end):
        return np.linalg.norm(points - start, axis=1)

    vec = end - start
    cross = np.cross(vec, start - points)
    return np.divide(abs(cross), np.linalg.norm(vec))


# https://stackoverflow.com/questions/56463412/distance-from-a-point-to-a-line-segment-in-3d-python
def lineseg_dist3D(p: np.ndarray, a: np.ndarray, b: np.ndarray):

    # normalized tangent vector
    d = np.divide(b - a, np.linalg.norm(b - a))

    # signed parallel distance components
    s = np.dot(a - p, d)
    t = np.dot(p - b, d)

    # clamped parallel distance
    h = np.maximum.reduce([s, t, np.zeros(len(p))])

    # perpendicular distance component
    c = np.cross(p - a, d)

    res = np.hypot(h, np.linalg.norm(c, axis=1))
    res[res < np.finfo(np.float64).eps] = 0

    return res


def rdp(M, epsilon=0):
    M = np.array(M)
    start, end = M[0], M[-1]
    if M.shape[1] == 2:
        dists = line_dists2D(M, start, end)
    elif M.shape[1] == 3:
        dists = lineseg_dist3D(M, start, end)
    else:
        raise ValueError("point dimension must be 2d or 3d")
    index = np.argmax(dists)
    dmax = dists[index]

    if dmax == np.nan:
        raise ValueError

    if dmax > epsilon:
        result1 = rdp(M[: index + 1], epsilon)
        result2 = rdp(M[index:], epsilon)

        result = np.vstack((result1[:-1], result2))
    else:
        result = np.array([start, end])

    return result

  points = np.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]).reshape(-1, 3)
  points = np.array([1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 3]).reshape(-1, 2)
  print(rdp(points))

@soichih
I tried to make a sample on 3d Points, i think this is working

edit: fixed close to 0 and linalg norm over rows

@star-plu-cn-sk2
Copy link

star-plu-cn-sk2 commented Jun 3, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants