#find the nearest point in two dimensions
#1 first if there are only two points, then calculate the distance directly
#2 if there are three points, get the nearest point
#3 if there are more than three points
#1 sort the point by the x value
#2 sort the points by the y value
#3 divide the points by the middle value of x
#4 get the nearest point of the two parts,get the pair whose distance is less, marked as D
import math
import unittest
def merge(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
list3 = []
i = list1_begin
j = list2_begin
while (i<list1_end) and (j < list2_end):
if list1[i] < list2[j]:
list3.append(list1[i])
i = i+1
else:
list3.append(list2[j])
j = j+1
while(i<list1_end):
list3.append(list1[i])
i = i+1
while(j<list2_end):
list3.append(list2[j])
j = j+1
return list3
def mergeByX(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
list3 = []
i = list1_begin
j = list2_begin
while (i<list1_end) and (j < list2_end):
if list1[i].x < list2[j].x:
list3.append(list1[i])
i = i+1
else:
list3.append(list2[j])
j = j+1
while(i<list1_end):
list3.append(list1[i])
i = i+1
while(j<list2_end):
list3.append(list2[j])
j = j+1
return list3
def array_need_to_be_merged(array, begin, end):
list1 = []
i = begin
while(i<end):
list1.append(array[i])
i = i+1
return list1
def mergeByY(list1, list2, list1_begin, list1_end, list2_begin, list2_end):
list3 = []
i = list1_begin
j = list2_begin
while (i<list1_end) and (j < list2_end):
if list1[i].p.y < list2[j].p.y:
list3.append(list1[i])
i = i+1
else:
list3.append(list2[j])
j = j+1
while(i<list1_end):
list3.append(list1[i])
i = i+1
while(j<list2_end):
list3.append(list2[j])
j = j+1
return list3
def doMergeByY(origin_array, step):
i = 0
new1 =[]
new2 =[]
length = len(origin_array)
while i + 2*step < length:
list1 = array_need_to_be_merged(origin_array, i, i+step)
list2 = array_need_to_be_merged(origin_array, i+step, i +2*step)
new1 += mergeByY(list1, list2, 0, step, 0, step)
i = i + 2*step
if i+step < length:
list1 = array_need_to_be_merged(origin_array, i, i+step)
list2 = array_need_to_be_merged(origin_array, i+step, length)
new2 += mergeByY(list1, list2, 0, step, 0, length-i-step)
else:
while i < length:
new2.append(origin_array[i])
i = i+1
sorted_array = new1+new2
return sorted_array
def doMergeByX(origin_array, step):
i = 0
new1 =[]
new2 =[]
length = len(origin_array)
while i + 2*step < length:
list1 = array_need_to_be_merged(origin_array, i, i+step)
list2 = array_need_to_be_merged(origin_array, i+step, i +2*step)
new1 += mergeByX(list1, list2, 0, step, 0, step)
i = i + 2*step
if i+step < length:
list1 = array_need_to_be_merged(origin_array, i, i+step)
list2 = array_need_to_be_merged(origin_array, i+step, length)
new2 += mergeByX(list1, list2, 0, step, 0, length-i-step)
else:
while i < length:
new2.append(origin_array[i])
i = i+1
sorted_array = new1+new2
return sorted_array
def merge_sort_by_x(origin_array):
step =1
length = len(origin_array)
sorted_array = origin_array
while step < length:
sorted_array = doMergeByX(sorted_array, step)
step += step
sorted_array = doMergeByX(sorted_array,step)
return sorted_array
def merge_sort_by_y(origin_array):
step =1
length = len(origin_array)
sorted_array = origin_array
while step < length:
sorted_array = doMergeByY(sorted_array, step)
step += step
sorted_array = doMergeByY(sorted_array,step)
return sorted_array
class point_x:
def __init__(self, p, id):
self.p = p
self.id = id
class point_y:
def __init__(self,p, index):
self.p = p
self.index =index
def __str__(self):
return "x:"+str(self.p.x)+"y:"+str(self.p.y)+"index:"+str(self.index)
class test_merge_sort(unittest.TestCase):
def test_do_merge(self):
p1 = point(1,2)
p2 = point(3,4)
p3 = point(7,5)
p4 = point(8,6)
list1 =[p1,p2,p3,p4]
p5 = point(2,3)
p6 = point(4,10)
p7= point(5,9)
p8 = point(6,7)
list2 =[p5,p6,p7,p8]
list3 = list1 + list2
list4 = doMergeByX(list3, 4)
list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
self.assertEqual(list4, list5)
def test_merge_sort_by_x(self):
p1 = point(1,2)
p2 = point(3,4)
p3 = point(7,5)
p4 = point(8,6)
p5 = point(2,3)
p6 = point(4,10)
p7= point(5,9)
p8 = point(6,7)
# p9 =point(6,7)
list4 = merge_sort_by_x([p1,p2,p3,p4,p5,p6,p7,p8])
list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
# print (list5.index(p3))
self.assertEqual(list4, list5)
# def test_merge_sort_by_y(self):
# p1 = point(1,2)
# p2 = point(3,4)
# p3 = point(7,5)
# p4 = point(8,6)
# p5 = point(2,3)
# p6 = point(4,10)
# p7= point(5,9)
# p8 = point(6,7)
# list4 = merge_sort_by_y([p1,p2,p3,p4,p5,p6,p7,p8])
# list5 = [p1,p5,p2,p3,p4,p8,p7,p6]
# self.assertEqual(list4, list5)
def test_merge_sort_by_all(self):
p1 = point(1,2)
p2 = point(3,4)
p3 = point(7,5)
p4 = point(8,6)
p5 = point(2,3)
p6 = point(4,10)
p7= point(5,9)
p8 = point(6,7)
p9 = point(6,6)
# list4 = merge_sort_by_x([p1,p2,p3,p4,p5,p6,p7,p8])
# list5 = [p1,p5,p2,p6,p7,p8,p3,p4]
# origin_array = list4
# array_y =[]
# k=0
# for i in origin_array:
# p = point_y(i,k)
# k=k+1
# array_y.append(p)
# for x in array_y:
# print (x)
# print ("begin:")
# list6 = merge_sort_by_y(array_y)
# for l in list6:
# print (l)
# print (cal_min_distance_of_points(list6))
print("nearest")
print (nearest([p1,p2,p3,p4,p5,p6,p7,p8,p9]))
class point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance(point1, point2):
square_x = math.pow((point1.x - point2.x), 2)
square_y = math.pow((point1.y - point2.y), 2)
return math.sqrt(square_y+square_x)
class test_nearest(unittest.TestCase):
def test_distance(self):
p1 = point(0,4)
p2 = point(3,0)
self.assertEqual(5.0, distance(p1,p2))
# def test_n(self):
# p1 = point(1,2)
# p2 = point(3,4)
# p3 = point(7,5)
# d1 = distance(p1,p2)
# self.assertEqual(d1,find_nearest([p1,p2,p3], 0,2))
def cal_min_distance_of_points(points):
length = len(points)
min_d = 99000000
i=0
while(i< length):
p1 = points[i].p
j =i +1
while(j <length):
p2 = points[j].p
d = distance(p1,p2)
if (d < min_d):
min_d = d
j=j+1
i = i+1
return min_d
def find_nearest(points, point_y, left, right):
if (right-left==1):
return distance(points[left], points[right])
elif(right-left==2):
d1 = distance(points[left], points[left+1])
d2 = distance(points[left], points[left+2])
d3 = distance(points[left+1], points[left+2])
if (d1<d2 and d1 < d3):
return d1
elif (d2<d1 and d2 <d3):
return d2
else:
return d3
else:
m = (left+right)//2
# print ("m")
# print (m)
sorted_array_y = point_y
left_array=[]
right_array=[]
for i in sorted_array_y:
if i.index <= m:
left_array.append(i)
else:
right_array.append(i)
d1 = find_nearest(points, left_array, left, m)
d2 = find_nearest(points, right_array, m+1, right)
min_d=d1
if d2<d1 :
min_d =d2
new_array_for_cal=[]
for i in sorted_array_y:
if (math.fabs(i.p.x - points[m].x)<min_d):
new_array_for_cal.append(i)
d3 = cal_min_distance_of_points(new_array_for_cal)
if d3<min_d:
min_d = d3
return min_d
def nearest(points):
origin_array = merge_sort_by_x(points)
k=0
array_y=[]
for i in origin_array:
p = point_y(i,k)
k = k+1
array_y.append(p)
sorted_array_y = merge_sort_by_y(array_y)
n = len(origin_array)
return find_nearest(origin_array, sorted_array_y, 0, n-1)
if __name__ == "__main__":
unittest.main()