using namespace std;
using namespace Msp;
-#include <msp/io/print.h>
-
namespace R2C2 {
Signal::Signal(Layout &l, const SignalType &t):
- layout(l),
+ Object(l),
type(t),
address(0),
track(0),
block(0),
entry(0),
train(0),
- check_train_direction(false),
check_allocated_blocks(false),
passing(false)
{
layout.remove_signal(*this);
}
+Signal *Signal::clone(Layout *to_layout) const
+{
+ Signal *sig = new Signal((to_layout ? *to_layout : layout), type);
+ sig->set_position(position);
+ sig->set_rotation(rotation);
+ return sig;
+}
+
void Signal::set_address(unsigned a)
{
address = a;
for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
if(!(*i)->get_type().is_turnout())
{
- TrackPoint n = (*i)->get_nearest_point(p);
- float d = distance(p, n.pos);
+ Snap sn;
+ sn.position = p;
+ sn.rotation = rotation;
+ (*i)->snap(sn, 1000, SNAP_SEGMENT);
+ float d = distance(p, sn.position);
if(d<dist || dist<0)
{
- position = n.pos;
- direction = n.dir;
+ position = sn.position;
+ rotation = sn.rotation;
track = *i;
dist = d;
}
unsigned n_endpoints = track->get_type().get_endpoints().size();
for(unsigned j=0; j<n_endpoints; ++j)
{
- float a = track->get_endpoint_direction(j)-direction;
+ float a = track->get_snap_node(j).rotation-rotation;
while(a<-M_PI/2)
a += M_PI*2;
while(a>M_PI*3/2)
}
}
-void Signal::set_direction(float d)
+void Signal::set_rotation(float r)
{
- float a = direction-d;
+ float a = rotation-r;
while(a>M_PI*3/2)
a -= M_PI*2;
while(a<-M_PI/2)
a += M_PI*2;
if(a>=M_PI/2)
{
- direction += M_PI;
- if(direction>M_PI*2)
- direction -= M_PI*2;
+ rotation += M_PI;
+ if(rotation>M_PI*2)
+ rotation -= M_PI*2;
}
normalize_location();
}
-void Signal::tick(const Time::TimeDelta &)
+unsigned Signal::get_n_snap_nodes() const
{
- if(check_train_direction)
- {
- int train_entry = train->get_entry_to_block(*block);
- if(train_entry>=0 && static_cast<unsigned>(train_entry)==entry)
- {
- IO::print("Train passing in the proper direction\n");
- if(train_conn)
- train_conn.disconnect();
- train_conn = train->signal_advanced.connect(sigc::mem_fun(this, &Signal::train_advanced));
- }
- else
- IO::print("Train passing in the wrong direction (entry=%d, train_entry=%d)\n", entry, train_entry);
- check_train_direction = false;
- check_allocated_blocks = true;
- }
+ return 1;
+}
+
+Snap Signal::get_snap_node(unsigned i) const
+{
+ if(i>=1)
+ throw out_of_range("Signal::get_snap_node");
+
+ Snap sn;
+ sn.position = position;
+ sn.rotation = rotation;
+ return sn;
+}
+SnapType Signal::get_default_snap_type_to(const Object &other) const
+{
+ if(dynamic_cast<const Track *>(&other))
+ return SNAP_SEGMENT;
+
+ return NO_SNAP;
+}
+
+bool Signal::collide_ray(const Vector &start, const Vector &ray) const
+{
+ // XXX Totally hardcoded stuff, should be replaced with a geometry system
+ Vector center = position;
+ center.x += sin(rotation)*0.035;
+ center.y -= cos(rotation)*0.035;
+ Vector d(center.x-start.x, center.y-start.y);
+ float x = (d.x*ray.x+d.y*ray.y)/(ray.x*ray.x+ray.y*ray.y);
+ Vector nearest(start.x+ray.x*x-center.x, start.y+ray.y*x-center.y, start.z+ray.z*x-center.z);
+ if(nearest.z<0|| nearest.z>0.12)
+ return false;
+ return nearest.x*nearest.x+nearest.y*nearest.y<0.0001;
+}
+
+void Signal::tick(const Time::TimeDelta &)
+{
if(check_allocated_blocks)
{
unsigned n_blocks = 0;
++n_blocks;
iter=iter.next();
}
- IO::print("%d sensor blocks allocated\n", n_blocks);
check_allocated_blocks = false;
const list<SignalType::Indication> &indications = type.get_indications();
break;
}
- IO::print("Setting signal %d to aspect %d\n", address, aspect);
layout.get_driver().set_signal(address, aspect);
}
}
{
if(t)
{
- train = t;
- passing = false;
- check_train_direction = true;
+ int train_entry = t->get_entry_to_block(*block);
+ if(train_entry>=0 && static_cast<unsigned>(train_entry)==entry)
+ {
+ if(train_conn)
+ train_conn.disconnect();
+ train = t;
+ passing = false;
+ train_conn = train->signal_advanced.connect(sigc::mem_fun(this, &Signal::train_advanced));
+ check_allocated_blocks = true;
+ }
}
else
{
void Signal::train_advanced(Block &b)
{
if(&b==block)
- {
- IO::print("Train is passing the signal now\n");
passing = true;
- }
else if(passing && b.get_sensor_id())
{
- IO::print("Train has passed the signal\n");
layout.get_driver().set_signal(address, type.get_indications().back().aspect);
reset();
}
train = 0;
if(train_conn)
train_conn.disconnect();
- check_train_direction = false;
check_allocated_blocks = false;
}
void Signal::save(list<DataFile::Statement> &st) const
{
st.push_back((DataFile::Statement("position"), position.x, position.y, position.z));
- st.push_back((DataFile::Statement("direction"), direction));
+ st.push_back((DataFile::Statement("rotation"), rotation));
if(address)
st.push_back((DataFile::Statement("address"), address));
}
Signal::Loader::Loader(Signal &s):
DataFile::ObjectLoader<Signal>(s)
{
- add("address", &Loader::address);
- add("direction", &Loader::direction);
- add("position", &Loader::position);
+ add("address", &Loader::address);
+ add("position", &Loader::position);
+ add("rotation", &Loader::rotation);
}
void Signal::Loader::address(unsigned a)
obj.set_address(a);
}
-void Signal::Loader::direction(float d)
+void Signal::Loader::position(float x, float y, float z)
{
- obj.set_direction(d);
+ obj.set_position(Vector(x, y, z));
}
-void Signal::Loader::position(float x, float y, float z)
+void Signal::Loader::rotation(float d)
{
- obj.set_position(Vector(x, y, z));
+ obj.set_rotation(d);
}
} // namespace R2C2