2

私は(x、y、zおよび他のいくつかの非ポインター型)std::vectorを保持するを持っています。Point struct

これらの点は、bスプライン曲線を描くための制御点です。曲線を描くのに問題はありませんが、曲線を閉じる必要がある場合に問題が発生します。これには、特定の順序でコントロールポイント(コンテナ内にすでに存在する)を追加する必要があります。

たとえば、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

より多くのスペースを使用する場合は、最初にlpointをそれ自体に追加してから、必要に応じてsubseqを取得しながらイテレータをインクリメントできます。これは、新しいベクトルを作成する代わりに、2倍のベクトルのイテレータを操作できるため、「5つの異なるベクトルまたは1つの長いベクトル」にも対応します。

ごめんなさい、私はしばらく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ループは、ループ変数iの代わりにbeginとend(またはdernier)の観点から、おそらくより適切に記述できます。

追加には、おそらく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次に、回転したベクトルの最初の4つの要素が含まれます。これをループで使用してv.size()何度も実行すると、質問にある5つのベクトルが得られます。

于 2010-07-08T04:27:48.797 に答える
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 に答える
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

上記のすべての答えは、コンテナを変更する必要があります。そうせずにこれを解決し、それでも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 に答える