Minkowski sum of convex polygons¶
Definition¶
Consider two sets
Algorithm¶
Here we consider the polygons to be cyclically enumerated, i. e.
Since the size of the sum is linear in terms of the sizes of initial polygons, we should aim at finding a linear-time algorithm.
Suppose that both polygons are ordered counter-clockwise. Consider sequences of edges
Firstly we should reorder the vertices in such a way that the first vertex
of each polygon has the lowest y-coordinate (in case of several such vertices pick the one with the smallest x-coordinate). After that the sides of both polygons
will become sorted by polar angle, so there is no need to sort them manually.
Now we create two pointers
-
Append
-
Compare polar angles of
-
Increment the pointer which corresponds to the smallest angle (if the angles are equal, increment both).
Visualization¶
Here is a nice visualization, which may help you understand what is going on.

Distance between two polygons¶
One of the most common applications of Minkowski sum is computing the distance between two convex polygons (or simply checking whether they intersect).
The distance between two convex polygons
If we reflect
Implementation¶
Below is the implementation of Minkowski sum for polygons with integer points. Note that in this case all computations can be done in integers since instead of computing polar angles and directly comparing them we can look at the sign of cross product of two vectors.
struct pt{
long long x, y;
pt operator + (const pt & p) const {
return pt{x + p.x, y + p.y};
}
pt operator - (const pt & p) const {
return pt{x - p.x, y - p.y};
}
long long cross(const pt & p) const {
return x * p.y - y * p.x;
}
};
void reorder_polygon(vector<pt> & P){
size_t pos = 0;
for(size_t i = 1; i < P.size(); i++){
if(P[i].y < P[pos].y || (P[i].y == P[pos].y && P[i].x < P[pos].x))
pos = i;
}
rotate(P.begin(), P.begin() + pos, P.end());
}
vector<pt> minkowski(vector<pt> P, vector<pt> Q){
// the first vertex must be the lowest
reorder_polygon(P);
reorder_polygon(Q);
// we must ensure cyclic indexing
P.push_back(P[0]);
P.push_back(P[1]);
Q.push_back(Q[0]);
Q.push_back(Q[1]);
// main part
vector<pt> result;
size_t i = 0, j = 0;
while(i < P.size() - 2 || j < Q.size() - 2){
result.push_back(P[i] + Q[j]);
auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]);
if(cross >= 0 && i < P.size() - 2)
++i;
if(cross <= 0 && j < Q.size() - 2)
++j;
}
return result;
}