Obtain the ordinate value corresponding to the specified abscissa from the point on the curve

It's easy to get a point on a straight line. What about a curve? How to get the ordinates corresponding to the specified abscissa for the second-order Bezier, third-order Bezier, and multi segment mixed curves?

The following figure:

Implementation plan

Point set on curve

Geometry provides a function GetFlattenedPathGeometry to get the polygons displayed after drawing.

We can use 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("Fuck!");
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     }

The final interface shows that the acquired point set is laid out as follows:

 

Point on curve

We found that the larger the corner, the denser the points. So it can be seen that the larger the angle change, the denser the points needed.

It's easy to get the vertical coordinate corresponding to the abscissa through the slope of a straight line, so what about the curve with so many points?

Can we save our country by curving and drawing two adjacent points directly, so as to obtain the point coordinates between the two points? Let's try~

Or the original code, just pass in an X coordinate parameter.

Then between the two points, obtain the Y coordinate corresponding to the X coordinate:

 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         }

Click the window, on the curve, get the point corresponding to the X coordinate at the click point. The renderings are as follows:

 

 Github: Demo

Keywords: C# github

Added by danman252 on Thu, 05 Dec 2019 17:38:19 +0200