-
Notifications
You must be signed in to change notification settings - Fork 0
/
Visual_view.cpp
136 lines (125 loc) · 4.13 KB
/
Visual_view.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "Visual_view.h"
#include "Geometry.h"
#include "Utility.h"
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <utility>
using std::copy; using std::ostream_iterator;
using std::cout; using std::endl;
using std::ios;
using std::make_pair;
using std::map;
using std::setw;
using std::string;
using std::vector;
// we display the coordinates every three rows and columns
const int show_coord_num_c = 3;
// the width of the axis lable
const int axis_label_width_c = 4;
void Visual_view::update_location(const string& name, Point location)
{
auto result = object_locations.insert(make_pair(name, location));
if(!result.second) {
// If the object with this name is already there, update the location.
(result.first) -> second = location;
}
}
void Visual_view::update_remove(const string& name)
{
object_locations.erase(name);
}
void Visual_view::plot(int size, double scale, Point origin) const
{
vector<vector<string>> map(size);
for(vector<string>& vec : map) {
// resize each vector and fill each cell out with the default display
vec.assign(size, ". ");
}
// collect subscripts for all objects
for(auto it = object_locations.begin(); it != object_locations.end(); ++it) {
int ix, iy;
if(get_subscripts(size, scale, origin, ix, iy, it -> second)) {
if(map[iy][ix] == ". ") {
// if there is no other objects occupying the same spot yet
// go ahead and fill up the spot
map[iy][ix] = (it -> first).substr(0, num_letters_c);
} else {
// otherwise, fill up with an * to indicate
// there are multiple objects at the current spot
map[iy][ix] = "* ";
}
}
}
// A simple class that facilitates saving and restoring output settings
class Cout_format_saver {
public:
Cout_format_saver() :
old_flags(cout.flags()), old_precision(cout.precision())
{
// we don't want any digits to the right of the decimal point
// when printing axis labels
cout.precision(0);
}
~Cout_format_saver()
{
cout.flags(old_flags);
cout.precision(old_precision);
}
private:
ios::fmtflags old_flags;
int old_precision;
};
// From this point on, until the function ends, the only numbers
// we're printing are axis labels. So change to new format here.
Cout_format_saver saver;
// Print out the map and coordinates.
// Since large y subscripts appear first, print in reverse order.
ostream_iterator<string> out_it(cout);
for(int i = size - 1; i >= 0; --i) {
if(i % show_coord_num_c) {
cout << " ";
} else {
// print out y-coordinates every three rows
cout << setw(axis_label_width_c) << i * scale + origin.y << " ";
}
copy(map[i].begin(), map[i].end(), out_it);
cout << endl;
}
// print out x-coordinates every three columns
for(int i = 0; i < size; i += show_coord_num_c) {
cout << " " << setw(axis_label_width_c) << i * scale + origin.x;
}
cout << endl;
}
bool Visual_view::get_object_location(Point& point, const string& name) const
{
auto it = object_locations.find(name);
if(it != object_locations.end()) {
point = it -> second;
return true;
} else {
return false;
}
}
void Visual_view::list_outliers(int size, double scale, Point origin) const
{
bool first = true; // is this the first outside object?
int ix, iy;
for(auto it = object_locations.begin(); it != object_locations.end(); ++it) {
if(!get_subscripts(size, scale, origin, ix, iy, it -> second)) {
if(first) {
cout << it -> first;
first = false;
} else {
cout << ", " << it -> first;
}
}
}
if(!first) {
// If we have printed at least one outside object,
// print the following statement as well.
cout << " outside the map" << endl;
}
}