This question was also asked by others. I have been thinking about it for some time and hope to get a better method.
The problem is that there are some discrete points which are to be merged into a curve in the coordinate system. One of them looks like a straight line, now, the starting and ending coordinates of this line are required, and the equation of this line is obtained. for example:
We can see with the naked eye that the labeled section is similar to a straight line. The problem is thatProgramFind out.
My thoughts
In my opinion, if this line exists, then the point in this line should be "similar" in the Y deviation between the adjacent two, to what extent is the similarity required, a "allowable error value" is required ". in this allowable error value, try to put this curve as much as possibleContinuous pointDraw a straight line, and then use the least square method to obtain the linear equation based on these points.
Obtain these consecutive points:
Static List < Point > Getsequential ( List <Point > Points, Double Allowlapse ){ VaR Resultlist = New List < List < Point >> (); VaR Currentresult = New List < Point > (); Currentresult. Add (points [0]); For ( Int I = 1; I <points. Count; I ++ ){ // If the height difference between this vertex and the previous vertex is within a reasonable range If (Points [I]. Y-points [I-1]. Y) <allowlapse) currentresult. Add (points [I]); Else {Resultlist. Add (currentresult); currentresult = New List < Point > (); Currentresult. Add (points [I]) ;}} resultlist. Add (currentresult ); // Select the group of data with the most vertices from the set List < Point > Result = resultlist. orderbydescending (list => list. Count). First (); Return Result ;}
The definition of Point class is very simple:
Internal classPoint{Public doubleX {Get;Private set;}Public doubleY {Get;Private set;}PublicPoint (DoubleX,DoubleY) {x = x; y = y ;}}
Based on some vertices, use the least square method to obtain the straight line:
Static void Leastsquare ( List <Point > Points ){ Double Avgx = points. Average (point => point. X ); Double Avgy = points. Average (point => point. y ); Double Numerator = points. sum (point => (point. X-avgx) * (point. Y-avgy )); Double Denominator = points. sum (point => (point. X-avgx) * (point. X-avgx )); Double K = numerator/denominator; // Slope Double X0 = avgy-K * avgx; // Output the result here for convenience of testing Console . Writeline ( "Y = {0} + {1} X \ nstart ({2}, {3}) \ tend ({4}, {5}) \ npoints count: {6 }" , X0, K, points. first (). x, points. first (). y, points. last (). x, points. last (). y, points. count );}
Test Results
Y difference allowed |
Equation |
Start Point |
Endpoint |
Included points |
0.005 |
Y = 0.27 + 0.45x |
(0.13, 0.328201) |
(0.15, 0.337173) |
3 |
0.010 |
Y = 0.25 + 0.60x |
(0.12, 0.318606) |
(0.17, 0.350823) |
6 |
0.015 |
Y = 0.48 + 1.08x |
(0.54, 1.060612) |
(0.77, 1.318348) |
24 |
0.020 |
Y = 0.23 + 1.46x |
(0.28, 0.611221) |
(0.77, 1.318348) |
50 |
0.025 |
Y = 0.22 + 1.48x |
(0.26, 0.56426) |
(0.77, 1.318348) |
52 |
0.030 |
Y = 0.13 + 1.64x |
(0.09, 0.255596) |
(0.77, 1.318348) |
69 |
0.035 |
Y = 0.13 + 1.64x |
(0.08, 0.222174) |
(0.77, 1.318348) |
70 |
0.040 |
Y = 0.12 + 1.65x |
(0.07, 0.183729) |
(0.77, 1.318348) |
71 |
By comparing the illustrations at the beginning of this article, we can see that the "y difference allowed" is between 0.020 and 0.025, and the data obtained is relatively reliable. however, there is another problem with this approach. If each vertex is a little higher than the previous vertex (within the allowed range of the y difference), there will be more accumulation at the same time. From the overall perspective, the line composed of these points is an upward parabolic line.AlgorithmThere is a problem.
If you have any ideas, please refer to the appendix for data download (the data only contains the Y coordinate value, X starts from 0.0, and the adjacent two points x interval is 0.01 ).