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. AS3.0 给addEventListener里的方法加上参数传递

    方法一:for(var i:int=1;i<=4;i++){this["btn"+i].addEventListener(MouseEvent.CLICK,EventUp(b ...

  2. SpringBoot 下 mybatis 的缓存

    背景: 说起 mybatis,作为 Java 程序员应该是无人不知,它是常用的数据库访问框架.与 Spring 和 Struts 组成了 Java Web 开发的三剑客--- SSM.当然随着 Spr ...

  3. linux php5.6 安装Redis扩展

    wget http://pecl.php.net/get/redis-4.2.0.tgz tar -zxvf redis-.tgz cd redis- /usr/local/php5./bin/php ...

  4. java第五次笔记

  5. Linux快捷键总结

    使用Linux很久了,现对经常用到的快捷键做一个总结: 最重要的一个当然是tab了 [root@localhost ~]# cd /etc/sys sysconfig/ sysctl.conf sys ...

  6. font awesome 页面小图标

    font awesome 页面小图标 前段时间做页面,从网上查找资料,发现了一个好用的工具,就是font awesome奥森图标,使用了一下,发现非常方便,而且很灵活,纯css编写,可以和bootst ...

  7. JAVAEE第七周

    JSON 一.什么是JSON -JSON指的是JavaScript对象表示法(Javascript Object Notation) -JSON是轻量级的文本数据交换格式 -JSON独立于语言 -JS ...

  8. 005dayPython学习:编写并执行Pythong代码和流程梳理

    一.创建 python 文件 PS:文件路径和文件名尽量不要包含中文! 二.编写python代码 1.头部的特殊两行 #!/usr/bin/env python # -*- coding:utf-8 ...

  9. P2010 回文日期 题解

    这题其实就是纯暴力,暴力,再暴力,毫无技巧可言(总之您怎么乱搞都不会超时QAQ) 首先,根据题意,我们明白每年自多产生一个回文日期,因为对于每年的三百多天,前四位是固定的. 所以,我们只需要进行一个从 ...

  10. 认识jQuery

    JQ的优势 轻量级. 强大的选择器 出色的DOM操作的封装 可靠的事件处理机制 完善的Ajax 不污染顶级变量 出色的浏览器兼容性 链式操作 隐式迭代 行为层与结构层分离 丰富的插件支持 完善的文档 ...