3
$\begingroup$

How to calculate the bounding box of any Reuleaux triangle?

The Reuleaux triangle are given in the following form:

[
    [
        (-13.705965094283357, -8.320529222222632),
        27.771461198696837,
        1.2608311697667869,
        61.260831169766824
    ],
    [
        (14.058772226517263, -7.70944934392086),
        27.771461198696837,
        121.2608311697668,
        181.2608311697668
    ],
    [
        (-0.3528071322338966, 16.029978566143498),
        27.771461198696837,
        241.26083116976682,
        301.2608311697668
    ]
]

The above is a Python list of three sub-lists, each list describes an arc, the first element is a tuple, it is a coordinate of the arc's center, the second element is the radius of the arc, the third and fourth elements are the starting and ending degrees of the arc.

The centers of the arcs are vertices of an equilateral triangle, all arcs have the same radius and span 60 degrees.

(The center of the Reauleaux triangles are all at the origin)

Basically, I want to remove the extra blank spaces in pictures like this by limiting the axes:

enter image description here

To do that, I need to calculate the bounding box of any given Reuleaux triangle, but I don't know how to do that, and again, Google searching proved futile.

I only know a very specific case, if the Reuleaux triangle is directly upwards (I don't know how to describe it in any natural language), like this:

enter image description here

Then the left-most point is the left vertex, the right-most point is the right vertex, the top is the other vertex, and the lowest point is on the lowest arc halfway between the vertices, and the bounding box is a square.

I know how to calculate the bounding box in this specific case, but I won't show the calculations here, for fear of over-cluttering the post.

So how to calculate the bounding box of any Reuleaux triangle given the parameters above?


I am trying to find the four coordinates of the square that is tangent to the Reuleaux triangle.

For example, if the lowest side is parallel to the x axis, and the equilateral triangle has radius $r$, then the three coordinates of the vertices are:

$\begin{aligned} (0&, r) \\ (- \frac{\sqrt{3} r} {2}&, - \frac{r} {2}) \\ (\frac{\sqrt{3} r} {2}&, - \frac{r} {2}) \end{aligned}$

And the lowest point is:

$(0, r - \sqrt{3} r)$

Then the coordinates of the vertices of the bounding square is (counter-clockwise):

$\begin{aligned} (- \frac{\sqrt{3} r} {2}&, r - \sqrt{3} r) \\ (\frac{\sqrt{3} r} {2}&, r - \sqrt{3} r) \\ (\frac{\sqrt{3} r} {2}&, r) \\ (- \frac{\sqrt{3} r} {2}&, r) \end{aligned}$

I already worked all these out before I have written the post, and that's how I made the second picture.

I am asking, given the coordinates of the three vertices of a ROTATED Reuleaux triangle, how to calculate the four coordinates of the vertices of the bounding square of the triangle?


The accepted method indeed does work.

enter image description here

$\endgroup$
4
  • 1
    $\begingroup$ Why not replace tan$(\pi/3)$ in your formulas with $\sqrt3$? $\endgroup$
    – kabenyuk
    Jun 24, 2022 at 12:34
  • $\begingroup$ Of course I know $tan(\frac{\pi} {3}) = \sqrt{3}$, and the latter is what I actually use in my calculations in my programs, but I think the former is more mathematically correct. $\endgroup$ Jun 24, 2022 at 12:53
  • $\begingroup$ Mathematically $\tan(\tfrac{\pi}{3})$ is neither more or less correct that $\sqrt{3}$. $\endgroup$
    – jjagmath
    Jun 24, 2022 at 13:13
  • $\begingroup$ But it looks awful and raises the suspicion that the author does not know this formula. $\endgroup$
    – kabenyuk
    Jun 24, 2022 at 14:15

3 Answers 3

2
$\begingroup$

In any orientation of a Reuleaux triangle, at least two of the three vertices will lie on the desired bounding square. This is a property that I encourage you to try to prove on your own.

Given this fact, plus the property that the bounding box is a square whose edge length $r$ equals the radius of the defining arcs of the triangle (i.e. the triangle's "width"), one can use the provided coordinate data in a simple way to deduce the bounding box coordinates.

  1. Extract the coordinates of the arc centers.
  2. Find the minimum and maximum $x$-values; call these $x_{\text{min}}$ and $x_{\text{max}}$.
  3. Calculate $\delta_x = x_{\text{max}} - x_{\text{min}}$.
  4. There are two cases: either $\delta_x = r$, or $\delta_x < r$. In the first case, you know $x_{\text{min}}$ is the left edge of the bounding square and $x_{\text{max}}$ is the right edge.
  5. In the second case, you know that the triangle has exactly one vertex on the left or right bounding square edge. To determine whether it is the min or max $x$-value, compute $|x_1 - x_2|$, $|x_2 - x_3|$, $|x_3 - x_1|$ for the three vertices, and whichever distance is the smallest corresponds to the two vertices that are not on the left or right bounding square edge. The third vertex will either be $x_{\text{min}}$ or $x_{\text{max}}$; if the former, then the bounding square will have left edge $x_{\text{min}}$ and right edge $x_{\text{min}} + r$; if the latter, then the left edge is $x_{\text{max}} - r$ and the right edge is $x_{\text{max}}$.
  6. Repeat steps 2 through 5 for the $y$-values, which give you the top and bottom bounding square edges.
$\endgroup$
0
$\begingroup$

If your Reuleaux triangle is rotated, a square can be expressed.

The area of the square formed by rotating the triangle given the width $r=1$ of the incribed equilateral triangle is $$A=2\sqrt{3}+1/6\pi-3=0.9877003907...$$ which is close to 1.

This means that regardless of the position of Reuleaux triangle, it can always be enclosed by a square of width $r$. This $r$ is the length of the side of an equilateral triangle incribed in the Reuleaux triangle which you already know how to solve (see this link if not).

By looking at r, you will get the minimum length of the bounding box, which is a square. How to find the coordinates of the square? Use the top coordinates of the triangle, and draw r/2-way to the left and right you will have the two vertices of the box. Then, the other two vertices at the bottom can be constructed easily.

$\endgroup$
7
  • $\begingroup$ I already know that, it doesn't work if the triangle is rotated. $\endgroup$ Jun 24, 2022 at 11:26
  • $\begingroup$ I added another link where you can find a rotated Reuleaux triangle. $\endgroup$ Jun 24, 2022 at 11:27
  • $\begingroup$ Would you at least copy the text from that link into your answer? Link-only answers will be useless once the link is dead. $\endgroup$ Jun 24, 2022 at 11:31
  • $\begingroup$ The content in that webpage is not very super helpful either. $\endgroup$ Jun 24, 2022 at 11:44
  • $\begingroup$ I updated the answer. $\endgroup$ Jun 24, 2022 at 11:51
0
$\begingroup$

You have a figure consisting of circular arcs, and you want their axis-aligned bounding box.

Let's assume we use a very simple axis-aligned bounding box class, that starts as a point at origin, and expands whenever we add a point to it, so that it includes that point. Say,

from math import pi, sin, cos, floor, ceil

class BoundingBox:

    def __init__(self, x=0, y=0):
        self.xmin = x
        self.ymin = y
        self.xmax = x
        self.ymax = y

    @property
    def xmin(self):
        return self.xmin

    @property
    def ymin(self):
        return self.ymin

    @property
    def xmax(self):
        return self.xmax

    @property
    def ymax(self):
        return self.ymax

    @property
    def width(self):
        return self.xmax - self.xmin

    @property
    def height(self):
        return self.ymax - self.ymin

    def add(self, x, y):
        self.xmin, self.xmax = min(self.xmin, x, self.xmax), max(self.xmin, x, self.xmax)
        self.ymin, self.ymax = min(self.ymin, y, self.ymax), max(self.ymin, y, self.ymax)

Now, all we need to do is to add the endpoints of each arch, as well as the points where the arc is at its extremum on either axis –– that is, the points where the angle parameter is 0, 90, 180, or 270.

For example, adding to the above BoundingBox class,

    def addArcPoint(self, x0, y0, r, angle):
        theta = angle * pi / 180.0
        self.add(x0 + r*cos(theta), y0 + r*sin(theta))

    def addArc(self, x0, y0, r, minDeg, maxDeg):
        self.addArcPoint(x0, y0, r, minDeg)
        self.addArcPoint(x0, y0, r, maxDeg)
        if minDeg > maxDeg:
            maxDeg, minDeg = minDeg, maxDeg
        for angle in range(ceil(minDeg/90.0)*90, floor(maxDeg/90.0)*90 + 1, 90):
            self.addArcPoint(x0, y0, r, angle)

The expression ceil(minDeg/90)*90 yields the closest multiple of 90 degrees not less than minDeg, and floor(maxDeg/90)*90 the closest multiple of 90 degrees not greater than maxDeg. Since the upper limit in range() is exclusive, we add one to the upper limit so that it will be included in the range too. The multiples of 90 degrees (including zero) are where the arc reaches an extremum along one axis:

  • 0, -360, +360 are maximum points along x axis
  • 90, -270 are maximum points along y axis
  • 180, -180 are minimum points along x axis
  • 270, -90 are minimum points along y axis

If the original list is say rouleaux, then

    bb = BoundingBox()
    for arc in rouleaux:
        bb.addArc(arc[0][0], arc[0][1], arc[1], arc[2], arc[3])

should yield the axis-aligned bounding box as bb.

If you output to SVG, I recommend using something like

    border = 2
    xmin, ymin = floor(bb.xmin) - border, floor(bb.ymin) - border
    xmax, ymax = ceil(bb.xmax) + border, ceil(bb.ymax) + border
    # 'viewBox="%d %d %d %d"' % (xmin, ymin, xmax - xmin + 1, ymax - ymin + 1)

to set the viewBox attribute.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .