# ETOOBUSY đźš€ minimal blogging for the impatient

# SVG path bounding box: arcs of ellipses

**TL;DR**

Letâ€™s take a look at the bounding box for arcs of ellipses, at the very last!

In the previous post Ellipses (for SVG): transformation
implementation we saw the implementation of a function to turn the
representation of an arc of ellipse inside a SVG path (based on the two
endpoints and other parameters) to a more *tractable* representation
(the *parametric representation*, in particular) for finding the
*bounding box*.

So, we have a representation (from Ellipses (for SVG): parameter and angles):

and we also have all the needed parameters, including a contiguous range for the parameter $t$â€¦ we can move on towards the bounding box!

# Maxima and minima

As before with BĂ©zier curves (see SVG path bounding box: quadratic BĂ©zier curves and SVG path bounding box: cubic BĂ©zier curves) we can treat the two axes independently and use the derivatives to find the candidate values of $t$ that might yield us maxima or minima in the required interval.

The two derivatives are:

Finding the zero for the $X$ coordinate means finding $t$ such that:

We can find this with the help of `atan2`

:

Note that there is also another candidate that is spaced $\pi$ apart:

Both these two candidates also have equivalents that are spaced by multiples of $2\pi$, of course. We should find the two equivalents that are closer to $t_{begin}$ and greater than it, then check if the actually fall in the $[t_{begin}, t_{end}]$ interval; if any of them does, then it must be considered for the bounding box evaluation.

Similar equations and reasoning can be done for the $Y$ axis, of course.

# Implementation

On to the implementation:

```
1 sub ellipse_bb ($C, $R, $phi, $t_start, $t_end) {
2 my %retval = (min => {}, max => {});
3 my $pi2 = 2 * PI;
4 $_ -= floor($_ / $pi2) * $pi2 for ($t_start, $t_end);
5 $t_end += $pi2 if $t_end < $t_start;
6
7 # align to a sane range, might be improved...
8 my ($Rx, $Ry, $cosp, $sinp) = ($R->{x}, $R->{y}, cos($phi), sin($phi));
9 for my $axis (qw< x y >) {
10 my @candidates = ($t_start, $t_end);
11 my $theta = atan2(-$Ry * $sinp, $Rx * $cosp);
12 for (1 .. 2) {
13 $theta -= floor($theta / $pi2) * $pi2; # normale
14 $theta += $pi2 if $theta < $t_start; # try to fit in range
15 push @candidates, $theta if $theta < $t_end;
16 $theta += PI; # prepare for 2nd iteration
17 }
18
19 for my $theta (@candidates) {
20 my $v = $C->{$axis} +
21 $Rx * $cosp * cos($theta) +
22 $Ry * $sinp * sin($theta);
23 $retval{min}{$axis} //= $retval{max}{$axis} //= $v;
24 if ($v < $retval{min}{$axis}) { $retval{min}{$axis} = $v }
25 elsif ($v > $retval{max}{$axis}) { $retval{max}{$axis} = $v }
26 }
27
28 ($cosp, $sinp) = (-$sinp, $cosp); # prepare for y-iteration
29 }
30 return \%retval;
31 }
```

Lines 3 through 5 re-normalize the interval putting $t_{begin}$ inside
$[0, 2\pi[$ and $t_{end}$ *immediately* after it.

The two axes are treated separately (line 9), just like we did for
BĂ©zier curves. Our candidates for finding the minima and maxima start
with our endpoints (line 10), then we calculate $t_1$ using `atan2`

(line 11) and establish whether it or its $\pi$-spaced sibling fall in
the interval (lines 12 through 17).

Lines 19 through 26 take care to evaluate the parametric function in the candidate values for $t$ and update the bounding box accordingly.

Line 28 isâ€¦ peculiar. To reuse the same exact formulas of the $X$ axis also for the $Y$ axis, itâ€™s sufficient to do the indicating swappingâ€¦ cool, this saves us a lot of cut-and-paste!

# Conclusions

We now have the last missing piece in our quest for the bounding box of a SVG pathâ€¦ itâ€™s been funny, hasnâ€™t it?!? đź¤“