All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mathiewz.slick.geom.Line Maven / Gradle / Ivy

Go to download

The main purpose of this libraryis to modernize and maintain the slick2D library.

The newest version!
package com.github.mathiewz.slick.geom;

/**
 * Implemenation of a bunch of maths functions to do with lines. Note that lines
 * can't be used as dynamic shapes right now - also collision with the end of a
 * line is undefined.
 *
 * @author Kevin Glass
 */
public class Line extends Shape {
    /** The start point of the line */
    private Vector2f start;
    /** The end point of the line */
    private Vector2f end;
    /** The vector between the two points */
    private Vector2f vec;
    /** Temporary storage - declared globally to reduce GC */
    private final Vector2f loc = new Vector2f(0, 0);
    /** Temporary storage - declared globally to reduce GC */
    private final Vector2f closest = new Vector2f(0, 0);

    /**
     * Create a new line based on the origin and a single point
     *
     * @param x
     *            The end point of the line
     * @param y
     *            The end point of the line
     */
    public Line(float x, float y) {
        this(0, 0, x, y);
    }

    /**
     * Create a new line based on two points
     *
     * @param x1
     *            The x coordinate of the start point
     * @param y1
     *            The y coordinate of the start point
     * @param x2
     *            The x coordinate of the end point
     * @param y2
     *            The y coordinate of the end point
     */
    public Line(float x1, float y1, float x2, float y2) {
        this(new Vector2f(x1, y1), new Vector2f(x2, y2));
    }

    /**
     * Create a line with relative second point
     *
     * @param x1
     *            The x coordinate of the start point
     * @param y1
     *            The y coordinate of the start point
     * @param dx
     *            The x change to get to the second point
     * @param dy
     *            The y change to get to the second point
     */
    public Line(float x1, float y1, float dx, float dy, boolean isDeltaMode) {
        this(new Vector2f(x1, y1), new Vector2f(x1 + dx, y1 + dy));
    }

    /**
     * Create a new line based on two points
     *
     * @param start
     *            The start point
     * @param end
     *            The end point
     */
    public Line(float[] start, float[] end) {
        super();

        set(start, end);
    }

    /**
     * Create a new line based on two points
     *
     * @param start
     *            The start point
     * @param end
     *            The end point
     */
    public Line(Vector2f start, Vector2f end) {
        super();

        set(start, end);
    }

    /**
     * Configure the line
     *
     * @param start
     *            The start point of the line
     * @param end
     *            The end point of the line
     */
    public void set(float[] start, float[] end) {
        set(start[0], start[1], end[0], end[1]);
    }

    /**
     * Get the start point of the line
     *
     * @return The start point of the line
     */
    public Vector2f getStart() {
        return start;
    }

    /**
     * Get the end point of the line
     *
     * @return The end point of the line
     */
    public Vector2f getEnd() {
        return end;
    }

    /**
     * Find the length of the line
     *
     * @return The the length of the line
     */
    public float length() {
        return vec.length();
    }

    /**
     * Find the length of the line squared (cheaper and good for comparisons)
     *
     * @return The length of the line squared
     */
    public float lengthSquared() {
        return vec.lengthSquared();
    }

    /**
     * Configure the line
     *
     * @param start
     *            The start point of the line
     * @param end
     *            The end point of the line
     */
    public void set(Vector2f start, Vector2f end) {
        super.pointsDirty = true;
        if (this.start == null) {
            this.start = new Vector2f();
        }
        this.start.set(start);

        if (this.end == null) {
            this.end = new Vector2f();
        }
        this.end.set(end);

        vec = new Vector2f(end);
        vec.sub(start);

        vec.lengthSquared();
    }

    /**
     * Configure the line without garbage
     *
     * @param sx
     *            The x coordinate of the start
     * @param sy
     *            The y coordinate of the start
     * @param ex
     *            The x coordiante of the end
     * @param ey
     *            The y coordinate of the end
     */
    public void set(float sx, float sy, float ex, float ey) {
        super.pointsDirty = true;
        start.set(sx, sy);
        end.set(ex, ey);
        float dx = ex - sx;
        float dy = ey - sy;
        vec.set(dx, dy);
    }

    /**
     * Get the x direction of this line
     *
     * @return The x direction of this line
     */
    public float getDX() {
        return end.getX() - start.getX();
    }

    /**
     * Get the y direction of this line
     *
     * @return The y direction of this line
     */
    public float getDY() {
        return end.getY() - start.getY();
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#getX()
     */
    @Override
    public float getX() {
        return getX1();
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#getY()
     */
    @Override
    public float getY() {
        return getY1();
    }

    /**
     * Get the x coordinate of the start point
     *
     * @return The x coordinate of the start point
     */
    public float getX1() {
        return start.getX();
    }

    /**
     * Get the y coordinate of the start point
     *
     * @return The y coordinate of the start point
     */
    public float getY1() {
        return start.getY();
    }

    /**
     * Get the x coordinate of the end point
     *
     * @return The x coordinate of the end point
     */
    public float getX2() {
        return end.getX();
    }

    /**
     * Get the y coordinate of the end point
     *
     * @return The y coordinate of the end point
     */
    public float getY2() {
        return end.getY();
    }

    /**
     * Get the shortest distance from a point to this line
     *
     * @param point
     *            The point from which we want the distance
     * @return The distance from the line to the point
     */
    public float distance(Vector2f point) {
        return (float) Math.sqrt(distanceSquared(point));
    }

    /**
     * Check if the given point is on the line
     *
     * @param point
     *            The point to check
     * @return True if the point is on this line
     */
    public boolean on(Vector2f point) {
        getClosestPoint(point, closest);

        return point.equals(closest);
    }

    /**
     * Get the shortest distance squared from a point to this line
     *
     * @param point
     *            The point from which we want the distance
     * @return The distance squared from the line to the point
     */
    public float distanceSquared(Vector2f point) {
        getClosestPoint(point, closest);
        closest.sub(point);
        return closest.lengthSquared();
    }

    /**
     * Get the closest point on the line to a given point
     *
     * @param point
     *            The point which we want to project
     * @param result
     *            The point on the line closest to the given point
     */
    public void getClosestPoint(Vector2f point, Vector2f result) {
        loc.set(point);
        loc.sub(start);

        float projDistance = vec.dot(loc);

        projDistance /= vec.lengthSquared();

        if (projDistance < 0) {
            result.set(start);
            return;
        }
        if (projDistance > 1) {
            result.set(end);
            return;
        }

        result.setX(start.getX() + projDistance * vec.getX());
        result.setY(start.getY() + projDistance * vec.getY());
    }

    /**
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "[Line " + start + "," + end + "]";
    }

    /**
     * Intersect this line with another
     *
     * @param other
     *            The other line we should intersect with
     * @return The intersection point or null if the lines are parallel
     */
    public Vector2f intersect(Line other) {
        return intersect(other, false);
    }

    /**
     * Intersect this line with another
     *
     * @param other
     *            The other line we should intersect with
     * @param limit
     *            True if the collision is limited to the extent of the lines
     * @return The intersection point or null if the lines don't intersect
     */
    public Vector2f intersect(Line other, boolean limit) {
        Vector2f temp = new Vector2f();

        if (!intersect(other, limit, temp)) {
            return null;
        }

        return temp;
    }

    /**
     * Intersect this line with another
     *
     * @param other
     *            The other line we should intersect with
     * @param limit
     *            True if the collision is limited to the extent of the lines
     * @param result
     *            The resulting intersection point if any
     * @return True if the lines intersect
     */
    public boolean intersect(Line other, boolean limit, Vector2f result) {
        float dx1 = end.getX() - start.getX();
        float dx2 = other.end.getX() - other.start.getX();
        float dy1 = end.getY() - start.getY();
        float dy2 = other.end.getY() - other.start.getY();
        float denom = dy2 * dx1 - dx2 * dy1;

        if (denom == 0) {
            return false;
        }

        float ua = dx2 * (start.getY() - other.start.getY()) - dy2 * (start.getX() - other.start.getX());
        ua /= denom;
        float ub = dx1 * (start.getY() - other.start.getY()) - dy1 * (start.getX() - other.start.getX());
        ub /= denom;

        if (limit && (ua < 0 || ua > 1 || ub < 0 || ub > 1)) {
            return false;
        }

        float u = ua;

        float ix = start.getX() + u * (end.getX() - start.getX());
        float iy = start.getY() + u * (end.getY() - start.getY());

        result.set(ix, iy);
        return true;
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#createPoints()
     */
    @Override
    protected void createPoints() {
        points = new Float[4];
        points[0] = getX1();
        points[1] = getY1();
        points[2] = getX2();
        points[3] = getY2();
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#transform(com.github.mathiewz.slick.geom.Transform)
     */
    @Override
    public Shape transform(Transform transform) {
        Float[] temp = new Float[4];
        createPoints();
        transform.transform(points, 0, temp, 0, 2);

        return new Line(temp[0], temp[1], temp[2], temp[3]);
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#closed()
     */
    @Override
    public boolean closed() {
        return false;
    }

    /**
     * @see com.github.mathiewz.slick.geom.Shape#intersects(com.github.mathiewz.slick.geom.Shape)
     */
    @Override
    public boolean intersects(Shape shape) {
        if (shape instanceof Circle) {
            return shape.intersects(this);
        }
        return super.intersects(shape);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy