1 #ifndef TERMOX_WIDGET_WIDGETS_GRAPH_HPP
2 #define TERMOX_WIDGET_WIDGETS_GRAPH_HPP
13 #include <termox/painter/color.hpp>
14 #include <termox/painter/glyph.hpp>
15 #include <termox/painter/painter.hpp>
16 #include <termox/widget/boundary.hpp>
17 #include <termox/widget/point.hpp>
18 #include <termox/widget/widget.hpp>
26 template <
typename Number_t =
double>
38 std::vector<Coordinate> coordinates = {};
44 : boundary_{b}, coordinates_{std::move(x)}
46 assert(b.west < b.east && b.south < b.north);
47 auto constexpr empty_braille = U
'⠀';
59 assert(b.west < b.east && b.south < b.north);
71 void reset(std::vector<Coordinate> x)
73 coordinates_ = std::move(x);
78 template <
typename Iter1_t,
typename Iter2_t>
79 void reset(Iter1_t first, Iter2_t last)
82 std::is_same_v<
typename std::iterator_traits<Iter1_t>::value_type,
84 "Must add with a iterators pointing to Coordinates.");
86 std::copy(first, last, std::back_inserter(coordinates_));
93 coordinates_.push_back(c);
100 coordinates_.clear();
115 (double)
area.width / distance(boundary_.west, boundary_.east);
117 (double)
area.height / distance(boundary_.south, boundary_.north);
119 for (
auto const c : coordinates_) {
120 auto const h_offset = h_ratio * distance(boundary_.west, c.x);
121 auto const v_offset =
122 area.height - v_ratio * distance(boundary_.south, c.y);
123 if (h_offset >=
area.width)
125 if (v_offset >=
area.height || v_offset < 0)
127 auto const point = Point{(int)h_offset, (
int)v_offset};
128 auto const mask = this->to_cell_mask(h_offset, v_offset);
129 auto current = p.at(point);
130 current.symbol = combine(current.symbol, mask);
131 p.put(current, point);
138 std::vector<Coordinate> coordinates_;
142 [[nodiscard]]
static auto distance(Number_t smaller, Number_t larger)
145 return larger - smaller;
149 [[nodiscard]]
static auto to_cell_mask(
double h_offset,
double v_offset)
152 auto const h_cell = h_offset - std::floor(h_offset);
153 auto const v_cell = v_offset - std::floor(v_offset);
157 else if (v_cell < 0.5)
159 else if (v_cell < 0.75)
167 else if (v_cell < 0.5)
169 else if (v_cell < 0.75)
177 [[nodiscard]]
static auto combine(char32_t braille, std::uint8_t mask)
180 return braille | mask;
185 template <
typename Number_t =
double>
186 [[nodiscard]]
auto graph(
187 Boundary<Number_t> b = {},
188 std::vector<typename Graph<Number_t>::Coordinate> x = {})
189 -> std::unique_ptr<Graph<Number_t>>
191 return std::make_unique<Graph<Number_t>>(b, std::move(x));
195 template <
typename Number_t =
double>
196 [[nodiscard]]
auto graph(
typename Graph<Number_t>::Parameters p)
197 -> std::unique_ptr<Graph<Number_t>>
199 return std::make_unique<Graph<Number_t>>(std::move(p));
206 template <
typename Number_t =
double>
218 std::vector<std::pair<Coordinate, Color>> coordinates = {};
224 std::vector<std::pair<Coordinate, Color>> x = {})
225 : boundary_{b}, coordinates_{std::move(x)}
227 assert(b.west < b.east && b.south < b.north);
239 assert(b.west < b.east && b.south < b.north);
251 void reset(std::vector<std::pair<Coordinate, Color>> x)
253 coordinates_ = std::move(x);
259 template <
typename Iter1_t,
typename Iter2_t>
260 void reset(Iter1_t first, Iter2_t last)
263 std::is_same_v<
typename std::iterator_traits<Iter1_t>::value_type,
264 std::pair<Coordinate, Color>>,
265 "Must add with a iterators pointing to Coordinates, Color pair.");
266 coordinates_.clear();
267 std::copy(first, last, std::back_inserter(coordinates_));
272 void add(std::pair<Coordinate, Color> p)
274 coordinates_.push_back(p);
281 coordinates_.clear();
297 (double)
area.width / distance(boundary_.west, boundary_.east);
299 (double)
area.height / distance(boundary_.south, boundary_.north);
301 for (
auto const& [coord, color] : coordinates_) {
302 auto const h_offset = h_ratio * distance(boundary_.west, coord.x);
303 auto const v_offset =
304 area.height - v_ratio * distance(boundary_.south, coord.y);
305 if (h_offset >=
area.width)
307 if (v_offset >=
area.height || v_offset < 0)
309 auto const point = Point{(int)h_offset, (
int)v_offset};
310 auto const is_top = is_top_region(v_offset);
311 auto const glyph = combine(p.at(point), is_top, color);
319 std::vector<std::pair<Coordinate, Color>> coordinates_;
323 [[nodiscard]]
static auto distance(Number_t smaller, Number_t larger)
326 return larger - smaller;
331 [[nodiscard]]
static auto is_top_region(
double v_offset) ->
bool
333 return (v_offset - std::floor(v_offset)) < 0.5;
337 [[nodiscard]]
static auto combine(Glyph current,
bool is_top, Color c)
340 if (current.symbol == U
' ')
341 current = U
'▀' | fg(Color::Background);
351 template <
typename Number_t =
double>
352 [[nodiscard]]
auto color_graph(
353 Boundary<Number_t> b = {},
354 std::vector<std::pair<typename Color_graph<Number_t>::Coordinate, Color>>
355 x = {}) -> std::unique_ptr<Color_graph<Number_t>>
357 return std::make_unique<Color_graph<Number_t>>(b, std::move(x));
361 template <
typename Number_t =
double>
362 [[nodiscard]]
auto color_graph(
typename Color_graph<Number_t>::Parameters p)
363 -> std::unique_ptr<Color_graph<Number_t>>
365 return std::make_unique<Color_graph<Number_t>>(std::move(p));
372 template <
typename Number_t,
378 static_assert(west < east && south < north);
389 std::vector<std::pair<Coordinate, Color>> coordinates = {};
395 std::vector<std::pair<Coordinate, Color>> x = {})
396 : coordinates_{std::move(x)}
412 void reset(std::vector<std::pair<Coordinate, Color>> x)
414 coordinates_ = std::move(x);
420 template <
typename Iter1_t,
typename Iter2_t>
421 void reset(Iter1_t first, Iter2_t last)
424 std::is_same_v<
typename std::iterator_traits<Iter1_t>::value_type,
425 std::pair<Coordinate, Color>>,
426 "Must add with a iterators pointing to Coordinates, Color pair.");
427 coordinates_.clear();
428 std::copy(first, last, std::back_inserter(coordinates_));
433 void add(std::pair<Coordinate, Color> p)
435 coordinates_.push_back(p);
442 coordinates_.clear();
456 constexpr
double h_distance = distance(boundary_.west, boundary_.east);
457 constexpr
double v_distance =
458 distance(boundary_.south, boundary_.north);
461 auto const h_ratio = (double)
area.width / h_distance;
462 auto const v_ratio = (
double)
area.height / v_distance;
464 for (
auto const& [coord, color] : coordinates_) {
465 auto const h_offset = h_ratio * distance(boundary_.west, coord.x);
466 auto const v_offset =
467 area.height - (v_ratio * distance(boundary_.south, coord.y));
468 if (h_offset >=
area.width)
470 if (v_offset >=
area.height || v_offset < 0)
472 auto const point = Point{(int)h_offset, (
int)v_offset};
473 auto const is_top = is_top_region(v_offset);
474 auto const glyph = combine(p.at(point), is_top, color);
481 static constexpr
auto boundary_ =
484 std::vector<std::pair<Coordinate, Color>> coordinates_;
488 [[nodiscard]]
static constexpr
auto distance(Number_t smaller,
489 Number_t larger) -> Number_t
491 return larger - smaller;
496 [[nodiscard]]
static auto is_top_region(
double v_offset) ->
bool
498 return (v_offset - std::floor(v_offset)) < 0.5;
502 [[nodiscard]]
static auto combine(Glyph current,
bool is_top, Color c)
505 if (current.symbol == U
' ')
506 current = U
'▀' | fg(Color::Background);
516 template <
typename Number_t,
521 [[nodiscard]]
auto color_graph_static_bounds(
522 std::vector<std::pair<
523 typename Color_graph_static_bounds<Number_t, west, east, north, south>::
527 Color_graph_static_bounds<Number_t, west, east, north, south>>
529 return std::make_unique<
530 Color_graph_static_bounds<Number_t, west, east, north, south>>(
535 template <
typename Number_t,
540 [[nodiscard]]
auto color_graph_static_bounds(
541 typename Color_graph_static_bounds<Number_t, west, east, north, south>::
544 Color_graph_static_bounds<Number_t, west, east, north, south>>
546 return std::make_unique<
547 Color_graph_static_bounds<Number_t, west, east, north, south>>(
Bounded box that can display added Color Coordinates within a static Bound.
Definition: graph.hpp:377
void reset(Iter1_t first, Iter2_t last)
Replace with copies of <Coordinate, Color>s given by iterators.
Definition: graph.hpp:421
void reset(std::vector< std::pair< Coordinate, Color >> x)
Replace the current state with the given Coordinates vector x.
Definition: graph.hpp:412
Color_graph_static_bounds(Parameters p)
Create a Color_graph_static_bounds with given Parameters.
Definition: graph.hpp:400
static constexpr auto boundary() -> Boundary< Number_t >
Return the currently set Boundary.
Definition: graph.hpp:406
Color_graph_static_bounds(std::vector< std::pair< Coordinate, Color >> x={})
Create a Color_graph_static_bounds with given Coordinates and Colors.
Definition: graph.hpp:394
void clear()
Remove all points from the Graph and repaint.
Definition: graph.hpp:440
void add(std::pair< Coordinate, Color > p)
Add a single <Coordinate, Color> to the Graph.
Definition: graph.hpp:433
auto paint_event(Painter &p) -> bool override
Handles Paint_event objects.
Definition: graph.hpp:454
auto coordinates() const -> std::vector< std::pair< Coordinate, Color >> const &
Return a reference to the current container of Coordinates.
Definition: graph.hpp:447
Bounded box that can display added Color Coordinates within the Boundary.
Definition: graph.hpp:207
auto paint_event(Painter &p) -> bool override
Handles Paint_event objects.
Definition: graph.hpp:293
auto coordinates() const -> std::vector< std::pair< Coordinate, Color >> const &
Return a reference to the current container of Coordinates.
Definition: graph.hpp:286
void reset(std::vector< std::pair< Coordinate, Color >> x)
Replace the current state with the given Coordinates vector x.
Definition: graph.hpp:251
void clear()
Remove all points from the Graph and repaint.
Definition: graph.hpp:279
Color_graph(Parameters p)
Create a Color_graph with given Parameters.
Definition: graph.hpp:231
void add(std::pair< Coordinate, Color > p)
Add a single <Coordinate, Color> to the Graph.
Definition: graph.hpp:272
Color_graph(Boundary< Number_t > b={}, std::vector< std::pair< Coordinate, Color >> x={})
Create a Color_graph with given Boundary and Coordinates, Colors.
Definition: graph.hpp:223
auto boundary() const -> Boundary< Number_t >
Return the currently set Boundary.
Definition: graph.hpp:245
void set_boundary(Boundary< Number_t > b)
Set a new Boundary and repaint the Widget.
Definition: graph.hpp:237
void reset(Iter1_t first, Iter2_t last)
Replace with copies of <Coordinate, Color>s given by iterators.
Definition: graph.hpp:260
Color numbers [0 - 180] are valid.
Definition: color.hpp:16
Bounded box that can display added Coordinates within the Boundary.
Definition: graph.hpp:27
auto paint_event(Painter &p) -> bool override
Handles Paint_event objects.
Definition: graph.hpp:111
Graph(Boundary< Number_t > b={}, std::vector< Coordinate > x={})
Create a Graph with given Boundary and Coordinates.
Definition: graph.hpp:43
void reset(Iter1_t first, Iter2_t last)
Replace the current state with copies of Coordinates given by iterators.
Definition: graph.hpp:79
void add(Coordinate c)
Add a single Coordinate to the Graph.
Definition: graph.hpp:91
Graph(Parameters p)
Create a Graph with given Parameters.
Definition: graph.hpp:52
void reset(std::vector< Coordinate > x)
Replace the current state with the given Coordinates vector x.
Definition: graph.hpp:71
void clear()
Remove all points from the Graph and repaint.
Definition: graph.hpp:98
void set_boundary(Boundary< Number_t > b)
Set a new Boundary and repaint the Widget.
Definition: graph.hpp:57
auto coordinates() const -> std::vector< Coordinate > const &
Return a reference to the current container of Coordinates.
Definition: graph.hpp:105
auto boundary() const -> Boundary< Number_t >
Return the currently set Boundary.
Definition: graph.hpp:65
Contains functions to paint Glyphs to a Widget's screen area.
Definition: painter.hpp:21
Four point Boundary, edges are inclusive.
Definition: boundary.hpp:10
x is horizontal, y is vertical.
Definition: graph.hpp:210
Definition: graph.hpp:216
x is horizontal, y is vertical.
Definition: graph.hpp:382
Definition: graph.hpp:388
x is horizontal, y is vertical.
Definition: graph.hpp:30