Hello Codeforces,
this blog is going to be about the rotating calipers technique. Apparently, it's a basic technique that can be used to solve various problems on convex polygons, however, I couldn't find a codeforces blog about it, so I just decided to write one.
General idea behind the algorithm
For the following, we are going to assume that $$$P$$$ is a convex polygon in the 2D plane with a non-negative area. Furthermore, we are going to assume that no three points of the polygon are collinear, meaning that the angle at each vertex of the polygon is smaller than $$$180^{\circ}$$$. We call a line $$$l$$$ a line of support if it intersects the boundary of the polygon, but not its interior. Suppose that we have two parallel lines of support, $$$l_1$$$ and $$$l_2$$$. It is pretty straightforward that both of these lines lay on opposite sides of the polygon respectively. You could for example set the line $$$l_1$$$ to a vertical line intersecting the leftmost vertex, and $$$l_2$$$ intersecting the rightmost one. Rotating the two lines around the polygon, while they are kept tightly on its border is the fundamental idea of the rotating calipers technique. Here's an animation of what this might look like:
Additionally, a pair of vertices $$$(v_1, v_2), v_1, v_2 \in P$$$ is called an anti-podal pair if there exist two parallel lines of support that intersect with the vertices $$$v_1$$$ and $$$v_2$$$ respectively.
Finding the diameter of a convex polygon
The first application of the rotating calipers technique that is going to be considered is the calculation of the diameter of a convex polygon, or the largest distance between two points that lay inside the polygon in $$$O(n)$$$ time. Note that if the polygon is not convex, then you can simply calculate the convex hull of the polygon and then apply the following algorithm.
Let $$$p_1$$$ and $$$p_2$$$ be the points that define the diameter of the polygon, e.g. $$$dist(p_1, p_2)$$$ is the maximum possible distance inside the polygon. It is not difficult to see that $$$p_1$$$ and $$$p_2$$$ must lay on the boundary of the polygon, simply because if you draw a line from $$$p_1$$$ to $$$p_2$$$, you're able to extend that line to the boundary, and that way you have found a greater distance. Actually, the two points that define the diameter must be vertices of the polygon. Why? Assume that $$$p_1$$$ lays on an edge of the polygon. Then, there are two directions you could move $$$p_1$$$ to. One of them increases the distance to $$$p_2$$$ and one of them decreases it. Choose the direction that increases the distance and move the point to that direction. This contradicts the assumption that $$$dist(p_1, p_2)$$$ is maximum possible, so the point $$$p_1$$$ cannot lay on the edge of the polygon. We can even prove a stronger result: $$$(p_1, p_2)$$$ is an anti-podal pair!
Construct a circle $$$C$$$ with a center at $$$p_2$$$ and a radius of $$$dist(p_1, p_2)$$$. The points of the polygon must all lay inside the circle, because otherwise $$$p_1$$$ and $$$p_2$$$ wouldn't have the maximum possible distance. Now construct a tangent line $$$l_1$$$ at the point $$$p_1$$$. By definition, the tangent line doesn't intersect the interior of the circle, so it also doesn't intersect the interior of the polygon. Therefore, $$$l_1$$$ has to be a line of support. Now repeat the same procedure with a circle centered around $$$p_1$$$, and the resulting line of support is called $$$l_2$$$. It is easy to see that $$$l_1$$$ and $$$l_2$$$ are parallel to each other. Altogether, the pair $$$(p_1, p_2)$$$ must be an anti-podal pair:
Now that we know that $$$(p_1, p_2)$$$ is an anti-podal pair, we could construct a simple algorithm for calculating the diameter:
- Calculate all possible anti-podal pairs
- Return the maximum possible distance of all anti-podal pairs
However, there are two open questions remaining:
- If we want the algorithm to be efficient, we need to know how many anti-podal pairs there are
- How can we calculate all possible anti-podal pairs efficiently?
Upper bound on the number anti-podal pairs
Consider any anti-podal pair $$$(p_1, p_2)$$$ (the distance between them doesn't have to be the diameter, it just has to be an anti-podal pair). By definition, there have to be two parallel lines of support $$$l_1, l_2$$$ that intersect the vertices $$$p_1$$$ and $$$p_2$$$ respectively. Now, we can rotate these parallel lines simultaneously until they hit an edge of the polygon. That way, it is possible to map every anti-podal pair to a pair of either two edges or an edge and a vertex. In an algorithm that calculates all anti-podal pairs, it would be sufficient to check for every edge its parallel line of support.
Now there are two cases that need to be considered:
Case 1: The parallel line of support only intersects a vertex. From the image below, we can conclude that there are two anti-podal pairs related to edge $$$AB$$$: The pairs $$$(A, D)$$$ and $$$(B, D)$$$.
Case 2: The parallel line intersects an edge of the polygon. In the image below, we can see that there are 4 possible anti-podal pairs. Since we are looking at two edges however, we can say that each edge accounts for $$$4 / 2 = 2$$$ pairs.
So we can conclude that the number of anti-podal pairs is at most $$$2*n \in O(n)$$$, while $$$n$$$ is the number of edges/vertices of the polygon. Note that it's possible to prove tighter bounds, but for the simplicity of this blog it's enough to have proven that the number of anti-podal pairs is in $$$O(n)$$$.
Algorithm for generating all anti-podal pairs
Our algorithm now consists of iterating over every edge while maintaining a parallel line of support. That's where the rotating calipers technique is going to be used. When going from one edge to the next one, we keep rotating the line of support around the polygon until the lines are parallel again. When an edge is being visited, the anti-podal pairs can be generated the way it was described in the previous section. The algorithm somewhat resembles the two pointer technique. However, as it is with many other geometry problems, the main difficulty does not lay in the description of the solution, but rather in its correct implementation.
In this implementation, the edges are like vectors from one vertex $$$v_i$$$ to the next vertex $$$v_{i+1}$$$. The vertices of the polygon must be sorted in either clockwise or counterclockwise order, the code should work for both. The main difficulty is the criteria on when to stop rotating the parallel line. For that, we'll take a look at an example:
The following two properties hold true:
We observe that there occurs a sign change in the cross product whenever we reach the vertex that allows a parallel line of support. So whenever this occurs, we stop rotating the parallel line. The runtime of this algorithm is $$$O(n)$$$, because iterating over all edges takes $$$O(n)$$$ time, and the parallel line visits every vertex at most once. The implementation:
Width of a convex polygon
Now that we are able to calculate the diameter of a convex polygon, we want to see what other problems we can use the rotating calipers technique for. Let the width of a convex polygon be the shortest distance between two parallel lines of support. The width is like the minimum distance that two walls would need to have such that the entire polygon would fit in between these walls. If the polygon is not convex then we can again just calculate the convex hull and then apply the same procedure.
We can use the same algorithm that we used for the previous problem. We iterate over every edge of the polygon and maintain a parallel line of support $$$l$$$ to the edge. $$$l$$$ can either intersect with an edge or with a vertex of the polygon. Let's look at both of these cases separately:
- $$$l$$$ intersects with a vertex. Then all you have to do is to calculate the distance from that vertex to the edge.
- $$$l$$$ intersects with an edge. Select any point on the line $$$l$$$ and calculate the distance to the edge.
After doing all of these calculations, you return the minimum value as the final result. The algorithm has a total runtime of $$$O(n)$$$.
Minimum distance between two convex polygons
Another application for the rotating calipers technique is the problem of the minimum distance between two convex polygons. Note that here, the polygons must be convex from the beginning, unlike in previous problems, where the calculation of a convex hull was sufficient. Additionally we assume that the polygons don't intersect each other, otherwise, the minimum distance would be 0.
Let $$$P$$$ and $$$Q$$$ be two convex polygons, and we want to calculate the minimum distance between them. Let $$$p$$$ and $$$q$$$ be the points that fulfill that minimum distance, e.g. $$$p \in P$$$, $$$q \in Q$$$ and $$$dist(p, q)$$$ is minimum possible. $$$p$$$ and $$$q$$$ must lay on the boundaries of $$$P$$$ and $$$Q$$$ respectively. Furthermore, who would have guessed it, the points $$$p$$$ and $$$q$$$ admit parallel lines of support.
The aforementioned claim is not easy to see, so let's prove it. For that, we need to consider three cases:
Case 1: $$$p$$$ and $$$q$$$ are vertices. We construct a circle $$$C$$$ with $$$q$$$ as a center and $$$dist(p, q)$$$ as the radius. There are obviously no vertices of $$$P$$$ inside $$$C$$$, because that would mean that a smaller distance would be possible. Construct a tangent line $$$l_p$$$ to the circle through $$$p$$$. The claim now is that $$$l_p$$$ is a line of support. Assume that $$$l_p$$$ is not a line of support, e.g. it intersects with the interior of $$$P$$$. Here's an image of what this could look like:
The problem with the assumption becomes pretty clear: A part of the edge between $$$p$$$ and $$$r$$$ lays inside the circle, so a shorter distance than $$$dist(p, q)$$$ is possible. However, that's a contradiction and so $$$l_p$$$ must be a line of support. We can construct another line of support $$$l_q$$$ using the same line of argument. Additionally, $$$l_p$$$ and $$$l_q$$$ are parallel by definition of tangent lines.
Case 2: One point lays on a vertex and the other point on an edge. Without loss of generality, we assume that point $$$p$$$ is a vertex of $$$P$$$ and $$$q$$$ lays on an edge $$$e_q$$$ of $$$Q$$$. Construct a line of support $$$l_p$$$ similar to how it was done in case 1. Now we need to prove that $$$l_p$$$ is parallel to the edge $$$e_q$$$. This follows from the fact that the distance between $$$p$$$ and $$$q$$$ is minimum possible.
Since the distance between $$$p$$$ and $$$q$$$ is minimum possible, the angle in the image above must be exactly $$$90^{\circ}$$$. The angle between $$$l_p$$$ and the line between $$$p$$$ and $$$q$$$ must be $$$90^{\circ}$$$ as well, therefore, $$$l_p$$$ and the edge $$$e_q$$$ are parallel to each other.
Case 3: Both $$$p$$$ and $$$q$$$ lay on an edge. These edges must be parallel to each other, because if they wouldn't, then we could find a shorter distance where either case 1 or case 2 applies. So, $$$p$$$ and $$$q$$$ also admit parallel lines of support, namely the lines that go through the edges.
The algorithm for minimum distance between two polygons
Now that we know that $$$p$$$ and $$$q$$$ admit parallel lines of support, the rotating calipers algorithm comes back into play. But instead of having two calipers for each polygon, we now have only one caliper per polygon. However, we must pay attention on how we place these calipers initially. If we were to set the calipers like this for example:
then we could never reach $$$p$$$ and $$$q$$$ at the same time. One way to solve this problem is to initially set the caliper for polygon $$$P$$$ to be a vertical line intersecting with the leftmost vertex of $$$P$$$. Similarly, the caliper for polygon $$$Q$$$ is a vertical line intersecting with the rightmost vertex of $$$Q$$$. As we did for calculating the diameter, we iterate over every edge of $$$P$$$. Let $$$(p_i, p_{i+1})$$$ be the edge of $$$P$$$ that we are currently visiting. Furthermore, let $$$q_j$$$ be the vertex of $$$Q$$$ that is currently visited. We now have to check for all three cases that were mentioned in the last proof:
- Vertex-vertex case: check $$$dist(p_i, q_j)$$$ and $$$dist(p_{i+1}, q_j)$$$ and update the minimum value accordingly.
- Edge-vertex case: check the distance between the line segment $$$(p_i, p_{i+1})$$$ and $$$q_j$$$ and update the minimum value accordingly.
- Edge-edge case: check the distance between the line segments $$$(p_i, p_{i+1})$$$ and $$$(q_j, q_{j+1})$$$. However, this is only possible if these line segments are parallel to each other.
To complete the calculation, you'd have to iterate over all edges of $$$Q$$$ as well. The runtime of this algorithm is $$$O(n+m)$$$, while $$$n = |P|, m = |Q|$$$.
Maximum distance between two polygons
The algorithm for calculating the minimum distance can be perfectly translated to calculating the maximum distance. The only change one would have to make is to take the maximum over all possible calculated values instead of the minimum. Literally. That's all you have to do. Unlike in the previous problem, the algorithm should also work for intersecting polygons. The proof of correctness also becomes much easier:
Let $$$p$$$ and $$$q$$$ be the points in $$$P$$$ and $$$Q$$$ respectively with maximum distance. $$$p$$$ and $$$q$$$ admit parallel lines of support. Construct a circle $$$C_q$$$ with center $$$q$$$ and diameter $$$dist(p, q)$$$. Then, construct a line $$$l_p$$$ through point $$$p$$$ tangent to $$$C_q$$$. $$$l_p$$$ must be a line of support, since all vertices of $$$P$$$ have to lay inside $$$C_q$$$, otherwise, a greater distance would be achievable. Construct $$$l_q$$$ analogously. By definition of tangent lines, $$$l_p$$$ and $$$l_q$$$ must be parallel.
Note that calculating the hull of both polygons together and then running the diameter algorithm from above does not always work, because the diameter of $$$P$$$ might be larger than the greatest distance between polygons $$$P$$$ and $$$Q$$$.
Conclusion
In this blog, a few basic applications of the rotating calipers technique were discussed. Those are by all means not all applications that exist out there, but rather a few basic ones to understand in which ways we can apply this technique. A few problem links:
Currently, I'm working on my own problemset about rotating calipers, click on this link if you want to check it out.
UPD: Part 2 of this blog is out
Pray tell, where to use this?
Calculating maximum distance between two polygons, calculating minimum distance between two polygons, calculate width of polygon: such can be done easier for real world applications am I right?
For example astrologers need distance earth to moon. But I think; the celestial body are spherical, so distance calculation is easy.
Also when botanist studies living organisms, maybe proteins. Maybe distance between two protein helps them? I don't know but I think similar technique from sun to moon distance can be used: parallax effect. Proteins are not spherical but I think marginal error can be ignored.
Maybe this can be used to measure distance between irregularly shaped biuldings? For xeample, America's famous pentagon is a pentagon building. Distance from that to circular Apple headquarters. This can be difficult with euclidean geometry, I think.
Sorry if this algorithm has benefits in strange locations, for example finance or chemist perposes. I am just interested.
Wait until you hear about a domain called math
Do tell, however. Of what practicallity is this type of mathematics?
Will maximum distance between polygons, minimum distance between polygons. Will these stop wars in Europe and middle east? Do tell: will witdh of strange polygons stop climate changing? Glaciers melting completley devastating icy ecosystems? Raising chance of greast cities e.g. new york / los angeles from being flooded over?
Do tell, where will important use cases come from this?
You are missing the point, as most pedantics do. And in doing so, you will fail to see why it is this life you hold so dear is worth fighting for. Pray tell, when did a pretty painting ever bring end to famine? Never. Yet we still do it, although it has zero practical applications. Makes you think..
Correct is your painting example: I do stand corrected. Thank you for valuable insights.
I've used this algorithm when I worked at a 3D-printing company, to check if its impossible to rotate a model to fit the rectangular build platform. We chose to use the diameter of a polygon because we didn't want to proceed with some more expensive calculations if the model definitely could not fit in the build platform, while being able to accommodate any possible model.
When I was trying to learn about the algorithm on the job, I actually used a Codeforces post (although I can't find that post right now).
Worked as a swe?
Could you add some more problems where rotating calipers might be useful?
Also, very well written blog.
Thanks, I've added a few more problems.