|
6 | 6 | #define MATPLOTPLUSPLUS_COMMON_H
|
7 | 7 |
|
8 | 8 | #include <algorithm>
|
| 9 | +#include <cctype> |
9 | 10 | #include <complex>
|
10 | 11 | #include <functional>
|
11 | 12 | #include <map>
|
12 | 13 | #include <matplot/util/concepts.h>
|
| 14 | +#include <numeric> |
13 | 15 | #include <sstream>
|
14 | 16 | #include <string>
|
15 | 17 | #include <string_view>
|
16 | 18 | #include <vector>
|
17 |
| -#include <cctype> |
18 | 19 |
|
19 | 20 | namespace matplot {
|
20 | 21 | bool iequals(std::string_view str1, std::string_view str2);
|
@@ -504,6 +505,85 @@ namespace matplot {
|
504 | 505 |
|
505 | 506 | double distance(double x1, double y1, double x2, double y2);
|
506 | 507 |
|
| 508 | + /// \brief Simple read-only 2d view for vector_2d. |
| 509 | + /// It could iterates over all vector's elements and get value using |
| 510 | + /// only one index (offset). |
| 511 | + class vector_2d_view { |
| 512 | + using vector_2d = matplot::vector_2d; |
| 513 | + const vector_2d &_vec; |
| 514 | + const std::size_t _sz; |
| 515 | + |
| 516 | + /// \brief Helper method for determining the whole array size. |
| 517 | + /// Required for caching inner vector's size. |
| 518 | + std::size_t calculate_size(const vector_2d &vec) { |
| 519 | + return std::accumulate( |
| 520 | + vec.begin(), vec.end(), (std::size_t)(0), |
| 521 | + [](auto cnt, const auto &vec) { return cnt + vec.size(); }); |
| 522 | + } |
| 523 | + |
| 524 | + public: |
| 525 | + static const double &get_element_from_offset(const vector_2d &vec, |
| 526 | + std::size_t offset) { |
| 527 | + std::size_t row_size = vec[0].size(); |
| 528 | + std::size_t cur_row = offset / row_size; |
| 529 | + std::size_t cur_column = offset % row_size; |
| 530 | + return vec[cur_row][cur_column]; |
| 531 | + } |
| 532 | + |
| 533 | + static vector_2d_view from_vector_2d(const vector_2d &vec) { |
| 534 | + return vector_2d_view(vec); |
| 535 | + } |
| 536 | + std::size_t size() const { return _sz; } |
| 537 | + vector_2d_view(const vector_2d &vec) |
| 538 | + : _vec(vec), _sz(calculate_size(vec)) {} |
| 539 | + |
| 540 | + double operator()(std::size_t i, std::size_t j) { |
| 541 | + return _vec.at(i).at(j); |
| 542 | + } |
| 543 | + friend class iterator; |
| 544 | + |
| 545 | + class iterator { |
| 546 | + vector_2d_view *const _vec; |
| 547 | + std::size_t _row_offset; |
| 548 | + std::size_t _col_offset; |
| 549 | + |
| 550 | + static bool is_empty_iterator(const iterator &it) { |
| 551 | + return it._vec == nullptr; |
| 552 | + } |
| 553 | + static bool is_end_iterator(const iterator &it) { |
| 554 | + return is_empty_iterator(it) || |
| 555 | + it._row_offset * it._col_offset >= it._vec->size(); |
| 556 | + } |
| 557 | + |
| 558 | + public: |
| 559 | + iterator(vector_2d_view *const vec) |
| 560 | + : _vec(vec), _row_offset(0), _col_offset(0) {} |
| 561 | + |
| 562 | + bool operator==(const iterator &it) const { |
| 563 | + return is_end_iterator(it) |
| 564 | + ? is_end_iterator(*this) |
| 565 | + : it._vec == _vec && it._row_offset == _row_offset && |
| 566 | + it._col_offset == _col_offset; |
| 567 | + } |
| 568 | + |
| 569 | + auto operator*() const { return (*_vec)(_row_offset, _col_offset); } |
| 570 | + |
| 571 | + iterator &operator++() { |
| 572 | + _col_offset++; |
| 573 | + if (_col_offset >= _vec->_vec.at(_row_offset).size()) { |
| 574 | + _col_offset = 0; |
| 575 | + _row_offset++; |
| 576 | + } |
| 577 | + return *this; |
| 578 | + } |
| 579 | + |
| 580 | + // iterator traits |
| 581 | + using value_type = double; |
| 582 | + }; |
| 583 | + iterator begin() { return iterator{this}; } |
| 584 | + iterator end() { return iterator{nullptr}; } |
| 585 | + }; |
| 586 | + |
507 | 587 | } // namespace matplot
|
508 | 588 |
|
509 | 589 | #endif // MATPLOTPLUSPLUS_COMMON_H
|
0 commit comments