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. eXosip2 编译安装

    eXosip2-3.6.0 编译安装 刚开始我使用了 下面文章介绍里版本  我以为不支持tcp 其实是因为我服务端的端口 没有写对. https://www.cnblogs.com/elisha-bl ...

  2. Ubuntu安装tomcat

    1.下载需要的tomcat二进制包(tar.gz)结尾的. https://tomcat.apache.org/download-80.cgi 2.通过xftp5 上传到指定的文件夹 3.cd进指定文 ...

  3. Spring Boot:Thymeleaf 使用详解

    Thymeleaf 介绍 简单说,Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完全替代 JSP .相较与其他的模板引擎,它有如下三个极吸引人的特点: 1 ...

  4. java根据#号截取字符串,使用Pattern的方法

    public class Regex1 { public static void main(String[] args) { String s = "神秘的海洋出现了一只#话题#海怪阿拉斯加 ...

  5. Saiku控制页面展示的数据过长自动换行(二十四)

    Saiku控制页面展示的数据过长自动换行 目前用到saiku来展示数据,发现数据文本过长也不会自动换行,然而用户那边又需要换行(会好看些),所以就来改一改源码啦 首先我们使用谷歌浏览器 inspect ...

  6. python基础之作业2----购物车小练习

    product_list = [    ("Iphone",6000),    ("Mac pro",12800),    ("Bike", ...

  7. centos7初上手2-安装tomcat服务

    上一篇文章说完安装mysql数据库,这篇文章来学习一下tomcat安装 1.先做准备工作,安装jdk,先看服务器上有没有安装相关java文件 下载好1.8版本的安装包,用xftp传到服务器上(根据个人 ...

  8. 磁盘挂载方法 fdisk parted

    1创建磁盘分区 [root@web01 ~]# fdisk -cu /dev/sdc -c 关闭dos兼容模式-u 使用扇区进行分区 (默认位柱面)[root@web01 ~]# partprobe ...

  9. HTTP请求协议

    请求(Request)协议 * GET请求方式 * 请求行 * http协议的版本信息 1.1 * 请求地址 - URL?key=value&key=value * 请求方式 - GET * ...

  10. pytest自动化6:pytest.mark.parametrize装饰器--测试用例参数化

    前言:pytest.mark.parametrize装饰器可以实现测试用例参数化. parametrizing 1.  下面是一个简单是实例,检查一定的输入和期望输出测试功能的典型例子 2.  标记单 ...