1、暴力法

 def g(A,B,P):
     """
     判断点PA矢量在AB矢量的顺时针还是逆时针方向,
     若在逆时针方向则返回1,同向返回0,在顺时针方向返回-1
     :param A:
     :param B:
     :param P:
     :return: 1或0或-1
     """
     #使用PxQ=XpYq-XqYp,若大于0则表示Q在P的逆时针方向
     result = (P[1]-A[1])*(B[0]-A[0])-(B[1]-A[1])*(P[0]-A[0])
     if result<0:
         return -1
     elif result==0:
         return 0
     else:
         return 1

 def isInTriangle(Pi,Pj,Pk,P):
     """
     判断点P是否在其他三个点组成的三角形中,是的话返回true
     :param P:
     :param Pi:
     :param Pj:
     :param Pk:
     :return:
     """
     if g(Pi,Pj,Pk)==0:
         return 0
     if g(Pi,Pj,P)*g(Pi,Pj,Pk)>=0 and g(Pj,Pk,P)*g(Pj,Pk,Pi)>=0 and g(Pk,Pi,P)*g(Pk,Pi,Pj)>=0:
         return 1
     return 0

 def bruteForce(S):
     """
     暴力方法求解凸包
     :param S: 输入的顶点集合
     :return: Q的凸包
     """
     n=len(S)
     flag=ones((n,1))
     output = []
     if n==3:
         #以逆时针方式输出Q的点
         if g(S[0], S[1], S[2])>0:
             output.append(S[0])
             output.append(S[1])
             output.append(S[2])

         elif g(S[0], S[1], S[2])<0:
             output.append(S[2])
             output.append(S[1])
             output.append(S[0])
         return output
     # 若取得的三个点共线怎么办?????
     for i in range(n - 3):
         for j in range(i + 1, n - 2):
             for k in range(j + 1, n - 1):
                 for p in range(k + 1, n):
                     # 有一个点在其他点组成的三角形里
                     if isInTriangle(S[i], S[j], S[k], S[p]):
                         # 则将该点对应的标志位置为0
                         flag[p] = 0
                     if isInTriangle(S[p], S[j], S[k], S[i]):
                         # 则将该点对应的标志位置为0
                         flag[i] = 0
                     if isInTriangle(S[k], S[p], S[i], S[j]):
                         # 则将该点对应的标志位置为0
                         flag[j] = 0
                     if isInTriangle(S[p], S[j], S[i], S[k]):
                         # 则将该点对应的标志位置为0
                         flag[k] = 0
     print(flag)
     sub_S = []
     for i in range(n):
         if flag[i][0]:  # if标志不为0,将添加到sub_S:
             sub_S.append(S[i])  # 则sub_S保存的是在凸包的顶点

     sub_S = np.array(sub_S)
     # 找到sub_S的x坐标最大点B和x坐标最小点A
     sub_S_index = argsort(sub_S[:, 0])
     A = sub_S[sub_S_index[0]]
     B = sub_S[sub_S_index[-1]]

     # 按照点在AB直线上方还是下方将sub_S分为两部分Sup,Sdown
     Sup = []
     Sdown = []
     for i in range(len(sub_S)):
         if g(A, B, sub_S[i]) > 0:
             Sup.append(sub_S[i])
         if g(A, B, sub_S[i]) < 0:
             Sdown.append(sub_S[i])

     # 将Sup按照横坐标递减排序,将Sdown按照横坐标递增排序
     Sup = np.array(Sup)
     Sup = Sup[argsort(-Sup[:, 0])]
     Sdown = np.array(Sdown)
     Sdown = Sdown[argsort(Sdown[:, 0])]

     # 从B开始按照x坐标递减依次输出Sup,到达A,按照x坐标从小到大依次输出Sdown
     output=[]
     # for i in range(len(sub_S)):
     output.append(A)
     output.extend(Sdown)
     output.append(B)
     output.extend(Sup)
     return output

2、GrahamScan

def GrahamScan(S):
     """
     GrahamScan求凸包
     :param S:
     :return:
     """
     #预处理:找到S中y坐标最小的点P0,以水平为极轴求得每个点极角
     n = len(S)
     P = []

     S = S[argsort(S[:, 1])]
     #P.append(tuple(S[0]))
     P.append(list(S[0, 0:2]))
     PointPolar = []  # 保存(x,y,极角)
     for i in range(1, n):
         polar = math.atan2(S[i][1] - S[0][1], S[i][0] - S[0][0])
         polar = polar / math.pi * 180
         PointPolar.append([S[i][0], S[i][1], polar])
     # 将PointPolar的点按照极角从小到大排序,保存在result
     result = preProcessing(PointPolar)

     new_dict2 = remove_dup(result, P[0])
     #P.extend(new_dict2.keys())
     for key in new_dict2:
         P.append(list(key))
     #若m<=1返回凸包是空
     m=len(P)
     if m<=2:
         return
     # 将P[0],P[1],P[2]依次压栈Q
     stack = []
     stack.append(P[0])
     stack.append(P[1])
     stack.append(P[2])
     for i in range(3, m):
         while isInTriangle(P[0], P[i], stack[-2], stack[-1]):
             stack.pop()
         stack.append(P[i])
     return stack
 def preProcessing(PointPolar):
     """
     当多个点的极角相同时,保留距离原点最远的点
     :param dict:
     :return:一个list,经预处理的P[0:m],按照极角从小到大保存要处理的点集
     """
     sorted_polar=sorted(PointPolar,key=lambda d:d[2])
     return sorted_polar

 def remove_dup(sorted_polar,raw):
     """
     :param sorted_dict:
     :return:
     """
     sorted_dict = {}
     for d in sorted_polar:
         sorted_dict[(d[0], d[1])] = d[2]
     new_dict = {}
     new_dict2 = {}
     for k, v in sorted_dict.items():
         new_dict.setdefault(v, []).append(k)
     for k, v in new_dict.items():
         if len(v) > 1:
             d = []
             for item in v:
                 d.append((item[0]-raw[0]) * (item[0]-raw[0]) + (item[1]-raw[1]) * (item[1]-raw[1]))
             v = v[argmax(d)]
             new_dict2[v] = k
         else:
             new_dict2[v[0]] = k
     return new_dict2

结果:

python学习5---实现凸包的更多相关文章

  1. Python学习--04条件控制与循环结构

    Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...

  2. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  3. Python 学习小结

    python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...

  4. Python学习路径及练手项目合集

    Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159

  5. python学习笔记-python程序运行

    小白初学python,写下自己的一些想法.大神请忽略. 安装python编辑器,并配置环境(见http://www.cnblogs.com/lynn-li/p/5885001.html中 python ...

  6. Python学习记录day6

    title: Python学习记录day6 tags: python author: Chinge Yang date: 2016-12-03 --- Python学习记录day6 @(学习)[pyt ...

  7. Python学习记录day5

    title: Python学习记录day5 tags: python author: Chinge Yang date: 2016-11-26 --- 1.多层装饰器 多层装饰器的原理是,装饰器装饰函 ...

  8. [Python] 学习资料汇总

    Python是一种面向对象的解释性的计算机程序设计语言,也是一种功能强大且完善的通用型语言,已经有十多年的发展历史,成熟且稳定.Python 具有脚本语言中最丰富和强大的类库,足以支持绝大多数日常应用 ...

  9. Python学习之路【目录】

    本系列博文包含 Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习编程的童鞋提供一点帮助!!! 目录: Python学习[第一篇]python简介 Python学习[第二篇]p ...

随机推荐

  1. PROJ.4学习——地图投影

    PROJ.4学习——地图投影(坐标系投影) 前言 PROJ是由大量的基础投影库构成.这里主要讨论学习PROJ库的相关参数. 这里大部分是讲如何将3D坐标系投影到2D平面上.投影时,涉及到基准线,单位, ...

  2. padding属性很有用

    html代码中的text-align有时失效,特别是用bootstrap时,用padding-left:xx%,能够很好定位,而且只能够电脑和手机浏览器显示的统一.

  3. JavaScript 进制转换

    //十进制转其他 var x=111; alert(x.toString(8)); alert(x.toString(16)); //其他转十进制 var x='112'; alert(parseIn ...

  4. Oralce数据库的优化

    Oralce数据库的优化(面试必问) (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效):ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 ...

  5. Tomcat服务器提示:The server is temporarily unable to service your request due to maintenance downtime or capacity problems

    今天网站突然不能访问了,这里做一下记录提示: The server is temporarily unable to service your request due to maintenance d ...

  6. oracle新建表空间的四条语句

    1.create user platform identified by intest; 2.create tablespace PLATFORM_DATA datafile 'c:\PLATFORM ...

  7. “幕后英雄”之Backing Fields【Microsoft Entity Framework Core随笔】

    刘德华 有一首歌叫<马桶>,其中有一句歌词是:每一个马桶都是英雄. EFCore也有一个英雄,在幕后默默地任劳任怨.它就叫 "支持字段" (Backing Fields ...

  8. Elasticsearch安装部署教程

    1)下载elasticsearch-1.1.2.zip 2)用ssh工具连接目录主机,在命令窗口输入:mkdir -p /opt/elasticsearch创建elasticsearch文件夹   3 ...

  9. Devexpress GridControl 多选

    以前dev的多选要自己处理,一般的处理方式就是在单元格中添加checkbox控件.后来的版本中dev增加了多选的支持,只需要设置一下属性就可以了,属性如下图: 然后效果设计页面就是这个样子: 运行以后 ...

  10. Excel 使用单元格的值 查询MySQL数据库并返回数据给相应的单元格

    Dim MyConn As ObjectPrivate Sub ConnectDB()Set MyConn = CreateObject("ADODB.Connection")   ...