0

Foo* 型の std::list と、サイズが異なる Bar* 型の別の std::list があります。両方のタイプは、描画順序のためにリストを z 座標でソートできるポジショニング システムを実装します (実際には x、y、z 値を持つ Point で、z 値よりも小さい Predicate 関数でソートされます)。

上記以外は全く違います。リストを組み合わせて、独自のタイプだけでなく、すべての z 値を互いに比較できるようにする方法はありますか?

たとえば、現在、すべての Foo がソートされているか、すべての Bar がソートされています。次に、すべての Foo が描画されるか、すべての Bar が描画されます。これにより、Bar の z が Foo よりも低い場合でも、上に描画されます。明らかに意図した結果ではありません。

これを入力しているときにひらめきましたが、並列処理は機能するのでしょうか? 各リストを個別に並べ替えますが、Foo、Bar、Foo、Bar などを交互に描画します。それとも同じ問題が発生しますか? z値に関係なく、他のものの上に描画するものがありますか?

ありがとう。

4

1 に答える 1

5

位置を含むベースから両方のタイプを継承させてみてくださいvirtual Draw()

struct Base
{
    Point pos;

    virtual ~Base() {}
    virtual void Draw() = 0;
};

struct Foo : base {};
struct Bar : base {};

std::list<Base*> list;

//...

list.sort([](Base *left, Base *right)
{
    return left->pos.z < right->pos.z;
});

for(auto iter = list.begin(), end = list.end(); iter != end; ++iter)
{
    (*iter)->Draw();
}

Fooリストを別々に保ちたい場合、 と の描画を交互に行うと、 の 2 つが の前に来るBarとうまくいきません。FooBar

しかし、あなたは正しい方向に考えています。個別に並べ替えてから、描画中に 2 つのリストを結合できます。

foo_list.sort();
bar_list.sort();

auto fiter = foo_list.begin(), fend = foo_list.end();
auto biter = bar_list.begin(), bend = bar_list.end();

while(fiter != fend && biter != bend)
{
    // draw whichever Foo or Bar is closest, and increment only that iterator.

    if((*fiter)->z_pos < (*biter)->z_pos)
    {
        (*fiter)->Draw();
        ++fiter;
    }
    else
    {
        (*biter)->Draw();
        ++biter;
    }
}

// reached the end of one of the lists. flush out whatever's left of the other.

for(; fiter != fend; ++fiter)
{
    (*fiter)->draw();
}

for(; biter != bend; ++biter)
{
    (*biter)->draw();
}

単一のリストのみを保持し、2 つの完全に別個のタイプを保持する場合は、バリアントを使用することもできます。

struct visitor
{
    float operator()(Foo* f) const { return f->z_position; }
    float operator()(Bar* b) const { return b->z_position; }
};

std::list<boost::variant<Foo*, Bar*>> list;

//...

list.sort([](boost::variant<Foo*, Bar*> const &left, boost::variant<Foo*, Bar*> const &right)
{
    return apply_visitor(visitor(), left) < apply_visitor(visitor(), right);
});

for(auto iter = list.begin(), end = list.end(); iter != end; ++iter)
{
    (*iter)->Draw();
}
于 2011-07-05T03:58:14.237 に答える