http://blog.sina.com.cn/s/blog_616e189f0100qc0u.html

陈氏凸包算法—算法参考:Computing the convex hull of a simple polygon 作者:Chern-Lin Chen

陈氏算法提供了一个线性效率求凸包的算法,本文使用VS2008对算法进行了测试,论文中有很多错误的地方,大家可以参考源码进行更正。话不多说,大家请看源码,和运行效果。

作者对原算法的错误处进行了校正,可以作为大家学习参考使用,如果在公共场合使用本资源和算法更正的内容请标明出处,并及时与作者取得联系。未经允许不得以任何形式在公共场合(包括论文)中使用或模仿本算法。版权归作者所有(中国石油大学(华东)QQ531961673)。

本文算法更改和实现都是本人个人完成,如有转载或使用,请标明出处,并与作者取得联系,谢谢。

#pragma once

#include <vector>

#include <deque>

#include <algorithm>

#include <cstddef>

#include <cmath>

#include<functional>

using std::vector;

using std::deque;

class covexHull

{

public:

covexHull(void);

~covexHull(void);

void compute();//凸多边形计算的入口

void draw(CClientDC & dc );//绘制凸多边形

void addPoint(const CPoint &point);//添加计算的节点

private:

class PointAndAngle{//内部类,用于临时过程的处理(用于计算简单多边形)

public:

CPoint point;

double angle;

bool operator < (const PointAndAngle & p1)const{//小于运算符重载,用于排序

return angle < p1.angle;

}

};

std::vector<CPoint>::iterator findLeftPoint();//找到最左边的点

int computeS(const CPoint & p1, const CPoint &p2, const CPoint &p3)const;//计算S

void computeSimplePolygon();//计算简单多边形

void computeCovexHull();//计算凸多边形

private:

vector<CPoint> m_points;//点集合(无序)

deque<PointAndAngle> m_pointAndAngle;//简单多边形排序后点集合(有序)

deque<CPoint> m_stack;//凸多边形点集合(有序)

};

实现部分:

#include "StdAfx.h"

#include "covexHull.h"

covexHull::covexHull(void)

{

}

void covexHull::addPoint(const CPoint &point)

{

m_points.push_back(point);

}

inline vector<CPoint>::iterator covexHull:: findLeftPoint()

{

//最左边的点,就是x的值最小的点

std::vector<CPoint>::iterator ret = m_points.begin();

for(std::vector<CPoint>::iterator it = m_points.begin() ; it != m_points.end() ; ++it)

{

if(it->x < ret->x)

ret = it;

}

return ret;

}

void covexHull::draw(CClientDC & dc)

{

//先绘制所有的点

for(vector<CPoint>::iterator it = m_points.begin() ; it != m_points.end() ; ++it)

{

dc.Ellipse(it->x-3, it->y-3, it->x+3, it->y+3);

}

//绘制简单多边形

{

deque<PointAndAngle>::iterator it =  m_pointAndAngle.begin();

if(it != m_pointAndAngle.end())//防止列表为空

dc.MoveTo(it->point.x,it->point.y);

for(; it!= m_pointAndAngle.end() ; ++it)

{

dc.LineTo(it->point.x,it->point.y);

}

if(m_pointAndAngle.size() != 0)//防止列表为空

dc.LineTo(m_pointAndAngle.begin()->point.x,m_pointAndAngle.begin()->point.y);

}

//绘制凸多边形

{

CPen * oldPen;

CPen * newPen = new CPen(PS_SOLID,1,RGB(255,0,0));//更改画笔颜色

oldPen = dc.SelectObject(newPen);

deque<CPoint>::iterator it =  m_stack.begin();

if(it != m_stack.end())

dc.MoveTo(it->x,it->y);

for(; it!= m_stack.end() ; ++it)

{

dc.LineTo(it->x,it->y);

}

if(m_stack.size() != 0)

dc.LineTo(m_stack.begin()->x,m_stack.begin()->y);

dc.SelectObject(&oldPen);

delete newPen;

}

}

void covexHull::compute()

{

computeSimplePolygon();//先计算简单多边形

computeCovexHull();//计算凸多边形

}

void covexHull::computeSimplePolygon()

{

m_pointAndAngle.clear();

vector<CPoint>::iterator it = findLeftPoint();//先找到最左侧的点

CPoint point(it->x,it->y);//将这个点保存下来

m_points.erase(it);//将最左侧的点从列表中删除(因为这个点自身求角度无意义)

PointAndAngle paa;

for(vector<CPoint>::iterator i = m_points.begin() ; i != m_points.end() ; ++i)//计算所有点与最左侧点的角度

{

paa.point = *i;

if(i->x - point.x == 0)//要先判断除数为的情况

{

if(i->y > point.y)

paa.angle = 90.0/360.0*atan(1.0)*4;//PI = atan(1.0)*4

else

paa.angle = -90.0/360.0*atan(1.0)*4;

}

else

paa.angle = atan(double(double(i->y - point.y)/double(i->x - point.x)));//计算角度

m_pointAndAngle.push_back(paa);//放入简单多变行容器

}

std::sort(m_pointAndAngle.begin(),m_pointAndAngle.end());//按照角度从小到大排序

paa.point = point;

m_pointAndAngle.push_front(paa);//最后将最左侧的点放入集合

m_points.push_back(point);//将最左侧点放入点集合

}

int covexHull::computeS(const CPoint & p1, const CPoint &p2, const CPoint &p3)const

{

return (p3.x - p1.x)*(-p2.y + p1.y) - (-p3.y + p1.y)*(p2.x - p1.x);//计算S,注意实际坐标系与屏幕坐标系之间的转换

}

void covexHull::computeCovexHull()

{

m_stack.clear();

if(m_pointAndAngle.size() < 3)//当小于个点,就不用计算了

return;

m_stack.push_front(m_pointAndAngle.at(0).point);//先将前两个点放入栈中

m_stack.push_front(m_pointAndAngle.at(1).point);

deque<PointAndAngle>::iterator it = m_pointAndAngle.begin() + 2;//迭代器先要移动两个位置(因为那两个位置已经放入栈中了)

for(;it != m_pointAndAngle.end() ;)//迭代求解

{

if(computeS(m_stack.at(1),m_stack.at(0),it->point) > 0)//当S大于,此时点在直线的右侧

{

if(computeS(m_stack.back(),m_stack.front(),it->point) > 0)//当S大于,将点压入栈中,否则不压入(不进栈,迭代器移动,相当于reject)

{

m_stack.push_front(it->point);

}

++it;//迭代器移动

}else//S小于说明点在直线左侧,当前栈顶肯定不是凸点

{

m_stack.pop_front();//弹出栈顶

if(m_stack.size() < 2)//栈内元素太少,将当前点直接填入栈中

m_stack.push_front(it->point);

//注意这里迭代器并没有移动

}

}

}

covexHull::~covexHull(void)

{

}

测试效果:

完整源码:http://guanxinquan.download.csdn.net/上下载

转载于:https://www.cnblogs.com/kex1n/p/3305786.html

求多边形凸包(线性算法)--陈氏凸包算法--相关推荐

  1. matlab 凸包质心算法,求多边形凸包(线性算法)--陈氏凸包算法--Computing the convex hull of a simple polygon(源码)...

    陈氏凸包算法-算法参考:Computing the convex hull of a simple polygon 作者:Chern-Lin Chen 陈氏算法提供了一个线性效率求凸包的算法,本文使用 ...

  2. 计算几何入门 1.6:凸包的构造——Graham Scan算法

    上文简要分析出了凸包构造问题算法的下界:O(nlogn),在此就引入一种下界意义上最优的算法:Graham Scan算法.这种算法可以保证在最坏情况下时间复杂度也不超过nlogn.我们先大致了解一下算 ...

  3. CGAL笔记之凸包算法—3D凸包

    CGAL笔记之凸包算法-3D凸包 1 介绍 2 静态凸壳结构 2.1 特性类 2.1.1 示例 2.1.2 低维结果示例 2.2 极值点 2.3 半空间交集 2.3.1 例子 2.4 凸性检查 3 动 ...

  4. [Poj 2187] 计算几何之凸包(二) {更高效的算法}

    { 承上一节 继续介绍点集的凸包  (下文中所有凸包 若不做特殊说明均指点集的凸包) 这一节介绍相比更高效的算法 } ========================================= ...

  5. Graham算法解决凸包问题

    Graham算法解决凸包问题 模板题,题目来自洛谷如下. 圈奶牛[模板]二维凸包 题目简要描述 给定一些点,求凸包的周长. 输入格式 输入数据的第一行是一个整数.表示农夫约翰想要围住的放牧点的数目n. ...

  6. Graham-Scan算法计算凸包的Python代码实现

    对于一个点集P来讲,它的凸包就是一个凸多边形Q,其中满足P中的每个点都在Q的边界上或内部.就像下图所示 凸包的计算算法有好多种,wiki和算法导论第33章中都有比较详细的介绍,比如下面是算法导论中给出 ...

  7. 小白算法学习 凸包 graham

    一.概念: 凸包(Convex Hull)是一个计算几何(图形学)中的概念. 在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包. X的凸包可以用X内所有点(X1,...X ...

  8. Graham算法构造凸包(python)

    一.算法步骤 首先找到点集中y坐标最小的点作为初始点p0p_0p0​,若y坐标相同,选取x坐标最小的一个点作为p0p_0p0​ 以p0为原点,对点集进行极角排序得到集合{p0,p1...pn}\lef ...

  9. 拼题---求链式线性表的倒数第K项(两种算法的比较)

    7-17 求链式线性表的倒数第K项 (20 分) 给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字. 输入格式: 输入首先给出一个正整数K,随后是若干正整数,最后以一个负整数表 ...

最新文章

  1. 古老的SSM企业级应用
  2. 如何用Transformer来做目标检测?一文简述DERT及其变体
  3. HDU 1294 Rooted Trees Problem
  4. java程序中怎么保证多线程的运行安全_Java线程安全问答(草稿)
  5. SAP Cloud for Customer最新版本2002 RUI如何启用adaptation模式
  6. android 手机 与 python服务器_Python服务器与多种客户端(Python/Java/Android)之间的通信...
  7. Android笔记 网络源代码浏览器demo
  8. 【设计模式】第三章 单例模式
  9. 半自动驾驶大对决:特斯拉和凯迪拉克谁是真王
  10. 网站锁定php文件命令,PHP文件的锁定机制
  11. GIS中的基本概念收集
  12. oracle plsql存储过程中out模式参数的用法
  13. 校园网客户端没有linux版,Linux版校园网客户端公测中(已添加GUI输入窗口)njit-clent...
  14. 算法竞赛入门经典(第2版)-刘汝佳-第九章例题解题源码(C++语言)(部分)
  15. ios html5键盘弹出视图上移,ios 软键盘弹出, 页面整体上移问题
  16. 欧格教育:提升店铺流量的方法
  17. 轻松解决 f2pool鱼池ethermine连接失败antpool矿池连接不上的问题E池连接超时
  18. 深耕物料处理赛道,宏工科技助力涂料绿色自动化生产
  19. idea自动排版html,idea怎么格式化代码?
  20. 逆序输出数组,将给定数组逆序输出

热门文章

  1. 微信小程序下发消息通知
  2. CSS网页布局之传统解决方案与Flex大法
  3. TouchDesigner 之 幻影之星
  4. 物联网市场FD-SOI制程会取代FinFET吗?
  5. 数学图形(1.3)旋轮线
  6. 两种实现多线程的方式 迅雷案列
  7. 大搜车孙信宇:一个好的团队应该去中心化
  8. 社会工程学攻击案例-伪装木马
  9. 732. 我的日程安排表 III
  10. 说说Java生态圈的那些事儿