Dimensions of bounding box for arbitrary circle sector

2.4k Views Asked by At

I need to determine the dimensions of bounding box for arbitrary circle sector as shown in the diagram below.

bounding box of arbitrary circle sector

Given:
φ = Start angle in the range of 0 ~ 2π
θ = Sweep angle in the range of 0 ~ 2π
r = radius

Determine:
- Width of bounding box (w)
- Height of bounding box (h)
- Coordinates of the circle center (C)

This problem is for on-screen display, so uses screen coordinates.
i.e. x increases to the right, y increases downwards, and positive rotation is clockwise.

As far as I can see, the result will be dependent on which quadrant points A and B fall in relative to each other.
For example if A falls in the bottom-right quadrant and B in the bottom-left quadrant, then w will be the horizontal distance between A and B. However if A falls in the bottom-right quadrant and B in the top-left quadrant, then w will be the horizontal distance between A and C plus the radius of the circle (since the left edge of the bounding box will be tangent to the circle).

My algorithm to solve this seems to be rapidly becoming overly complex.

Is there a simple and efficient way to solve this?

Edit

Below is the core of the algorithm I've come up with (in JAVA).

If anyone has a more efficient approach than this, please let me know.

    // Calculate end angle
    arcAngleEnd = arcAngleStart + arcAngleSweep;

    /**
     * Do all calculations based on a unit circle for the moment.
     * We'll determine the actual radius later.
     **/

    float uLeft, uTop, uRight, uBottom;

    // Calculate arc Start and End unit vector components.
    float uXstart = (float) Math.cos(Math.toRadians(arcAngleStart));
    float uYstart = (float) Math.sin(Math.toRadians(arcAngleStart));
    float uXend = (float) Math.cos(Math.toRadians(arcAngleEnd));
    float uYend = (float) Math.sin(Math.toRadians(arcAngleEnd));

    // Determine bottom bound
    if ((arcAngleStart <= 90 && arcAngleEnd >= 90) || (arcAngleStart > 90 && arcAngleEnd >= 450)) {

        // Arc crosses the local +y axis
        uBottom = 1;

    } else if (uYstart <=0 && uYend <= 0) {

        // Arc does not extend below the local x axis
        uBottom = 0;

    } else {

        // Bottom bounds will be which ever is greater out of arc start and end points.
        uBottom = Math.max(uYstart, uYend);
    }

    // Determine left bound
    if ((arcAngleStart <= 180 && arcAngleEnd >= 180) || (arcAngleStart > 180 && arcAngleEnd >= 540)) {

        // Arc crosses the local -x axis
        uLeft = -1;

    } else if (uXstart >=0 && uXend >= 0) {

        // Arc does not extend left of the local y axis
        uLeft = 0;

    } else {

        // Left bounds will be which ever is lesser out of arc start and end points.
        uLeft = Math.min(uXstart, uXend);
    }

    // Determine top bound
    if ((arcAngleStart <= 270 && arcAngleEnd >= 270) || (arcAngleStart > 270 && arcAngleEnd >= 630)) {

        // Arc crosses the local -y axis
        uTop = -1;

    } else if (uYstart >=0 && uYend >= 0) {

        // Arc does not extend above the local x axis
        uTop = 0;

    } else {

        // Top bounds will be which ever is lesser out of arc start and end points.
        uTop = Math.min(uYstart, uYend);
    }

    // Determine right bound
    if (arcAngleEnd >= 360) {

        // Arc crosses the local +x axis
        uRight = 1;

    } else if (uXstart <=0 && uXend <= 0) {

        // Arc does not extend right of the local y axis
        uRight = 0;

    } else {

        // Right bounds will be which ever is greater out of arc start and end points.
        uRight = Math.max(uXstart, uXend);
    }
1

There are 1 best solutions below

3
On

You have six points that might drive the box. They are $C$, the points where the circle touches the square (except the rightmost), $A$, and $B$. You have no way to determine $C$ from the radius and angles. Nothing in your givens locates the shape in your window. We might as well assume $C$ is $(0,0)$ The rightmost point, the greatest $x,$ is either $0$ from $C$, or $r \cos \phi$ from $A$, or $r \cos (\phi + \theta)$ from $B$. It is probably easiest to compute each of these and take the maximum. Alternately, you could say it is $0$ if $\frac \pi 2 \le \phi $ and $\phi + \theta \le \frac {3\pi}2$, $r \cos \phi$ if $\phi \le \frac \pi 2$ and $\phi \le 2\pi-\theta - \phi$, where the first assures that the $x$ coordinate of $A$ is positive and the second assures that the $x$ coordinate of $A$ is greater than that of $B$. You can use similar logic to find the other three edges of the box, then subtract to find the width and height.