[数据结构] 最小覆盖圆

这个数据结构是根据 最小覆盖圆 算法进行改造得到,主要是描述一个圆的半径、圆心坐标、圆覆盖的点的圆,以及维护一个加入点的操作(push_point方法)。

成员变量如下:

  • Center 圆心坐标,是一个struct point类型
  • Radius 圆的半径,是一个double类型
  • allPoint 点的数组,是一个vector< struct point >类型,表示这个圆覆盖的所有点

成员方法如下:

  • bool inside_circle (const point&):判断输入的point是否在圆内,在圆内则返回ture,否则返回false
  • void push_point (const point&):加入一个点,具体操作如下:
    1. 将该点加入allPoint数组
    2. 判断这个点的是否在圆内部,如果在圆内部直接返回
    3. 如果这个点在圆外部,则进行最小圆覆盖算法处理:从allPoint数组中进行枚举出一个或者两个点与push_point输入的点来形成新的圆(最小覆盖圆算法)
      1.   枚举一个点的原因是会存在钝角三角形的外接圆情况,此时这个钝角三角的外接圆一定可以缩小为其中两个点为直径的圆。

cpp代码:

 1 struct point {
 2     double x,y;
 3 
 4     point():x(0.0),y(0.0) {}
 5     point(double x, double y): x(x),y(y) {}
 6 
 7     point operator + (const point &p) const { // (x1+x2), (y1+y2)
 8         return {this->x + p.x, this->y + p.y};
 9     }
10     point operator - (const point &p) const { // (x1-x2), (y1-y2)
11         return {this->x - p.x, this->y - p.y};
12     }
13     point operator / (const double &number) const { // (x / n), (y / n)
14         return {this->x / number, this->y / number};
15     }
16     double distance (const point &p) const { // sq_distance = ((x1 - x2)^2 + (y1 - y2)^2) = distance^2
17         return (this->x - p.x) * (this->x - p.x) + (this->y - p.y) * (this->y - p.y);
18     }
19     point circumcenter (const point &p1, const point &p2) const { // The center of the circumscribed circle of three points
20         double x1 = this->x, x2 = p1.x, x3 = p2.x;
21         double y1 = this->y, y2 = p1.y, y3 = p2.y;
22         if ( (y2 - y1) * (x3 - x1) == (x2 - x1) * (y3 - y1)) {
23             double d1 = this->distance(p1); // this and p1
24             double d2 = this->distance(p2); // this and p2
25             double d3 = p1.distance(p2); // p1 and p3
26             if (d1 > d2 && d1 > d3) {
27                 return (*this + p1) / 2.0;
28             } else if (d2 > d3) {
29                 return (*this + p2) / 2.0;
30             } else {
31                 return (p1 + p2) / 2.0;
32             }
33         }
34         double new_x = ((y2-y1)*(y3*y3-y1*y1+x3*x3-x1*x1)-(y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1)) / (2.0*((x3-x1)*(y2-y1)-(x2-x1)*(y3-y1)));
35         double new_y = ((x2-x1)*(x3*x3-x1*x1+y3*y3-y1*y1)-(x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1)) / (2.0*((y3-y1)*(x2-x1)-(y2-y1)*(x3-x1)));
36         return {new_x, new_y};
37     }
38 };
39 struct circle {
40     point center;
41     double radius;
42     std::vector< point > all_points;
43 
44     circle (): center(point()), radius(0.0) {}
45 
46     bool inside_point (const point &p) const { // if distance <= radius, return true;
47         return p.distance(this->center) <= this->radius;
48     }
49 
50     void push_point (const point &p) {
51         this->all_points.push_back(p);
52 
53         if(this->inside_point(p)) return;
54 
55         this->center = p;
56         this->radius = 0.0;
57 
58         for (auto i = 0; i < this->all_points.size() - 1; i++) {
59             if( this->inside_point(this->all_points[i]) ) continue;
60 
61             this->center = (p + this->all_points[i]) / 2.0;
62             this->radius = p.distance(this->center);
63 
64             for (int j = 0; j < i; j++) {
65                 if(this->inside_point(this->all_points[j])) continue;
66 
67                 this->center = p.circumcenter(this->all_points[i], this->all_points[j]);
68                 this->radius = p.distance(this->center);
69             }
70         }
71     }
72 };

 

posted @ 2022-12-08 17:57  蒟蒻zExNocs  阅读(209)  评论(0)    收藏  举报