poj 3130 半平面交求多边形的核,存在性判断(跟3335题一模一样,只不过输入的的顺序不一样)...

所谓星形多边形,指的是这样的多边形:在其内部至少有一点P,其余任何一个在多边形内(包含边上)的点和P点的连线都在多边形内,P称为中点,通常一个星形多边形有不止一个中点。

判定方法是先将所有边两两求出交点,然后依次判断这些交点是不是中点,只要有一个是,多边形就是星形多边形,否则就不是。因为可以证明,只要是星形多边形,这些交点中至少有一个一定是其中点。

判断P点是否是中点的方法是:所有顶点与P点之间连一条线,若有连线不全在多变形内,则不是中点。这个问题又可以转化为按一定的顺序(顺时针或逆时针)遍历每条边,看P点是否在所有边的同一侧(右侧或左侧),是的话,P就是中点。

 
   
#include < cmath >
#include
< stdio.h >
#include
< string .h >
#include
< algorithm >
#include
< iostream >
using namespace std;

typedef
double TYPE;
#define MaxPoint 110
#define Epsilon 1e-10 /*验证* // /精度的范围 ,根据不同的情况调整精度值
// 空间中的点,可以用来作为二维点来用
struct POINT { /* 验证 */
TYPE x; TYPE y; TYPE z;
POINT() : x(
0 ), y( 0 ), z( 0 ) {};
POINT(TYPE _x_, TYPE _y_, TYPE _z_
= 0 )
: x(_x_), y(_y_), z(_z_) {};
// 要用 G++ 提交 ,可以不用这个
POINT operator = ( const POINT & A){
x
= A.x;
y
= A.y;
z
= A.z;
}
};

// 多边形 ,逆时针或顺时针给出x,y
struct POLY { /* 验证 */
// n个点
int n;
// x,y为点的指针,首尾必须重合
TYPE * x;
TYPE
* y;
POLY() : n(
0 ), x(NULL), y(NULL) {};
POLY(
int _n_, const TYPE * _x_, const TYPE * _y_) {
n
= _n_;
x
= new TYPE[n + 1 ];
memcpy(x, _x_, n
* sizeof (TYPE));
x[n]
= _x_[ 0 ];
y
= new TYPE[n + 1 ];
memcpy(y, _y_, n
* sizeof (TYPE));
y[n]
= _y_[ 0 ];
}
};

// 判断 x 是正数还是负数
inline int Sign(TYPE x){ /* 验证 */
return x <- Epsilon ?- 1 :x > Epsilon;
}

void Interect(POINT x,POINT y,TYPE a,TYPE b,TYPE c, int & s,POINT q[]){
TYPE u
= fabs(a * x.x + b * x.y + c);
TYPE v
= fabs(a * y.x + b * y.y + c);
q[
++ s].x = (x.x * v + y.x * u) / (u + v);
q[s].y
= (x.y * v + y.y * u) / (u + v);
}
// 利用半平面切割
void Cut(TYPE a,TYPE b,TYPE c, int & KarnalPoint,POINT p[])
{
int s = 0 ;
int i;
POINT q[MaxPoint];
for (i = 1 ; i <= KarnalPoint; i ++ ){ // 遍历所有顶点是否能观察到该边

if (Sign(a * p[i].x + b * p[i].y + c) <= 0 ){ // 因为线段是顺时针给出的,如果是逆时针就是<=0

q[
++ s] = p[i]; // 若是则存储
}
else {

if (Sign(a * p[i - 1 ].x + b * p[i - 1 ].y + c) < 0 ) // 逆时针就是<0
Interect(p[i - 1 ], p[i], a, b, c, s, q);

if (Sign(a * p[i + 1 ].x + b * p[i + 1 ].y + c) < 0 ) // 逆时针就是<0
Interect(p[i + 1 ], p[i], a, b, c, s, q);
}
}
// 最后的p数组存放半平面的点集合
for (i = 1 ;i <= s;i ++ )
p[i]
= q[i];
p[s
+ 1 ] = p[ 1 ],p[ 0 ] = p[s];
KarnalPoint
= s;
}

POLY PolygonKernal(
int n, POINT point[])
{
int KarnalPoint = n;
POINT p[MaxPoint];
// p 的大小和 tr 的大小一样
for ( int i = 0 ; i < n; i ++ ){
p[i
+ 1 ] = point[i]; // 初始化边界
}
point[n]
= point[ 0 ];
p[n
+ 1 ] = p[ 1 ];
p[
0 ] = p[n];

TYPE a,b,c;
for ( int i = 0 ;i < n;i ++ ){
a
= point[i + 1 ].y - point[i].y ; // 计算出相邻两点所在直线ax+by+c=0
b = point[i].x - point[i + 1 ].x;
c
= point[i + 1 ].x * point[i].y - point[i].x * point[i + 1 ].y;
Cut(a, b, c, KarnalPoint, p);
}

TYPE X[MaxPoint],Y[MaxPoint];
for ( int i = 0 ; i < KarnalPoint; i ++ ){
X[i]
= p[i].x;
Y[i]
= p[i].y;
}
POLY poly(KarnalPoint, X, Y);

return poly;
}
int main(){
int n,t;
POINT point[MaxPoint];

while (cin >> n,n != 0 )
{

for ( int i = 0 ;i < n;i ++ ){
scanf(
" %lf%lf " , & point[i].x, & point[i].y);
}
POLY poly
= PolygonKernal(n, point);
if (poly.n == 0 ) puts( " 0 " ); // 这里如果有一个点,或者一条线段都可以,所以判断poly.n是不是等于0就行了,不用判断面积
else puts( " 1 " );
}
return 0 ;
}

转载于:https://www.cnblogs.com/laipDIDI/articles/2041888.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值