-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdrawer.cpp
116 lines (93 loc) · 4.36 KB
/
drawer.cpp
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
105
106
107
108
109
110
111
112
113
114
115
116
#include "drawer.h"
#include "cs225/Animation.h"
Drawer::Drawer(const std::string output) : output_file_name(output) {
//this->output_file_name = output;
this->png = new cs225::PNG();
png->readFromFile(empty_map_file);
}
Drawer::~Drawer() {
delete this->png;
}
void Drawer::addAirport(const std::pair<double, double>& coords) {
this->airport_coords.push_back(coords);
}
void Drawer::addAirports(std::vector<const std::pair<double, double>>& coords) {
for (const std::pair<double, double>& coord : coords) {
addAirport(coord);
}
}
void Drawer::addAirports(Graph& g, GraphBuilder& builder, std::vector<Vertex> route) {
for (Vertex vertex : route) {
Airport airport = builder.get_airport_from_code(vertex);
const std::pair<double, double>& coord = {airport.latitude, airport.longitude};
addAirport(coord);
}
}
std::pair<int, int> Drawer::convertCoordsToPixel(double latitude, double longitude) {
//remeber goes in lat long, but comes out x, y which is opposite
//there are 360 longitudinal lines
//Inspired by https://stackoverflow.com/questions/14329691/convert-latitude-longitude-point-to-a-pixels-x-y-on-mercator-projection
if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
std::cout << "Warning. Airport with coordinates " << latitude << ", " << longitude << " are invalid and may not print!" << std::endl;
}
int x = PRIME_MERIDIAN + ((this->map_width * longitude) / 360);
if (longitude < LEFT_SIDE_LONG) {
x = this->map_width + x;
}
//-3 was just trial and error specific to b/w map
int y = EQUATOR - ((this->map_height * latitude) / 180) - 3;
return std::pair<int, int>(x, y);
}
void Drawer::drawAirport(Airport a, cs225::HSLAPixel color) {
const std::pair<double, double> coords = std::pair<double, double>(a.latitude, a.longitude);
drawAirport(coords, color);
}
void Drawer::drawAirport(const std::pair<double, double> coords, cs225::HSLAPixel color) {
auto pixel_coords = convertCoordsToPixel(coords.first, coords.second);
for (int x = std::max(0, pixel_coords.first - (this->map_width/AIRPORT_SIZE_MULTIPLIER)); x < std::min(this->map_width, pixel_coords.first + (this->map_width/AIRPORT_SIZE_MULTIPLIER)); ++x) {
for (int y = std::max(0, pixel_coords.second - (this->map_width/AIRPORT_SIZE_MULTIPLIER)); y < std::min(this->map_height, pixel_coords.second + this->map_width/AIRPORT_SIZE_MULTIPLIER);++y) {
png->getPixel(x, y) = color;
}
}
}
void Drawer::drawFlight(Airport a, Airport b, cs225::HSLAPixel color) {
drawFlight(std::pair<double, double>(a.latitude, a.longitude), std::pair<double, double>(b.latitude, b.longitude), color);
}
void Drawer::drawFlight(std::pair<double, double> coorda, std::pair<double, double> coordb, cs225::HSLAPixel color) {
std::pair<int, int> first_pixel = convertCoordsToPixel(coorda.first, coorda.second);
std::pair<int, int> second_pixel = convertCoordsToPixel(coordb.first, coordb.second);
if (first_pixel.first > second_pixel.first) {
//Algorithm goes left to right, so swap nessisary
std::swap(first_pixel, second_pixel);
}
//pseudocode based on https://en.wikipedia.org/wiki/Line_drawing_algorithm
auto dx = second_pixel.first - first_pixel.first;
auto dy = second_pixel.second - first_pixel.second;
for (int x = first_pixel.first; x < second_pixel.first; ++x) {
int y = first_pixel.second + dy * (x - first_pixel.first) / dx;
png->getPixel(x - 1, y) = color;
png->getPixel(x, y) = color;
png->getPixel(x + 1, y) = color;
}
}
void Drawer::drawPrebuiltMap(cs225::HSLAPixel route_color = {216, 1, .7, 1}) {
cs225::HSLAPixel color;
for (unsigned long f = 0; f < airport_coords.size(); ++f) {
std::pair<int, int> pixel_coords = convertCoordsToPixel(airport_coords[f].first, airport_coords[f].second);
if (f == 0) {
color = RED;
} else if (f == airport_coords.size() - 1) {
color = GREEN;
} else {
color = LIGHT_BLUE;
}
drawAirport(airport_coords[f], color);
}
for (unsigned long f = 0; f < this->airport_coords.size() - 1; ++f) {
drawFlight(airport_coords[f], airport_coords[f + 1], route_color);
}
png->writeToFile(output_file_name);
}
cs225::PNG* Drawer::getPNG() {
return this->png;
}