zoukankan      html  css  js  c++  java
  • 获取离散点的边界点

    今天公司要求实现一个算法,在给出一堆离散点中,画出最外层的边界。实际就是从离散点中找出最外面的点(或称边界点),这些点用线连接起来即可。

    一、实现的原理:

    1.任意点(point1)找出最远距离的一个点(point2),该点point2即为其中一个边界点。
    2.point1与point2组成的向量v1(point1 - point2)中找出与其最大夹角的一个向量v2。
    3.重复:v2中找与其最大夹角的向量v3.....
    4.直到最后找到的向量方向为点point2的向量时结束。

    二、这里实现的代码为C#,只要搞懂原理,可以转为各种语言的实现

    1.首先是平面向量类 PlaneVector

    PlaneVector
      1     /// <summary>
      2     /// 平面向量类
      3     /// </summary>
      4     public struct PlaneVector
      5     {
      6         public static readonly PlaneVector Empty;
      7 
      8         /// <summary>
      9         /// 向量的X值
     10         /// </summary>
     11         private double _X;
     12 
     13         /// <summary>
     14         /// 向量的Y值
     15         /// </summary>
     16         private double _Y;
     17 
     18         public double X
     19         {
     20             get
     21             {
     22                 return _X;
     23             }
     24             set
     25             {
     26                 _X = value;
     27             }
     28         }
     29 
     30         public double Y
     31         {
     32             get
     33             {
     34                 return _Y;
     35             }
     36             set
     37             {
     38                 _Y = value;
     39             }
     40         }
     41 
     42         public PlaneVector(double x, double y)
     43         {
     44             _X = x;
     45             _Y = y;
     46         }
     47 
     48         public PlaneVector(Point destPoint, Point sourcePoint)
     49         {
     50             _X = destPoint.X - sourcePoint.X;
     51             _Y = destPoint.Y - sourcePoint.Y;
     52         }
     53 
     54         public PlaneVector(PointF destPoint, PointF sourcePoint)
     55         {
     56             _X = destPoint.X - sourcePoint.X;
     57             _Y = destPoint.Y - sourcePoint.Y;
     58         }
     59 
     60         public PlaneVector(PlaneVector destPlaneVector, PlaneVector sourcePlaneVector)
     61         {
     62             _X = destPlaneVector._X - sourcePlaneVector._X;
     63             _Y = destPlaneVector._Y - sourcePlaneVector._Y;
     64         }
     65 
     66         public void Add(PlaneVector pv)
     67         {
     68             _X += pv._X;
     69             _Y += pv._Y;
     70         }
     71 
     72         public void Subtract(PlaneVector pv)
     73         {
     74             _X -= pv._X;
     75             _Y -= pv._Y;
     76         }
     77 
     78         public override bool Equals(object obj)
     79         {
     80             if (!(obj is PlaneVector))
     81             {
     82                 return false;
     83             }
     84             PlaneVector tf = (PlaneVector) obj;
     85             return (((tf.X == this.X) && (tf.Y == this.Y)) && tf.GetType().Equals(base.GetType()));
     86         }
     87 
     88         public override int GetHashCode()
     89         {
     90             return base.GetHashCode();
     91         }
     92 
     93         public override string ToString()
     94         {
     95             return string.Format("[{0},{1}]"this._X, this._Y);
     96         }
     97 
     98         static PlaneVector()
     99         {
    100             Empty = new PlaneVector(0f, 0f);
    101         }
    102 
    103         public static PlaneVector operator +(PlaneVector left, PlaneVector right)
    104         {
    105             return Add(left, right);
    106         }
    107 
    108         public static PlaneVector operator -(PlaneVector left, PlaneVector right)
    109         {
    110             return Subtract(left, right);
    111         }
    112 
    113         public static bool operator ==(PlaneVector left, PlaneVector right)
    114         {
    115             return ((left.X == right.X) && (left.Y == right.Y));
    116         }
    117 
    118         public static bool operator !=(PlaneVector left, PlaneVector right)
    119         {
    120             return !(left == right);
    121         }
    122 
    123         public static PlaneVector Add(PlaneVector left, PlaneVector right)
    124         {
    125             return new PlaneVector(left.X + right.X, left.Y + right.Y);
    126         }
    127 
    128         public static PlaneVector Subtract(PlaneVector left, PlaneVector right)
    129         {
    130             return new PlaneVector(left.X - right.X, left.Y - right.Y);
    131         }
    132 
    133     }

    2.算法的实现

    GetBorderPointFs
      1     public static class Common
      2     {
      3         /// <summary>
      4         /// 获取两个向量的夹角
      5         /// </summary>
      6         /// <param name="sourcePlaneVector">源向量</param>
      7         /// <param name="destPlaneVector">目标向量</param>
      8         /// <returns></returns>
      9         public static double GetAngle(PlaneVector sourcePlaneVector, PlaneVector destPlaneVector)
     10         {
     11             double temp = 0;
     12             double norm1 = 0;
     13             double norm2 = 0;
     14 
     15             norm1 = System.Math.Sqrt(sourcePlaneVector.X * sourcePlaneVector.X + sourcePlaneVector.Y * sourcePlaneVector.Y);
     16             norm2 = System.Math.Sqrt(destPlaneVector.X * destPlaneVector.X + destPlaneVector.Y * destPlaneVector.Y);
     17 
     18             temp = sourcePlaneVector.X * destPlaneVector.X + sourcePlaneVector.Y * destPlaneVector.Y;
     19 
     20             if (norm1 == 0 || norm2 == 0)
     21             {
     22                 return 0;
     23             }
     24             else
     25             {
     26                 temp = temp / (norm1 * norm2);
     27 
     28                 if (temp > 1.0)
     29                 {
     30                     temp = 1.0;
     31                 }
     32                 else if (temp < -1.0)
     33                 {
     34                     temp = -1.0;
     35                 }
     36 
     37                 return System.Math.Acos(temp);
     38             }
     39         }
     40 
     41         /// <summary>
     42         /// 获取一个点在一个点集合中的最远点
     43         /// </summary>
     44         /// <param name="aPointF"></param>
     45         /// <param name="aPoints">点集合</param>
     46         /// <returns>最远点</returns>
     47         public static System.Drawing.PointF GetFarthestPointF(System.Drawing.PointF aPointF, List<System.Drawing.PointF> aPoints)
     48         {
     49             if (aPointF == null)
     50             {
     51                 throw new ArgumentNullException("aPointF");
     52             }
     53 
     54             if (aPoints == null)
     55             {
     56                 throw new ArgumentNullException("aPoints");
     57             }
     58 
     59             System.Drawing.PointF farthestPointF = System.Drawing.PointF.Empty;
     60 
     61             double maxLength = 0;
     62             double tempLength = 0;
     63 
     64             double x = 0;
     65             double y = 0;
     66 
     67             foreach (System.Drawing.PointF aDestPoint in aPoints)
     68             {
     69                 x = (double)(aDestPoint.X - aPointF.X);
     70                 y = (double)(aDestPoint.Y - aPointF.Y);
     71 
     72                 tempLength = Math.Sqrt(x * x + y * y);
     73 
     74                 if (maxLength < tempLength)
     75                 {
     76                     maxLength = tempLength;
     77                     farthestPointF = aDestPoint;
     78                 }
     79             }
     80 
     81             return farthestPointF;
     82         }
     83 
     84         /// <summary>
     85         /// 获取离散点集的边界点
     86         /// </summary>
     87         /// <param name="aPoints">一组离散点</param>
     88         /// <returns>离散点的边界点</returns>
     89         public static List<System.Drawing.PointF> GetBorderPointFs(List<System.Drawing.PointF> aPoints)
     90         {
     91             List<System.Drawing.PointF> aBorderPoints = new List<System.Drawing.PointF>();
     92 
     93             if (aPoints == null)
     94             {
     95                 throw new ArgumentNullException("aPoints");
     96             }
     97 
     98             if (aPoints.Count < 3)
     99             {
    100                 aBorderPoints.AddRange(aPoints);
    101 
    102                 return aBorderPoints;
    103             }
    104 
    105             //1.获取任意点的最远点
    106 
    107             System.Drawing.PointF farthestPointF = GetFarthestPointF(aPoints.First(), aPoints);
    108 
    109             //2.获取边界点 --------------------------------------->
    110 
    111             System.Drawing.PointF sourcePointF = farthestPointF;
    112             System.Drawing.PointF destPointF = aPoints.First();
    113 
    114             System.Drawing.PointF maxAnglePoint = System.Drawing.PointF.Empty;
    115 
    116             while (!farthestPointF.Equals(maxAnglePoint))
    117             {
    118                 PlaneVector sourcePlaneVector = new PlaneVector(destPointF, sourcePointF);
    119 
    120                 double maxAngle = 0;
    121 
    122                 foreach (System.Drawing.PointF aDestPoint in aPoints)
    123                 {
    124                     PlaneVector destPlaneVector = new PlaneVector(aDestPoint, sourcePointF);
    125 
    126                     double tempAngle = GetAngle(sourcePlaneVector, destPlaneVector);
    127 
    128                     if (maxAngle <= tempAngle)
    129                     {
    130                         maxAngle =tempAngle;
    131                         maxAnglePoint = aDestPoint;
    132                     }
    133                 }
    134 
    135                 aBorderPoints.Add(maxAnglePoint);
    136 
    137                 destPointF = sourcePointF;
    138                 sourcePointF = maxAnglePoint;
    139                 
    140 
    141             } //---------------------------------------< 2.获取边界点 
    142 
    143             return aBorderPoints;
    144         }
    145     }

    GetBorderPointFs 返回的经过计算最后得出的边界点集合。这里主要是使用GetAngle方法来获取连个向量的角度大小,注意的是,角度的单位不是一般的度,而是pi。

    这里是实现的代码,里面做有一个测试的程序,在窗体上随便点上几个点,按生成图形即可看到结果。

    附件: 实现的代码.rar

  • 相关阅读:
    关于返回上一页功能
    Mybatis Update statement Date null
    SQLite reset password
    Bootstrap Validator使用特性,动态(Dynamic)添加的input的验证问题
    Eclipse使用Maven2的一次环境清理记录
    Server Tomcat v7.0 Server at localhost failed to start
    PowerShell一例
    Server Tomcat v7.0 Server at libra failed to start
    商标注册英语
    A glance for agile method
  • 原文地址:https://www.cnblogs.com/yejiansnake/p/1657883.html
Copyright © 2011-2022 走看看