Check if a specified polygon intersects a specified rectangle. - Java java.lang

Java examples for java.lang:Math Geometry Shape

Description

Check if a specified polygon intersects a specified rectangle.

Demo Code



public class Main{
    /**/*from   ww  w.  j av  a  2  s . co  m*/
     * Check if a specified polygon intersects a specified rectangle. Integer
     * domain.
     *
     * @param x X coordinates of polyline.
     * @param y Y coordinates of polyline.
     * @param x0 X of upper left corner of rectangle.
     * @param y0 Y of upper left corner of rectangle.
     * @param x1 X of lower right corner of rectangle.
     * @param y1 Y of lower right corner of rectangle.
     * @return True if the polyline intersects the rectangle, false otherwise.
     */
    public static boolean isPolygonIntersectingRectangle(int[] x, int[] y,
            int x0, int y0, int x1, int y1) {
        int n = x.length;

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

        if (n == 1) {
            return GeometryUtils.isPointInsideRectangle(x0, y0, x1, y1,
                    x[0], y[0]);
        }

        //
        // If the polyline constituting the polygon intersects the rectangle
        // the polygon does too.
        //
        if (GeometryUtils.isPolylineIntersectingRectangle(x, y, x0, y0, x1,
                y1)) {
            return true;
        }

        // Check last leg as well
        if (GeometryUtils.isLineIntersectingRectangle(x[n - 2], y[n - 2],
                x[n - 1], y[n - 1], x0, y0, x1, y1)) {
            return true;
        }

        //
        // The rectangle and polygon are now completely including each other
        // or separate.
        //
        if (GeometryUtils.isPointInsidePolygon(x, y, x0, y0)
                || GeometryUtils.isPointInsideRectangle(x0, y0, x1, y1,
                        x[0], y[0])) {
            return true;
        }

        // Separate
        return false;
    }
    /**
     * Check if a specified point is inside a specified rectangle.
     *
     * @param x0, y0, x1, y1 Upper left and lower right corner of rectangle
     * (inclusive)
     * @param x,y Point to check.
     * @return True if the point is inside the rectangle, false otherwise.
     */
    public static boolean isPointInsideRectangle(int x0, int y0, int x1,
            int y1, int x, int y) {
        return x >= x0 && x < x1 && y >= y0 && y < y1;
    }
    /**
     * Check if a specified polyline intersects a specified rectangle. Integer
     * domain.
     *
     * @param x, y Polyline to check.
     * @param x0, y0, x1, y1 Upper left and lower left corner of rectangle
     * (inclusive).
     * @return True if the polyline intersects the rectangle, false otherwise.
     */
    public static boolean isPolylineIntersectingRectangle(int[] x, int[] y,
            int x0, int y0, int x1, int y1) {
        if (x.length == 0) {
            return false;
        }

        if (GeometryUtils
                .isPointInsideRectangle(x[0], y[0], x0, y0, x1, y1)) {
            return true;
        } else if (x.length == 1) {
            return false;
        }

        for (int i = 1; i < x.length; i++) {
            if (x[i - 1] != x[i] || y[i - 1] != y[i]) {
                if (GeometryUtils.isLineIntersectingRectangle(x[i - 1],
                        y[i - 1], x[i], y[i], x0, y0, x1, y1)) {
                    return true;
                }
            }
        }

        return false;
    }
    /**
     * Check if a specified line intersects a specified rectangle. Integer
     * domain.
     *
     * @param lx0, ly0 1st end point of line
     * @param ly1, ly1 2nd end point of line
     * @param x0, y0, x1, y1 Upper left and lower right corner of rectangle
     * (inclusive).
     * @return True if the line intersects the rectangle, false otherwise.
     */
    public static boolean isLineIntersectingRectangle(int lx0, int ly0,
            int lx1, int ly1, int x0, int y0, int x1, int y1) {
        // Is one of the line endpoints inside the rectangle
        if (GeometryUtils.isPointInsideRectangle(x0, y0, x1, y1, lx0, ly0)
                || GeometryUtils.isPointInsideRectangle(x0, y0, x1, y1,
                        lx1, ly1)) {
            return true;
        }

        // If it intersects it goes through. Need to check three sides only.

        // Check against top rectangle line
        if (GeometryUtils.isLineIntersectingLine(lx0, ly0, lx1, ly1, x0,
                y0, x1, y0)) {
            return true;
        }

        // Check against left rectangle line
        if (GeometryUtils.isLineIntersectingLine(lx0, ly0, lx1, ly1, x0,
                y0, x0, y1)) {
            return true;
        }

        // Check against bottom rectangle line
        if (GeometryUtils.isLineIntersectingLine(lx0, ly0, lx1, ly1, x0,
                y1, x1, y1)) {
            return true;
        }

        return false;
    }
    /**
     * Check if a given point is inside a given (complex) polygon.
     *
     * @param x, y Polygon.
     * @param pointX, pointY Point to check.
     * @return True if the given point is inside the polygon, false otherwise.
     */
    public static boolean isPointInsidePolygon(double[] x, double[] y,
            double pointX, double pointY) {
        boolean isInside = false;
        int nPoints = x.length;

        int j = 0;
        for (int i = 0; i < nPoints; i++) {
            j++;
            if (j == nPoints) {
                j = 0;
            }

            if (y[i] < pointY && y[j] >= pointY || y[j] < pointY
                    && y[i] >= pointY) {
                if (x[i] + (pointY - y[i]) / (y[j] - y[i]) * (x[j] - x[i]) < pointX) {
                    isInside = !isInside;
                }
            }
        }

        return isInside;
    }
    /**
     * Check if a given point is inside a given polygon. Integer domain.
     *
     * @param x, y Polygon.
     * @param pointX, pointY Point to check.
     * @return True if the given point is inside the polygon, false otherwise.
     */
    public static boolean isPointInsidePolygon(int[] x, int[] y,
            int pointX, int pointY) {
        boolean isInside = false;
        int nPoints = x.length;

        int j = 0;
        for (int i = 0; i < nPoints; i++) {
            j++;
            if (j == nPoints) {
                j = 0;
            }

            if (y[i] < pointY && y[j] >= pointY || y[j] < pointY
                    && y[i] >= pointY) {
                if (x[i] + (double) (pointY - y[i])
                        / (double) (y[j] - y[i]) * (x[j] - x[i]) < pointX) {
                    isInside = !isInside;
                }
            }
        }

        return isInside;
    }
    /**
     * Check if two line segments intersects. Integer domain.
     *
     * @param x0, y0, x1, y1 End points of first line to check.
     * @param x2, yy, x3, y3 End points of second line to check.
     * @return True if the two lines intersects.
     */
    public static boolean isLineIntersectingLine(int x0, int y0, int x1,
            int y1, int x2, int y2, int x3, int y3) {
        int s1 = GeometryUtils.sameSide(x0, y0, x1, y1, x2, y2, x3, y3);
        int s2 = GeometryUtils.sameSide(x2, y2, x3, y3, x0, y0, x1, y1);

        return s1 <= 0 && s2 <= 0;
    }
    /**
     * Check if two points are on the same side of a given line. Algorithm from
     * Sedgewick page 350.
     *
     * @param x0, y0, x1, y1 The line.
     * @param px0, py0 First point.
     * @param px1, py1 Second point.
     * @return <0 if points on opposite sides. =0 if one of the points is
     * exactly on the line >0 if points on same side.
     */
    private static int sameSide(double x0, double y0, double x1, double y1,
            double px0, double py0, double px1, double py1) {
        int sameSide = 0;

        double dx = x1 - x0;
        double dy = y1 - y0;
        double dx1 = px0 - x0;
        double dy1 = py0 - y0;
        double dx2 = px1 - x1;
        double dy2 = py1 - y1;

        // Cross product of the vector from the endpoint of the line to the point
        double c1 = dx * dy1 - dy * dx1;
        double c2 = dx * dy2 - dy * dx2;

        if (c1 != 0 && c2 != 0) {
            sameSide = c1 < 0 != c2 < 0 ? -1 : 1;
        } else if (dx == 0 && dx1 == 0 && dx2 == 0) {
            sameSide = !isBetween(y0, y1, py0) && !isBetween(y0, y1, py1) ? 1
                    : 0;
        } else if (dy == 0 && dy1 == 0 && dy2 == 0) {
            sameSide = !isBetween(x0, x1, px0) && !isBetween(x0, x1, px1) ? 1
                    : 0;
        }

        return sameSide;
    }
    /**
     * Check if two points are on the same side of a given line. Integer domain.
     *
     * @param x0, y0, x1, y1 The line.
     * @param px0, py0 First point.
     * @param px1, py1 Second point.
     * @return <0 if points on opposite sides. =0 if one of the points is
     * exactly on the line >0 if points on same side.
     */
    private static int sameSide(int x0, int y0, int x1, int y1, int px0,
            int py0, int px1, int py1) {
        return sameSide((double) x0, (double) y0, (double) x1, (double) y1,
                (double) px0, (double) py0, (double) px1, (double) py1);
    }
}

Related Tutorials