叉乘的利用。
判断凸包用index作为凸包顺时针或逆时针的标记,若计算出的temp与标记异号,说明不是凸包
判断圆点是否在凸包内用叉乘,顺便计算各边与原点组成的三角形的有向面积
判断凸包是否在园内,计算远点到各边的距离与半径比较即可
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
int n;
double pegr,area[155];
#define eps 1e-8
struct point{
double x,y;
}peg,p[155];
double dis(point a,point b){
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double det(double x1,double y1,double x2,double y2){
return x1*y2-x2*y1;
}
double cor(point b,point a,point d,point c){
return det(b.x-a.x,b.y-a.y,d.x-c.x,d.y-c.y);
}
int precision(double a){
if(fabs(a)<eps){
return 0;
}
return a>0?1:-1;
}
bool convex(){
int i=0;
int index=precision(cor(p[(i+1)%n],p[i],p[(i+2)%n],p[i]));
while(!index&&i<n){
i++;
index=precision(cor(p[(i+1)%n],p[i],p[(i+2)%n],p[i]));
}
i++;
for(;i<n;i++){
int temp=precision(cor(p[(i+1)%n],p[i],p[(i+2)%n],p[i]));
if(temp*index<0)
return false;
}
return true;
}
bool inside(){
int i=0;
area[i]=cor(p[i],peg,p[(i+1)%n],peg);
int index=precision(area[i]);
while(!index&&i<n){
i++;
area[i]=cor(p[i],peg,p[(i+1)%n],peg);
index=precision(area[i]);
}
i++;
for(;i<n;i++){
area[i]=cor(p[i],peg,p[(i+1)%n],peg);
int temp=precision(area[i]);
if(temp*index<0)
return false;
}
return true;
}
bool contain(){
int i=0;
for(;i<n;i++){
if(precision(area[i])<0)
area[i]*=-1;
double d=dis(p[i],p[(i+1)%n]);
d=sqrt(d);
//double area=cor(p[i],peg,p[(i+1)%n],peg);
//cout<<"距离: "<<area/d<<' '<<pegr<<endl;
if(area[i]/d<pegr){
//cout<<area[i]/d<<' '<<i<<endl;
return false;
}
}
return true;
}
int main(){
// freopen("D:\\INPUT.txt","r", stdin);
while(cin>>n&&n>=3){
cin>>pegr>>peg.x>>peg.y;
//pegr*=pegr;
//point p=new point[n];//point p[155];
int i=0;
for(;i<n;i++){
cin>>p[i].x>>p[i].y;
}
bool flag1=convex();
if(flag1){
bool flag2=inside();
bool flag3=contain();
//cout<<flag2<<' '<<flag3<<endl;
if(flag2&&flag3){
cout<<"PEG WILL FIT"<<endl;
}
else{
cout<<"PEG WILL NOT FIT"<<endl;
}
}
else{
cout<<"HOLE IS ILL-FORMED"<<endl;
}
//delete []p;
}
return 0;
}