Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.gebauz.bauzoid.math.collisionx;

import com.badlogic.gdx.Gdx;
import com.gebauz.bauzoid.graphics.spritex.Sprite;
import com.gebauz.bauzoid.math.Line2;
import com.gebauz.bauzoid.math.MathUtil;
import com.gebauz.bauzoid.math.Matrix4;
import com.gebauz.bauzoid.math.Vector2;
import com.gebauz.bauzoid.math.Vector4;

public class EllipseElement extends BaseShapeElement
{
        // Constants========================================================================================
       
        public static final int NUM_LINE_SEGMENTS = 12;

        // Embedded Types===================================================================================

        // Fields===========================================================================================
       
        public float x;
        public float y;
        public float radiusX;
        public float radiusY;
       
        // Methods==========================================================================================

        public EllipseElement(float initX, float initY, float initRadiusX, float initRadiusY)
        {
                x = initX; y = initY;
                radiusX = initRadiusX; radiusY = initRadiusY;
        }

        @Override
        public boolean isInside(float pX, float pY)
        {
                float diffX = pX - x;
                float diffY = pY - y;
               
                return (((diffX * diffX) / (radiusX * radiusX) + (diffY * diffY) / (radiusY * radiusY)) <= 1.0f);
        }
       
        private Vector4[] getLineSegments(Matrix4 transform)
        {
                Vector4 points[] = new Vector4[NUM_LINE_SEGMENTS];
               
                final float angleStep = 360.0f / NUM_LINE_SEGMENTS;
               
                if (transform != null)
                {
                        for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                        {
                                points[i] = transform.transform(new Vector4(x + MathUtil.sin(angleStep * (float)i) * radiusX, y + MathUtil.cos(angleStep * (float)i) * radiusY, 0, 1));
                        }
                }
                else
                {
                        for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                        {
                                //points[i] = new Vector4(MathUtil.sin(angleStep * (float)i), MathUtil.cos(angleStep * (float)i), 0, 1);
                                points[i] = new Vector4(x + MathUtil.sin(angleStep * (float)i) * radiusX, y + MathUtil.cos(angleStep * (float)i) * radiusY, 0, 1);
                        }
                }
                return points;
        }
       
        private Vector4[] getLineSegments()
        {
                return getLineSegments(null);
        }

        @Override
        public boolean intersects(Shape shape, Matrix4 transform)
        {
                Vector4 points[] = getLineSegments(transform);
               
                for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                {
                        int j = (i + 1) % (NUM_LINE_SEGMENTS-1);
                       
                        if (shape.isInside(points[i].x, points[i].y) || shape.isInside(points[j].x, points[j].y))
                        {
                                return true;
                        }
                       
                        Line2 line = new Line2(points[i].x, points[i].y, points[j].x, points[j].y);
                        if (shape.intersectsLine(line))
                                return true;
                }              

                return false;
        }
       
        /*
     bool SegmentIntersectRectangle(double a_rectangleMinX,
                                 double a_rectangleMinY,
                                 double a_rectangleMaxX,
                                 double a_rectangleMaxY,
                                 double a_p1x,
                                 double a_p1y,
                                 double a_p2x,
                                 double a_p2y)
  {
    // Find min and max X for the segment

    double minX = a_p1x;
    double maxX = a_p2x;

    if(a_p1x > a_p2x)
    {
      minX = a_p2x;
      maxX = a_p1x;
    }

    // Find the intersection of the segment's and rectangle's x-projections

    if(maxX > a_rectangleMaxX)
    {
      maxX = a_rectangleMaxX;
    }

    if(minX < a_rectangleMinX)
    {
      minX = a_rectangleMinX;
    }

    if(minX > maxX) // If their projections do not intersect return false
    {
      return false;
    }

    // Find corresponding min and max Y for min and max X we found before

    double minY = a_p1y;
    double maxY = a_p2y;

    double dx = a_p2x - a_p1x;

    if(Math::Abs(dx) > 0.0000001)
    {
      double a = (a_p2y - a_p1y) / dx;
      double b = a_p1y - a * a_p1x;
      minY = a * minX + b;
      maxY = a * maxX + b;
    }

    if(minY > maxY)
    {
      double tmp = maxY;
      maxY = minY;
      minY = tmp;
    }

    // Find the intersection of the segment's and rectangle's y-projections

    if(maxY > a_rectangleMaxY)
    {
      maxY = a_rectangleMaxY;
    }

    if(minY < a_rectangleMinY)
    {
      minY = a_rectangleMinY;
    }

    if(minY > maxY) // If Y-projections do not intersect return false
    {
      return false;
    }

    return true;
  }
        */

        @Override
        public boolean intersects(Shape shape, Matrix4 transform, Vector2 displaceResult)
        {
                return intersects(shape, transform);
               
                // shape is static level element, this shape element is from ship
                // transform this shape element's element into static level element space
                // check if there is an intersection and get the displacement vector from the static level element's shape
                // the caller needs to transform the displace result back into global space (half of transform.inv)
               
                /*Vector4 points[] = getLineSegments(transform);
                Vector2 displaceVectors[] = new Vector2[points.length];
               
                for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                {
                        displaceVectors[i] = new Vector2(0, 0);
                }
               
                boolean result = false;
               
                for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                {
                        int j = (i + 1) % (NUM_LINE_SEGMENTS-1);
                       
                        Line2 line = new Line2(points[i].x, points[j].y, points[j].x, points[j].y);
                       
                        if (shape.isInside(points[i].x, points[i].y))
                        {
                                Vector2 v = line.getMinimalVectorFrom(points[i].x, points[i].y);
                               
                                if (v.squaredLength() > displaceVectors[i].squaredLength())
                                        displaceResult.set(v.x, v.y);

                                result = true;
                        }
                       
                        if (shape.isInside(points[j].x, points[j].y))
                        {                              
                                Vector2 v = line.getMinimalVectorFrom(points[j].x, points[j].y);

                                if (v.squaredLength() > displaceVectors[i].squaredLength())
                                        displaceResult.set(v.x, v.y);
                               
                                result = true;
                        }
                       
                        if (shape.intersectsLine(line))
                        {
                                Vector2 v = line.getMinimalVectorFrom(points[j].x, points[j].y);

                                if (v.squaredLength() > displaceVectors[i].squaredLength())
                                        displaceResult.set(v.x, v.y);
                               
                                result = true;
                        }
                }              

                return result;*/

        }
       
       
       
        public boolean intersectsLine(Line2 line)
        {
                // speed up by not using line segments but actual ellipse formula
               
                Vector4 points[] = getLineSegments();
               
                for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
                {
                        int j = (i + 1) % (NUM_LINE_SEGMENTS-1);
                       
                        Line2 thisLine = new Line2(points[i].x, points[i].y, points[j].x, points[j].y);
                        if (thisLine.intersectsSegment(line))
                                return true;
                }
               
                return false;
        }

        public void debugRender(Sprite sprite)
        {
               
        }
       
        // Getters/Setters==================================================================================

}