cocos2d-x 学习笔记-判断点击点是否在不规则多边形中

来源:互联网 发布:java软件下载 免费 编辑:程序博客网 时间:2024/06/05 19:01

本文使用的跟射线方法类似, 自己的总结:

      原理就是,在触摸点位置,做一条水平(Y值不变)或者垂直(X值不变)的线, 与多边形的每条边判断是否与这条线相交,然后只取在触摸点的正方向或者负方向(这里就类似射线)一个方向的相交点,如果有,该多边形相交点个数count++。当每条边都判断完后,  如果count为奇数则在多边形内, 反之在外面.

注意:

       1. 首先射线有可能同时经过多边形的多个顶点, 在此只设置每条线段前面的端点可以相交, 后面的端点不相交。

       2. 点在边上:这种情况也不能用交点个数的奇偶性来判断了,所以提前判断这个点是否在边上。

下面这段代码使用的是横向向左射线,已经测试过。

// 以触摸点的y值不变,发射横向射线,与对比的线相交 判断有没有在触摸点x值左边的相交点, 并返回对应值// <参数1:x1, 参数2:y1> 首端点x,y轴坐标, <参数3:x2, 参数4:y2> 末端点x,y轴坐标, <参数5:x, 参数6:y> 点击点x,y轴坐标// 返回值: -1:在线上, 0:不相交, 1:相交int HelloWorld::isIntersect(float x1, float y1, float x2, float y2, float x,float y) {// 定义最小和最大的X Y轴值float minX = 0, maxX = 0, minY = 0, maxY = 0;minX = x1;maxX = x2;minY = y1;maxY = y2;// 如果不是这种情况, 则把两个大小值换下if (minX > maxX) {minX = x2;maxX = x1;}if (minY > maxY) {minY = y2;maxY = y1;}// 射线与边无交点的其他情况if (y < minY || y > maxY || x < minX) {return 0;}// 对比线垂直的情况, 这段可以快速判断出对比线段垂直的情况, (不过感觉没必要判断,不要这段代码也行.)if (minX == maxX) {// y值只有两种(1 在线段y值中,2 和线段y值外(必不相交, 前面已经排除了), 这里排除掉在末端点y2上的情况)if(y == y2)return 0;// 剩下的y在minY和maxY之间// 1 如果x == minx也相等, 表示在对比线上,返回-1;// 2 如果x < minX 则肯定不相交, 返回 0;// 3 那么 x> minX时, 肯定相交, 返回1.if (x == minX)return -1;else if (x < minX)return 0;elsereturn 1;}// 对比线平行的情况if (minY == maxY) {// 在前面排除掉 y < minY 和 y > maxY 的情况后只剩下,y和两个y值相等的情况, 即触摸点与这个对比线在一条线上// 前面判断过x < minX的情况, 如果x<maxX 则表示在线上(排除与末端点x2相等的情况)if(x <= maxX && x != x2)return -1;elsereturn 0;}// 剩下的情况, 计算射线与边所在的直线的交点的横坐标float x0 = x1 + (float) ((x2 - x1) / (y2 - y1)) * (y - y1);// 交点在射线右侧,不相交if (x0 > x)return 0;else if (x0 == x) {return -1;}// 穿过下端点不计if (x0 == x2) {return 0;}return 1;}// 当有触摸点时只要调用这个函数就行,把多边形的关键点作为参数传入,或者不传也行, 但是最后一个点和第一个点的线段也要判断。// 参数1: 控制点的数组, 参数2:点击的点// 返回值: 0:在外面, 1:在里面, 2:在线上int HelloWorld::pointsInPolygon(CCPointArray* pArray, const CCPoint& pos) {//CCPointArray *array = CCPointArray::create(20);//array->addControlPoint(ccp(300, 300));//array->addControlPoint(ccp(300, 450));//array->addControlPoint(ccp(480, 300));//array->addControlPoint(ccp(550, 450));//array->addControlPoint(ccp(600, 200));//array->addControlPoint(ccp(400, 200));//array->addControlPoint(ccp(300, 300));// 数组的个数 里面的数组是测试用的//int count = array->count();    int count = pArray->count();// 在多边形内的数量int nCount = 0;// 返回值int nFlag = 0;for (int i = 0; i < count; ++i) {int next = i + 1;if (next == count)break;CCPoint pos1 = pArray->getControlPointAtIndex(i);CCPoint pos2 = pArray->getControlPointAtIndex(next);nFlag = isIntersect(pos1.x, pos1.y, pos2.x, pos2.y, pos.x, pos.y);if (-1 == nFlag) {// 在线上return 2;}if (1 == nFlag)nCount += 1;}if (1 == nCount % 2) {// 在里面return 1;} else {// 不在里面return 0;}}


判断点击是否在多边形内的方法,这是其中一种, 不过已经适用大部分情况了, 但还有更多种简单方法需要我去学习。



0 0
原创粉丝点击