項目要求,現需要一個能根據Excel的坐標數據,在圖像上進行描點連線,並且連線的方式是以所有的點進行最大輪廓連線。現在實現了要求,但是由於代碼寫得太亂,我只是簡單的說一下實現算法就好了,代碼也會貼出來,時間過於久,我也有些地方忘記了,但是整體算法還是記得的~
下面開始簡單的說一下:
首先,所有點的坐標數據就像下圖所示:
問題:如何將所有的點以最大的輪廓連線呢??
思路:應該是數學問題,如何將坐標列表重新排序成以最大輪廓的坐標列表,因為matplotlib庫可以根據一個列表里面的坐標數據直接生成連線。
我的排序算法是:
1.首先,將所有坐標進行排序,可以以x排序,然后找到最左邊的坐標點和最右邊的坐標;
2.以最左邊和最右邊的坐標進行求解方程,兩點確定一條直線,就是求該直線的方程;
3.將剩余的所有坐標x代入步驟2的方程組,求出解和坐標y進行比較,將線下方的點和上方的點坐標分別求出來,然后存入一個列表備份;
4.將下方坐標的列表進行排序,由小到大,然后存入一個最終列表中,最終列表第一個肯定是最左邊的點,然后就是下方的點;
5.將下方坐標的列表進行排序,由大到小,然后繼續分別存入最終列表,最后在最終列表中在加上最左邊的坐標點,使連線閉合;
6.然后用matplotlib里面的pyplot函數,將最終列表連線即可。
上面的算法我寫在了一個函數里面,這是非常不對的,但是如今還是不想將其整理出來,哈哈,思維不亂就行~~

1 try: 2 # 先提取成一個個位置坐標 3 coordinate = [] 4 for i in range(len(x)): 5 coordinate.append([x[i], y[i]]) 6 7 # print(coordinate) 8 9 # 這是基准列表,x最小最大,y最小最大 10 sort_list = [] 11 # 剩下的坐標數據 12 ret_list = [] 13 # 下方的點數據 14 under_list = [] 15 # 總的排序結果 16 final_list = [] 17 # 臨時列表 18 temp = [] 19 20 # 下方的點 21 down_dot = [] 22 # 上方的點 23 up_dot = [] 24 25 y_max_and_y_min = [] 26 27 # 進行x排序 28 sort_x(coordinate) 29 30 # 排序完成肯定是第一個最小,最后一個最大,將這兩個數據添加到確定的基准列表里面 31 sort_list.append(coordinate[0]) 32 sort_list.append(coordinate[len(coordinate) - 1]) 33 34 # 這下面進行以y大小進行排序,,重新存儲在一個新列表里面 35 sort_y(coordinate) 36 y_max_and_y_min.append(coordinate[0]) 37 y_max_and_y_min.append(coordinate[len(coordinate) - 1]) 38 39 # 這句代碼實現的功能是和基准列表進行比對,求除了基准列表剩下的所有坐標數據 40 ret_list = [item for item in coordinate if item not in sort_list] + [item for item in sort_list if 41 item not in coordinate] 42 43 print("確定的坐標:" + str(sort_list)) 44 45 print("剩余的坐標: " + str(ret_list)) 46 47 # 最左坐標 48 left_x = sort_list[0][0] 49 left_y = sort_list[0][1] 50 51 # 最右坐標 52 right_x = sort_list[1][0] 53 right_y = sort_list[1][1] 54 55 # 最下坐標 56 down_x = y_max_and_y_min[0][0] 57 down_y = y_max_and_y_min[0][1] 58 59 # 最上坐標 60 up_x = y_max_and_y_min[1][0] 61 up_y = y_max_and_y_min[1][1] 62 63 # 實現兩點之間的公式 64 # y = k*x + b 65 66 # 總判斷公式,,蠻重要 67 k = (right_y - left_y) / (right_x - left_x) 68 b = left_y - k * left_x 69 70 print("y=" + str(k) + "x" + '+' + str(b)) 71 72 # 開始進行比對,判斷剩余列表里面的每一個點,如果在直線下方,就加入下方列表里面 73 for i in range(len(ret_list)): 74 # print(ret_list[i]) 75 if (under(k, b, ret_list[i])): 76 under_list.append(ret_list[i]) 77 78 print("下面列表的數據", under_list) 79 80 # 對下方列表再以x為基准進行排序 81 under_list = sort_x(under_list) 82 83 # 排序完成直接都添加到確定的列表里面,先添加一個最左的坐標,在循環結束之后再添加最右的數據 84 final_list.append(sort_list[0]) 85 86 for t in under_list: 87 final_list.append(t) 88 # 邊添加還邊讓數據從剩余列表里面去掉 89 ret_list.remove(t) 90 91 final_list.append(sort_list[1]) 92 93 ################################################################################ 94 # 到此,,下方的排序已經結束 95 print(final_list) 96 num_under = len(final_list) 97 98 print(ret_list) 99 100 # 剩下的列表進行冒泡排序,還是由小到大,但是最后翻轉一下列表就可以 101 ret_list = sort_x(ret_list) 102 ret_list = (list(reversed(ret_list))) 103 104 print(ret_list) 105 106 for t in ret_list: 107 """將剩下的坐標添加到處理后的列表里面""" 108 final_list.append(t) 109 110 # 這個是再補一個坐標,使曲線閉合 111 final_list.append(sort_list[0]) 112 113 print(ret_list) 114 print("最終列表-----------", final_list) 115 116 # 分離后的x,y坐標數據 117 final_x = [] 118 final_y = [] 119 120 for i in range(len(final_list)): 121 """將坐標數據從新分離成兩個列表""" 122 final_x.append(final_list[i][0]) 123 final_y.append(final_list[i][1]) 124 125 # print(final_x) 126 # print(final_y) 127 128 # 在這需要將列表翻裝一下,調試好久才發現 129 final_list = list(reversed(final_list)) 130 131 # 將圖像顯示出來 132 # showResult(final_x, final_y,'title', 'x', 'y')
連線起來的最終效果圖:
項目要求2: 判斷一個點是否在所圍的輪廓內。
實現方法:
1.首先判斷是否在x坐標是否在最左,最右之間,y坐標是否在最上,最下坐標之間,如果不在,直接判定不在;
2.判斷是否為原來數據的點,如果是直接判定在輪廓內;
3.然后將需要判斷的坐標代入最左最右組成的方程上,判斷該坐標是該直線的上方還是下方。
4.若在下方,判斷在下方的坐標點哪兩個坐標之間,根據左右兩個坐標點進行直線方程的求解,然后將需判斷坐標的x代入,求解是否大於y坐標,如果大於就判定是在輪廓里面;
5.若在上方,判定條件改成小於才在輪廓里面;
代碼如下:

# 下面進行判斷一個點是否在圈內 # x_judge = 0.396 # y_judge = 0.592 x_get = self.input_x.text() y_get = self.input_y.text() if (len(x_get)==0): QMessageBox.critical(self, 'reslult', '請輸入x,y') x_judge = final_x[0] y_judge = final_y[0] judge = [float(x_judge), float(y_judge)] self.input_x.setText(str(x_judge)) self.input_y.setText(str(y_judge)) else: x_judge = float(x_get) y_judge = float(y_get) judge = [float(x_judge), float(y_judge)] if judge == sort_list[0] or judge == sort_list[1] or judge == y_max_and_y_min[0] or judge == \ y_max_and_y_min[1]: """先判斷是否是基准點""" print("在--相等") flag=True QMessageBox.critical(self,'reslult' , 'in') elif is_midle(judge[0], left_x, right_x) and is_midle(judge[1], down_y, up_y): """先判斷是否在大圈之內""" # 先判斷是在上方的點還是上方的點,如果在下方用下方的公式,否則,相反 if not under(k, b, judge): print("在下方") for i in range(len(down_dot) - 1): if is_midle(judge[0], down_dot[i][0], down_dot[i + 1][0]): # print(down_dot[i][0],down_dot[i+1][0]) print(down_dot[i], down_dot[i + 1]) k_test, b_test = generate_equation(down_dot[i], down_dot[i + 1]) print(k_test, b_test) if not (under(k_test, b_test, judge)): print("不在") flag = False QMessageBox.critical(self,'reslult' , 'not in') break else: print("在") flag = True QMessageBox.critical(self, 'reslult' ,'in') break else: pass elif not up_under(k, b, judge): print("在上方") for i in range(len(up_dot) - 1): if is_midle(judge[0], up_dot[i + 1][0], up_dot[i][0]): print(up_dot[i], up_dot[i + 1]) k_test, b_test = generate_equation(up_dot[i], up_dot[i + 1]) print(k_test, b_test) if (up_under(k_test, b_test, judge)): print("在") flag = True QMessageBox.critical(self, 'reslult' ,'in') break else: print("不在") flag=False QMessageBox.critical(self,'reslult' , 'not in') break else: pass else: print("不在") flag = False QMessageBox.critical(self,'reslult' ,'not in') if (flag == True): plt.scatter(x_judge, y_judge, color='green', marker='o') elif (flag == False): plt.scatter(x_judge,y_judge,color='red',marker='o') plt.plot(final_x, final_y, color='black', linewidth=2.0) plt.scatter(final_x, final_y, color='black', marker='+') plt.title(str(flag)) plt.xlabel('x') plt.ylabel('y') for x1, y1 in zip(final_x, final_y): plt.text(x1,y1, str(x1), ha='center', va='bottom', fontsize=10.5) for x2, y2 in zip(final_x, final_y): plt.text(x2+0.1,y2, str(y2), ha='center', va='bottom', fontsize=10.5) plt.show()
至此,項目的要求算為完成,然后組成了GUI界面,所用的庫是PYQT5。其實這個庫真的挺好用的。
說下打包成exe 的時候遇到的問題,最新版的matplotlib庫用pyinstaller根據打包不成功,如果按照網上的說法一個個依賴去尋找,太過於麻煩,
我查了半天資料,發現有個大佬說舊版的matplotlib可以,我連忙卸載新版的,下載舊版的,打包,,成功。就很完美~~~
至此,項目結束。
完成代碼我放在了我的網盤上,有點點亂~下面是網盤鏈接:
https://wws.lanzous.com/i7xTKiz7o7g