Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit f795a6b

Browse files
committed
JarvisMarch.cpp
1 parent b872073 commit f795a6b

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

JarvisMarch.cpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//
2+
// algorithm - some algorithms in "Introduction to Algorithms", third edition
3+
// Copyright (C) 2018 lxylxy123456
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
#ifndef MAIN
20+
#define MAIN
21+
#define MAIN_JarvisMarch
22+
#endif
23+
24+
#ifndef FUNC_JarvisMarch
25+
#define FUNC_JarvisMarch
26+
27+
#include <algorithm>
28+
#include "utils.h"
29+
30+
#include "SegmentsIntersect.cpp"
31+
32+
template <typename T>
33+
class Angle: public Vector<T> {
34+
public:
35+
Angle(): Vector<T>(0, 0) {}
36+
Angle(T X, T Y): Vector<T>(X, Y) {}
37+
Angle(Vector<T> a, Vector<T> b): Vector<T>(b - a) {}
38+
int get_partition() const { // when x = y = 0, assume inf
39+
const T &x = this->x, &y = this->y;
40+
if (y > 0) { // 2
41+
if (x > 0) // 3 | 1
42+
return 1; // 4---+---0
43+
else if (x == 0) // 5 | 7
44+
return 2; // 6
45+
else
46+
return 3;
47+
} else if (y == 0) {
48+
if (x > 0)
49+
return 0;
50+
else if (x == 0)
51+
return -1;
52+
else
53+
return 4;
54+
} else {
55+
if (x > 0)
56+
return 7;
57+
else if (x == 0)
58+
return 6;
59+
else
60+
return 5;
61+
}
62+
}
63+
bool operator<(const Angle<T>& rhs) const {
64+
const Angle<T>& lhs = *this;
65+
int lp = lhs.get_partition(), rp = rhs.get_partition();
66+
if (lp == -1)
67+
return false;
68+
else if (rp == -1)
69+
return true;
70+
else if (lp != rp)
71+
return lp < rp;
72+
else
73+
return lhs.Cross(rhs) > 0;
74+
}
75+
bool operator==(const Angle<T>& rhs) const {
76+
const Angle<T>& lhs = *this;
77+
int lp = lhs.get_partition(), rp = rhs.get_partition();
78+
if (lp == -1 || rp == -1)
79+
return false;
80+
else if (lp != rp)
81+
return false;
82+
else
83+
return lhs.Cross(rhs) == 0;
84+
}
85+
};
86+
87+
template <typename T>
88+
void JarvisMarch(std::vector<Vector<T>>& Q, std::vector<Vector<T>>& ans) {
89+
Vector<T> p0 = Q[0];
90+
for (auto i = Q.begin(); i != Q.end(); i++)
91+
if (i->y < p0.y || (i->y == p0.y && i->x < p0.x))
92+
p0 = *i;
93+
Angle<T> last_angle(1, 0);
94+
Vector<T> last = p0;
95+
while (true) {
96+
ans.push_back(last);
97+
Angle<T> candidate_angle;
98+
Vector<T> candidate;
99+
for (auto i = Q.begin(); i != Q.end(); i++) {
100+
Angle<T> current(last, *i);
101+
if (!(current < last_angle)) {
102+
if (current < candidate_angle ||
103+
(current == candidate_angle &&
104+
(candidate - last).Length() < (*i - last).Length())) {
105+
candidate_angle = current;
106+
candidate = *i;
107+
}
108+
}
109+
}
110+
if (candidate == p0)
111+
break;
112+
last = candidate;
113+
last_angle = candidate_angle;
114+
}
115+
}
116+
#endif
117+
118+
#ifdef MAIN_JarvisMarch
119+
int main(int argc, char *argv[]) {
120+
const size_t n = get_argv(argc, argv, 1, 200);
121+
const size_t m = get_argv(argc, argv, 2, 10);
122+
std::vector<int> b;
123+
random_integers(b, -n, n, m * 2);
124+
using T = double;
125+
std::vector<Vector<T>> Q, S;
126+
Q.reserve(m);
127+
for (size_t i = 0; i < m; i++)
128+
Q.push_back(Vector<T>(b[2 * i + 0], b[2 * i + 1]));
129+
JarvisMarch(Q, S);
130+
std::cout << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>"
131+
<< std::endl;
132+
std::cout << "<svg height=\"" << 2 * n << "\" width=\"" << 2 * n << "\">"
133+
<< std::endl;
134+
std::cout << "\t<rect fill=\"#ffffff\" x=\"0\" y=\"0\" width=\"" << 2 * n
135+
<< "\" height=\"" << 2 * n << "\"/>" << std::endl;
136+
std::cout << "\t<polygon stroke=\"#000000\" fill=\"#cccccc\" points=\"";
137+
for (auto i = S.begin(); i != S.end(); i++)
138+
std::cout << n + i->x + 1 << "," << n + i->y + 1 << " ";
139+
std::cout << "\"/>" << std::endl;
140+
for (auto i = Q.begin(); i != Q.end(); i++)
141+
std::cout << "\t<circle cx=\"" << n + i->x + 1 << "\" cy=\""
142+
<< n + i->y + 1 << "\" r=\"2\"/>" << std::endl;
143+
std::cout << "</svg>" << std::endl;
144+
return 0;
145+
}
146+
#endif
147+

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220
| 33 | AnySegmentsIntersect.cpp | Below | 1024 |
221221
| 33 | AnySegmentsIntersect.cpp | Any Segments Intersect | 1025 |
222222
| 33 | GrahamScan.cpp | Graham Scan | 1031 |
223+
| 33 | JarvisMarch.cpp | Jarvis March | 1038 |
223224

224225
# Supplementary Files
225226
* `utils.h`: Utils

0 commit comments

Comments
 (0)