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
|
// Osman Zakir
// 7 / 4 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 15 Exercise 6
// chapter15ex6.cpp
// Exercise Specifications:
/**
* Design and implement a bar graph class. Its basic data is a vector<double>
* holding N values, and each value should be represented by a “bar” that is
* a rectangle where the height represents the value.
*/
#include <vector>
#include <iostream>
#include <algorithm>
#include "../../Graph.h"
#include "../../Window.h"
namespace Graph_lib
{
struct Bar_graph : Shape
{
Bar_graph(const Point &graph_tl, const int graph_width, const int graph_height, const Color &bar_fill,
const Color &bar_outline, const Color &graph_outline, const Color &graph_fill, const std::vector<double> &values);
void draw_lines() const;
int graph_width() const { return m_graph_width; }
int graph_height() const { return m_graph_height; }
const std::vector<double> &values_v() const { return m_values; }
const Vector_ref<Rectangle> &bars_v() const { return m_bars_v; }
void set_graph_width(const int value) { m_graph_width = value; }
void set_graph_height(const int value) { m_graph_height = value; }
private:
Point m_graph_tl; // top-left of rectangle bouning graph
int m_graph_width; // width of rectangle bounding graph
int m_graph_height; // height of rectangle bounding graph
std::vector<double> m_values;
Color m_bar_fill;
Color m_bar_outline;
Color m_graph_outline;
Color m_graph_fill;
Vector_ref<Rectangle> m_bars_v;
};
}
int main()
{
using namespace std;
using namespace Graph_lib;
constexpr int win_x = 100;
constexpr int win_y = 100;
constexpr int win_width = 600;
constexpr int win_height = 400;
const Point win_tl{ win_x, win_y };
Graph_lib::Window win{ win_tl, win_width, win_height, "Bar graphs" };
try
{
constexpr int graph_width = win_width - 40;
constexpr int graph_height = win_height - 60;
vector<double> values{ 5.6, 5.6, 4.3, 5.0 };
const Point rect_tl{ 100, 100 };
Bar_graph bar_graph{ Point{100, 100}, graph_width, graph_height, Color::blue, bar_graph.color(),
Color::black, Color::invisible, values };
bar_graph.set_color(Color::black);
bar_graph.set_fill_color(Color::blue);
win.attach(bar_graph);
gui_main();
}
catch (const runtime_error &e)
{
Text err_msg_start{ Point{(win_width / 2) - 200, win_height / 2}, "Runtime error: " };
Text err_msg{ Point{(win_width / 2) + err_msg_start.label().length() + 5, win_height / 2}, e.what() };
err_msg_start.set_color(Color::black);
err_msg.set_color(Color::black);
win.attach(err_msg_start);
win.attach(err_msg);
gui_main();
}
}
Graph_lib::Bar_graph::Bar_graph(const Point &graph_tl, const int graph_width, const int graph_height, const Color &bar_fill,
const Color &bar_outline, const Color &graph_outline, const Color &graph_fill, const std::vector<double> &values)
:m_graph_tl{ graph_tl }, m_graph_width{ graph_width }, m_graph_height{ graph_height }, m_bar_fill{ bar_fill },
m_bar_outline{ bar_outline }, m_graph_outline{ graph_outline }, m_graph_fill{ graph_fill }, m_values{ values}
{
const std::size_t N = values.size();
Rectangle bounding_rect{ graph_tl, graph_width, graph_height };
bounding_rect.set_color(graph_outline);
bounding_rect.set_fill_color(graph_fill);
bounding_rect.draw();
if (N == 0)
{
error("invalid number of values!");
}
int bar_width = (graph_width / N);
double bar_spaces = bar_width * 1.0 / (2 * N - 1);
bar_width -= bar_spaces;
auto it = std::max_element(values.begin(), values.end());
int max_value = *it;
for (std::size_t i = 0; i < N; ++i)
{
int bar_height = std::round(values[i]) * (graph_height / max_value);
m_bars_v.push_back(new Rectangle{
Point{ (i * bar_width) + (bar_spaces * 2), bar_height }, bar_width, bar_height
});
m_bars_v[i].set_color(bar_outline);
m_bars_v[i].set_fill_color(bar_fill);
}
}
void Graph_lib::Bar_graph::draw_lines() const
{
for (std::size_t i = 0; i < m_bars_v.size(); ++i)
{
m_bars_v[i].draw();
}
}
|