C# 曲线上的点(二) 获取距离最近的点

Wesley13
• 阅读 690

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

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# 曲线上的点(二) 获取距离最近的点

点赞
收藏
评论区
推荐文章
Irene181 Irene181
3年前
手把手教你用Python替代Mapinfo更快查找两张表中距离最近的点
一、前言大家好,我是崔艳飞。工作中有时需要把A表中的经纬度点,从B表中匹配一个最近的点出来,用Mapinfo也可以实现,但处理速度慢,特别是数据量大时根本处理不动,此时用Python就能轻松实现,还能显示处理进度,详细如下。二、项目目标用Python实现两张表间最近点的计算。三、项目准备软件:PyCharm需要的库:pandas,xlrd,os
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
CGAL HelloWorld
点和线段如何创建点和线段,并计算两点之间的距离、点到线段的距离、点与线段的位置关系和中点。定义Kernel(几何图元)操作predicate(位置,距离和中点)Codeinclude<iostreaminclude<CGAL/Simple_cartesian.hty
Stella981 Stella981
3年前
Docker下dubbo开发三部曲之三:java开发
在前两章《Docker下dubbo开发,三部曲之一:极速体验》(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fboling_cavalry%2Farticle%2Fdetails%2F72303126)和《Docker下dubbo开发,三部曲之二:本地环
Wesley13 Wesley13
3年前
Java中当前对象引用
题:计算机画图时,有点的概念,每个点由它的横坐标x和纵坐标y描述。写一个类。求两个点之间的曼哈顿距离横向距离纵向距离例如,一个点(0,0)和另一个点(1,1)的曼哈顿距离为2packagetest;publicclassPoint{
Stella981 Stella981
3年前
Codeforces Round #611 (Div. 3)
原题面:https://codeforces.com/contest/1283(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fcodeforces.com%2Fcontest%2F1283)A.MinutesBeforetheNewYear题目大意:给定时间,问距离零点
Stella981 Stella981
3年前
Flutter 之贝塞尔曲线(一)
贝塞尔曲线简介!(https://oscimg.oschina.net/oscnet/863784996212c918a1feef7a916bce28f31.png"bezier1.png")bezier1.png由上图可以看出:A,C依据控制点B不断的取点使得AD:ABBE:BCDF:DE,构成一个二阶贝塞尔曲线。AD:
Wesley13 Wesley13
3年前
Java虚拟机垃圾回收相关知识点全梳理(下)
一、前言上一篇文章《Java虚拟机垃圾回收相关知识点全梳理(上)(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.luozhou.top%2F2019%2F04%2F28%2Fjvmgc01%2F)》我整理分享了JVM运行时数据区域的划分,垃圾判定算法以及垃圾回
Stella981 Stella981
3年前
Docker下Java文件上传服务三部曲之二:服务端开发
本章是《Docker下Java文件上传服务三部曲》的第二篇,上一章《Docker下Java文件上传服务三部曲之一:准备环境》(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fboling_cavalry%2Farticle%2Fdetails%2F79361
Stella981 Stella981
3年前
CSS实现文字两端对齐
最近的项目遇到了这样的需求:(要求标题部分不管文字多少,都必须两端对齐)如下图:!(https://oscimg.oschina.net/oscnet/6e151291c0c55e2a231d00ec198d6c5be11.png)当时也没有多想直接使用‘&ensp;’进行代替,毕竟产品同学想快一点看到效果,不敢怠慢!不过到第二个页面就傻眼了