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

如下图形:

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

 实现方案

曲线上的点集

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     }

最终界面显示,获取的点集是如下布局的:

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

曲线上的点

我们发现,拐角越大,获取的点越密集。所以可以看出,角度变化越大,需要的点越密集。

直线通过斜率很容易获取横坐标对应的纵坐标,那么这有如此多点的曲线呢?

我们是不是可以曲线救国,通过相邻的俩个点画直接,从而获取俩点间的点坐标呢?我们来尝试下~

还是原来的代码,传入一个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坐标对应的点。效果图如下:

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

 Github: Demo

03-26 10:59