Voronoi泰森多边形应用案例-python

88 篇文章 11 订阅
37 篇文章 1 订阅

Voronoi泰森多边形应用案例-python

下面代码为Voronoi泰森多边形的应用案例。在下面代码中,我们会对输入的数据集,计算泰森多边形,之后在这个基础上,再对泰森多边形进行分割,之后我们可以通过书输入点,然后直接计算出其在我们分割的那个框里,再次基础上,结合泰森多边形的边界线知识,就可以很快的判断输入点的坐标距离输入数据集那个点最近。



import random 
import math 
from scipy.spatial import Voronoi, voronoi_plot_2d
import os

from scipy.spatial import cKDTree
import numpy as np
import matplotlib .pyplot as plt
import cv2
from sklearn.datasets import make_classification

x_min = -100
x_max =100
a=-1
b=1
num=10
y_min = -100
y_max =100
divide_num=5

x_lmin = -2
x_lmax =2
y_lmin = -2
y_lmax =2
#判断点是否在框中
def judge_frame(point):

    x, y = point[0], point[1]
    flag = (x >= x_min and x <= x_max and y >= y_min and y <= y_max)
    return flag

# 判断两线段相交


def judge_inter(A, B, C, D):

    def vector(piont_1, point_2):   # 输入numpy格式
        return point_2 - piont_1

    def vector_product(vec_1, vec_2):   # 计算向量
        return vec_1[0] * vec_2[1] - vec_2[0] * vec_1[1]

    AC = vector(A, C)
    AD = vector(A, D)
    BC = vector(B, C)
    BD = vector(B, D)
    CA = vector(C, A)
    CB = vector(C, B)
    DA = vector(D, A)
    DB = vector(D, B)

    # 相交返回true
    return (vector_product(AC, AD) * vector_product(BC, BD) <= 0 ) \
           and (vector_product(CA, CB) * vector_product(DA, DB) <= 0)


# 判断得出两线段的交点
def intersection(point_1, point_2):
    point_bound = [[[x_min, y_min], [x_max, y_min]], [[x_max, y_min], [x_max, y_max]],
                   [[x_min, y_max], [x_max, y_max]], [[x_min, y_max], [x_min, y_min]]]

    for line in point_bound:
        if judge_inter(point_1, point_2, line[0], line[1]):
            x1, x2, x3, x4 = point_1[0], point_2[0], line[0][0], line[1][0]
            y1, y2, y3, y4 = point_1[1], point_2[1], line[0][1], line[1][1]
            px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
            py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
            return [px, py]

# 求射线方程
def ray(barr, piont):

    # 计算障碍的中垂线
    def medLine(x1, y1, x2, y2):
        A = 2 * (x2 - x1)
        B = 2 * (y2 - y1)
        C = x1 ** 2 - x2 ** 2 + y1 ** 2 - y2 ** 2
        return A, B, C
    A, B, C = medLine(barr[0][0], barr[0][1], barr[1][0], barr[1][1])
    return [A, B, C]

#判断两线段是否相交
def Intersect(l1, l2):
    v1 = (l1[0] - l2[0], l1[1] - l2[1])
    v2 = (l1[0] - l2[2], l1[1] - l2[3])
    v0 = (l1[0] - l1[2], l1[1] - l1[3])
    a = v0[0] * v1[1] - v0[1] * v1[0]
    b = v0[0] * v2[1] - v0[1] * v2[0]

    temp = l1
    l1 = l2
    l2 = temp
    v1 = (l1[0] - l2[0], l1[1] - l2[1])
    v2 = (l1[0] - l2[2], l1[1] - l2[3])
    v0 = (l1[0] - l1[2], l1[1] - l1[3])
    c = v0[0] * v1[1] - v0[1] * v1[0]
    d = v0[0] * v2[1] - v0[1] * v2[0]

    if a*b < 0 and c*d < 0:
        return True
    else:
        return False

# 判断直线与线段相交并求出交点
def ray_inter_point(ray, point, barr):
    point_bound = [[[x_min, y_min], [x_max, y_min]], [[x_max, y_min], [x_max, y_max]],
                   [[x_min, y_max], [x_max, y_max]], [[x_min, y_max], [x_min, y_min]]]
    list_inter = []
    for bound in point_bound:
        sPoint, ePoint = bound[0], bound[1]
        line = [sPoint[1] - ePoint[1], ePoint[0] - sPoint[0], sPoint[0] * ePoint[1] - ePoint[0] * sPoint[1]]

        a0, b0, c0 = ray[0], ray[1], ray[2]
        a1, b1, c1 = line[0], line[1], line[2]

        D = a0 * b1 - a1 * b0
        x = (b0 * c1 - b1 * c0) / D
        y = (a1 * c0 - a0 * c1) / D

        list_inter.append([x, y])
    result=[]
    for i in list_inter:
            result.append(i)
    return(result)

path="C:/Users/gaoxi/Desktop/data/input.png"
# 使用 make_classification 创建数据

def save_point(self,vor):
		with open('C:/Users/gaoxi/Desktop/data/vor/input_vor.txt','w',encoding='utf-8') as file:
			 #vor.vertices
			 for i in  vor.vertices:
				 file.write(str(i[0])+"  "+str(i[1])+'\n')




#points=[]
#for i in range(num):
    
#        c=a + (b-a)*np.random.random()
#        d=a + (b-a)*np.random.random()
#        points.append([c,d])
#points = np.array(points)


points = np.load('C:/Users/gaoxi/Desktop/data/data/pose_det_results_list.npy')
barr_center = points


# 计算Voronoi图


vor = Voronoi(barr_center)




vertices, ridge_vertices = [], []

my_dict={}
new_dict = []

for k,v in vor.ridge_dict.items():
    my_dict[str(v[0])+str(v[1])]=k

    if -1 in v:
        new_dict.append(list(k))



print("my_dict",my_dict)
vers=[]

pots=[]

###   l1 [xa, ya, xb, yb]   l2 [xa, ya, xb, yb]

#求解voronio线段
for ver_rela in vor.ridge_vertices:
    print("ver_rela:",ver_rela)

    if -1 in ver_rela:
        continue
    else:
        # 两个都在
      
            if vor.vertices[ver_rela[0]].tolist() not in vertices:
                vertices.append(vor.vertices[ver_rela[0]].tolist())
            if vor.vertices[ver_rela[1]].tolist() not in vertices:
                vertices.append(vor.vertices[ver_rela[1]].tolist())
            pots.append(my_dict[str(ver_rela[0])+str(ver_rela[1])])
            vers.append([vor.vertices[ver_rela[0]].tolist(),vor.vertices[ver_rela[1]].tolist()])
        # 一个都不在
#求解voronio射线
for ver_rela in vor.ridge_vertices:
  #  print("ver_rela:",ver_rela)
    if -1 in ver_rela:
        pots.append(my_dict[str(ver_rela[0])+str(ver_rela[1])])
        temp = [0, 1]
        temp.pop(ver_rela.index(-1))
        if judge_frame(vor.vertices[ver_rela[temp[0]]])  or 1:
            # 与边界的交点
            barr_ind = new_dict.pop(0)
            points1=vor.vertices[ver_rela[temp[0]]].tolist()
            barr = [vor.points[barr_ind[0]], vor.points[barr_ind[1]]]
            f_ray = ray(barr, vor.vertices[ver_rela[temp[0]]])  # 改为直线方程
          #  print(f_ray)
            inter = ray_inter_point(f_ray, vor.vertices[ver_rela[temp[0]]], barr)
            points2_list=inter

            for i in points2_list:
                l1=[points1[0],points1[1],i[0],i[1]]
                flag=0
                #plt.plot([i[0], points1[0]],
                #               [i[1], points1[1]],
                #              color = 'r')
                for pointsz in vers:
                    l2=[pointsz[0][0],pointsz[0][1],pointsz[1][0],pointsz[1][1]]
                    if  Intersect(l1,l2) :
                        flag=1 
                        break                   
                if flag==0 :
                     # print("true")
                      vertices.append(i)
                      vers.append([points1,i])
                      break


            #print("points1:",points1)
            #print("points2:",points2_list)

       

vertices = np.array(vertices)


ridge_vertices = np.array(ridge_vertices)
#绘图
def test1():
    
    for i in range(num):
  
        plt.annotate(str(i), (vor.points[i][0], vor.points[i][1]), size = 10)

    for i in range(len(vor.vertices)):
  
        plt.annotate(str(i), (vor.vertices[i][0], vor.vertices[i][1]), size = 10,color='r')


    plt.xlim((-4, 4))
    plt.ylim((-4, 4))
    plt.scatter(vertices[:, 0], vertices[:, 1])
    plt.scatter(points[:, 0], points[:, 1])

    for pointsz in vers:
        plt.plot([pointsz[0][0], pointsz[1][0]],
                 [pointsz[0][1], pointsz[1][1]],
                 color = 'k')

  #  voronoi_plot_2d(vor)
   # print(vers)
    #print(pots)
#plt.show()
test1()################################################
x_list=np.linspace(x_lmin, x_lmax, num=divide_num)
y_list=np.linspace(y_lmin,  x_lmax, num=divide_num)
print("x_list",x_list)
print("y_list",y_list)

frame=[]


for i in range(len(x_list)-1):
    x1=x_list[i]
    x2=x_list[i+1]
    for j in range(len(y_list)-1):
        y1=y_list[j]
        y2=y_list[j+1]
        frame.append([[x1,y1],[x2,y1],[x2,y2],[x1,y2]])

print(frame)

def test2():
    for points in frame:
        for i in range(4):
            if i<3:
                 plt.plot([points[i][0], points[i+1][0]],
                         [points[i][1], points[i+1][1]],
                         color = 'k')
            else:
                  plt.plot([points[i][0], points[0][0]],
                         [points[i][1], points[0][1]],
                         color = 'k')
    plt.show()
###   l1 [xa, ya, xb, yb]   l2 [xa, ya, xb, yb]

index=[]


#检测框中通过那些射线或者线段
def  frame_points():
    for j in range(len(frame)):
        print(j)
        fra=frame[j]
        x_minz=fra[0][0]
        x_maxz=fra[1][0]
        y_minz=fra[0][1]
        y_maxz=fra[2][1]
        a=[]
        for i in range(len(vers)):
            #print(vers[i])
            posts=vers[i]
            l2=[posts[0][0],posts[0][1],posts[1][0],posts[1][1]]
            if  x_minz<posts[0][0] and posts[0][0]<x_maxz and x_minz<posts[1][0] and posts[1][0]<x_maxz:
                if y_minz<posts[0][1] and posts[0][1]<y_maxz and y_minz<posts[1][1] and posts[1][1]<y_maxz:
                   
                    a.append(pots[i][0])
                    a.append(pots[i][1])
                    continue
            for z in range(4):
                if z<3:
                     l1=[fra[z][0],fra[z][1],fra[z+1][0],fra[z+1][1]]
                     if Intersect(l1, l2):
                         a.append(pots[i][0])
                         a.append(pots[i][1])
                         break
                else:
                     l1=[fra[z][0],fra[z][1],fra[0][0],fra[0][1]]
                     if Intersect(l1, l2):
                         a.append(pots[i][0])
                         a.append(pots[i][1])
                         break
        if len(a)==0:
            x=(x_minz+x_maxz)/2
            y=(y_minz+y_maxz)/2
            min_distance=(points[0][0]-x)**2+(points[0][1]-y)**2
            index_min=0
            for k in range(1,len(points)):
                if  (points[k][0]-x)**2+(points[k][1]-y)**2<min_distance:
                    index_min=k
                    min_distance=(points[k][0]-x)**2+(points[k][1]-y)**2
            index.append([index_min])
        else:
              a=list(set(a))
              index.append(a)



frame_points()
po=[1.48,0.52]
#寻找查找点在那个框中
def find(po):
    position=0
    for i in range(len(x_list)-1):
        x1=x_list[i]
        x2=x_list[i+1]
        if x1<=po[0] and po[0]<=x2:

            for j in range(len(y_list)-1):
                y1=y_list[j]
                y2=y_list[j+1]
                print(y1,y2)
                if  y1<=po[1] and po[1]<=y2:
                    return position
                else: 
                    position=position+1
              #  print("position",position)
        else:
          #  print("sucess")
            position=position+len(x_list)-1
          #  print("position",position)
    
position=find(po)



print("position:",position)

print("index of position is:",index[position])


#寻找最近点得索引
def find_min_index(po,index_list):
            x=po[0]
            y=po[1]
            min_distance=(points[index_list[0]][0]-x)**2+(points[index_list[0]][1]-y)**2
            index_min=index_list[0]
            for k in range(1,len(index_list)):
                if  (points[index_list[k]][0]-x)**2+(points[index_list[k]][1]-y)**2<min_distance:
                    index_min=index_list[k]
                    min_distance=(points[index_list[k]][0]-x)**2+(points[index_list[k]][1]-y)**2
            return index_min


find_index=find_min_index(po,index[position])

print("find_index:",find_index)
test2()


os.system("pause")
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值