4
$\begingroup$

Given a circular sector defined by sweeping from a 'start' to a 'stop' angle (see diagram below) and a radius, how do you compute the bounds of the rectangle that fits to the edges of the sector? Additionally, assuming that the top left corner of the rectangle is at (0, 0), where is the center of the arc within the rectangle?

The diagram below should clarify all the assumptions in my situation and gives two examples of the sectors I can have. The red rectangle is the rectangle of interest. Please note the particular challenges:

  • Sweeping direction is always clockwise, and sectors can extend past 180 degrees. Naming convention (i.e. 0 degrees is at 3 o'clock) as shown.

  • Angles can wrap around +/- 180 degrees; -10 and 190 are equivalent, but this means that any calculations of angular distances (if needed) need to account for that. For example, with a start angle of 170 and a stop of -170, the angle of the sector is only 20, not -340 (which is what a blind application of 'stop' - 'start' would give you)

  • One final complication: the coordinate system I am working in has the origin at the top left rather than bottom left, so the bottom right corner of the rectangle will have positive x and y coordinates.

Circular sector illustration

If anyone's curious, this is for computer graphics in a user interface. The circular sector is actually broken into a 'wheel' of menu options, and I need its size to be able to lay out other UI elements around it. The position of the center of the circular sector is required to determine whether a mouse click is within an element or not.

Thank you!

2 Answers 2

2

Here's some R code that solves the problem. Translate to the language of your choice. It implements the solution in Ross Millikan's answer, so upvote that if this is useful. The function getCoords takes an interval (which is a vector whose first component is the start angle and whose second is the end angle) and returns a vector of four components in the form (top, left, bottom, right).

The coordinate system takes the top left corner to be (0,0) and the bottom right corner to be (1,1) so you should scale the output appropriately.

Example usage:

> interval <- c(315, 45) > getCoords(interval) [1] 0.1464466 0.5000000 0.8535534 1.0000000 

This sets the interval to start at 315 degrees (equivalently -45 degrees) and end at 45 degrees. The top and bottom of the resulting rectangle are 0.146... and 0.854... and the left and right coordinates are 0.5 (because the centre of the wedge is at 0.5) and 1.0 (because this sector includes the rightmost point of the circle).

Code:

isInInterval <- function(theta, interval) {     theta <- theta %% 360     i <- interval[1] %% 360     f <- interval[2] %% 360  #set all values to be in the range [0, 360)     if (i < f) {         return (theta >= i && theta <= f)     } else {         return (!(theta < i && theta > f))     } }  getXcoord <- function(theta) {     return((1+cos(theta * 2*pi / 360))/2) }  getYcoord <- function(theta) {     return((1+sin(theta * 2*pi / 360))/2) }  getCoords <- function(interval) {     i <- interval[1]     f <- interval[2]      xi <- getXcoord(i)     yi <- getYcoord(i)     xf <- getXcoord(f)     yf <- getYcoord(f)      is0   <- isInInterval(0, interval)     is90  <- isInInterval(90, interval)     is180 <- isInInterval(180, interval)     is270 <- isInInterval(270, interval)      if (is0)   {right <- 1}  else {right <- max(xi, xf, 0.5)}     if (is90)  {bottom <- 1} else {bottom <- max(yi, yf, 0.5)}     if (is180) {left <- 0}   else {left <- min(xi, xf, 0.5)}     if (is270) {top <- 0}    else {top <- min(yi, yf, 0.5)}      return(c(top, left, bottom, right)) } 
  • 0
    Indeed, getting the center of the sector (relative to the top left corner) is trivial once the calculations above have been done. xCenter = 0.5 - left, and yCenter = 0.5 - top. Thanks again!2011-06-14
2

Your output is the coordinate of each side of the box. I would start by checking whether $0^{\circ},90^{\circ},180^{\circ},270^{\circ}$ are included. For each one that is, you have one coordinate. Any other coordinate has to be either the center of the circle (if the arc goes from $70^{\circ}$ to $110^{\circ}$, for example) or the end point of one radius, so just check those three.