C# 曲線上的點(一) 獲取指定橫座標對應的縱座標值
獲取直線上的點,很容易,那曲線呢?二階貝塞爾、三階貝塞爾、多段混合曲線,如何獲取指定橫座標對應的縱座標?
如下圖形:
實現方案
曲線上的點集
Geometry提供了一個函式GetFlattenedPathGeometry,可以獲取其繪製後顯示的多邊形。
我們可以通過其Figures -> PathSegment -> Point,
1public List<Point> GetPointsOnPath(Geometry geometry) 2{ 3List<Point> points = new List<Point>(); 4PathGeometry pathGeometry = geometry.GetFlattenedPathGeometry(); 5foreach (var figure in pathGeometry.Figures) 6{ 7var ordinateOnPathFigureByAbscissa = GetOrdinateOnPathFigureByAbscissa(figure); 8points.AddRange(ordinateOnPathFigureByAbscissa); 9} 10return points; 11} 12private List<Point> GetOrdinateOnPathFigureByAbscissa(PathFigure figure) 13{ 14List<Point> outputPoints = new List<Point>(); 15Point current = figure.StartPoint; 16foreach (PathSegment s in figure.Segments) 17{ 18PolyLineSegment segment = s as PolyLineSegment; 19LineSegment line = s as LineSegment; 20Point[] points; 21if (segment != null) 22{ 23points = segment.Points.ToArray(); 24} 25else if (line != null) 26{ 27points = new[] { line.Point }; 28} 29else 30{ 31throw new InvalidOperationException("尼瑪!"); 32} 33foreach (Point next in points) 34{ 35var ellipse = new Ellipse() 36{ 37Width = 6, 38Height = 6, 39Fill = Brushes.Blue 40}; 41Canvas.SetTop(ellipse, next.Y); 42Canvas.SetLeft(ellipse, next.X); 43ContentCanvas.Children.Add(ellipse); 44current = next; 45} 46} 47return outputPoints; 48}
最終介面顯示,獲取的點集是如下佈局的:
曲線上的點
我們發現,拐角越大,獲取的點越密集。所以可以看出,角度變化越大,需要的點越密集。
直線通過斜率很容易獲取橫座標對應的縱座標,那麼這有如此多點的曲線呢?
我們是不是可以曲線救國,通過相鄰的倆個點畫直接,從而獲取倆點間的點座標呢?我們來嘗試下~
還是原來的程式碼,傳入一個X座標引數即可。
然後倆點之間,獲取X座標對應的Y座標:
1private bool TryGetOrdinateOnVectorByAbscissa(Point start, Point end, double abscissa, out double ordinate) 2{ 3ordinate = 0.0; 4if ((start.X < end.X && abscissa > start.X && abscissa < end.X) || 5(start.X > end.X && abscissa < start.X && abscissa > end.X)) 6{ 7var xRatio = (abscissa - start.X) / (end.X - start.X); 8var yLength = end.Y - start.Y; 9var y = yLength * xRatio + start.Y; 10ordinate = y; 11return true; 12} 13return false; 14}
點選視窗,在曲線上,獲取點選處X座標對應的點。效果圖如下:
Github:Demo