凸包算法是計算幾何中的最經典問題之一了。給定一個點集,計算其凸包。凸包是什么就不羅嗦了

本文給出了《計算幾何——算法與應用》中一書所列凸包算法的Python實現和Matlab實現,並給出了一個Matlab動畫演示程序。

啊,實現誰都會實現啦╮(╯▽╰)╭,但是演示就不一定那么好做了。

算法CONVEXHULL(P)

輸入:平面點集P

輸出:由CH(P)的所有頂點沿順時針方向組成的一個列表

1.   根據x-坐標,對所有點進行排序,得到序列p1, …, pn

2.   在Lupper中加入p1和p2(p1在前)

3. for(i←3 ton)

4.   do 在Lupper中加入pi

5.   while(Lupper中至少還有三個點,而且最末尾的三個點所構成的不是一個右拐)

6.   do 將倒數第二個頂點從Lupper中刪去

7.   在Llower 中加入pn和pn-1(pn在前)

8. for(i←n-2 downto1)

9.   do 在Llower 中加入pi

10.    while(Llower 中至少還有三個點,而且最末尾的三個點所構成的不是一個右拐)

11.    do 將倒數第二個頂點從Llower 中刪去

12.  將第一個和最后一個點從Llower 中刪去

(以免在上凸包與下凸包聯接之后,出現重復頂點)

13.  將Llower 聯接到Lupper后面(將由此得到的列表記為L)

14.  return(L)

看看,不是很多的樣子是吧。

這里面需要說明的地方只有一點,那就是方向的判定問題。

設有三個點P,Q,R,現需求R位於向量PQ的左側還是右側(或者R在PQ上)。

計算PR與PQ的叉積,也就是外積。

如果將向量PR以P為旋轉中心旋轉只向量PQ的方向走過一個正角(逆時針),意味着R在PQ的右側,此時外積為正。

另外需要注意的是,如果在凸包上有三點共線的情況,在本例中三點是均位於凸包邊界點集中的。如果想避免這一點,可以通過微量抖動數據的方式解決。

廢話不多說,Python實現如下:

1 #!/usr/bin/env python

2 #coding: gbk

3

4 ########################################################################

5 #Author: Feng Ruohang

6 #Create: 2014/10/02 13:39

7 #Digest: Computate the convex hull of a given point list

8 ########################################################################

9

10

11 direction = lambda m: (m[2][0] - m[0][0]) * (m[1][1] - m[0][1]) - (m[1][0] - m[0][0]) * (m[2][1] - m[0][1])12 '''

13 A Quick Side_check version Using Lambda expression14 Input:  Given a list of three point : m should like [(p_x,p_y), (q_x,q_y), (r_x,r_y)]15 Output: Return a Number to indicate whether r on the right side of vector(PQ).16 Positive means r is on the right side of vector(PQ).17 This is negative of cross product of PQ and PR: Defined by:(Qx-Px)(Ry-Py)-(Rx-Px)(Qy-Py)18 Which 'negative' indicate PR is clockwise to PQ, equivalent to R is on the right side of PQ19 '''

20

21

22 defconvex_hull(point_list):23 '''

24 Input:  Given a point List: A List of Truple (x,y)25 Output: Return a point list: A List of Truple (x,y) which is CONVEX HULL of input26 For the sake of effeciency, There is no error check mechanism here. Please catch outside27 '''

28 n = len(point_list)  #Total Length

29 point_list.sort()30

31 #Valid Check:

32 if n

35 #Building Upper Hull: Initialized with first two point

36 upper_hull = point_list[0:1]37 for i in range(2, n):38 upper_hull.append(point_list[i])39 while len(upper_hull) >= 3 and not direction(upper_hull[-3:]):40 del upper_hull[-2]41

42 #Building Lower Hull: Initialized with last two point

43 lower_hull = [point_list[-1], point_list[-2]]44 for i in range(n - 3, -1, -1):  #From the i-3th to the first point

45 lower_hull.append(point_list[i])46 while len(lower_hull) >= 3 and not direction(lower_hull[-3:]):47 del lower_hull[-2]48 upper_hull.extend(lower_hull[1:-1])49 returnupper_hull50

51

52 #========Unit Test:

53 if __name__ == '__main__':54 test_data = [(i, i ** 2) for i in range(1, 100)]55 result =convex_hull(test_data)56 printresult57

58 2015年1月23日

使用很簡單,看DocString就行。

下面順便給出了Matlab 的實現,以及可視化的算法演示:

效果就是個小動畫,像這樣吧。

Matlab的凸包算法有三個文件:

side_check2:檢查三個點構成的彎折的方向

Convex_hull: 凸包算法Matlab實現

Convex_hull_demo:凸包算法的演示。

拷在一個目錄里

運行convex_hull_demo( randn(200,2)*100); 就可以看到可視化演示了

這個是輔助函數

%filename: side_check2.m

%Input: Matrix of three point: (2x3 or 3x2)

% P(p_x,p_y),Q(q_x,q_y),R(r_x,r_y)

%Output: 如果P Q R三點構成一個右拐,返回True

% 右拐意味着點R在PQ向量的右側.此時

function result = side_check2(D)

if all(size(D) ~= [3,2])

if all(size(D)==[2,3])

D = D';

else

error('error dimension')

end

end

result = (det([[1;1;1], D]) < 0 );

這個是純算法實現。

%filename: convex_hull.m

%CONVEX_HULL

%INPUT: Point Set:(n x 2)

%OUPUT: HULL Point List: (x x 2)

function L=t(P)

[num,dimension] = size(P);

if dimension ~= 2

error('dimension error')

end

P = sortrows(P,[1,2]);

%if there is only one or two point remain,return it

if num < 3

L = P;

return

end

%STEP ONE: Upper Hull:

L_upper = P([1,2],:); %Take first two points

for i = 3:num

L_upper = [L_upper;P(i,:)]; %add the point into list

while size(L_upper,1) >= 3

l_size = size(L_upper,1);

if det([ones(3,1),L_upper(l_size-2:l_size,:)])= 3

l_size = size(L_lower,1);

if det([ones(3,1),L_lower(l_size-2:l_size,:)])

這個是演示:

%CONVEX_HULL

%INPUT: Point Set:(n x 2)

%OUPUT: HULL Point List: (x x 2)

%Samples: convex_hull_demo( randn(200,2)*100)

function L=convex_hull_demo(P)

%Test Data

%data_size = data_size

%P = randi([-50,50],[data_size,2]);

[num,dimension] = size(P);

if dimension ~= 2

error('dimension error')

end

P = sortrows(P,[1,2]);

%====Visual Lization

board_left = min(P(:,1));

board_right = max(P(:,1));

board_bottom = min(P(:,2));

board_up = max(P(:,2));

x_padding = (board_right- board_left)*0.1;

y_padding = (board_up- board_bottom)*0.1;

plot_range= [board_left - x_padding,board_right + x_padding,board_bottom-y_padding,board_up+y_padding];

clf;

scatter(P(:,1),P(:,2),'b.');

axis(plot_range);

hold on

%====VisualLization

%if there is only one or two point remain,return it

if num < 3

L = P;

end

%STEP ONE: Upper Hull:

L_upper = P([1,2],:); %Take first two points

hull_handle = plot(L_upper(:,1),L_upper(:,2),'ob-');

for i = 3:num

L_upper = [L_upper;P(i,:)]; %add the point into list

while size(L_upper,1) >= 3

l_size = size(L_upper,1);

if side_check2(L_upper(l_size-2:l_size,:)) %Check if it is valid

break; %Quit if Valid

else

L_upper(l_size-1,:) = []; %Remove the inner point and continue if not

end

set(hull_handle,'XData',L_upper(:,1),'YData',L_upper(:,2));drawnow;

end

set(hull_handle,'XData',L_upper(:,1),'YData',L_upper(:,2));drawnow;

end

%Visualization

plot(L_upper(:,1),L_upper(:,2),'bo-');

%Visualization

%STEP Two: Build the lower hull

L_lower = [P([num,num-1],:)]; % Add P(n) and P(n-1)

set(hull_handle,'XData',L_lower(:,1),'YData',L_lower(:,2));drawnow;

for i = num-2:-1:1

L_lower = [L_lower;P(i,:)];

while size(L_lower,1) >= 3

l_size = size(L_lower,1);

if side_check2(L_lower(l_size-2:l_size,:)) %Check if it is valid

break; %Quit if Valid

else

L_lower(l_size-1,:) = []; %Remove the inner point and continue if not

end

set(hull_handle,'XData',L_lower(:,1),'YData',L_lower(:,2));drawnow;

end

set(hull_handle,'XData',L_lower(:,1),'YData',L_lower(:,2));drawnow;

end

L_lower([1,size(L_lower,1)],:) = [];

if isempty(L_lower)

L = L_upper;

else

L = [L_upper;L_lower(2:size(L_lower,1)-1,:)];

end

hold off;

return

凸包计算几何matlab,計算幾何-凸包算法 Python實現與Matlab動畫演示相关推荐

  1. matlab 2010 工具箱,Matlab2010下使用FULLBNT工具箱實現簡單的靜態貝葉斯網絡及推理...

    基於matlab的貝葉斯網絡工具箱BNT是kevin p.murphy基於matlab語言開發的關於貝葉斯網絡學習的開源軟件包,提供了許多貝葉斯網絡學習的底層基礎函數庫,支持多種類型的節點(概率分布) ...

  2. 基于matlab的捷联惯导算法设计及仿真,基于 Matlab 的捷联惯导算法设计及仿真1doc.doc...

    基于 Matlab 的捷联惯导算法设计及仿真1doc 基于 Matlab 的捷联惯导算法设计及仿真1 严恭敏 西北工业大学航海学院,西安 (710072) E-mail:yangongmin@163. ...

  3. C#適應練習:幾種常見設計模式的實現

    一.單例及原型模式 單例:即使用一個固定對象的對象進行操作,實現起來很簡單 using System; using System.Collections.Generic; using System.L ...

  4. java 余弦定理_Java實現余弦定理計算文本相似度

    相似度度量(Similarity),即計算個體間的相似程度,相似度度量的值越小,說明個體間相似度越小,相似度的值越大說明個體差異越大. 對於多個不同的文本或者短文本對話消息要來計算他們之間的相似度如何 ...

  5. matlab 召回率,查准率、召回率、敏感性、特異性和F1-score的計算及Matlab實現

    查准率(Precision):所有診斷為患病(1)樣本中實際為患病的比率. 召回率(Recall):所有患病樣本中被發現並診斷為患病的比率. 查准率 = TP/(TP+FP) 召回率 = TP/P = ...

  6. J.护城河(凸包计算几何)

    J.护城河(凸包&计算几何) 题意 ​ 凸包求周长裸题 思路 ​ 复习一波凸包. 首先凸包有两种方法: 1.graham 2.andrew 主流是graham扫描法. graham的流程: 1 ...

  7. matlab 白色像素点,MATLAB 簡單的計算白色輪廓中像素點的個數

    近來,有朋友問到,如何計算白色輪廓中的像素點的個數.我在這里就舉一個超級簡單的例子,就是假設一副二值圖片,其背景是黑色的,而你的邊緣是白色的,而且你的白色邊緣中不包含黑色的點,就如附件中的那個圖像.下 ...

  8. matlab三维凸包,用 qhull 计算三维点集的凸包

    因为 qhull 是一个复杂的命令行工具箱,用户可以通过各种命令选项去调用适当的程序.比如,要对点集进行 Delaunay 网格化,可以直接使用 "qdelaunay" 命令来实现 ...

  9. 計算機程序設計:7大編程原則

    計算機程序設計:7大編程原則 寫出乾淨優雅的代碼並不是一件容易的事情. 編程的工作同石匠的工作相類似,即是技術活,也是體力活,而編寫優秀的軟件,算是一件比較難的事.編程大牛們並不是直接上手編寫,而是根 ...

最新文章

  1. Openfire3.9.3源代码导入eclipse中开发配置指南
  2. 用CSS伪元素制作箭头
  3. linux mv命令批量,linux 如何用mv命令批量更改文件名?
  4. IE6、IE7、Firefox无提示关闭窗口的代码
  5. Android知识点
  6. python parser count_8 个 Python 实用脚本,早掌握早下班!
  7. Cobertura和Sonar 5.1的问题
  8. 练字格子纸模板pdf_这么好用的模板,我要好好保存下来!
  9. Leetcode-最长回文子串(包含动态规划以及Manacher算法)
  10. bt云服务器地址,windows2008搭建bttracker服务器
  11. IOS Andriod 抖音无水印下载和快手无水印下载
  12. 如何用Matlab修正异方差性,matlab 异方差 white
  13. mysql查询 多门课程的平均成绩_数据库学生成绩分析问题.doc
  14. groovy简单介绍
  15. 【实战】Udacity弹窗测试—ABtest
  16. 我的团长我的团可能的故事原现
  17. 谈了四年的男友寒心了,她已是接近30的老女人
  18. 荣耀路由器搭建php,荣耀路由器怎么设置? – 192路由网
  19. Android逆向:通过Xposed解密柠某直播本地数据
  20. HTTP 状态返回码

热门文章

  1. 用电脑给照片加水印其实很简单,可以这样做
  2. 2022年全国职业院校技能大赛试题6(中职组)
  3. 大话设计模式——中介者模式
  4. linux判断tomcat状态,LINUX下如何查看tomcat运行状态,判断其是否启动
  5. python变量作用域 if,Python 变量作用域
  6. 解决百度地图JavaScript API GL v1.0版本重新加载页面
  7. 视口文件html,视口.html
  8. UE4学习笔记----定向光源属性
  9. 关于逻辑、数学和编程的深层次思考
  10. CRM 项目总结——工作篇