Convex hull polygon generation algorithm---fast convex hull method

Fast convex hull method to generate convex hull polygons

introduce

The fast convex hull method is used to find the convex hull points of a group of points.
The main steps are divided into two steps.

  1. Find the four vertices up, down, left and right
  2. Iteratively find convex hull points
Grid grid = new Grid();

insert image description here

Generate a grid object, and all_points stores all scattered points.
The first step is relatively simple and can be obtained by sorting all points. Stored in peak_points.
The second step requires multiple judgments on multiple situations and iterative solutions.
Can be split into three functional functions and a theme function

  • Function 1 - Calculate the area of ​​a triangle with three known points - Use the area of ​​the triangle to determine the distance between the points and the line
  • Function 2—determine whether the point is on the left side of the line
  • Function 3—Iterative function. Compute the (left point set, head, tail) combination operation to find the F point until the left point set is empty. At this time, F is the convex hull point, and add it to the stack CH
  • Function 4—Main function. Iteration entrance
    insert image description here
    solution steps:
    1. Add stack CH to P1
    2. Connect P1 and P2 to solve the LEFT point set. Form the first (LEFT, head, tail) combination
    3. Iterate over the first (LEFT, head, tail) combination. When LEFT is empty during the iteration, CH is added to F at this time. Otherwise, new combinations (LEFT1, head, F), (LEFT2, F, tail) are formed. Repeat iteration
    4. After the large combination of (LEFT, P1, P2) is calculated, calculate each combination of P2-P3, P3-P4, and P4-P1. CH is the convex hull point

data structure

  • point class
  • Grid class
class point
    {
    
    
        public string pointname;
        public double x;
        public double y;
        public double h;

        public point(string name, double x, double y, double h)
        {
    
    
            pointname = name;
            this.x = x;
            this.y = y;
            this.h = h;
        }
        public point()
        {
    
     }
    }
    class Grid
    {
    
    
            //使用快速凸包法
        public double BaseHeight;//参考高程
        public List<point> all_points = new List<point>();//所有点
        public List<point> points = new List<point>();//移除四个顶点的点集
        public List<point> peak_points = new List<point>();//四个顶点
        public List<point> CH = new List<point>();//栈CH
     }

Step 1 Find four vertices

Vertex P1 P2 P3 P4
P1: x minimum
P2: y maximum
P3: x maximum
p4: y minimum
namely the top, bottom, left and right four points in the scatter point set.
Using List sorting method

//1.查找四个顶点
        public void FindPeak()
            {
    
    
            points.AddRange(all_points);
                List<point> ps = new List<point>();
                int n = all_points.Count;
                ps.AddRange(all_points);
                ps.Sort((point p_1, point p_2) => p_1.x.CompareTo(p_2.x));//按照x升序
                point p1 = new point(ps[0].pointname, ps[0].x, ps[0].y, ps[0].h);
                point p3 = new point(ps[n - 1].pointname, ps[n - 1].x, ps[n - 1].y, ps[n - 1].h);
                ps.Sort((point p_1, point p_2) => p_1.y.CompareTo(p_2.y));//按照y升序
                point p4 = new point(ps[0].pointname, ps[0].x, ps[0].y, ps[0].h);
                point p2 = new point(ps[n - 1].pointname, ps[n - 1].x, ps[n - 1].y, ps[n - 1].h);
            //遍历移除四个顶点
            for (int j = 0; j < all_points.Count; j++)
            {
    
    
                if (all_points[j].pointname == p1.pointname ||
                    all_points[j].pointname == p2.pointname ||
                    all_points[j].pointname == p3.pointname ||
                    all_points[j].pointname == p4.pointname )
                {
    
    
                    points.Remove(all_points[j]);
                }
            }
            peak_points.Add(p1);
            peak_points.Add(p2);
            peak_points.Add(p3);
            peak_points.Add(p4);
        }

The purpose of this part is to find the four vertices of peak_points

Step 2: Use iteration to find the convex hull points

2.1 Function - Calculate Area of ​​Three Points - Used to determine the distance from a point to a line

//函数---计算面积
        double arc(point p1,point p2,point p3)
        {
    
    
            return 1/2.0*Math.Abs(p1.x*(p2.y-p3.y)+p2.x*(p3.y-p1.y)+p3.x*(p1.y-p2.y));
        }

2.2 Function—The judgment point is on the left side of the line

Line p1-p2, determine whether p3 is to the left of line p1-p2

public int judge_left(point p1,point p2,point p3)
        {
    
    
            if (p1.x * p2.y - p2.x * p1.y + p3.x * (p1.y - p2.y) + p3.y * (p2.x - p1.x) > 0)
            {
    
    
                return 1;
            }
            return -1;
        }

2.3 Iterative function

(Left point set head tail) combination
Iteratively generate new F to form (left point set head tail) combination until the left point set is empty, then the F is a convex hull point and added to the CH stack.

public void fun(List<point> left_point,point head,point tail)
        {
    
    
            int flag = -1;//记录位置
            double areamax = 0;//记录最大面积
            for (int i = 0; i < left_point.Count; i++)
            {
    
    
                if (arc(head, tail, left_point[i]) > areamax)
                {
    
    
                    areamax = arc(head, tail, left_point[i]);
                    flag = i;
                }
            }
            //以上为寻找F
            if (flag == -1) //left_point为空
            {
    
    
                CH.Add(tail);
            }
            //找到F
            else
            {
    
    
                point F = left_point[flag];//F点
                left_point.RemoveAt(flag);//移除F
                List<point> left_point1 = new List<point>();
                List<point> left_point2 = new List<point>();
                for (int j = 0; j < left_point.Count; j++)
                {
    
    
                    if (judge_left(head, F, left_point[j]) == 1)
                    {
    
    
                        left_point1.Add(left_point[j]);
                    }
                }
                fun(left_point1,head,F);
                for (int k = 0; k < left_point.Count; k++)
                {
    
    
                    if (judge_left(F, tail, left_point[k]) == 1)
                    {
    
    
                        left_point2.Add(left_point[k]);
                    }
                }
                fun(left_point2,F,tail);
            }
        }

sought convex hull point

public void Converx()
        {
    
    
            CH.Add(peak_points[0]);//第一步加入第一点
            for (int i = 0; i < peak_points.Count; i++)//大遍历,四个顶点
            {
    
    
                List<point> Left = new List<point>();//LP
                for (int j = 0; j < points.Count; j++)
                {
    
    
                    if (judge_left(peak_points[i%4], peak_points[(i + 1)%4], points[j]) == 1)
                    {
    
    
                        Left.Add(points[j]); //LP加入,同时points移除
                        points.Remove(points[j]);
                       // j--;//
                    }
                }
                //求出Left
                fun(Left,peak_points[i%4],peak_points[(i+1)%4]);
            }
        }

Finally, the CH is the convex hull point. The drawing results are as follows:
insert image description here
Reference textbook "Surveying and Mapping Programming (Volume 2)" Li Yingbing

Guess you like

Origin blog.csdn.net/weixin_51205206/article/details/124411961
Recommended