1. 程式人生 > >poj1584 A round peg in a ground hole【計算幾何】

poj1584 A round peg in a ground hole【計算幾何】

instead end 是不是 clas 計算幾何 you 否則 cto let

含【判斷凸包】,【判斷點在多邊形內】,【判斷圓在多邊形內】模板

凸包:即凸多邊形

用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連接起來構成的凸多邊形,它能包含點集中所有的點。

The DIY Furniture company specializes in assemble-it-yourself furniture kits. Typically, the pieces of wood are attached to one another using a wooden peg that fits into pre-cut holes in each piece to be attached. The pegs have a circular cross-section and so are intended to fit inside a round hole.
A recent factory run of computer desks were flawed when an automatic grinding machine was mis-programmed. The result is an irregularly shaped hole in one piece that, instead of the expected circular shape, is actually an irregular polygon. You need to figure out whether the desks need to be scrapped or if they can be salvaged by filling a part of the hole with a mixture of wood shavings and glue.
There are two concerns. First, if the hole contains any protrusions (i.e., if there exist any two interior points in the hole that, if connected by a line segment, that segment would cross one or more edges of the hole), then the filled-in-hole would not be structurally sound enough to support the peg under normal stress as the furniture is used. Second, assuming the hole is appropriately shaped, it must be big enough to allow insertion of the peg. Since the hole in this piece of wood must match up with a corresponding hole in other pieces, the precise location where the peg must fit is known.
Write a program to accept descriptions of pegs and polygonal holes and determine if the hole is ill-formed and, if not, whether the peg will fit at the desired location. Each hole is described as a polygon with vertices (x1, y1), (x2, y2), . . . , (xn, yn). The edges of the polygon are (xi, yi) to (x i+1
, y i+1) for i = 1 . . . n ? 1 and (xn, yn) to (x1, y1).

Input

Input consists of a series of piece descriptions. Each piece description consists of the following data:
Line 1 < nVertices > < pegRadius > < pegX > < pegY >
number of vertices in polygon, n (integer)
radius of peg (real)
X and Y position of peg (real)
n Lines < vertexX > < vertexY >
On a line for each vertex, listed in order, the X and Y position of vertex The end of input is indicated by a number of polygon vertices less than 3.

Output

For each piece description, print a single line containing the string:
HOLE IS ILL-FORMED if the hole contains protrusions
PEG WILL FIT if the hole contains no protrusions and the peg fits in the hole at the indicated position
PEG WILL NOT FIT if the hole contains no protrusions but the peg will not fit in the hole at the indicated position

Sample Input

5 1.5 1.5 2.0
1.0 1.0
2.0 2.0
1.75 2.0
1.0 3.0
0.0 2.0
5 1.5 1.5 2.0
1.0 1.0
2.0 2.0
1.75 2.5
1.0 3.0
0.0 2.0
1

Sample Output

HOLE IS ILL-FORMED
PEG WILL NOT FIT

題意:

給定n個點 這n個點組成一個多邊形

給定一個peg的坐標和半徑

首先判斷這個多邊形是不是凸多邊形 若不是 輸出“HOLE IS ILL-FORMED”

否則判斷peg和多邊形的關系 若peg所代表的圓在多邊形內部輸出“PEG WILL FIT”

否則輸出“PEG WILL NOT FIT”

思路:

首先將n個點構造成封閉圖形,判斷是不是一個凸包

  求連續兩條邊的叉乘,如果正負號與之前的出現了不同,說明不是凸包

再判斷圓心與多邊形的關系

  設圓心為P,逐條枚舉n邊形的邊AB,利用
  技術分享圖片

  計算PA和PB的夾角,最後求和得到的就是環顧角。

  (1) 圓心在多邊形內部時,環顧角=±360

  (2) 圓心在多邊形外部時,環顧角=0

  (3) 圓心在多邊形邊上時(不包括頂點),環顧角=±180

  (4) 圓心在多邊形頂點時,環顧角為(0,360)之間的任意角,其實就是圓心所在的頂點的兩條鄰接邊的夾角。

最後判斷整個圓是否在多邊形內部

  只需要求出圓心到邊的最短距離 若大於半徑則在多邊形內

  設圓心為P,逐條枚舉n邊形的邊AB,利用技術分享圖片得到△PAB的面積,

  再根據公式S=0.5*|AB|*h,可以得到技術分享圖片

  枚舉所有h與圓的半徑R比對,只要所有的邊都有h - R>=0,則說明圓在多邊形內

  1 //#include <bits/stdc++.h>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<stdio.h>
  6 
  7 using namespace std;
  8 typedef long long int LL;
  9 
 10 const double eps = 1e-6;
 11 const double pi = 3.141592654;
 12 int n;
 13 double radius;
 14 struct point{
 15     double x, y;
 16 }peg;
 17 
 18 int precision(double x)
 19 {
 20     if(fabs(x) <= eps){
 21         return 0;
 22     }
 23     return x > 0 ? 1: -1;
 24 }
 25 
 26 double dotdet(double x1, double y1, double x2, double y2)
 27 {
 28     return x1 * x2 + y1 * y2;
 29 }
 30 
 31 double det(double x1, double y1, double x2, double y2)
 32 {
 33     return x1 * y2 - x2 * y1;
 34 }
 35 
 36 double cross(point a, point b, point c, point d)
 37 {
 38     return det(b.x - a.x, b.y - a.y, d.x - c.x, d.y - c.y);
 39 }
 40 
 41 double distant(point a, point b)
 42 {
 43     return sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
 44 }
 45 
 46 double angle(point a, point b, point p)
 47 {
 48     return acos(dotdet(a.x - p.x, a.y - p.y, b.x - p.x, b.y - p.y) / (distant(a, p) * distant(b, p)));
 49 }
 50 
 51 bool isconvex(point *vectex)
 52 {
 53     int direction = 0;
 54     //1, 逆時針;-1, 順時針
 55     for(int i = 0; i < n; i++){
 56         int temp = precision(cross(vectex[i], vectex[i + 1], vectex[i + 1], vectex[i + 2]));
 57 
 58         if(!direction){
 59             direction = temp;
 60         }
 61         if(direction * temp < 0){
 62             return false;
 63         }
 64     }
 65     return true;
 66 }
 67 
 68 bool is_in(point *vectex)
 69 {
 70     double circleAngle = 0.0;
 71     for(int i = 1; i <= n; i++){
 72         if(precision(cross(peg, vectex[i], peg, vectex[i + 1])) >= 0){
 73             circleAngle += angle(vectex[i], vectex[i + 1], peg);
 74         }
 75         else{
 76             circleAngle -= angle(vectex[i], vectex[i + 1], peg);
 77         }
 78     }
 79 
 80     if(precision(circleAngle) == 0){
 81         return false;
 82         //peg在多邊形外部
 83     }
 84     else if(precision(circleAngle - pi) == 0 || precision(circleAngle + pi) == 0){
 85         //peg在多邊形邊上
 86         if(precision(radius) == 0){
 87             return true;
 88         }
 89     }
 90     else if(precision(circleAngle - 2 * pi) == 0 || precision(circleAngle + 2 * pi) == 0){
 91         return true;
 92     }
 93     else{
 94         //peg在多邊形頂點上
 95         if(precision(radius) == 0){
 96             return true;
 97         }
 98     }
 99     return false;
100 }
101 
102 bool isfit(point *vectex)
103 {
104     for(int i = 0; i <= n; i++){
105         int k = precision(fabs(cross(peg, vectex[i], peg, vectex[i + 1]) / distant(vectex[i], vectex[i + 1])) - radius);
106         if(k < 0){
107             return false;
108         }
109     }
110     return true;
111 }
112 
113 int main()
114 {
115     while(scanf("%d", &n) != EOF && n >= 3){
116         cin>> radius >> peg.x >> peg.y;
117         point *vectex = new point[n + 2];
118 
119         for(int i = 1; i <= n; i++){
120             cin>>vectex[i].x >> vectex[i].y;
121         }
122 
123         //構成封閉多邊形
124         vectex[0].x = vectex[n].x;
125         vectex[0].y = vectex[n].y;
126         vectex[n + 1].x = vectex[1].x;
127         vectex[n + 1].y = vectex[1].y;
128 
129         if(!isconvex(vectex)){
130             cout<<"HOLE IS ILL-FORMED"<<endl;
131         }
132         else{
133             bool flag1 = is_in(vectex);
134             bool flag2 = isfit(vectex);
135 
136             if(flag1 && flag2){
137                 cout<<"PEG WILL FIT"<<endl;
138             }
139             else{
140                 cout<<"PEG WILL NOT FIT"<<endl;
141             }
142         }
143         delete vectex;
144     }
145     return 0;
146 }

poj1584 A round peg in a ground hole【計算幾何】