1. 程式人生 > >C# 曲線上的點(一) 獲取指定橫坐標對應的縱坐標值

C# 曲線上的點(一) 獲取指定橫坐標對應的縱坐標值

child tps spa 參數 ali info left for int end

獲取直線上的點,很容易,那曲線呢?二階貝塞爾、三階貝塞爾、多段混合曲線,如何獲取指定橫坐標對應的縱坐標?

如下圖形:

技術分享圖片

實現方案

曲線上的點集

Geometry提供了一個函數GetFlattenedPathGeometry,可以獲取其繪制後顯示的多邊形。

我們可以通過其Figures -> PathSegment -> Point,

 1     public List<Point> GetPointsOnPath(Geometry geometry)
 2     {
 3         List<Point> points = new
List<Point>(); 4 PathGeometry pathGeometry = geometry.GetFlattenedPathGeometry(); 5 foreach (var figure in pathGeometry.Figures) 6 { 7 var ordinateOnPathFigureByAbscissa = GetOrdinateOnPathFigureByAbscissa(figure); 8 points.AddRange(ordinateOnPathFigureByAbscissa);
9 } 10 return points; 11 } 12 private List<Point> GetOrdinateOnPathFigureByAbscissa(PathFigure figure) 13 { 14 List<Point> outputPoints = new List<Point>(); 15 Point current = figure.StartPoint; 16 foreach (PathSegment s in
figure.Segments) 17 { 18 PolyLineSegment segment = s as PolyLineSegment; 19 LineSegment line = s as LineSegment; 20 Point[] points; 21 if (segment != null) 22 { 23 points = segment.Points.ToArray(); 24 } 25 else if (line != null) 26 { 27 points = new[] { line.Point }; 28 } 29 else 30 { 31 throw new InvalidOperationException("尼瑪!"); 32 } 33 foreach (Point next in points) 34 { 35 var ellipse = new Ellipse() 36 { 37 Width = 6, 38 Height = 6, 39 Fill = Brushes.Blue 40 }; 41 Canvas.SetTop(ellipse, next.Y); 42 Canvas.SetLeft(ellipse, next.X); 43 ContentCanvas.Children.Add(ellipse); 44 current = next; 45 } 46 } 47 return outputPoints; 48 }

最終界面顯示,獲取的點集是如下布局的:

技術分享圖片

曲線上的點

我們發現,拐角越大,獲取的點越密集。所以可以看出,角度變化越大,需要的點越密集。

直線通過斜率很容易獲取橫坐標對應的縱坐標,那麽這有如此多點的曲線呢?

我們是不是可以曲線救國,通過相鄰的倆個點畫直接,從而獲取倆點間的點坐標呢?我們來嘗試下~

還是原來的代碼,傳入一個X坐標參數即可。

然後倆點之間,獲取X坐標對應的Y坐標:

 1         private bool TryGetOrdinateOnVectorByAbscissa(Point start, Point end, double abscissa, out double ordinate)
 2         {
 3             ordinate = 0.0;
 4             if ((start.X < end.X && abscissa > start.X && abscissa < end.X) ||
 5                 (start.X > end.X && abscissa < start.X && abscissa > end.X))
 6             {
 7                 var xRatio = (abscissa - start.X) / (end.X - start.X);
 8                 var yLength = end.Y - start.Y;
 9                 var y = yLength * xRatio + start.Y;
10                 ordinate = y;
11                 return true;
12             }
13             return false;
14         }

點擊窗口,在曲線上,獲取點擊處X坐標對應的點。效果圖如下:

技術分享圖片

Github: Demo

C# 曲線上的點(一) 獲取指定橫坐標對應的縱坐標值