[OpenGL] 绘制并且判断凹凸多边形、自相交多边形。
#include <iostream>
#include <ctime>
#include <GL/glut.h>
#include <math.h>
#include <vector>
using namespace std;
struct Pos
{
int x;
int y;
};
struct Edge
{
int x1, x2;
int y1, y2;
int vx;
int vy;
int a, b, c;
};
struct Poly
{
// 点集
int xx[100];
int yy[100];
// 边集
Edge Edges[100];
int plotNums = 0; //点数量
int edgeNums = 0; //边数量
// 记录凹点
int conv = 0;
};
Poly poly;
// 求交点坐标
Pos CrossPos(int p1,int p2){
Pos res;
int A1 = poly.Edges[p1].a;
int B1 = poly.Edges[p1].b;
int A2 = poly.Edges[p2].a;
int B2 = poly.Edges[p2].b;
int C1 = poly.Edges[p1].c;
int C2 = poly.Edges[p2].c;
int m = A1 * B2 - A2 * B1;
if (m == 0)
cout <<"第"<<p1<<"边和第"<<p2<<"边"<< "无交点" << endl;
else
{
res.x = (C2*B1 - C1 * B2) / m;
res.y = (C1*A2 - C2 * A1) / m;
}
return res;
}
// 判断点是否在线段内
bool JudgeInLine(Pos pos,Edge edge)
{
int maxX = edge.x1 >= edge.x2 ? edge.x1 : edge.x2;
int minX = edge.x1 <= edge.x2 ? edge.x1 : edge.x2;
int maxY = edge.y1 >= edge.y2 ? edge.y1 : edge.y2;
int minY = edge.y1 <= edge.y2 ? edge.y1 : edge.y2;
if (pos.x<=maxX && pos.x>=minX && pos.y<=maxY && pos.y>=minY)
{
return true;
}
return false;
}
// 求叉积 返回正负值
int CrossProduct(int n)
{
n = n % poly.edgeNums;
int np = (n + 1) % poly.edgeNums;
return (poly.Edges[n].vx*poly.Edges[np].vy - poly.Edges[np].vx*poly.Edges[n].vy) >= 0 ? 1 : -1;
}
// 切割凹多边形
void ChangePoly() {
int convP = poly.conv; //凹点的下一个点
Pos interPos;
for (int i = 0; i < poly.edgeNums; i++)
{
if (i<convP-1 || i>convP+1)
{
interPos = CrossPos(convP, i);
}
}
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glColor3f(1.0f, 0.0f, 0.0f);
for (int i = 0; i <= convP; i++)
{
glVertex2f(poly.xx[i], poly.yy[i]);
}
glVertex2f(interPos.x, interPos.y);
glEnd();
glBegin(GL_POLYGON);
glColor3f(0.0f, 1.0f, 1.0f);
glVertex2f(interPos.x, interPos.y);
for (int i=convP+1;i<poly.plotNums;i++)
{
glVertex2f(poly.xx[i], poly.yy[i]);
}
glEnd();
glFlush();
}
// 判断是什么多边形
bool Judge()
{
/*输出边信息*/
for (int i = 0; i < poly.edgeNums; i++)
{
cout << "Vx:" << poly.Edges[i].vx << " " << "Vy:" << poly.Edges[i].vy << " " << "A:" << poly.Edges[i].a<< " " << "B:" << poly.Edges[i].b << " " << "C:" << poly.Edges[i].c <<endl;
}
/*判断自交*/
Pos interPos;
if (poly.edgeNums > 3)
for (int i = 0; i < poly.edgeNums; i++)
{
interPos = CrossPos(i, (i + 2) % poly.edgeNums);
if (JudgeInLine(interPos, poly.Edges[i]) && JudgeInLine(interPos, poly.Edges[(i + 2) % poly.edgeNums]))
{
cout << "该多边形为自相交多边形" << endl;
return false;
}
}
/*判断凹凸*/
// 判断向量叉积 是否为同一正负
int judge;
if (CrossProduct(0) >= 0)
judge = 1;
else
judge = -1;
//判断每一个角,两边向量乘积是否同符号
for (int i = 1; i <= poly.edgeNums; i++)
{
if (judge*CrossProduct(i) < 0)
{
poly.conv = i;
ChangePoly();
cout << "该多边形为凹多边形" << endl;
return false;
}
}
cout << "该多边形为凸多边形" << endl;
return true;
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);//设置投影矩阵
gluOrtho2D(0.0, 400.0, 0.0, 300.0);//二维视景区域
glColor3f(1.0, 0.0, 0.0);
glPointSize(3.0);//点的大小
}
void plotpoint(GLint x, GLint y)
{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void displayFcn(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < poly.plotNums; i++)
{
plotpoint(poly.xx[i], poly.yy[i]);
}
glBegin(GL_POLYGON);
for (int i = 0; i < poly.edgeNums; i++)
{
glVertex2f(poly.xx[i], poly.yy[i]);
}
glEnd();
glFlush();
}
void mouse(GLint button, GLint action, GLint x, GLint y)
{
if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN)
{
poly.xx[poly.plotNums] = x;
poly.yy[poly.plotNums] = 300 - y;
cout << "x:" << x << " " << "y:" << 300 - y << endl;
poly.plotNums++;
glutPostRedisplay();//重绘窗口
}
if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN)
{
poly.edgeNums = poly.plotNums;
if (poly.plotNums > 2)
{
for (int i = 1; i <= poly.plotNums; i++)
{
poly.Edges[i - 1].x1 = poly.xx[i - 1];
poly.Edges[i - 1].y1 = poly.yy[i - 1];
poly.Edges[i - 1].x2 = poly.xx[i%poly.plotNums];
poly.Edges[i - 1].y2 = poly.yy[i%poly.plotNums];
poly.Edges[i - 1].vx = poly.Edges[i - 1].x2 - poly.Edges[i - 1].x1;
poly.Edges[i - 1].vy = poly.Edges[i - 1].y2 - poly.Edges[i - 1].y1;
poly.Edges[i - 1].a = poly.Edges[i - 1].vy;
poly.Edges[i - 1].b = -poly.Edges[i - 1].vx;
poly.Edges[i - 1].c = poly.Edges[i - 1].x2 * poly.Edges[i - 1].y1 - poly.Edges[i - 1].x1 * poly.Edges[i - 1].y2;
}
if (Judge())
glutPostRedisplay();//重绘窗口
}
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(50, 100);
glutInitWindowSize(400, 300);
glutCreateWindow("mouse");
init();
glutDisplayFunc(displayFcn);
glutMouseFunc(mouse);
glutMainLoop();
}
[OpenGL] 绘制并且判断凹凸多边形、自相交多边形。的更多相关文章
- PHP 判断点是否在多边形内
如何判断一个点是否在一个多边形内,何时会用到这个场景. 我们就模拟一个真是场景.我们公司是快递公司,在本地区域有6个分点.每个分点有3-5个工人负责附近的快递派遣发送,所以根据每个点的服务区域我们就能 ...
- java/c# 判断点是否在多边形区域内
java/c# 判断点是否在多边形区域内 年06月29日 ⁄ 综合 ⁄ 共 1547字 ⁄ 字号 小 中 大 ⁄ 评论关闭 最近帮别人解决了一个问题,如何判断一个坐标点,是否在多边形区域内(二维). ...
- 百度地图 判断marker是否在多边形内
昨天画了圆形,判marker是否存在圆形内.今天来画多边形,判断marker在多边形内. 需要引入一个js <script type="text/javascript&quo ...
- hrbustoj 1429:凸多边形(计算几何,判断点是否在多边形内,二分法)
凸多边形 Time Limit: 2000 MS Memory Limit: 65536 K Total Submit: 130(24 users) Total Accepted: 40(1 ...
- C# 判断点是否在多边形内
/// <summary>/// 判断点是否在多边形内/// </summary>/// <param name="pnt">点</par ...
- PHP判断点是否在多边形区域内外
小谢博客原文地址https://xgs888.top/post/view?id=79 PHP判断点是否在多边形区域内外:根据数学知识的射线法, 射线与几何多边形相交的点的个数为奇数则是在几何内部: 偶 ...
- hrbustoj 1306:再遇攻击(计算几何,判断点是否在多边形内,水题)
再遇攻击 Time Limit: 1000 MS Memory Limit: 65536 K Total Submit: 253(37 users) Total Accepted: 56(2 ...
- zoj 1081:Points Within(计算几何,判断点是否在多边形内,经典题)
Points Within Time Limit: 2 Seconds Memory Limit: 65536 KB Statement of the Problem Several dra ...
- [zoj] 1081 Points Within || 判断点是否在多边形内
原题 多组数据. n为多边形顶点数,m为要判断的点数 按逆时针序给出多边形的点,判断点是否在多边形内,在的话输出"Within",否则输出"Outside" / ...
随机推荐
- 多玩YY语音的面试题:C++中如何在main()函数之前执行操作?
多玩YY语音的面试题:C++中如何在main()函数之前执行操作? 第一反应main()函数是所有函数执行的开始.但是问题是main()函数执行之前如何执行呢? 联想到MFC里面的 C**App类的t ...
- C语言实现常用数据结构——队列
#include<stdio.h> #include<stdlib.h> #define MAX_SIZE 10 /* 用一个动态数组来实现队列 */ typedef stru ...
- Windows新终端中玩转ASCII和Emoji游戏的正确姿势
Windows新终端中玩转ASCII和Emoji游戏的正确姿势 前一段时间,我搬运了几个Windows Terminal中玩游戏的视频,详情请看 发布在即!来一睹官方团队如何玩转 Windows Te ...
- SQL 对float类型列进行排序引发的异常
车祸现场 要求:根据学分和完成时间获取前200名学员,当学分相同时,完成时间较早的排在前面 可以明显看到,完成时间为4.1号的记录排在了3.27号前面. 事故原因 float 表示近似数值,存在精度损 ...
- Smobiler实现手机弹窗
前言 在实际项目中有很多场景需要用到弹窗,如图1 那么这些弹窗在Smobiler中如何实现呢? 正文 Smobiler实现弹窗有两种方式:1.MessageBox.Show 2.ShowDialog和 ...
- 201907 TIOBE 编程语言排行榜-Python坐稳第三
目录 一.编程语言7月排行榜 二.Top10编程语言指数走势(2002-2018) 三.历史排名(1988-2019) 四.编程语言"名人榜"( 2003-2018) 五.Top2 ...
- 【测试-测试心得】测试发现BUG后,怎么定位问题?
一.判断前后端 Safari中可以右键,选择“检查元素”,再选择“网络”同样可以抓取到http请求,如图 怎么区分是前端错误还是后端错误? 1.在开发者工具中,如果console中有报错,则表示前端代 ...
- POJ 3680:Intervals(最小费用最大流)***
http://poj.org/problem?id=3680 题意:给出n个区间[Li,Ri],每个区间有一个权值wi,要使得每个点都不被超过k个区间覆盖(最多能被k个区间覆盖),如果选取了第i个区间 ...
- Vue快速学习_第一节
之前写CRM都是Django前后端一起写的,在大部分项目中实际上前后端是分离的,因此我们需要学习一个前端框架来进行前端页面的编写,这里选择了Vue进行学习,好了开始学习吧. 1.ES6部分知识点学习 ...
- Django前端HTML通过JS实现表格可编辑,动态添加行,回车完成新建文件夹
功能描述: 点击“新建文件夹”按钮,在table的末尾增加一行:单击页面的新增行,使单元格td变成可编辑状态:输入内容后,当单元格失去焦点时,保存输入的内容:回车后通过AJAX提交后台完成新建文件夹. ...