欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-11 09:39:07
如何在一条曲线上,获取到距离指定点最近的点位置? 与上一篇 C# 曲线上的点(一) 获取指定横坐标对应的纵坐标值 类似, 我们通过曲线上获取的密集点,通过俩点之间连线,获取连线上最近的点。我们能够获取到一系列最近的点集,最近只取距离最小的点即可。 我们这样的算法是否精确呢?不算太精确,但是对于获取曲 ......

如何在一条曲线上,获取到距离指定点最近的点位置?

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

 

与上一篇 c# 曲线上的点(一) 获取指定横坐标对应的纵坐标值 类似,

我们通过曲线上获取的密集点,通过俩点之间连线,获取连线上最近的点。我们能够获取到一系列最近的点集,最近只取距离最小的点即可。

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

我们这样的算法是否精确呢?不算太精确,但是对于获取曲线上最近点,基本能满足。

斜率变化不大的线段,点不密集;斜率变化较大的线段,点相当密集,所以由此点集得到的最近点,是相对准确的。

实现方案,以下代码可以直接复用:

 1     public static point getclosestpointonpath(point p, geometry geometry)
 2     {
 3         pathgeometry pathgeometry = geometry.getflattenedpathgeometry();
 4 
 5         var points = pathgeometry.figures.select(f => getclosestpointonpathfigure(f, p))
 6             .orderby(t => t.item2).firstordefault();
 7         return points?.item1 ?? new point(0, 0);
 8     }
 9 
10     private static tuple<point, double> getclosestpointonpathfigure(pathfigure figure, point p)
11     {
12         list<tuple<point, double>> closepoints = new list<tuple<point, double>>();
13         point current = figure.startpoint;
14         foreach (pathsegment s in figure.segments)
15         {
16             polylinesegment segment = s as polylinesegment;
17             linesegment line = s as linesegment;
18             point[] points;
19             if (segment != null)
20             {
21                 points = segment.points.toarray();
22             }
23             else if (line != null)
24             {
25                 points = new[] { line.point };
26             }
27             else
28             {
29                 throw new invalidoperationexception();
30             }
31             foreach (point next in points)
32             {
33                 point closestpoint = getclosestpointonline(current, next, p);
34                 double d = (closestpoint - p).lengthsquared;
35                 closepoints.add(new tuple<point, double>(closestpoint, d));
36                 current = next;
37             }
38         }
39         return closepoints.orderby(t => t.item2).first();
40     }

俩点之间的连线,如果当前点在此方向的投影为负或者大于当前长度,则取俩侧的点:

 1     private static point getclosestpointonline(point start, point end, point p)
 2     {
 3         double length = (start - end).lengthsquared;
 4         if (math.abs(length) < 0.01)
 5         {
 6             return start;
 7         }
 8         vector v = end - start;
 9         double param = (p - start) * v / length;
10         return (param < 0.0) ? start : (param > 1.0) ? end : (start + param * v);
11     }

效果图:

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