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

  • 相关阅读:
    [转] HashMap的工作原理
    [原创] hadoop学习笔记:hadoopWEB监控
    [编辑] 分享一些java视频
    [原创]spring学习笔记:关于springsource-tool-suite插件的安装
    [原创]安装Oracle 11gR2,以及如何在win8下使用plsql develper连接Oracle数据库 ,在这里和大家分享下
    dedecms _ 当前位置问题的代码
    form表单验证
    input 不支持HTML5的placeholder属性
    Dede文章列表
    DEDE首页调用{dede:field.content/}
  • 原文地址:https://www.cnblogs.com/yejiansnake/p/1657883.html
Copyright © 2011-2022 走看看