离散点外包凸多边形生成算法(C#或者C++),要有详细代码和说明,最好有可运行的样例程序好的另外加分,急

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了离散点外包凸多边形生成算法(C#或者C++),要有详细代码和说明,最好有可运行的样例程序好的另外加分,急相关的知识,希望对你有一定的参考价值。

find&&find_if
临时对象——构造函数的调用.根据若干个离散点创建最大外包凸多边形图形算法
//卷包裹法---创建最大外包凸多边形

//stdafx.h

#define PI 3.1415926
#define NULL 0
#define LEN sizeof(struct XYpoint)

long pointSum;

struct XYpoint

double x;
double y;
struct XYpoint *next;
;

XYpoint *creat(void);

struct XYpoint *insert(struct XYpoint *head2,struct XYpoint *p);

struct XYpoint *del(struct XYpoint *head,struct XYpoint *p);

struct XYpoint *miny(struct XYpoint *head);

double angle(struct XYpoint *a,struct XYpoint *b,struct XYpoint *c);

double dis(struct XYpoint *a,struct XYpoint *b);

struct XYpoint *tank( struct XYpoint *head ,struct XYpoint *head2);

struct XYpoint *convexHull( struct XYpoint *head ,struct XYpoint *head2);

void print(struct XYpoint *head2);

//stdafx.cpp
#include "stdafx.h"
#include <math.h>
#include <vector>

//using namespace std;

struct XYpoint *creat(void)

struct XYpoint *head;
struct XYpoint *p1,*p2;
FILE *fp;
if((fp=fopen("in_put.txt","r"))==NULL)

printf("can not open the file\n");
exit(0);

pointSum=0;
p1=p2=(struct XYpoint *)malloc(LEN);
fscanf(fp,"%lf,%lf",&p1->x,&p1->y);
head=NULL;
while(!feof(fp))

pointSum=pointSum+1;
if(pointSum==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct XYpoint *)malloc(LEN);
fscanf(fp,"%lf,%lf",&p1->x,&p1->y);

p2->next=NULL;
fclose(fp);
return(head);


struct XYpoint *insert(struct XYpoint *head2,struct XYpoint *p)

struct XYpoint *p1,*p0;
p0=p;
p1=head2;
while(p1->next!=NULL)

p1=p1->next;

p1->next=p0;
p0->next=NULL;
if (head2->next==NULL)
printf("not been insert!\n");
return (head2);


struct XYpoint *del(struct XYpoint *head,struct XYpoint *p)

struct XYpoint *p0,*p1;
if(head==NULL)

printf("\nlist null\n");
goto end;

p0=head;
while((p->x!=p0->x||p->y!=p0->y)&&p0->next!=NULL)

p1=p0;
p0=p0->next;

if(p->x==p0->x&&p->y==p0->y)

if(p0==head)
head=p0->next;
else
p1->next=p0->next;

else
printf("not been found!\n");

end:
return (head);


struct XYpoint *miny(struct XYpoint *head)

double min;
struct XYpoint *p,*p1;
p=head;
min=p->y;
p1=p;
p=p->next;
while (p!=NULL)

if (min>p->y)
min=p->y,p1=p;
else if(min==p->y&&p1->x>p->x)
min=p->y,p1=p;
else p=p->next;

return(p1);



double angle(struct XYpoint *a,struct XYpoint *b,struct XYpoint *c)

struct XYpoint *p0,*p1,*p2;
double dsx,dsy,dex,dey,cosfi,norm,fi;
p0=a;
p1=b;
p2=c;
dsx=p1->x-p0->x;
dsy=p1->y-p0->y;
dex=p2->x-p1->x;
dey=p2->y-p1->y;

cosfi=dsx*dex+dsy*dey;
norm=(dsx*dsx+dsy*dsy)*(dex*dex+dey*dey);
cosfi/=sqrt( norm );
fi=acos(cosfi);
if(cosfi<=-1) fi=PI;
if(cosfi>=1) fi=0;
return(fi);


double dis(struct XYpoint *a,struct XYpoint *b)

struct XYpoint *p1,*p2;
double dsx,dsy,dx;
p1=a;
p2=b;
dsx=p2->x-p1->x;
dsy=p2->y-p1->y;
dx=sqrt(dsx*dsx+dsy*dsy);

return(dx);


struct XYpoint *tank( struct XYpoint *head ,struct XYpoint *head2)

double minfi,fi;
double dx,dy;
struct XYpoint *p,*p1,*p2;

p2=p=head;
p1=head2;
minfi=PI;
while(p!=NULL)

dx=p->x-p1->x;
dy=p->y-p1->y;
if(dx!=0)

fi=atan(dy/dx);
if(fi<0)
fi=fi+PI;

else if(dx==0&&dy==0) fi=PI;
else fi=PI/2.0;
if(minfi>=fi)

minfi=fi;p2=p;

p=p->next;


return (p2);


struct XYpoint *convexHull( struct XYpoint *head ,struct XYpoint *head2)


double min;
double tempAngle;
struct XYpoint *lastP,*nowP,*p,*p1,*p2;
p=head;
nowP=p1=head2;
lastP=nowP;
p1=p1->next;
nowP=p1;

while(p1->next!=NULL)

p1=p1->next;
lastP=nowP;
nowP=p1;


min=angle(lastP,nowP,p);
p2=p;
p=p->next;
while(p!=NULL)

tempAngle=angle(lastP,nowP,p);
if (min>tempAngle)

min=tempAngle;
p2=p;
p=p->next;

else if(min==tempAngle)

if(dis(nowP,p2)<dis(nowP,p))
p2=p;
p=p->next;

else

p=p->next;



return(p2);


void print(struct XYpoint *head2)

FILE *fp;
struct XYpoint *p;
p=head2;

if((fp=fopen("out_put.txt","w"))==NULL)

printf("can not open the file\n");
exit(0);

fprintf(fp,"%ld",pointSum);
fprintf(fp,"\n");
while(p!=NULL)

fprintf(fp,"%lf,%lf",p->x,p->y);
fprintf(fp,"\n");
p=p->next;

fclose(fp);


/*
int _tmain(int argc, _TCHAR* argv[])

struct XYpoint *head ,*head2,*pp,*qq;
head=creat();
pp=miny(head);
head2=(struct XYpoint *)malloc(LEN);
head2->x=pp->x;
head2->y=pp->y;
head2->next=NULL;
pp=tank(head,head2);
qq=(struct XYpoint *)malloc(LEN);
qq->x=pp->x;
qq->y=pp->y;
qq->next=NULL;
head2=insert(head2,qq);
head=del(head,pp);
pp=convexHull(head,head2);
do

qq=(struct XYpoint *)malloc(LEN);
qq->x=pp->x;
qq->y=pp->y;
qq->next=NULL;
head2=insert(head2,qq);
head=del(head,pp);
pp=convexHull(head,head2);
while(!(head2->x==pp->x&&head2->y==pp->y));

print(head2);

return 0;

*/

//view.h
class CCreateHullView : public CView

private:
int m_nPtnum;
XYpoint *m_pPtHead;
XYpoint *m_pHullHead;
;

//view.cpp
CCreateHullView::CCreateHullView()

// TODO: add construction code here
m_nPtnum = 0;
m_pPtHead = NULL;
m_pHullHead = NULL;


CCreateHullView::~CCreateHullView()

if (m_nPtnum > 0)

XYpoint *p = m_pPtHead;
while (NULL != p)

m_pPtHead = p->next;
p->next = NULL;
delete p;
p = m_pPtHead;

m_pPtHead = NULL;
m_nPtnum = 0;

p = m_pHullHead;
while (NULL != p)

m_pHullHead = p->next;
p->next = NULL;
delete p;
p = m_pHullHead;

m_pHullHead = NULL;



void CCreateHullView::OnLButtonDown(UINT nFlags, CPoint point)

// TODO: Add your message handler code here and/or call default
if (0 == m_nPtnum)

m_pPtHead = new XYpoint;
m_pPtHead->x = point.x;
m_pPtHead->y = point.y;
m_pPtHead->next = NULL;
m_nPtnum++;

XYpoint *p = new XYpoint;
p->x = point.x;
p->y = point.y;
p->next = m_pPtHead;
m_pPtHead = p;
m_nPtnum++;

Invalidate();
CView::OnLButtonDown(nFlags, point);


void CCreateHullView::OnCreateHull()

// TODO: Add your command handler code here
if (0 < m_nPtnum)

struct XYpoint *head ,*head2,*pp,*qq;
head = m_pPtHead;
pp = miny(head);
head2=(struct XYpoint *)malloc(LEN);
head2->x=pp->x;
head2->y=pp->y;
head2->next=NULL;
pp=tank(head,head2);
qq=(struct XYpoint *)malloc(LEN);
qq->x=pp->x;
qq->y=pp->y;
qq->next=NULL;
head2=insert(head2,qq);
head=del(head,pp);
pp=convexHull(head,head2);
do

qq=(struct XYpoint *)malloc(LEN);
qq->x=pp->x;
qq->y=pp->y;
qq->next=NULL;
head2=insert(head2,qq);
head=del(head,pp);
pp=convexHull(head,head2);
while(!(head2->x==pp->x&&head2->y==pp->y));

//print(head2);
m_pHullHead = head2;
Invalidate();



void CCreateHullView::OnDraw(CDC* pDC)

CCreateHullDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here

XYpoint *p = NULL;
if (0 < m_pHullHead)

p = m_pHullHead;
pDC->Rectangle((int)(m_pHullHead->x) - 2, (int)(m_pHullHead->y) - 2, (int)(m_pHullHead->x) + 2, (int)(m_pHullHead->y) + 2);
pDC->MoveTo((int)(m_pHullHead->x), (int)(m_pHullHead->y));
p = m_pHullHead->next;
while (NULL != p)

pDC->Rectangle(
(int)(p->x) - 2,
(int)(p->y) - 2,
(int)(p->x) + 2,
(int)(p->y) + 2
);
pDC->LineTo(CPoint((int)p->x, (int)p->y));
p = p->next;

p = m_pHullHead;
pDC->LineTo(CPoint((int)p->x, (int)p->y));



p = m_pPtHead;
while (NULL != p)

pDC->Rectangle(
(int)(p->x) - 2,
(int)(p->y) - 2,
(int)(p->x) + 2,
(int)(p->y) + 2
);
// pDC->FillSolidRect(
// (int)(p->x) - 2,
// (int)(p->y) - 2,
// (int)(p->x) + 2,
// (int)(p->y) + 2,
// RGB(225, 0, 0)
// );
p = p->next;



不知道可以不,应该可以运行吧,你先试试
参考技术A 可以取x最小的一个点开始,然后遍历所有点,然后取连线逆时针角度最大且小于90度的点作为下一个点,然后以此点为原点重复上一步,直到遇到开始点。 参考技术B 百度浙大ACM模板,或者吉林大学ACM模板,里面应该有求凸包的算法代码。复杂度有nlogn的和n^2的。 或者直接百度凸包算法本回答被提问者采纳

点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部

判断一点是否在不规则图像的内部算法,如下图是由一个个点组成的不规则图像,判断某一点是否在不规则矩形内部,先上效果图

技术分享

算法实现如下,算法简单,亲试有效

 

    public class PositionAlgorithmHelper
    {
        /// <summary>
        /// 判断当前位置是否在不规则形状里面
        /// </summary>
        /// <param name="nvert">不规则形状的定点数</param>
        /// <param name="vertx">当前x坐标</param>
        /// <param name="verty">当前y坐标</param>
        /// <param name="testx">不规则形状x坐标集合</param>
        /// <param name="testy">不规则形状y坐标集合</param>
        /// <returns></returns>
        public static bool PositionPnpoly(int nvert, List<double> vertx, List<double> verty, double testx, double testy)
        {
            int i, j, c = 0;
            for (i = 0, j = nvert - 1; i < nvert; j = i++)
            {
                if (((verty[i] > testy) != (verty[j] > testy)) && (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))
                {
                    c = 1 + c; ;
                }
            }
            if (c % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }

用上图坐标进行测试:

    class Program
    {
        static void Main(string[] args)
        {
            test1();
        }

        /// <summary>
        /// test1
        /// </summary>
        public static void test1()
        {
            //不规则图像坐标
            List<Position> position = new List<Position>();
            position.Add(new Position() { x = 6, y = 0 });
            position.Add(new Position() { x = 10, y = 2 });
            position.Add(new Position() { x = 16, y = 2 });
            position.Add(new Position() { x = 20, y = 6 });
            position.Add(new Position() { x = 14, y = 10 });
            position.Add(new Position() { x = 16, y = 6 });
            position.Add(new Position() { x = 12, y = 6 });
            position.Add(new Position() { x = 14, y = 8 });
            position.Add(new Position() { x = 10, y = 8 });
            position.Add(new Position() { x = 8, y = 6 });
            position.Add(new Position() { x = 12, y = 4 });
            position.Add(new Position() { x = 6, y = 4 });
            position.Add(new Position() { x = 8, y = 2 });

            //用户当前位置坐标
            List<Position> userPositions = new List<Position>();
            userPositions.Add(new Position() { x = 14, y = 4 });
            userPositions.Add(new Position() { x = 15, y = 4 });
            userPositions.Add(new Position() { x = 10, y = 6 });
            userPositions.Add(new Position() { x = 8, y = 5 });

            //不规则图像x坐标集合
            List<double> xList = position.Select(x => x.x).ToList();
            //不规则图像y坐标集合
            List<double> yList = position.Select(x => x.y).ToList();

            foreach (var userPosition in userPositions)
            {
                bool result = PositionAlgorithmHelper.PositionPnpoly(position.Count, xList, yList, userPosition.x, userPosition.y);

                if (result)
                {
                    Console.WriteLine(string.Format("{0},{1}【在】坐标内", userPosition.x, userPosition.y));
                }
                else
                {
                    Console.WriteLine(string.Format("{0},{1}【不在】坐标内", userPosition.x, userPosition.y));
                }
            }
        }
    }

另外两种方式:

        /// <summary>  
        /// 判断点是否在多边形内.  
        /// ----------原理----------  
        /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,  
        /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。  
        /// 所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2),  
        /// 1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况  
        /// 2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。  
        /// 3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。  
        /// 4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。  
        /// </summary>  
        /// <param name="checkPoint">要判断的点</param>  
        /// <param name="polygonPoints">多边形的顶点</param>  
        /// <returns></returns>  
        public static bool IsInPolygon2(Position checkPoint, List<Position> polygonPoints)
        {
            int counter = 0;
            int i;
            double xinters;
            Position p1, p2;
            int pointCount = polygonPoints.Count;
            p1 = polygonPoints[0];
            for (i = 1; i <= pointCount; i++)
            {
                p2 = polygonPoints[i % pointCount];
                if (checkPoint.y > Math.Min(p1.y, p2.y)//校验点的Y大于线段端点的最小Y  
                    && checkPoint.y <= Math.Max(p1.y, p2.y))//校验点的Y小于线段端点的最大Y  
                {
                    if (checkPoint.x <= Math.Max(p1.x, p2.x))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断).  
                    {
                        if (p1.y != p2.y)//线段不平行于X轴  
                        {
                            xinters = (checkPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                            if (p1.x == p2.x || checkPoint.x <= xinters)
                            {
                                counter++;
                            }
                        }
                    }

                }
                p1 = p2;
            }

            if (counter % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>  
        /// 判断点是否在多边形内.  
        /// ----------原理----------  
        /// 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,  
        /// 如果P在多边形外部,则交点个数必为偶数(0也在内)。  
        /// </summary>  
        /// <param name="checkPoint">要判断的点</param>  
        /// <param name="polygonPoints">多边形的顶点</param>  
        /// <returns></returns>  
        public static bool IsInPolygon(Position checkPoint, List<Position> polygonPoints)
        {
            bool inside = false;
            int pointCount = polygonPoints.Count;
            Position p1, p2;
            for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点...  
            {
                p1 = polygonPoints[i];
                p2 = polygonPoints[j];
                if (checkPoint.y < p2.y)
                {//p2在射线之上  
                    if (p1.y <= checkPoint.y)
                    {//p1正好在射线中或者射线下方  
                        if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧  
                        {
                            //射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。  
                            //由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside)  
                            //所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside)  
                            inside = (!inside);
                        }
                    }
                }
                else if (checkPoint.y < p1.y)
                {
                    //p2正好在射线中或者在射线下方,p1在射线上  
                    if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判断,在P1和P2之间且在P1P2右侧  
                    {
                        inside = (!inside);
                    }
                }
            }
            return inside;
        }  

 

以上是关于离散点外包凸多边形生成算法(C#或者C++),要有详细代码和说明,最好有可运行的样例程序好的另外加分,急的主要内容,如果未能解决你的问题,请参考以下文章

用turf.js求多个点的外包多边形

用turf.js求多个点的外包多边形

C# | 批量将CAD图幅网格外扩生成新图框(附源代码下载)

在一个国家/地区生成随机纬度/经度多边形?

求任意多边形的最大内接圆算法,c++编程

泰森多边形-最强大脑节目知识