X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftrack.cpp;h=b679af783867f72746793f205179f004a9e02baa;hb=f950f5a77714a155e57c868101911e181a617818;hp=cf496c41ddae554b98da55d62e67bc2b3e0179b4;hpb=d15ac13f2e170f155b4bbd124df48400c339b644;p=r2c2.git
diff --git a/source/libr2c2/track.cpp b/source/libr2c2/track.cpp
index cf496c4..b679af7 100644
--- a/source/libr2c2/track.cpp
+++ b/source/libr2c2/track.cpp
@@ -12,16 +12,16 @@ using namespace Msp;
namespace R2C2 {
Track::Track(Layout &l, const TrackType &t):
- layout(l),
+ Object(l),
type(t),
block(0),
- rot(0),
slope(0),
flex(false),
turnout_id(0),
sensor_id(0),
links(type.get_endpoints().size()),
- active_path(0)
+ active_path(0),
+ path_changing(false)
{
if(type.is_turnout())
turnout_id = layout.allocate_turnout_id();
@@ -40,12 +40,20 @@ Track::~Track()
layout.remove_track(*this);
}
+Track *Track::clone(Layout *to_layout) const
+{
+ Track *track = new Track((to_layout ? *to_layout : layout), type);
+ track->set_position(position);
+ track->set_rotation(rotation);
+ return track;
+}
+
void Track::set_block(Block *b)
{
if(b && !b->has_track(*this))
- throw InvalidParameterValue("Track is not in the Block");
+ throw logic_error("track not in block");
if(!b && block && block->has_track(*this))
- throw InvalidState("Track is still in a Block");
+ throw logic_error("track still in block");
block = b;
}
@@ -53,23 +61,23 @@ void Track::set_block(Block *b)
Block &Track::get_block() const
{
if(!block)
- throw InvalidState("No Block");
+ throw logic_error("!block");
return *block;
}
void Track::set_position(const Vector &p)
{
- pos = p;
+ position = p;
}
void Track::set_rotation(float r)
{
- rot = r;
- while(rot<0)
- rot += M_PI*2;
- while(rot>M_PI*2)
- rot -= M_PI*2;
+ rotation = r;
+ while(rotation<0)
+ rotation += M_PI*2;
+ while(rotation>M_PI*2)
+ rotation -= M_PI*2;
}
void Track::set_slope(float s)
@@ -94,8 +102,8 @@ void Track::check_slope()
{
Vector epp0 = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
Vector epp1 = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
- pos.z = epp0.z;
- slope = epp1.z-pos.z;
+ position.z = epp0.z;
+ slope = epp1.z-position.z;
}
else
{
@@ -103,12 +111,12 @@ void Track::check_slope()
if(links[0])
{
Vector epp = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
- pos.z = epp.z;
+ position.z = epp.z;
}
else if(links[1])
{
Vector epp = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
- pos.z = epp.z;
+ position.z = epp.z;
}
}
}
@@ -116,7 +124,7 @@ void Track::check_slope()
void Track::set_turnout_id(unsigned i)
{
if(!type.is_turnout())
- throw InvalidState("Not a turnout");
+ throw logic_error("not a turnout");
turnout_id = i;
layout.create_blocks(*this);
@@ -128,7 +136,7 @@ void Track::set_turnout_id(unsigned i)
void Track::set_sensor_id(unsigned i)
{
if(type.is_turnout())
- throw InvalidState("Can't set sensor on a turnout");
+ throw logic_error("is a turnout");
sensor_id = i;
layout.create_blocks(*this);
@@ -139,10 +147,11 @@ void Track::set_sensor_id(unsigned i)
void Track::set_active_path(unsigned p)
{
if(!turnout_id)
- throw InvalidState("Not a turnout");
+ throw logic_error("not a turnout");
if(!(type.get_paths()&(1<
&eps = type.get_endpoints();
if(epi>=eps.size())
- throw InvalidParameterValue("TrackType::Endpoint index out of range");
+ throw out_of_range("Track::get_endpoint_position");
const TrackType::Endpoint &ep = eps[epi];
- float c = cos(rot);
- float s = sin(rot);
+ float c = cos(rotation);
+ float s = sin(rotation);
- Vector p(pos.x+c*ep.pos.x-s*ep.pos.y, pos.y+s*ep.pos.x+c*ep.pos.y, pos.z);
+ Vector p(position.x+c*ep.pos.x-s*ep.pos.y, position.y+s*ep.pos.x+c*ep.pos.y, position.z);
if(eps.size()==2 && epi==1)
p.z += slope;
return p;
@@ -176,11 +185,11 @@ float Track::get_endpoint_direction(unsigned epi) const
{
const vector &eps = type.get_endpoints();
if(epi>=eps.size())
- throw InvalidParameterValue("TrackType::Endpoint index out of range");
+ throw out_of_range("Track::get_endpoint_direction");
const TrackType::Endpoint &ep = eps[epi];
- return rot+ep.dir;
+ return rotation+ep.dir;
}
bool Track::snap_to(Track &other, bool link, float limit)
@@ -213,9 +222,9 @@ bool Track::snap_to(Track &other, bool link, float limit)
{
if(!link || (!flex && !other.get_flex()))
{
- set_rotation(other.rot+other_eps[j].dir-eps[i].dir+M_PI);
- Vector p(epp2.x-(eps[i].pos.x*cos(rot)-eps[i].pos.y*sin(rot)),
- epp2.y-(eps[i].pos.y*cos(rot)+eps[i].pos.x*sin(rot)),
+ set_rotation(other.rotation+other_eps[j].dir-eps[i].dir+M_PI);
+ Vector p(epp2.x-(eps[i].pos.x*cos(rotation)-eps[i].pos.y*sin(rotation)),
+ epp2.y-(eps[i].pos.y*cos(rotation)+eps[i].pos.x*sin(rotation)),
epp2.z);
if(eps.size()==2 && i==1)
p.z -= slope;
@@ -254,7 +263,7 @@ bool Track::snap(Vector &pt, float &d) const
if(dx*dx+dy*dy<1e-4)
{
pt = epp;
- d = rot+eps[i].dir;
+ d = rotation+eps[i].dir;
return true;
}
}
@@ -288,8 +297,8 @@ void Track::break_links()
Track *Track::get_link(unsigned i) const
{
- if(i>links.size())
- throw InvalidParameterValue("Link index out of range");
+ if(i>=links.size())
+ throw out_of_range("Track::get_link");
return links[i];
}
@@ -297,11 +306,11 @@ Track *Track::get_link(unsigned i) const
TrackPoint Track::get_point(unsigned epi, unsigned path, float d) const
{
TrackPoint p = type.get_point(epi, path, d);
- float c = cos(rot);
- float s = sin(rot);
+ float c = cos(rotation);
+ float s = sin(rotation);
- p.pos = Vector(pos.x+c*p.pos.x-s*p.pos.y, pos.y+s*p.pos.x+c*p.pos.y, pos.z);
- p.dir += rot;
+ p.pos = Vector(position.x+c*p.pos.x-s*p.pos.y, position.y+s*p.pos.x+c*p.pos.y, position.z);
+ p.dir += rotation;
if(type.get_endpoints().size()==2)
{
float len = type.get_path_length(path);
@@ -326,11 +335,24 @@ TrackPoint Track::get_point(unsigned epi, float d) const
return get_point(epi, active_path, d);
}
-bool Track::collide_ray(const Vector &start, const Vector &ray)
+TrackPoint Track::get_nearest_point(const Vector &p) const
{
- Vector local_start(start.x-pos.x, start.y-pos.y, start.z-pos.z);
- float c = cos(rot);
- float s = sin(rot);
+ Vector local(p.x-position.x, p.y-position.y, p.z-position.z);
+ float c = cos(rotation);
+ float s = sin(rotation);
+ local = Vector(c*local.x+s*local.y, c*local.y-s*local.x, local.z);
+
+ TrackPoint tp = type.get_nearest_point(local);
+ tp.pos = Vector(position.x+tp.pos.x*c-tp.pos.y*s, position.y+tp.pos.y*c+tp.pos.x*s, position.z+tp.pos.z);
+ tp.dir += rotation;
+ return tp;
+}
+
+bool Track::collide_ray(const Vector &start, const Vector &ray) const
+{
+ Vector local_start(start.x-position.x, start.y-position.y, start.z-position.z);
+ float c = cos(rotation);
+ float s = sin(rotation);
local_start = Vector(c*local_start.x+s*local_start.y, c*local_start.y-s*local_start.x, local_start.z);
Vector local_ray(c*ray.x+s*ray.y, c*ray.y-s*ray.x, ray.z);
@@ -341,8 +363,8 @@ bool Track::collide_ray(const Vector &start, const Vector &ray)
void Track::save(list &st) const
{
- st.push_back((DataFile::Statement("position"), pos.x, pos.y, pos.z));
- st.push_back((DataFile::Statement("rotation"), rot));
+ st.push_back((DataFile::Statement("position"), position.x, position.y, position.z));
+ st.push_back((DataFile::Statement("rotation"), rotation));
st.push_back((DataFile::Statement("slope"), slope));
if(turnout_id)
st.push_back((DataFile::Statement("turnout_id"), turnout_id));
@@ -360,16 +382,17 @@ void Track::turnout_event(unsigned addr, unsigned state)
if(addr==turnout_id)
{
active_path = state;
+ path_changing = false;
signal_path_changed.emit(active_path);
}
}
Track::Loader::Loader(Track &t):
- DataFile::BasicLoader