Пример #1
0
int edgesIntersect(double x1, double x2, double y1, double y2,
		   LRect r)
{
    int result = 0;
    if (linesIntersect(x1, x2, r.x1, r.x2, y1, y2, r.y1, r.y2) ||
	linesIntersect(x1, x2, r.x2, r.x3, y1, y2, r.y2, r.y3) ||
	linesIntersect(x1, x2, r.x3, r.x4, y1, y2, r.y3, r.y4) ||
	linesIntersect(x1, x2, r.x4, r.x1, y1, y2, r.y4, r.y1))
	result = 1;
    return result;
}
Пример #2
0
        bool Drawable::shapeOverlaps(const std::vector<Vector2>& edges) const
        {
            uint8_t inCorners = 0;

            for (const Vector2& corner : edges)
            {
                if (corner.x >= boundingBox.min.x &&
                    corner.x <= boundingBox.max.x &&
                    corner.y >= boundingBox.min.y &&
                    corner.y <= boundingBox.max.y)
                {
                    return true;
                }

                if (corner.x < boundingBox.min.x && corner.y < boundingBox.min.y) inCorners |= 0x01;
                if (corner.x > boundingBox.max.x && corner.y < boundingBox.min.y) inCorners |= 0x02;
                if (corner.x > boundingBox.max.x && corner.y > boundingBox.max.y) inCorners |= 0x04;
                if (corner.x < boundingBox.min.x && corner.y > boundingBox.max.y) inCorners |= 0x08;
            }

            // bounding box is bigger than rectangle
            if (inCorners == 0x0F)
            {
                return true;
            }

            Vector2 boundingBoxCorners[4] = {
                Vector2(boundingBox.min),
                Vector2(boundingBox.max.x, boundingBox.min.y),
                Vector2(boundingBox.max),
                Vector2(boundingBox.min.x, boundingBox.max.y)
            };

            for (uint32_t current = 0; current < edges.size(); ++current)
            {
                uint32_t next = (current == (edges.size() -1)) ? 0 : current + 1;

                if (linesIntersect(Vector2(edges[current].x, edges[current].y), Vector2(edges[next].x, edges[next].y), boundingBoxCorners[0], boundingBoxCorners[1]) || // left
                    linesIntersect(Vector2(edges[current].x, edges[current].y), Vector2(edges[next].x, edges[next].y), boundingBoxCorners[1], boundingBoxCorners[2]) || // top
                    linesIntersect(Vector2(edges[current].x, edges[current].y), Vector2(edges[next].x, edges[next].y), boundingBoxCorners[2], boundingBoxCorners[3]) || // right
                    linesIntersect(Vector2(edges[current].x, edges[current].y), Vector2(edges[next].x, edges[next].y), boundingBoxCorners[3], boundingBoxCorners[0])) // bottom
                {
                    return true;
                }
            }
            
            return false;
        }
Пример #3
0
bool isPathSelfIntersecting(const vector<CubicSpline> &splines)
{
    if(splines.size() == 0)
    {
        return false;
    }

    const int pointsPerSpline = 20;
    vector<VectorF> points;
    points.reserve(1 + pointsPerSpline * splines.size());
    points.push_back(splines[0].evaluate(0));

    for(size_t i = 0; i < splines.size(); i++)
    {
        for(int j = 1; j <= pointsPerSpline; j++)
        {
            points.push_back(splines[i].evaluate((float)j / pointsPerSpline));
        }
    }

    for(size_t i = 2; i < points.size(); i++)
    {
        for(size_t j = 1; j < i; j++)
        {
            if(linesIntersect(points[i - 1], points[i], points[j - 1], points[j], eps))
            {
                return true;
            }
        }
    }

    return false;
}
Пример #4
0
	bool SnakeLayer::testDie()
	{
		LineNode* n = static_cast<LineNode*>(*lineGroup->getChildren().rbegin());
		Point end = n->getEnd();
		if (!bounds.containsPoint(end))
		{
			gameOver();
			return true;
		}
		for (int i = 0; i < lineGroup->getChildrenCount(); i++)
		{
			LineNode* li = static_cast<LineNode*>(*(lineGroup->getChildren().begin() + i));
			for (int j = 0; j < lineGroup->getChildrenCount(); j++)
			{
				if (abs((int) i - (int) j) <= 1) continue;
				LineNode* lj = static_cast<LineNode*>(*(lineGroup->getChildren().begin() + j));
				if (linesIntersect(
					li->getStart(), li->getEnd(),
					lj->getStart(), lj->getEnd()))
				{
					gameOver();
					return true;
				}
			}
		}
		return false;
	}
Пример #5
0
bool CubicSpline::isSelfIntersecting() const
{
    const int pointsPerSpline = 20;
    vector<VectorF> points;
    points.reserve(1 + pointsPerSpline);

    for(int i = 0; i <= pointsPerSpline; i++)
    {
        points.push_back(evaluate((float)i / pointsPerSpline));
    }

    for(size_t i = 2; i < points.size(); i++)
    {
        for(size_t j = 1; j < i; j++)
        {
            if(linesIntersect(points[i - 1], points[i], points[j - 1], points[j], (abs(i - j) > 1 ? 0 : eps)))
            {
                return true;
            }
        }
    }

    return false;
}
Пример #6
0
bool CubicSpline::intersects(const CubicSpline &rt, VectorF ignoreAxis) const
{
#if 1
    vector<VectorF> path1 = getSplinePoints(*this);
    vector<VectorF> path2 = getSplinePoints(rt);
    for(size_t i = 1; i < path1.size(); i++)
    {
        for(size_t j = 1; j < path2.size(); j++)
        {
            if(linesIntersect(path1[i - 1], path1[i], path2[j - 1], path2[j], 0))
                return true;
        }
    }
    return false;
#else
    const int splitCount = 50; // number of line segments to split spline into
    ignoreAxis = normalize(ignoreAxis);

    for(int segmentNumber = 0; segmentNumber < splitCount; segmentNumber++)
    {
        float startT = (float)(segmentNumber) / splitCount;
        float endT = (float)(segmentNumber + 1) / splitCount;
        VectorF startP = rt.evaluate(startT);
        startP -= ignoreAxis * dot(ignoreAxis, startP); // move to plane normal to ignoreAxis
        VectorF endP = rt.evaluate(endT);
        endP -= ignoreAxis * dot(ignoreAxis, endP); // move to plane normal to ignoreAxis
        VectorF delta = endP - startP;

        if(absSquared(delta) < eps * eps) // if delta is too small
        {
            continue;
        }

        // solve dot(evaluate(t), cross(ignoreAxis, delta)) == 0 and it intersects if dot(evaluate(t) - startP, delta) / dot(delta, delta) is in [0, 1] and t is in [0, 1]
        VectorF normal = cross(ignoreAxis, delta);
        float cubic = dot(getCubic(), normal);
        float quadratic = dot(getQuadratic(), normal);
        float linear = dot(getLinear(), normal);
        float constant = dot(getConstant(), normal);
        float intersections[3];
        int intersectionCount = solveCubic(constant, linear, quadratic, cubic, intersections);

        for(int i = 0; i < intersectionCount; i++)
        {
            float t = intersections[i];

            if(t < 0 || t > 1)
            {
                continue;
            }

            float v = dot(evaluate(t) - startP, delta) / dot(delta, delta);

            if(v < 0 || v > 1)
            {
                continue;
            }

            return true;
        }
    }

    return false;
#endif
}
Пример #7
0
	Map::CollisionSide Map::findCollisionSide(GameEntity* entity1, GameEntity* entity2)
	{
		RectangleD frame1 = entity1->getCollisionFrame();
		RectangleD frame2 = entity2->getCollisionFrame();
		RectangleD intersect = frame1.getIntersect(frame2);
		if(intersect.width==0 || intersect.height==0)
		{
			//no collision happening
			return COLLISION_NONE;
		}
		
		Vector2d pos1End = entity1->getPosition();
		Vector2d pos1Begin(entity1->getPreviousX(), entity1->getPreviousY());
		Vector2d pos1Dif(pos1End.x-pos1Begin.x, pos1End.y-pos1Begin.y);
		
		Vector2d pos2End = entity2->getPosition();
		Vector2d pos2Begin(entity2->getPreviousX(), entity2->getPreviousY());
		pos2Begin += pos1Dif;
		Vector2d pos2Dif(pos2End.x-pos2Begin.x, pos2End.y-pos2Begin.y);
		
		double frame1_right = frame1.x + frame1.width;
		double frame1_bottom = frame1.y + frame1.height;
		
		RectangleD prevFrame2 = frame2;
		prevFrame2.x -= pos2Dif.x;
		prevFrame2.y -= pos2Dif.y;
		double prevFrame2_right = prevFrame2.x+prevFrame2.width;
		double prevFrame2_bottom = prevFrame2.y+prevFrame2.height;
		
		double dfix = 0.0000001;
		
		if(prevFrame2_bottom <= (frame1.y+dfix))
		//above frame1
		{
			if(prevFrame2_right <= (frame1.x+dfix))
			//top left
			{
				Vector2d lineBL_p1(prevFrame2.x, prevFrame2_bottom);
				Vector2d lineBL_p2(lineBL_p1.x+pos2Dif.x, lineBL_p1.y+pos2Dif.y);
				Vector2d lineBR_p1(prevFrame2_right, prevFrame2_bottom);
				Vector2d lineBR_p2(lineBR_p1.x+pos2Dif.x, lineBR_p1.y+pos2Dif.y);
				Vector2d lineTR_p1(prevFrame2_right, prevFrame2.y);
				Vector2d lineTR_p2(lineTR_p1.x+pos2Dif.x, lineTR_p1.y+pos2Dif.y);
				
				Vector2d box_TR(frame1_right, frame1.y);
				Vector2d box_TL(frame1.x, frame1.y);
				Vector2d box_BL(frame1.x, frame1_bottom);
				
				bool lineBR_top = linesIntersect(lineBR_p1, lineBR_p2, box_TL, box_TR);
				if(lineBR_top)
				{
					//push up
					return COLLISION_TOP;
				}
				bool lineBR_left = linesIntersect(lineBR_p1, lineBR_p2, box_TL, box_BL);
				if(lineBR_left)
				{
					//push left
					return COLLISION_LEFT;
				}
				
				PolygonD polyRight;
				polyRight.addPoint(lineTR_p1);
				polyRight.addPoint(lineTR_p2);
				polyRight.addPoint(lineBR_p2);
				polyRight.addPoint(lineBR_p1);
				if(polyRight.contains(box_BL))
				{
					//push left
					return COLLISION_LEFT;
				}
				//push up
				return COLLISION_TOP;
			}
			else if((prevFrame2.x+dfix) >= frame1_right)
			//top right
			{
				Vector2d lineBR_p1(prevFrame2_right, prevFrame2_bottom);
				Vector2d lineBR_p2(lineBR_p1.x+pos2Dif.x, lineBR_p1.y+pos2Dif.y);
				Vector2d lineBL_p1(prevFrame2.x, prevFrame2_bottom);
				Vector2d lineBL_p2(lineBL_p1.x+pos2Dif.x, lineBL_p1.y+pos2Dif.y);
				Vector2d lineTL_p1(prevFrame2.x, prevFrame2.y);
				Vector2d lineTL_p2(lineTL_p1.x+pos2Dif.x, lineTL_p1.y+pos2Dif.y);
				
				Vector2d box_TL(frame1.x, frame1.y);
				Vector2d box_TR(frame1_right, frame1.y);
				Vector2d box_BR(frame1_right, frame1_bottom);
				
				bool lineBL_top = linesIntersect(lineBL_p1, lineBL_p2, box_TL, box_TR);
				if(lineBL_top)
				{
					//push up
					return COLLISION_TOP;
				}
				bool lineBL_right = linesIntersect(lineBL_p1, lineBL_p2, box_TR, box_BR);
				if(lineBL_right)
				{
					//push right
					return COLLISION_RIGHT;
				}
				
				PolygonD polyLeft;
				polyLeft.addPoint(lineTL_p1);
				polyLeft.addPoint(lineTL_p2);
				polyLeft.addPoint(lineBL_p2);
				polyLeft.addPoint(lineBL_p1);
				if(polyLeft.contains(box_BR))
				{
					//push right
					return COLLISION_RIGHT;
				}
				//push up
				return COLLISION_TOP;
			}
			else
			//top middle
			{
				//push up
				return COLLISION_TOP;
			}
		}
		else if((prevFrame2.y+dfix) >= frame1_bottom)
		//below frame1
		{
			if(prevFrame2_right <= (frame1.x+dfix))
			//bottom left
			{
				Vector2d lineBR_p1(prevFrame2_right, prevFrame2_bottom);
				Vector2d lineBR_p2(lineBR_p1.x+pos2Dif.x, lineBR_p1.y+pos2Dif.y);
				Vector2d lineTR_p1(prevFrame2_right, prevFrame2.y);
				Vector2d lineTR_p2(lineTR_p1.x+pos2Dif.x, lineTR_p1.y+pos2Dif.y);
				Vector2d lineTL_p1(prevFrame2.x, prevFrame2.y);
				Vector2d lineTL_p2(lineTL_p1.x+pos2Dif.x, lineTL_p1.y+pos2Dif.y);
				
				Vector2d box_TL(frame1.x, frame1.y);
				Vector2d box_BL(frame1.x, frame1_bottom);
				Vector2d box_BR(frame1_right, frame1_bottom);
				
				bool lineTR_top = linesIntersect(lineTR_p1, lineTR_p2, box_BL, box_BR);
				if(lineTR_top)
				{
					//push down
					return COLLISION_BOTTOM;
				}
				bool lineTR_left = linesIntersect(lineTR_p1, lineTR_p2, box_TL, box_BL);
				if(lineTR_left)
				{
					//push left
					return COLLISION_LEFT;
				}
				
				PolygonD polyRight;
				polyRight.addPoint(lineTR_p1);
				polyRight.addPoint(lineTR_p2);
				polyRight.addPoint(lineBR_p2);
				polyRight.addPoint(lineBR_p1);
				if(polyRight.contains(box_TL))
				{
					//push left
					return COLLISION_LEFT;
				}
				//push down
				return COLLISION_BOTTOM;
			}
			else if((prevFrame2.x+dfix) >= frame1_right)
			//bottom right
			{
				Vector2d lineBL_p1(prevFrame2.x, prevFrame2_bottom);
				Vector2d lineBL_p2(lineBL_p1.x+pos2Dif.x, lineBL_p1.y+pos2Dif.y);
				Vector2d lineTL_p1(prevFrame2.x, prevFrame2.y);
				Vector2d lineTL_p2(lineTL_p1.x+pos2Dif.x, lineTL_p1.y+pos2Dif.y);
				Vector2d lineTR_p1(prevFrame2_right, prevFrame2.y);
				Vector2d lineTR_p2(lineTR_p1.x+pos2Dif.x, lineTR_p1.y+pos2Dif.y);

				Vector2d box_TR(frame1_right, frame1.y);
				Vector2d box_BR(frame1_right, frame1_bottom);
				Vector2d box_BL(frame1.x, frame1_bottom);
				
				bool lineTL_top = linesIntersect(lineTL_p1, lineTL_p2, box_BL, box_BR);
				if(lineTL_top)
				{
					//push down
					return COLLISION_BOTTOM;
				}
				bool lineTL_right = linesIntersect(lineTL_p1, lineTL_p2, box_TR, box_BR);
				if(lineTL_right)
				{
					//push right
					return COLLISION_RIGHT;
				}

				PolygonD polyLeft;
				polyLeft.addPoint(lineTL_p1);
				polyLeft.addPoint(lineTL_p2);
				polyLeft.addPoint(lineBL_p2);
				polyLeft.addPoint(lineBL_p1);
				if(polyLeft.contains(box_TR))
				{
					//push right
					return COLLISION_RIGHT;
				}
				//push down
				return COLLISION_BOTTOM;
			}
			else
			//bottom middle
			{
				//push down
				return COLLISION_BOTTOM;
			}
		}
		else
		//within top and bottom of frame 1
		{
			if(prevFrame2_right <= (frame1.x+dfix))
			//middle left
			{
				//push left
				return COLLISION_LEFT;
			}
			else if((prevFrame2.x+dfix) >= frame1_right)
			//middle right
			{
				//push right
				return COLLISION_RIGHT;
			}
			else
			{
				//this case should never happen unless some dingus updates without checking collisions,
				//or because double precision is a bitch sometimes
				Console::writeErrorLine("findCollisionSide hit an impossible case");
				return COLLISION_NONE;
			}
		}
	}
Пример #8
0
/*
 *---------------------------------------------------------
 *	This routine will return the edge index
 *	through which the cell was pushed across.
 *	The variable 'direction' will be TRUE if
 *	the edge was found from vstart->vend and FALSE if
 *	the edge is found from vend->vstart
 *---------------------------------------------------------
 */
int cellInPolyAndEdge( CELL *c, int *direction, Point3D *intersec3D, double *t, int prevEdge )
{
	
	int nverts, whichFace;
	int i, whichEdge, we[3], dir[3], it[3];
	Point2D p, v, qCurrent, qPrevious, intersec[3];
	Point2D v0, v1;
	Point3D p0, p1;
	double z[3], tt[3];
	
	whichFace = c->whichFace;
	nverts = faces[whichFace].nverts;
	/*
	 * Implementation dependent code! Assumes that we are
	 * always working with triangles!
	 */
	if ( nverts != 3 )
		errorMsg("Don't know how to deal with non-triangular faces (relax.c)!");
	/* 
	 * Map the current and previous cell's position to the
	 * 2D space of the face. I want to compute
	 * the intersection between a line defined by the
	 * previous and current cell's position and the edge
	 */
	mapOntoPolySpace(whichFace, c->x, c->y, c->z, &qCurrent );
	mapOntoPolySpace(whichFace, c->xp, c->yp, c->zp, &qPrevious );
	
#ifdef VERBOSE
	fprintf( stderr, "qPrevious [X] = %f [Y] = %f\n", qPrevious.x, qPrevious.y );
	fprintf( stderr, "qCurrent [X] = %f [Y] = %f\n", qCurrent.x, qCurrent.y );
#endif
	
	for(i = 0; i < nverts; i++)
	{
		we[i] = -1;
		tt[i] = -1;
		it[i] = -1;
		dir[i] = -1;
		p0.x = vert[faces[whichFace].v[i]].pos.x;
		p0.y = vert[faces[whichFace].v[i]].pos.y;
		p0.z = vert[faces[whichFace].v[i]].pos.z;
		p1.x = vert[faces[whichFace].v[(i+1)%nverts]].pos.x;
		p1.y = vert[faces[whichFace].v[(i+1)%nverts]].pos.y;
		p1.z = vert[faces[whichFace].v[(i+1)%nverts]].pos.z;
		
		mapOntoPolySpace(whichFace, p0.x, p0.y, p0.z, &v0);
		mapOntoPolySpace(whichFace, p1.x, p1.y, p1.z, &v1);
		
#ifdef VERBOSE
		fprintf( stderr, "[X0] = %f [Y0] = %f [Z0] = %f\n", p0.x, p0.y, p0.z );
		fprintf( stderr, "[X1] = %f [Y1] = %f [Z1] = %f\n", p1.x, p1.y, p1.z );
		fprintf( stderr, "v0 [X] = %f [Y] = %f\n", v0.x, v0.y );
		fprintf( stderr, "v1 [X] = %f [Y] = %f\n", v1.x, v1.y );
#endif
		
		p.x = qCurrent.x - v0.x;
		p.y = qCurrent.y - v0.y;
		v.x = v1.x - v0.x;
		v.y = v1.y - v0.y;
		
		z[i] = v.x * p.y - p.x * v.y;
		
		if (  Negative(z[i]) )
		{
			/* find which edge is this */
			we[i] = findEdgeForVert( faces[whichFace].v[i],
									faces[whichFace].v[(i+1)%nverts],
									&(dir[i]) );
			/*
			 * The difference between 'linesIntersect' and 'goodLinesIntersect' is that
			 * 'goodLinesIntersect' does not do a bounding box test, whereas 'linesIntersect'
			 * does. I have the 2 versions since I thought that sometimes, due to
			 * rounding off, the bounding box test was giving me wrong results.
			 */
			/*it[i] = goodLinesIntersect( qPrevious, qCurrent, v0, v1, &(intersec[i]), &(tt[i]) );*/
			it[i] = linesIntersect( qPrevious, qCurrent, v0, v1, &(intersec[i]), &(tt[i]) );
		}
	}
	/*
	 * If all z are greater or equal to 0.0, then the cell
	 * is inside the polygon. Otherwise we proceed to
	 * find out which edge it crossed
	 */
	/*if ( z[0] >= 0.0 && z[1] >= 0.0 && z[2] >= 0.0 ) return -1;*/
	if ( GreaterEqualZero(z[0]) && GreaterEqualZero(z[1]) && GreaterEqualZero(z[2]) )
		return -1;
	
	else{
#ifdef VERBOSE
		/*fprintf( stderr, "qCurrent [X] = %f [Y] = %f\n", qCurrent.x, qCurrent.y );
		 fprintf( stderr, "qPrevious [X] = %f [Y] = %f\n", qPrevious.x, qPrevious.y );
		 fprintf( stderr, "\nGeometry vertices for face %d\n", whichFace );*/
		fprintf( stderr, "\nCell NOT inside polygon!\n");
#endif
		
		for(i = 0; i < nverts; i++)
		{
			if ( Negative( z[i] ) /*z[i] < 0.0*/ && it[i] == DO_INTERSECT )
			{
				
#ifdef VERBOSE
				
				fprintf( stderr, "intersec [X] = %f [Y] = %f\n", intersec[i].x, intersec[i].y );
				fprintf( stderr, "[%d] z = %f e = %d dir = %d\n", i, z[i], we[i], dir[i] );
				fprintf( stderr, "intersect = %d t = %lg\n", it[i], tt[i]);
#endif
				/*	
				 * I have to make sure here that the just found intersection
				 * is not the same one as before
				 */
				if ( prevEdge != we[i] ){
					mapFromPolySpace(whichFace, intersec[i].x, intersec[i].y, intersec3D );
					*t = tt[i];
					*direction = dir[i];
#ifdef VERBOSE
					fprintf( stderr, "2D: x = %f y = %f\n", intersec[i].x, intersec[i].y);
					fprintf( stderr, "3D: x = %f y = %f z = %f\n", intersec3D->x, intersec3D->y, intersec3D->z );
#endif
					return we[i];
				}
			}
		}
		
		/*
		 * If I have reached this point we have a problem.
		 * Before leaving the program I am printing which
		 * should be useful info
		 */
		for(i = 0; i < nverts; i++)
		{
			//fprintf( stderr, "[%d] z = %lg t = %lg intersec = %d e = %d dir = %d\n",
				//	i, z[i], tt[i], it[i], we[i],dir[i] );
			if ( we[i] != -1 ){
				//fprintf( stderr, "edge = %d pf = %d nf = %d cell = %d\n",
					//	we[i], edges[we[i]].pf, edges[we[i]].nf, c->ctype );
				/*fprintf( stderr, "matrix for next->previous face:\n");
				 printMatrix( edges[we[i]].np );
				 fprintf( stderr, "matrix for previous->next face:\n");
				 printMatrix( edges[we[i]].pn );*/
			}
		}
		//fprintf( stderr, "For face %d we have the neighboring faces:\n", whichFace );
		for(i = 0; i < faces[whichFace].nPrimFaces; i++)
		{
			//fprintf( stderr, "[%d] angle = %f\n",
				//	faces[whichFace].primFaces[i],
				//	rad2deg(faces[whichFace].rotAngles[i]) );
		}
        
		return -2;
		//errorMsg("If I reached this point I could not find an edge to move cells!");
	}
}