C# 曲线上的点(一) 获取指定横坐标对应的纵坐标值

获取直线上的点,很容易,那曲线呢?二阶贝塞尔、三阶贝塞尔、多段混合曲线,如何获取指定横坐标对应的纵坐标?

如下图形:

 实现方案

曲线上的点集

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 else30  {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.Blue40  };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

相关文章