Skip to content
Snippets Groups Projects
Commit e5d61ced authored by Fabian Reister's avatar Fabian Reister
Browse files

Merge branch 'feature/iterators' into 'master'

Feature/iterators

See merge request Simox/simox!58
parents 6180aacc 02ac9e07
No related branches found
No related tags found
No related merge requests found
#pragma once
// This file is generated!
#include "iterator/xy_index_range_iterator.h"
#pragma once
#include <iterator>
namespace simox::iterator {
struct Point {
int x;
int y;
Point(int x, int y) : x(x), y(y) {}
Point() = default;
bool operator==(const Point &rhs) const { return x == rhs.x && y == rhs.y; }
static Point zero() { return {0, 0}; }
};
/**
* The XYIndexRangeIterator class.
*
* The aim of this class is to provide a convenient way to iterate over 2D arrays
* This class provides a 2D iterator that returns all indices to the 2D array, e.g.
*
* My2DArray arr(10, 20);
* for(auto [x,y] : XYIndexRangeIterator(arr)){
* auto val = arr.at(x,y);
* // do the magic
* }
*
* This is hightly inspired by cartographer::mapping::XYIndexRangeIterator
* see: https://github.com/cartographer-project/cartographer/blob/master/cartographer/mapping/2d/xy_index.h
*/
template <typename IndexType = Point>
class XYIndexRangeIterator
: public std::iterator<std::input_iterator_tag, IndexType> {
public:
// Constructs a new iterator for the specified range.
XYIndexRangeIterator(const IndexType &min_xy_index,
const IndexType &max_xy_index)
: min_xy_index(min_xy_index), max_xy_index(max_xy_index),
xy_index(min_xy_index) {}
// Constructs a new iterator for everything contained in 'cell_limits'.
explicit XYIndexRangeIterator(const IndexType &cell_limits)
: XYIndexRangeIterator(IndexType::zero(),
IndexType(cell_limits.x - 1, cell_limits.y - 1)) {}
XYIndexRangeIterator &operator++() {
if (xy_index.x < max_xy_index.x) {
++xy_index.x;
} else {
xy_index.x = min_xy_index.x;
++xy_index.y;
}
return *this;
}
IndexType &operator*() { return xy_index; }
bool operator==(const XYIndexRangeIterator &other) const {
return xy_index == other.xy_index;
}
bool operator!=(const XYIndexRangeIterator &other) const {
return !operator==(other);
}
XYIndexRangeIterator begin() const {
return XYIndexRangeIterator(min_xy_index, max_xy_index);
}
XYIndexRangeIterator end() const {
XYIndexRangeIterator it = begin();
it.xy_index = IndexType(min_xy_index.x, max_xy_index.y + 1);
return it;
}
private:
IndexType min_xy_index;
IndexType max_xy_index;
IndexType xy_index;
};
} // namespace simox::iterator
......@@ -48,3 +48,4 @@ ADD_SUBDIRECTORY(meta)
ADD_SUBDIRECTORY(shapes)
ADD_SUBDIRECTORY(simox)
ADD_SUBDIRECTORY(backport)
ADD_SUBDIRECTORY(iterator)
ADD_SU_TEST( XYIndexRangeIterator )
/*
* This file is part of ArmarX.
*
* ArmarX is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* ArmarX is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package
* @author Fabian Reister ( fabian dot reister at kit dot edu )
* @date 2021
* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
* GNU General Public License
*/
#define BOOST_TEST_MODULE SimoxUtility/iterator/XYIndexRangeIterator
#include <vector>
#include <iostream>
#include <numeric>
#include <algorithm>
#include <boost/test/included/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <SimoxUtility/iterator.h>
// BOOST_AUTO_TEST_SUITE(XYIndexRangeIterator)
BOOST_AUTO_TEST_CASE(test_loop)
{
// dimensions
constexpr int N = 10;
constexpr int M = 20;
// create 2D vector of size N*M
const auto v = std::vector<std::vector<int>>(M, std::vector<int>(N, 1));
const auto range_it = simox::iterator::XYIndexRangeIterator(simox::iterator::Point{N, M});
// max counters for test checks
int x_max = 0;
int y_max = 0;
int cnt = 0;
for(const auto& [x,y] : range_it){
x_max = std::max(x, x_max);
y_max = std::max(y, y_max);
// TODO(fabian.reister): access v
cnt++;
}
BOOST_CHECK_EQUAL(x_max, N-1);
BOOST_CHECK_EQUAL(y_max, M-1);
BOOST_CHECK_EQUAL(cnt, N*M);
}
BOOST_AUTO_TEST_CASE(test_foreach)
{
// dimensions
constexpr int N = 10;
constexpr int M = 20;
// create 2D vector of size N*M
const auto v = std::vector<std::vector<int>>(M, std::vector<int>(N, 1));
const auto range_it = simox::iterator::XYIndexRangeIterator(simox::iterator::Point{N, M});
int x_max = 0;
int y_max = 0;
int cnt = 0;
std::for_each(range_it.begin(), range_it.end(), [&](const auto& pnt){
const auto& [x,y] = pnt;
x_max = std::max(x, x_max);
y_max = std::max(y, y_max);
// TODO(fabian.reister): access v
cnt++;
});
BOOST_CHECK_EQUAL(x_max, N-1);
BOOST_CHECK_EQUAL(y_max, M-1);
BOOST_CHECK_EQUAL(cnt, N*M);
}
// BOOST_AUTO_TEST_SUITE_END()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment