2

我有一个std::vector包含Point struct(x,y,z 和其他一些非指针类型) 的。

这些点是用于绘制 bspline 曲线的控制点。我在绘制曲线时没有问题,但是当我必须关闭曲线时会出现复杂情况,这涉及以特定顺序添加控制点(容器内已经存在)。

例如,如果我有 5 个控制点

A B C D E

我必须得到 5 个这样的序列:

A B C D  //curve is drawn from B to C
B C D E  //curve is drawn from C to D
C D E A  //curve is drawn from D to E 
D E A B  //curve is drawn from E to A
E A B C  //curve is drawn from A to B

最初,我选择了std::rotate,但后来意识到这不是我想要的。

我在执行此操作时遇到了麻烦。我得到的最好的是 C++ 中的非工作版本(失败的原因不是问题,这是一个片段)。

static char letters = 'A';
typedef struct Point{
        float x,y,z;
        char name;

        Point(float x,float y,float z=0):name(letters++){}

}Point;
typedef std::vector<Point> lpoints;

void
rotate(lpoints& points)
{
    for (unsigned int i =0;i<5;i++){
                lpoints::iterator beg =   lista.begin() + (i%5);
                lpoints::iterator dernier=lista.begin()+(4+i)%6; 

                lpoints subseq(beg,dernier); //4 points in subseq

                //do stuff with subseq                                                       
    }
}

有没有办法做到这一点?我知道我可以用许多嵌套的 for 循环来实现它,但我试图避免这种情况,寻找更优雅的东西(如果这个词合适的话)。

提前致谢。

4

5 回答 5

5

如果您愿意使用更多空间,您可以先将 lpoints 附加到自身,然后在需要时在获取 subseq 时增加迭代器。这也适合您的“5 个不同的向量或一个长向量”,因为您可以只使用双倍向量的迭代器,而不是创建新的。

对不起,我有一段时间没有写C++了,所以这里是C++之类的伪代码

void 
rotate(lpoints& points) 
{ 
    pointsDouble = Append(points,points); // Do your own implementation
                                 // if points is A B C D E
                                 // pointsDouble is A B C D E A B C D E

    pointsDouble::iterator beg =   lista.begin(); 
    pointsDouble::iterator dernier=lista.begin()+4;  

    for (unsigned int i =0;i<5;i++){ 

        lpoints subseq(beg,dernier); //4 points in subseq 

        //do stuff with subseq

       ++beg; ++dernier;

    } 
}

for 循环也可以写得更好,用 begin 和 end(或 dernier)代替循环变量 i。

对于追加,您可能可以使用 std::copy (警告:我在 C++ 中生疏)。

lpoints pointsDouble(points);
std::copy(points.begin(), points.end(), std::back_inserter(pointsDouble));

(Luc 建议的 back_inserter)

于 2010-07-08T04:32:47.093 回答
3

使用 究竟有什么问题std::rotate()?例如,

std::vector<int> v(5);

std::rotate(v.begin(), v.begin() + 1, v.end());
std::vector<int> firstFour(v.begin(), v.begin() + 4);

firstFour然后包含旋转向量中的前四个元素。如果您在循环中使用它并运行它v.size()多次,您将获得问题中的五个向量。

于 2010-07-08T04:27:48.797 回答
0

以上所有答案都需要改变一个容器。不这样做也可以解决这个问题,并且仍然使用 stl / boost 算法。如果下面的内容由于我没有测试过而不能完全编译,则表示歉意。

std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

for(int i = 0; i < 5; i ++)
{
    using boost::join;
    using boost::adaptors::sliced;
    using std::ostream_iterator;
    using std::cout;
    using boost::copy;

    copy
        ( join(v | sliced(i,4), v | sliced(0, (4 + i) % 5))
        , ostream_iterator<int>(cout, " ") 
        )
    }
    cout << std::endl;

}

boost::sliced 的文档位于

http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/adaptors/reference/sliced.html#range.reference.adaptors.reference.sliced.sliced_example

于 2010-07-08T05:53:32.860 回答
0

詹姆斯上面写的差不多:

vector <char> newv[5];

for(int i=0; i<5; i++)
{
    newv[i].insert(newv[i].begin(),v.begin(), v.begin()+4);
    std::rotate(v.begin(), v.begin()+1, v.end());
}

经过测试,它可以工作。

于 2010-07-08T04:47:59.163 回答
0

你能做类似的事情:

// vector = (a,b,c,d,e);

front = vector.front();
vector.pop_front();
vector.push_back(front);
// now you have (b,c,d,e,a);

重复任意次数。然而,在内存洗牌方面可能效率低下

于 2010-07-08T04:35:30.557 回答