Convex Hull:O(n^3)算法

课程:计算几何
书籍:计算几何:算法与应用

极边:对凸包有贡献的那些边。从Counter Clockwise来看,所有点都会落在极边的左侧(或者在极边上),而右侧为空。

根据该思路,我们只需判断任意两点所构成的边是否为极边,即其他点是否都在同一侧(后者在边上)。

判断点在边上的哪一侧,我们仍然使用O(n^4)算法中的ToLeft测试。


代码:
Patch.h与O(n^4)算法算法一样,就不再重复表述出来。

Main.cpp

/*  indere 2018/6/22
*   O(n^3)构造凸包算法思路为:其他所有顶点都落在一条边的一侧,则该边为极边,边的端点是极点
*   输入:顶点数以及顶点坐标
*   输出:极点编号(看情况是否按Counter-Clockwise输出)
/

/*
10
7 9
-8 -1
-3 -1
1 4
-3 9
6 -4
7 5
6 6
-6 10
0 8
*/

#include "Point.h"

Point *points;
int pointsize;

void Initialize();                              //初始化points数组
void ConstructConvexHull(Point* points);        //根据Point数组信息 构造凸包
int  ToLeft(int v1, int v2, int s);             //ToLeft Test

int main() {

    Initialize();
    ConstructConvexHull(points);

    for (int i = 0; i < pointsize; i++) {
        if (points[i].isExtremePoint)
            cout << points[i];
    }
    return 0;
}

void Initialize() {
    cin >> pointsize;
    points = new Point[pointsize];
    for (int i = 0; i < pointsize; i++) {
        float x, y;
        cin >> x >> y;
        points[i] = Point(i + 1, x, y);
    }
}

void ConstructConvexHull(Point* points) {

    for (int i = 0; i < pointsize; i++) {
        points[i].isExtremePoint = false;
    }

    for (int i = 0; i < pointsize; i++) {
        for (int j = i + 1; j < pointsize; j++) {
            bool EXISTLEFT = true;
            bool EXISTRIGHT = true;
            for (int s = 0; s < pointsize; s++) {
                if (s != i && s != j ) {
                    int judge = ToLeft(i, j, s);

                    //这里我们对顶点在边上的情况不做判断 避免其产生错误结果
                    if (judge == 1) {
                        EXISTLEFT = false;
                    }
                    else if(judge == -1)
                        EXISTRIGHT = false;
                }
            }
            if (EXISTLEFT || EXISTRIGHT) {          //当其他所有顶点位于向量同侧时
                points[i].isExtremePoint = true;
                points[j].isExtremePoint = true;
            }
        }
    }
}

int  ToLeft(int v1, int v2, int s) {
    float result = (points[v2].x * points[s].y + points[v1].x * points[v2].y + points[v1].y * points[s].x)
        - (points[v1].y * points[v2].x + points[v1].x * points[s].y + points[v2].y * points[s].x);

    if (result > 0.0f)      //左侧
        return 1;
    if (result == 0.0f)     //共线
        return 2;
    if (result < 0.0f)      //右侧
        return -1;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值