Skip to content

Commit cde2ba8

Browse files
authored
Added Minkowski sum article (#615)
1 parent 21ca71b commit cde2ba8

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

img/minkowski.gif

248 KB
Loading

src/geometry/minkowski.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!--?title Minkowski sum of convex polygons -->
2+
# Minkowski sum of convex polygons
3+
4+
## Definition
5+
Consider two sets $A$ and $B$ of points on a plane. Minkowski sum $A + B$ is defined as $\\{a + b| a \in A, b \in B\\}$.
6+
Here we will consider the case when $A$ and $B$ consist of convex polygons $P$ and $Q$ with their interiors.
7+
Throughout this article we will identify polygons with ordered sequences of their vertices, so that notation like $|P|$ or
8+
$P_i$ makes sense.
9+
It turns out that the sum of convex polygons $P$ and $Q$ is a convex polygon with at most $|P| + |Q|$ vertices.
10+
11+
## Algorithm
12+
13+
Here we consider the polygons to be cyclically enumerated, i. e. $P_{|P|} = P_0,\ Q_{|Q|} = Q_0$ and so on.
14+
15+
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.
16+
Suppose that both polygons are ordered counter-clockwise. Consider sequences of edges $\\{\overrightarrow{P_iP_{i+1}}\\}$
17+
and $\\{\overrightarrow{Q_jQ_{j+1}}\\}$ ordered by polar angle. We claim that the sequence of edges of $P + Q$ can be obtained by merging
18+
these two sequences preserving polar angle order and replacing consequitive co-directed vectors with their sum. Straightforward usage of this idea results
19+
in a linear-time algorithm, however, restoring the vertices of $P + Q$ from the sequence of sides requires repeated addition of vectors,
20+
which may introduce unwanted precision issues if we're working with floating-point coordinates, so we will describe a slight
21+
modification of this idea.
22+
23+
24+
Firstly we should reorder the vertices in such a way that the first vertex
25+
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
26+
will become sorted by polar angle, so there is no need to sort them manually.
27+
Now we create two pointers $i$ (pointing to a vertex of $P$) and $j$ (pointing to a vertex of $Q$), both initially set to 0.
28+
We repeat the following steps while $i < |P|$ or $j < |Q|$.
29+
30+
1. Append $P_i + Q_j$ to $P + Q$.
31+
32+
2. Compare polar angles of $\overrightarrow{P_iP_{i + 1}}$ and $\overrightarrow{Q_jQ_{j+1}}$.
33+
34+
3. Increment the pointer which corresponds to the smallest angle (if the angles are equal, increment both).
35+
36+
## Visualization
37+
38+
Here is a nice visualization, which may help you understand what is going on.
39+
40+
<center>![Visual](&imgroot&/minkowski.gif)</center>
41+
42+
## Distance between two polygons
43+
One of the most common applications of Minkowski sum is computing the distance between two convex polygons (or simply checking whether they intersect).
44+
The distance between two convex polygons $P$ and $Q$ is defined as $\min\limits_{a \in P, b \in Q} ||a - b||$. One can note that
45+
the distance is always attained between two vertices or a vertex and an edge, so we can easily find the distance in $O(|P||Q|)$. However,
46+
with clever usage of Minkowski sum we can reduce the complexity to $O(|P| + |Q|)$.
47+
48+
If we reflect $Q$ through the point $(0, 0)$ obtaining polygon $-Q$, the problem boils down to finding the smallest distance between a point in
49+
$P + (-Q)$ and $(0, 0)$. We can find that distance in linear time using the following idea.
50+
If $(0, 0)$ is inside or on the boundary of polygon, the distance is $0$, otherwise the distance is attained between $(0, 0)$ and some vertex or edge of the polygon.
51+
Since Minkowski sum can be computed
52+
in linear time, we obtain a linear-time algorithm for finding the distance between two convex polygons.
53+
54+
## Implementation
55+
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
56+
instead of computing polar angles and directly comparing them we can look at the sign of cross product of two vectors.
57+
58+
```cpp minkowski
59+
struct pt{
60+
long long x, y;
61+
pt operator + (const pt & p) const {
62+
return pt{x + p.x, y + p.y};
63+
}
64+
pt operator - (const pt & p) const {
65+
return pt{x - p.x, y - p.y};
66+
}
67+
long long cross(const pt & p) const {
68+
return x * p.y - y * p.x;
69+
}
70+
};
71+
72+
void reorder_polygon(vector<pt> & P){
73+
size_t pos = 0;
74+
for(size_t i = 1; i < P.size(); i++){
75+
if(P[i].y < P[pos].y || (P[i].y == P[pos].y && P[i].x < P[pos].x))
76+
pos = i;
77+
}
78+
rotate(P.begin(), P.begin() + pos, P.end());
79+
}
80+
81+
vector<pt> minkowski(vector<pt> P, vector<pt> Q){
82+
// the first vertex must be the lowest
83+
reorder_polygon(P);
84+
reorder_polygon(Q);
85+
// we must ensure cyclic indexing
86+
P.push_back(P[0]);
87+
P.push_back(P[1]);
88+
Q.push_back(Q[0]);
89+
Q.push_back(Q[1]);
90+
// main part
91+
vector<pt> result;
92+
size_t i = 0, j = 0;
93+
while(i < P.size() - 2 || j < Q.size() - 2){
94+
result.push_back(P[i] + Q[j]);
95+
auto cross = (P[i + 1] - P[i]).cross(Q[j + 1] - Q[j]);
96+
if(cross >= 0)
97+
++i;
98+
if(cross <= 0)
99+
++j;
100+
}
101+
return result;
102+
}
103+
104+
```
105+
106+
## Problems
107+
* [Codeforces 87E Mogohu-Rea Idol](https://codeforces.com/problemset/problem/87/E)
108+
* [Codeforces 1195F Geometers Anonymous Club](https://codeforces.com/contest/1195/problem/F)
109+
* [TIMUS 1894 Non-Flying Weather](https://acm.timus.ru/problem.aspx?space=1&num=1894)

src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ and adding new articles to the collection.*
135135
- [Oriented area of a triangle](./geometry/oriented-triangle-area.html)
136136
- [Area of simple polygon](./geometry/area-of-simple-polygon.html)
137137
- [Check if points belong to the convex polygon in O(log N)](./geometry/point-in-convex-polygon.html)
138+
- [Minkowski sum of convex polygons](./geometry/minkowski.html)
138139
- [Pick's Theorem - area of lattice polygons](./geometry/picks-theorem.html)
139140
- [Lattice points of non-lattice polygon](./geometry/lattice-points.html)
140141
- **Convex hull**

test/test_minkowski.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include <bits/stdc++.h>
2+
3+
using namespace std;
4+
5+
#include "minkowski.h"
6+
7+
bool equal_polygons(const vector<pt> & p, const vector<pt> & q){
8+
if(p.size() != q.size())
9+
return false;
10+
for(size_t i = 0; i < p.size(); i++){
11+
if(p[i].x != q[i].x || p[i].y != q[i].y)
12+
return false;
13+
}
14+
return true;
15+
}
16+
17+
bool test1(){
18+
vector<pt> p = {
19+
pt{0, 0},
20+
pt{1, 0},
21+
pt{0, 1}
22+
};
23+
vector<pt> q = {
24+
pt{1, 1},
25+
pt{0, 1},
26+
pt{0, 0},
27+
pt{1, 0}
28+
};
29+
return equal_polygons(
30+
minkowski(p, q),
31+
vector<pt>{
32+
pt{0, 0},
33+
pt{2, 0},
34+
pt{2, 1},
35+
pt{1, 2},
36+
pt{0, 2}
37+
});
38+
}
39+
40+
bool test2(){
41+
vector<pt> p = {
42+
pt{1, 1},
43+
pt{0, 1},
44+
pt{0, 0},
45+
pt{1, 0}
46+
};
47+
vector<pt> q = {
48+
pt{2, 2},
49+
pt{0, 2},
50+
pt{0, 0},
51+
pt{2, 0}
52+
};
53+
return equal_polygons(
54+
minkowski(p, q),
55+
vector<pt>{
56+
pt{0, 0},
57+
pt{3, 0},
58+
pt{3, 3},
59+
pt{0, 3}
60+
});
61+
}
62+
63+
int main(){
64+
assert(test1());
65+
assert(test2());
66+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy