简体   繁体   中英

Rectangle Circle Intersection with Padding

I have the following method which works great to test if a rectangle intersects a circle. How could I modify it to say provide an additional parameter, the padding, which means that the rectangle and the circle need to be a certain number of pixels away from each other?

public static boolean rectangleCircleIntersection(RectangleRegion rect, CircularRegion circle, int padding) {
        int circleDistance_x = PsyMath.abs((circle.getX()+circle.getRadius()) - (rect.getX()+rect.getWidth()/2));
        int circleDistance_y = PsyMath.abs((circle.getY()+circle.getRadius()) - (rect.getY()+rect.getHeight()/2));

        if (circleDistance_x > (rect.getWidth()/2 + circle.getRadius())) { return false; }
        if (circleDistance_y > (rect.getHeight()/2 + circle.getRadius())) { return false; }

        if (circleDistance_x <= (rect.getWidth()/2)) { return true; } 
        if (circleDistance_y <= (rect.getHeight()/2)) { return true; }

        int cornerDistance_sq = (int)Math.pow((circleDistance_x - rect.getWidth()/2),2) +
                             (int)Math.pow((circleDistance_y - rect.getHeight()/2),2);

        return (cornerDistance_sq <= (int)Math.pow(circle.getRadius(),2));
    }

This was my attempt, but I'm not too confident it's correct:

public static boolean rectangleCircleIntersection(RectangleRegion rect, CircularRegion circle, int padding) {
        int circleDistance_x = PsyMath.abs((circle.getX()+circle.getRadius()) - (rect.getX()+rect.getWidth()/2));
        int circleDistance_y = PsyMath.abs((circle.getY()+circle.getRadius()) - (rect.getY()+rect.getHeight()/2));

        if (circleDistance_x > (rect.getWidth()/2 + circle.getRadius() + padding)) { return false; }
        if (circleDistance_y > (rect.getHeight()/2 + circle.getRadius() + padding)) { return false; }

        if ((circleDistance_x+padding) <= (rect.getWidth()/2)) { return true; } 
        if ((circleDistance_y+padding) <= (rect.getHeight()/2)) { return true; }

        int cornerDistance_sq = (int)Math.pow((circleDistance_x - rect.getWidth()/2),2) +
                             (int)Math.pow((circleDistance_y - rect.getHeight()/2),2);

        return (cornerDistance_sq <= (int)Math.pow(circle.getRadius(),2));
    }

instead of using rect.getWidth() and rect.getHeight, you can add padding to width and height and that new padded dimension.

const int PADDING = 5;
int rectHeight = rect.getHeight() + PADDING;
int rectWidth = rect.getWidth() + PADDING;

//use rectHeight and rectWidth for calculation now

EDIT: to account for padding on left you should adjust the position used in your calculation,

int posX = rect.getX() - PADDING/2;
int posY = rect.getY() - PADDING/2;
int rectHeight = rect.getHeight() + PADDING/2;
int rectWidth = rect.getWidth() + PADDING/2;

Just FYI, what you are essentially doing with that padding is creating a bigger rectangle around the current rectangle.

You can safely pad the circle and then check if they intersect. Padding the rectangle is not quite okay because the corners of the padded rectangle will be sqrt(2) times the padding away from the corners of the original rectangle.

So, assuming the code above works great, and that the radius is an int, you'd get:

public static boolean rectangleCircleIntersection(RectangleRegion rect, CircularRegion circle, int padding) {
    int paddedRadius = circle.getRadius() + padding;
    int circleDistance_x = PsyMath.abs((circle.getX()+paddedRadius) - (rect.getX()+rect.getWidth()/2));
    int circleDistance_y = PsyMath.abs((circle.getY()+paddedRadius) - (rect.getY()+rect.getHeight()/2));

    if (circleDistance_x > (rect.getWidth()/2 + paddedRadius)) { return false; }
    if (circleDistance_y > (rect.getHeight()/2 + paddedRadius)) { return false; }

    if (circleDistance_x <= (rect.getWidth()/2)) { return true; } 
    if (circleDistance_y <= (rect.getHeight()/2)) { return true; }

    int cornerDistance_sq = (int)Math.pow((circleDistance_x - rect.getWidth()/2),2) +
                         (int)Math.pow((circleDistance_y - rect.getHeight()/2),2);

    return (cornerDistance_sq <= (int)Math.pow(paddedRadius,2));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM