有一條曲線是由很多個點組成,假設由於某種原因,不能使用到所有點,只使用其中的部分點來描述這條曲線的特徵。
工具/原料
Excel
方法/步驟
原理大概如下,首先連線曲線的兩個端點(1,2),連線一條直線,然後對曲線中間的各個點做這條曲線的垂直線,取最大的點(3),然後連線1-2,2-3形成兩段折線。
然後將曲線上所有點向這段折線做垂直線取距離,距離最遠的為第4點,然後連線4個點,形成了三段曲線,再次將曲線上的所有點向折線做垂直距離,取最遠的為第5個點,依次類推,直至取出所需要的點。
因為涉及大量的重複執行內容,因此此方法只適用於使用程式設計方法實現,具體實現程式碼見下,VBA程式設計方法(VBA是什麼?VBA是巢狀在Excel中的內建程式設計模組,具體自行網路查詢)。
'記錄第一個點和最後一個點的坐滿到陣列中;
'首先用直線連線首點和末點,然後計算中間所有點到直線的垂直距離
'選取所有距離中最大的一個點,記錄為第三個點,然後將第三點更新到陣列中
'連線1、3,3、2,行成兩條直線,然後再次比對所有資料點到直線的垂直距離
'然後在所有點中,選取出最大的點,然後記為第四個點,更新到陣列中
'然後用直線連線四個點…依次類推,直至選取出10個點。
Public myarr(1 To 10, 1 To 2)
'定義全域性變數陣列
Sub index()
'主引導
For i = 1 To 10
myarr(i, 1) = 0
myarr(i, 2) = 0
Next
'清除之前的陣列快取
irow = Sheet1.Range("B65536").End(xlUp).Row
'尋找資料總行數
myarr(1, 1) = Sheet1.Cells(4, 7)
'橫座標是棒位,縱座標是功率
myarr(1, 2) = Sheet1.Cells(4, 6)
myarr(2, 1) = Sheet1.Cells(irow, 7)
myarr(2, 2) = Sheet1.Cells(irow, 6)
'初始化陣列,定義前兩個陣列為首點和末點
10 For i = 5 To irow - 1
x = Sheet1.Cells(i, 7)
'需要計算的每一個數據點的橫座標
y = Sheet1.Cells(i, 6)
'需要計算的每一個數據點的縱座標
For n = 1 To 10
'然後在資料中選擇對應的直線的端點
If x >= myarr(n, 1) Then
x1 = myarr(n - 1, 1)
y1 = myarr(n - 1, 2)
'前面一個端點的橫縱座標
x2 = myarr(n, 1)
y2 = myarr(n, 2)
'後面一個端點的橫縱座標
a = y2 - y1
b = x1 - x2
c = (x2 - x1) * y1 - (y2 - y1) * x1
'計算兩個點所確定的直線方程中的A、B和C,即Ax+by+C=0形式
d = Abs((a * x + b * y + c) / (Sqr(a ^ 2 + b ^ 2)))
'根據公式計算點到直線的距離
Sheet1.Cells(i, 8) = d
'在第三列中顯示距離
If d >= maxd Then
maxd = d
maxx = x
maxy = y
maxi = i
maxn = n
End If
'尋找距離中最大值
Exit For
End If
Next
Next
For m = 10 To maxn + 1 Step -1
myarr(m, 1) = myarr(m - 1, 1)
myarr(m, 2) = myarr(m - 1, 2)
'要從大到小,將後面的統統往後移一位
Next
myarr(maxn, 1) = Sheet1.Cells(maxi, 7)
myarr(maxn, 2) = Sheet1.Cells(maxi, 6)
'再將第n個點替換掉
If myarr(10, 2) > 0 Then
For i = 1 To 10
Sheet1.Cells(i + 16, 10) = myarr(i, 1)
Sheet1.Cells(i + 16, 11) = myarr(i, 2)
Next
Exit Sub
Else
maxd = 0
maxx = 0
maxy = 0
maxi = 0
maxn = 0
GoTo 10
End If
End Sub
資料的存放如下:
自動計算的結果作圖如下,可見符合的很好: