• 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     }

    效果图:

  • 相关阅读:
    Odd sum CodeForces
    Chips CodeForces
    Secrets CodeForces
    Voting CodeForces
    Jury Meeting CodeForces
    Planning CodeForces
    Maxim Buys an Apartment CodeForces
    Chemistry in Berland CodeForces
    Monitor CodeForces
    Four Segments CodeForces
  • 原文地址:https://www.cnblogs.com/kybs0/p/10596419.html
Copyright © 2020-2023  润新知