RX - как использовать это быстрым способом?
Я пытаюсь понять, как структурировать мою программу, чтобы использовать RX в быстром вопросе.
Мое приложение имеет вектор объектов в трехмерном мире. каждый объект занимал коробку и имел поток "попадания", который представлял над ним курсор мыши.
Я подумал о двух вариантах структуры:
Опция 1
struct object_t
{
string name_;
box bounding_box_;
observable<bool> hit_;
};
struct scene_t
{
scene_t(observable<point> mouse) : hit_(hit(mouse))
{
add({"background", {/* ... */}, {}};
}
object_t& add(object_t o)
{
int object_index = objects_.size();
o.hit_ = hit_
.map([=](int index){ return index == object_index; })
.distinct_until_changed();
objects_.push_back(o);
return objects_.back();
}
//! given a stream of mouse points,
//! calculate on which object index(in objects_) the mouse is hover over.
//! 0 if its over the background.
observable<int> hit(observable<point> mouse);
using objects_t = std::vector<object_t>;
objects_t objects_;
observable<int> hit_
};
Вариант 2
struct object_t
{
string name_;
box bounding_box_;
void signal_hit(boot is_hit) { hit_.get_observer().on_next(is_hit); }
observable<bool> hit() const { return hit_.get_observable(); }
private:
subject<bool> hit_;
};
struct scene_t
{
scene_t(observable<point> mouse) : hit_(hit(mouse))
{
add({"background", {/* ... */}, {}};
hit_
.start_with(0)
.buffer(2, 1) // take two hits together, the current and the previos
.subscribe([this](std::vector<int> indices) {
objects_[indices[1]].signal_hit(false); // we leave this one
objects_[indices[0]].signal_hit(true); // and entering this one
});
}
object_t& add(object_t o)
{
objects_.push_back(o);
return objects_.back();
}
//! ... as above
};
Теперь вопрос состоит в том, как связать результат функции попадания с потоком object_t::hit.
Я вижу два пути:
- Вариант 1 является полностью функциональным, но очень неэффективным, поскольку для каждой точки мыши все объекты потока должны будут рассчитать их значение.
- Вариант 2. не полностью функционален, так как я использую subject для принудительного переноса значений в нужный поток. но очень производительный, так как только правильный (два) объект (ы) попадания потока попадают в огонь.
Примечание. Реализация осуществляется в rxcpp, но она является общей для любого языка, в котором есть RX, или общей парадигмы FRP, поэтому я отметил тег rxjs\rx.net\frp и т. Д.
заранее спасибо:-)
1 ответ
Если есть один наблюдаемый источник и N подписчиков, то каждый раз, когда источник излучает, должно быть как минимум N вычислений. Там нет никакого способа обойти то, что я могу придумать.