我正在遍历定义圆(封闭形状)的点列表。对于每个点,我都在检查该点与下一个点之间的距离,并决定细分该距离是否大于4。
for (vector<Node>::reverse_iterator i = nodes.rbegin(); i != nodes.rend(); ++i) // going through list in reverse
{
ofVec3f v1 = i->position;
i += 1;
ofVec3f v2 = i->position;
i -= 1;
float distance = v1.distance(v2);
if (distance > 4) {
interpolate(v1, v2);
}
}
问题是,我想拥有它,以便上次迭代的i + 1元素是列表的第一个元素(因为它是闭合形状)。我以前在C#中有一个非常方便的函数,但由于迭代器的工作方式而无法使用。
int DiffLine::idxFix(int i) {
int c = nodes.size();
if (i < 0) { return c - 1; }
else { return i % c; }
}
在c ++中如何实现类似的目标?
答案 0 :(得分:1)
选中i + 1
。如果是rend()
,请从v2
获取rbegin()
。您说您的结构是一个“列表”,但是您使用+=
告诉我您具有随机访问迭代器,因此我在编写以下代码时假设您具有随机访问迭代器(例如nodes
是std::vector
)。如果不是这种情况(例如nodes
实际上是std::list
),则需要进行一些修改。
for (auto i = nodes.rbegin(); i != nodes.rend(); ++i) // going through list in reverse
{
ofVec3f v1 = i->position;
ofVec3f v2;
auto j = i + 1;
if (j == nodes.rend()) {
v2 = nodes.rbegin()->position;
}
else
{
v2 = j->position;
}
float distance = v1.distance(v2);
if (distance > 4) {
interpolate(v1, v2);
}
}
当然,您不必不必使用迭代器。如果这是一个随机访问迭代器(再次假设nodes
是std::vector
),则可以使用索引为循环的good-ol'
for (std::size_t i = nodes.size(); i != 0; --i)
{
ofVec3f v1 = nodes[i % nodes.size()].position;
ofVec3f v2 = nodes[i - 1].position;
float distance = v1.distance(v2);
if (distance > 4) {
interpolate(v1, v2);
}
}
请注意,以上代码将在第一次迭代时将FIRST元素与LAST元素进行比较。如果不可接受,那么我们可以进行一些更改。
答案 1 :(得分:0)
您可以为随机访问迭代器实现包装器,该包装器执行与c#方法类似的操作:
#include <vector>
#include <iostream>
template <typename RandomAccessIterator>
class LoopWrapper {
public:
LoopWrapper(const RandomAccessIterator& first,
const RandomAccessIterator& last)
: first_(first), dist_(last-first) {}
typename RandomAccessIterator::value_type& operator*() {
return *(first_ + pos_);
}
LoopWrapper& operator++() {
pos_++;
if (pos_ == dist_) {
pos_ = 0;
wrapped_ = true;
}
return *this;
}
LoopWrapper& operator--() {
pos_--;
if (pos_ < 0) pos_ = dist_ - 1;
return *this;
}
LoopWrapper operator+(int offset) {
LoopWrapper result = *this;
result.pos_ += offset;
result.pos_ %= dist_;
if (result.pos_ < 0) result.pos_ += dist_;
return result;
}
LoopWrapper operator-(int offset) {
LoopWrapper result = *this;
result.pos_ -= offset;
result.pos_ %= dist_;
if (result.pos_ < 0) result.pos_ += dist_;
return result;
}
operator RandomAccessIterator() { return first_ + pos_; }
bool Done() const { return wrapped_; }
private:
const RandomAccessIterator first_;
const int dist_;
int pos_ = 0;
bool wrapped_ = false;
};
int main() {
std::vector<int> v{1, 2, 3};
for (auto i = LoopWrapper(v.begin(), v.end()); !i.Done(); ++i) {
std::cout << *i << ", " << *(i + 1) << std::endl;
}
return 0;
}