几何算法:点集合构造简单多边形

问题:给定平面中n个点所组成的集合,将它们连接起来形成一条简单的封闭路径。所谓简单路径,是指边与边无交叉。

如下图所示10个点组成的简单轮廓:

思路:取x坐标最大的点A(如果最大x坐标的点不止一个,则取Y坐标最小的点),依次计算A点与其余各点的连线与水平线之间夹角的正切值,然后按照正切值排序,依次连接排序后的各点即组成一个简单图形。

原理:其它所有点都在A点的左侧,所有夹角的范围为-Pi/2~Pi/2,单调递增函数。

举一个例子如下:

各点坐标与A点的角度斜率如下(已经排序好):

x:426.192518536091,y:30.5668629242884,slope:-2.21036105157629
x:132.904271903869,y:111.805767306036,slope:0.0233827696146631
x:209.153583263584,y:158.396180071121,slope:0.216615047225945
x:51.2625493860163,y:271.425922467106,slope:0.409713066051227
x:172.80558813494,y:320.363658168522,slope:0.754116336162768
x:174.841647802313,y:361.474091434606,slope:0.903935084923323
x:262.993097888768,y:306.679940091763,slope:1.03059799172764
x:405.520514378101,y:212.478244240618,slope:2.00680658499766
x:410.405247491042,y:324.597360433357,slope:4.49064367657446
x:459.491329337233,y:104.169257382941,slope:1.79769313486232E+308

其中A点为:x:459.491329337233,y:104.169257382941,slope:1.79769313486232E+308

下面给出具体算法(C#实现):

几何点定义,实现IComparable<T>接口,按照正切值排序要用到:

  public struct GeometryPoint : IComparable<GeometryPoint>
{
public GeometryPoint(double x, double y, double slope = double.NaN)
{
this.x = x;
this.y = y;
this.slope = slope;
}
private double x;
public double X
{
get { return x; }
set { x = value; }
}
private double y;
public double Y
{
get { return y; }
set { y = value; }
}
private double slope;
public double SLOPE
{
get { return slope; }
set { slope = value; }
}

public int CompareTo(GeometryPoint p)
{
if (this.slope < p.slope)
{
return -1;
}
else if (this.slope > p.slope)
{
return 1;
}
else
{
if (this.x == p.x && this.SLOPE == p.SLOPE && this.SLOPE == double.MaxValue)
{
if (this.y == p.y)
{
return 0;
}
else if (this.y < p.y)
{
return 1;
}
else//(this.y > p.y)
{
return -1;
}
}
return 0;
}
}
public override string ToString()
{
return string.Format("x:{0},y:{1},slope:{2}", x, y, slope);
}
}

GeometryPoint 定义

简单封闭图形定义,并定义初始化简单封闭图形的方法,该方法随机产生多边形的顶点:

 public class SimplePolygon
{
private GeometryPoint[] geometrypoints;

public GeometryPoint[] GeometryPoints
{
get { return geometrypoints; }
set { geometrypoints = value; }
}

public SimplePolygon()
{
}
public void Initialize(int size, double minX, double maxX, double minY, double maxY)
{
if (size <= 0) throw new ArgumentOutOfRangeException();
geometrypoints = new GeometryPoint[size];
Random rnd = new Random(DateTime.Now.Millisecond);
double xRange = maxX - minX;
double yRange = maxY - minY;
int MaxXPointIndex = 0;//选取x坐标最大的点
for (int i = 0; i < size; i++)
{
GeometryPoint gp = new GeometryPoint(minX + xRange * rnd.NextDouble(), minY + yRange * rnd.NextDouble());
geometrypoints[i] = gp;
if (geometrypoints[MaxXPointIndex].X < gp.X)////选取x坐标最大的点
{
MaxXPointIndex = i;
}
else if (geometrypoints[MaxXPointIndex].X < gp.X && geometrypoints[MaxXPointIndex].Y > gp.Y)//选取x坐标最大的点,如果最大x坐标点有多个,去y最小者
{
MaxXPointIndex = i;
}
}
//计算斜率
for (int i = 0; i < size; i++)
{
if (i == MaxXPointIndex)
{
geometrypoints[MaxXPointIndex].SLOPE = double.MaxValue;
}
else
{
if (geometrypoints[i].X == geometrypoints[MaxXPointIndex].X)//与最大x坐标的x相同的点,因为x坐标之差为零,所以取SLOPE最大值
{
geometrypoints[i].SLOPE = double.MaxValue;
}
else//计算斜率,注意正切函数在-0.5Pi和0.5Pi之间是单调递增的
{
geometrypoints[i].SLOPE = (geometrypoints[i].Y - geometrypoints[MaxXPointIndex].Y) / (geometrypoints[MaxXPointIndex].X - geometrypoints[i].X);
}
}
}
//按照斜率slope排序,取稳定排序方法的堆排序。
HeapSort<GeometryPoint> heapsort = new HeapSort<GeometryPoint>();
heapsort.Sort(this.geometrypoints,0,size-1);
}
}


SimplePolygon定义

控制台程序调用方法,按照连线顺序打印顶点:

 class Program
{
static void Main(string[] args)
{
SimplePolygon sp = new SimplePolygon();
sp.Initialize(10, -50, 50, -50, 50);
for (int i = 0; i < sp.GeometryPoints.Length; i++)
{
Console.WriteLine(sp.GeometryPoints[i]);
}
Console.ReadKey();
}
}

SimplePolygon 控制台调用方法

如果用界面绘图,应用WPF几何绘图可实现如下效果,红线为计算正切值的示例连线,绿色线为生成的简单多边形:

关于坐标系与绘图的方法,请参照另一篇文章“轮廓算法”。

完毕。

作者:Andy Zeng

欢迎任何形式的转载,但请务必注明出处。

http://www.cnblogs.com/andyzeng/p/3754005.html

几何算法:点集合构造简单多边形,布布扣,bubuko.com

时间: 2024-10-10 01:53:29

几何算法:点集合构造简单多边形的相关文章

Java数据结构与算法之集合

线性表.链表.哈希表是常用的数据结构,在进行Java开发时,SDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中. 一.Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object.一些Collection允许相同元素而另一些不行.一些能排序而另一些不行.Java  SDK不提供直接继承自Collection的类,Java  SDK提供的类都是继承自Collection的"子接口"如List和Set

几何画板追踪法构造阴影方法

几何图形中常常有几条曲线相交,围成一个区域,或者几个图形叠加,有一个重叠部分,如何突出显示这个部分呢?本文教你利用几何画板追踪法画阴影. 以两个圆相交部份为例,操作步骤如下: 利用圆工具绘制两个相交圆.利用线段工具在两圆相交的部份绘制一条线段,端点落在两个圆上. 选中线段,选择“显示”——“追踪线段”.上下移动线段,反复扫描.如果阴影太稀疏,可以增加扫描次数.隐藏线段. 以上内容向大家介绍了利用几何画板追踪法构造阴影的方法,操作非常简单,只要能够理解追踪法即可.几何画板阴影的构造方法有很多,比如

查找和排序的基本操作:查找排序算法大集合

重点 查找算法着重掌握:顺序查找.二分查找.哈希表查找.二叉排序树查找. 排序算法着重掌握:冒泡排序.插入排序.归并排序.快速排序. 顺序查找 算法说明 顺序查找适合于存储结构为顺序存储或链接存储的线性表. 算法思想 顺序查找也称为线形查找,属于无序查找算法.从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功:若扫描结束仍没有找到关键字等于k的结点,表示查找失败. 算法实现 int sequenceSearch(int a[], int valu

yzoi2223集合构造的详细解法

Description - 问题描述 集合M的定义如下: 1是M中的元素 如果x是M中的元素,那么2x+1和4x+5都是M中的元素 那么,集合M中,最小的n个数是哪些? Input - 输入数据 一个整数n(1<=n<=100 000) Output - 输出数据 n个从小到大的整数,空格分隔. 仔细一分析便可推知最后需要输出的数一定是单调递增的.在当时做这题的时候,旁边的gxy同学直接从1开始暴力枚举所有的奇数(2x+1和4x+5肯定是一个奇数),然后判断和前面的数是否构成2x+1或4x+5

用几何画板参数如何构造动态解析式

几何画板提供丰富而方便的创造功能使用户可以随心所欲地编写出自己需要的教学课件,是最出色的教学软件之一.它主要以点.线.圆为基本元素,通过对这些基本元素的变换.构造.测算.计算.动画.跟踪轨迹等,构造出其它较为复杂的图形.下面以用参数构造几何画板动态解析式y=a(x-h)2+k为例,来看看动态解析式是如何通过参数来实现的. 具体步骤如下: 1.新建三个参数a.h.k,默认选择即可.  利用“数据”——“新建参数”新建a.h.k三个参数 2.绘制函数的图象.选择“绘图”——“绘制新函数”,弹出“新建

几何画板是这样构造扇形内部的

几何,就是研究空间结构及性质的一门学科.它面对了各种各样的图形.扇形就是几何学中的一个重要图形.几何画板作为专业绘图工具,不仅可以画扇形还可以画扇形统计图,其中重要的步骤就是构造扇形内部.下面本教程就来给大家分享一下如果用几何画板构造扇形内部? 方法一 利用构造菜单 步骤一 绘制扇形.打开几何画板,选择左侧工具箱“圆工具”,在画板上任意画一个圆O,使用“点工具”在圆上任取两点AB,依次选中点O.B.A,执行“构造”——“圆弧”命令,得到弧AB.构造线段OA.OB,隐藏圆O,得到扇形.  在几何画

【算法】—— 集合的子集

问题 给定一个集合,输出它的所有子集. 示例: 给定集合{1,2,3},应该输出: {} {1} {2} {1, 2} {3} {1, 3} {2, 3} {1, 2, 3} 解法1:增量构造法 增量构造法,每次选择一个元素放到集合中,每次操作的结果即是一个子集. 递归操作,每次向当前集合中添加一个比当前集合中最大的元素大1的数. from __future__ import print_function def print_subset(n, lst, cur): for i in range

matlab练习程序(构造简单多边形)

简单多边形是指各边不相交的多边形. 首先计算出所有顶点中心位置. 然后求每个顶点与中心的极角. 再对极角进行排序. 连接排序后的点就行了. 结果如下: matlab代码如下: clear all;close all;clc; n=30; p=rand(n,2); cen=mean(p); ang=atan2(p(:,1)-cen(1),p(:,2)-cen(2)); %每个点到坐标中心极角 p=[p,ang]; p=sortrows(p,3); %按极角排序 hold on; %连接各点 plo

算法训练 集合运算

时间限制:1.0s   内存限制:512.0MB 问题描述 给出两个整数集合A.B,求出他们的交集.并集以及B在A中的余集. 输入格式 第一行为一个整数n,表示集合A中的元素个数. 第二行有n个互不相同的用空格隔开的整数,表示集合A中的元素. 第三行为一个整数m,表示集合B中的元素个数. 第四行有m个互不相同的用空格隔开的整数,表示集合B中的元素. 集合中的所有元素均为int范围内的整数,n.m<=1000. 输出格式 第一行按从小到大的顺序输出A.B交集中的所有元素. 第二行按从小到大的顺序输