forked from c-koi/libboard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhull.cpp
More file actions
104 lines (94 loc) · 2.63 KB
/
hull.cpp
File metadata and controls
104 lines (94 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* @file hull.cpp
* @author Sebastien Fourey (GREYC)
*
* @brief Implementation of a naive 2D convex hull algorithm.
*
* This source code is part of the Board project, a C++ library whose
* purpose is to allow simple drawings in EPS, FIG or SVG files.
* Copyright (C) 2007 Sebastien Fourey <https://fourey.users.greyc.fr>
*/
#include <Board.h>
#include <board/Tools.h>
#include <vector>
using namespace LibBoard;
/**
* @brief isSeparing
*
* Check whether a segment [a,b] is on a line separating a vector of points.
* If not, the points a and b may be swapped so that all points
* are "on the left" of the vector a->b
*
* @param a
* @param b
* @param points
* @return true if the segment [a,b] is on a line separating the given points, otherwise false.
*/
bool isSeparing(Point & a, Point & b, const std::vector<Point> & points)
{
int sign = 0;
Point v1 = b - a;
for (Point p : points) {
if (p != a && p != b) {
Point v2 = p - a;
double wp = v1.x * v2.y - v1.y * v2.x;
if (std::abs(wp) < 1e-8) {
if ((a - p) * (b - p) < 0.0) {
// a, p and b are aligned (in that order)
return true;
}
}
if (((sign > 0) && (wp < 0.0)) || ((sign < 0) && (wp > 0.0))) {
return true;
}
sign = (wp > 0.0) ? 1 : -1;
}
}
if (sign == -1) {
std::swap(a, b);
}
return false;
}
int main(int, char *[])
{
Board board;
Style::setDefaultLineWidth(0.5);
Style::setDefaultPenColor(Color::Blue);
Style::setDefaultFillColor(Color::Null);
std::vector<Point> points;
int n = 25;
while (n--) {
points.push_back(Point(4 * (Tools::boardRand() % 50), 4 * (Tools::boardRand() % 50)));
}
typedef std::pair<Point, Point> Segment;
std::vector<Segment> segments;
// Compute the set of separating segments
for (size_t a = 0; a < points.size(); ++a) {
for (size_t b = a + 1; b < points.size(); ++b) {
Point pa = points[a];
Point pb = points[b];
if (!isSeparing(pa, pb, points)) {
segments.push_back(Segment(pa, pb));
// board << Line(pa, pb, Color::Red, 0.1);
}
}
}
// Build a polyline using the set of segments
Segment segment = segments.front();
std::vector<Point> polyline;
const Point stop = segment.first;
do {
polyline.push_back(segment.first);
for (const Segment & s : segments) {
if (s.first == segment.second) {
segment = s;
break;
}
}
} while (segment.first != stop);
board << Polyline(polyline, Path::Closed, Color::Cyan, Color("#a0a0c0"), 0.5);
for (Point p : points) {
board << Dot(p.x, p.y, Color::Blue, 1.0);
}
board.saveSVG("hull.svg");
}