到凸包的距离 [英] Distance to convexHull

查看:59
本文介绍了到凸包的距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找一种方法来计算到凸壳/多边形的距离,这样,如果该点在壳内,则该距离为正,如果在壳内,则该距离为负.例如,给定船体和一组点,可以计算正/负距离吗?

I have been searching for a method to compute a distance to a convexHull/polygon such that the distance is positive if the point is within the hull and negative if outside. For example, given a hull and a set of points, can the positive/negative distance be computed?

from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
import numpy as np

# Original points, hull and test points
points = np.random.rand(30, 2)   # 30 random points in 2-D
hull = ConvexHull(points)
newpoints = np.random.rand(30, 2)   # 30 random points in 2-D

# Plot original points, hull and new points
plt.plot(points[:,0], points[:,1], 'ro')
plt.plot(points[hull.vertices,0], points[hull.vertices,1], 'r--', lw=2)
plt.plot(newpoints[:,0], newpoints[:,1], 'go')

所以在上面,我想为每个绿点计算该带符号的距离.非常感谢您的宝贵时间!

So in the above I would like to calculate this signed distance for each of the green points. Thanks very much for your time!!

使用来自( http://www.fundza.com/vectors/point2line/index.html )可以计算无符号距离:

Update, using code from (http://www.fundza.com/vectors/point2line/index.html) can compute un-signed distance:

from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
import numpy as np
from vectors import *

# Original points, hull and test points
points = np.random.rand(30, 2)   # 30 random points in 2-D
hull = ConvexHull(points)
newpoints = np.random.rand(30, 2)   # 30 random points in 2-D



def pnt2line(pnt, start, end):
    line_vec = vector(start, end)
    pnt_vec = vector(start, pnt)
    line_len = length(line_vec)
    line_unitvec = unit(line_vec)
    pnt_vec_scaled = scale(pnt_vec, 1.0/line_len)
    t = dot(line_unitvec, pnt_vec_scaled)    
    if t < 0.0:
        t = 0.0
    elif t > 1.0:
        t = 1.0
    nearest = scale(line_vec, t)
    dist = distance(nearest, pnt_vec)
    nearest = add(nearest, start)
    return (dist, nearest)



pt_dist = []
for p_idx in range(30):
    pt = newpoints[p_idx,:]
    dist_list = []
    for v_idx in range(len(hull.vertices)):
        v1 = hull.vertices[v_idx - 1]
        v2 = hull.vertices[v_idx]
        start = points[v1]
        end = points[v2]
        temp = pnt2line(pt, start, end)
        dist_list.append(temp[0])
    pt_dist.append(min(dist_list))


# Plot original points, hull and new points
plt.plot(points[:,0], points[:,1], 'ro')
plt.plot(points[hull.vertices,0], points[hull.vertices,1], 'r--', lw=2)
plt.plot(newpoints[:,0], newpoints[:,1], 'go')
for p_idx in range(30):
    pt = newpoints[p_idx,:]
    dist = pt_dist[p_idx]
    distLabel = "%.2f" % dist
    plt.annotate(distLabel,xy=pt)

(注意将vector.py代码修改为2d):

(Note modified vector.py code to 2d):

import math

def dot(v,w):
    x,y = v
    X,Y = w
    return x*X + y*Y

def length(v):
    x,y = v
    return math.sqrt(x*x + y*y)

def vector(b,e):
    x,y = b
    X,Y = e
    return (X-x, Y-y)

def unit(v):
    x,y = v
    mag = length(v)
    return (x/mag, y/mag)

def distance(p0,p1):
    return length(vector(p0,p1))

def scale(v,sc):
    x,y = v
    return (x * sc, y * sc)

def add(v,w):
    x,y = v
    X,Y = w
    return (x+X, y+Y)

推荐答案

感谢您的建议!如果我在以下多边形函数中包含python点: http://geospatialpython.com/2011/01/point-in-polygon.html 我的完整代码为:

Thank you for your suggestions! If I include a python point in polygon function from: http://geospatialpython.com/2011/01/point-in-polygon.html My full code becomes:

from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
import numpy as np
from vectors import *

def pnt2line(pnt, start, end):
    line_vec = vector(start, end)
    pnt_vec = vector(start, pnt)
    line_len = length(line_vec)
    line_unitvec = unit(line_vec)
    pnt_vec_scaled = scale(pnt_vec, 1.0/line_len)
    t = dot(line_unitvec, pnt_vec_scaled)    
    if t < 0.0:
        t = 0.0
    elif t > 1.0:
        t = 1.0
    nearest = scale(line_vec, t)
    dist = distance(nearest, pnt_vec)
    nearest = add(nearest, start)
    return (dist, nearest)

def point_in_poly(x,y,poly):

    n = len(poly)
    inside = False

    p1x,p1y = poly[0]
    for i in range(n+1):
        p2x,p2y = poly[i % n]
        if y > min(p1y,p2y):
            if y <= max(p1y,p2y):
                if x <= max(p1x,p2x):
                    if p1y != p2y:
                        xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                    if p1x == p2x or x <= xints:
                        inside = not inside
        p1x,p1y = p2x,p2y

    return inside



# Original points, hull and test points
points = np.random.rand(30, 2)   # 30 random points in 2-D
hull = ConvexHull(points)
newpoints = np.random.rand(30, 2)   # 30 random points in 2-D



pt_dist = []
for p_idx in range(30):
    pt = newpoints[p_idx,:]
    dist_list = []
    for v_idx in range(len(hull.vertices)):
        v1 = hull.vertices[v_idx - 1]
        v2 = hull.vertices[v_idx]
        start = points[v1]
        end = points[v2]
        temp = pnt2line(pt, start, end)
        dist_list.append(temp[0])

    #Check point is within polygon
    inside =  point_in_poly(pt[0],pt[1],points[hull.vertices])
    if (inside == True):
        dist_temp = -1. * min(dist_list)
    else:
        dist_temp = min(dist_list)          

    pt_dist.append(dist_temp)


# Plot original points, hull and new points
plt.plot(points[:,0], points[:,1], 'ro')
plt.plot(points[hull.vertices,0], points[hull.vertices,1], 'r--', lw=2)
plt.plot(newpoints[:,0], newpoints[:,1], 'go')
for p_idx in range(30):
    pt = newpoints[p_idx,:]
    pt[1] = pt[1] + 0.01 
    dist = pt_dist[p_idx]
    distLabel = "%.2f" % dist
    plt.annotate(distLabel,xy=pt)

对Vectors.py进行了如上所述的修改.

With Vectors.py modified as above.

这给出了情节:

哪个看起来正确.谢谢!

Which looks correct. Thank you!

这篇关于到凸包的距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆