program "shoppinglist"
{
source "source/shoppinglist";
- require "mspparser";
+ require "mspdatafile";
};
library "marklin"
{
source "source/libmarklin";
- require "mspparser";
+ require "mspdatafile";
};
library "marklin3d"
#include <msp/gl/rendermode.h>
#include <msp/gl/select.h>
#include <msp/gl/texture.h>
-#include <msp/parser/parser.h>
+#include <msp/datafile/parser.h>
#include "layout.h"
using namespace std;
return track;
}
-void Layout3D::track_added(Track *t)
+void Layout3D::track_added(Track &t)
{
- tracks.push_back(new Track3D(*t, quality));
+ tracks.push_back(new Track3D(t, quality));
}
-void Layout3D::track_removed(Track *t)
+void Layout3D::track_removed(Track &t)
{
for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
- if(&(*i)->get_track()==t)
+ if(&(*i)->get_track()==&t)
{
delete *i;
tracks.erase(i);
Track3DSeq tracks;
unsigned quality;
- void track_added(Track *);
- void track_removed(Track *);
+ void track_added(Track &);
+ void track_removed(Track &);
};
} // namespace Marklin
#include <cmath>
#include <GL/gl.h>
#include <msp/gl/misc.h>
+#include "libmarklin/tracktype.h"
#include "track.h"
using namespace std;
{
prepare_render();
- const Point &pos=track.get_position();
- const Track::EndpointSeq &endpoints=track.get_endpoints();
- for(Track::EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ const vector<Endpoint> &endpoints=track.get_type().get_endpoints();
+ for(unsigned i=0; i<endpoints.size(); ++i)
{
- GL::set(GL_CULL_FACE, i->link);
- if(i->link)
+ const Endpoint &ep=endpoints[i];
+ GL::set(GL_CULL_FACE, track.get_link(i));
+ if(track.get_link(i))
glColor4f(0.5, 0, 1, 0.5);
else
glColor4f(1, 0, 0.5, 0.5);
- float c=cos(i->rot);
- float s=sin(i->rot);
+ float c=cos(ep.dir);
+ float s=sin(ep.dir);
glBegin(GL_QUADS);
- glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, 0);
- glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, 0);
- glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, pos.z+i->pos.z+0.02);
- glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, pos.z+i->pos.z+0.02);
+ glVertex3f(ep.x-s*0.025, ep.y+c*0.025, 0);
+ glVertex3f(ep.x+s*0.025, ep.y-c*0.025, 0);
+ glVertex3f(ep.x+s*0.025, ep.y-c*0.025, 0.02);
+ glVertex3f(ep.x-s*0.025, ep.y+c*0.025, 0.02);
glEnd();
}
base_seq.clear();
rail_seq.clear();
route_seq.clear();
- route_seq.resize(track.get_n_routes());
+ route_seq.resize(track.get_type().get_n_routes());
- const Track::PartSeq &parts=track.get_parts();
+ const vector<TrackPart> &parts=track.get_type().get_parts();
unsigned index=0;
- for(Track::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
build_part(*i, *builder, index);
}
-void Track3D::build_part(const Track::Part &part, GL::VertexArrayBuilder &va_builder, unsigned &base_index)
+void Track3D::build_part(const TrackPart &part, GL::VertexArrayBuilder &va_builder, unsigned &base_index)
{
static vector<Point> profile;
if(profile.empty())
#include <list>
#include <msp/gl/vertexarray.h>
+#include <msp/gl/vertexarraybuilder.h>
#include "libmarklin/track.h"
+#include "libmarklin/trackpart.h"
#include "misc.h"
namespace Marklin {
void prepare_render();
void build_object();
- void build_part(const Track::Part &, Msp::GL::VertexArrayBuilder &, unsigned &);
+ void build_part(const TrackPart &, Msp::GL::VertexArrayBuilder &, unsigned &);
};
typedef std::list<Track3D *> Track3DSeq;
#include <SDL.h>
#include <msp/gl/rendermode.h>
#include <msp/gl/select.h>
+#include <msp/gl/texture2d.h>
#include <msp/strings/codec.h>
#include <msp/strings/lexicalcast.h>
#include <msp/strings/utf8.h>
#include <msp/strings/utils.h>
#include <msp/time/units.h>
#include <msp/time/utils.h>
+#include "libmarklin/tracktype.h"
#include "designer.h"
#include "input.h"
#include "manipulator.h"
cat_layout=new Layout(catalogue);
cat_layout_3d=new Layout3D(*cat_layout);
- const Catalogue::TrackMap &ctracks=catalogue.get_tracks();
+ const map<unsigned, TrackType *> &ctracks=catalogue.get_tracks();
unsigned n=0;
- for(Catalogue::TrackMap::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i, ++n)
+ for(map<unsigned, TrackType *>::const_iterator i=ctracks.begin(); i!=ctracks.end(); ++i, ++n)
{
- Track *track=i->second->copy();
+ Track *track=new Track(*i->second);
track->set_position(Point((n%11)*0.1-0.5, 0.2-n/11*0.3, 0));
track->set_rotation(M_PI/2);
- cat_layout->add_track(track);
+ cat_layout->add_track(*track);
}
manipulator=new Manipulator(*this);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
+ GL::Texture2D *font_tex=new GL::Texture2D;
+ font_tex->set_min_filter(GL::LINEAR);
+ font_tex->load_image("dejavu-20.png");
font=new GL::Font();
- Parser::load(*font, "dejavu-20.font");
+ font->set_texture(*font_tex);
+ DataFile::load(*font, "dejavu-20.font");
mode=SELECT;
Application::main();
delete font;
+ delete font_tex;
delete input;
SDL_Quit();
if(t3d)
{
const Track &track=t3d->get_track();
+ const TrackType &ttype=track.get_type();
ostringstream ss;
ss.precision(2);
- ss<<track.get_article_number()<<' '<<track.get_description();
+ ss<<ttype.get_article_number()<<' '<<ttype.get_description();
if(mode!=CATALOGUE)
- ss<<" (slope "<<track.get_slope()/track.get_length()*100<<"%)";
+ ss<<" (slope "<<track.get_slope()/ttype.get_total_length()*100<<"%)";
if(track.get_turnout_id())
ss<<" (turnout "<<track.get_turnout_id()<<')';
else if(track.get_sensor_id())
ss<<" (sensor "<<track.get_sensor_id()<<')';
- tooltip=decode<Utf8>(ss.str());
+ tooltip=ss.str();
move_tooltip(pointer_x, pointer_y);
}
else
- tooltip=L"";
+ tooltip="";
tooltip_timeout=Time::TimeStamp();
}
selection->select_more();
else if(key==SDLK_l && (mod&KMOD_SHIFT))
{
- const TrackSeq &tracks=layout->get_tracks();
+ const set<Track *> &tracks=layout->get_tracks();
float len=0;
- for(TrackSeq::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
- len+=(*i)->get_total_length();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ len+=(*i)->get_type().get_total_length();
cout<<"Total length: "<<len<<"m\n";
}
else if(key==SDLK_l)
}
else if(key==SDLK_x)
{
- Selection::TrackSet tracks=selection->get_tracks();
+ set<Track *> tracks=selection->get_tracks();
selection->clear();
- for(Selection::TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- layout->remove_track(*i);
+ layout->remove_track(**i);
delete *i;
}
}
else if(key==SDLK_f && (mod&KMOD_SHIFT))
{
- const Selection::TrackSet &tracks=selection->get_tracks();
- const TrackSeq <racks=layout->get_tracks();
- for(Selection::TrackSet::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ const set<Track *> &tracks=selection->get_tracks();
+ const set<Track *> <racks=layout->get_tracks();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
(*i)->set_flex(!(*i)->get_flex());
(*i)->break_links();
- for(TrackSeq::const_iterator j=ltracks.begin(); j!=ltracks.end(); ++j)
+ for(set<Track *>::const_iterator j=ltracks.begin(); j!=ltracks.end(); ++j)
if(*j!=*i)
(*i)->snap_to(**j, true);
else if(key==SDLK_t)
{
Track *track=selection->get_track();
- if(selection->size()==1 && track->get_n_routes()>1)
+ if(selection->size()==1 && track->get_type().get_n_routes()>1)
{
ostringstream ss;
ss<<track->get_turnout_id();
else if(key==SDLK_s)
{
Track *track=selection->get_track();
- if(selection->size()==1 && track->get_n_routes()==1)
+ if(selection->size()==1 && track->get_type().get_n_routes()==1)
{
ostringstream ss;
ss<<track->get_sensor_id();
{
Track *track=ctrack->get_track().copy();
track->set_position(Point(gx, gy, 0));
- layout->add_track(track);
+ layout->add_track(*track);
selection->clear();
selection->add_track(track);
void Designer::manipulation_status(const string &status)
{
- tooltip=decode<Utf8>(status);
+ tooltip=status;
}
void Designer::manipulation_done(bool)
ostringstream ss;
ss.precision(3);
ss<<"Par "<<pard<<"mm - Perp "<<perpd<<"mm - Total "<<d<<"mm - Angle "<<adiff<<"°";
- tooltip=decode<Utf8>(ss.str());
+ tooltip=ss.str();
}
void Designer::measure_done()
int pointer_y;
int tooltip_x;
int tooltip_y;
- std::wstring tooltip;
+ std::string tooltip;
Msp::Time::TimeStamp tooltip_timeout;
Msp::Time::TimeStamp last_tick;
#include <cmath>
#include <GL/gl.h>
#include "3d/layout.h"
+#include "libmarklin/tracktype.h"
#include "designer.h"
#include "manipulator.h"
#include "selection.h"
if(mode)
cancel();
- TrackSeq new_tracks;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ list<Track *> new_tracks;
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
Track *track=i->track->copy();
- designer.get_layout()->add_track(track);
+ designer.get_layout()->add_track(*track);
new_tracks.push_back(track);
}
selection->clear();
- for(TrackSeq::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
+ for(list<Track *>::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
{
selection->add_track(*i);
- for(TrackSeq::iterator j=i; j!=new_tracks.end(); ++j)
+ for(list<Track *>::iterator j=i; j!=new_tracks.end(); ++j)
if(j!=i)
(*i)->snap_to(**j, true);
}
if(tracks.empty()) return;
float z=0;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
z+=i->track->get_position().z+i->track->get_slope()/2;
z/=tracks.size();
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
Point p=i->track->get_position();
i->track->set_position(Point(p.x, p.y, z));
i->track->set_slope(0);
}
- for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
(*i)->check_slope();
update_wrap();
if(neighbors.size()!=2)
return;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
- if(i->track->get_endpoints().size()!=2)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ if(i->track->get_type().get_endpoints().size()!=2)
return;
- TrackSeq tracks2;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ list<Track *> tracks2;
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
tracks2.push_back(i->track);
float total_len=0;
- TrackOrderSeq order;
- Track *cur=neighbors.front();
+ list<TrackOrder> order;
+ Track *cur=*neighbors.begin();
while(tracks2.size())
{
bool rev=false;
- for(TrackSeq::iterator i=tracks2.begin(); i!=tracks2.end(); ++i)
+ for(list<Track *>::iterator i=tracks2.begin(); i!=tracks2.end(); ++i)
{
- const Track::EndpointSeq &epl=(*i)->get_endpoints();
- if(epl.front().link==cur)
+ const vector<Track *> &links=(*i)->get_links();
+ if(links[0]==cur)
{
cur=*i;
tracks2.erase(i);
break;
}
- else if(epl.back().link==cur)
+ else if(links[1]==cur)
{
cur=*i;
rev=true;
}
}
order.push_back(TrackOrder(cur, rev));
- total_len+=cur->get_length();
+ total_len+=cur->get_type().get_total_length();
}
- const Track::Endpoint *ep=neighbors.front()->get_endpoint_by_link(order.front().track);
- float start_z=neighbors.front()->get_position().z+ep->pos.z;
- ep=neighbors.back()->get_endpoint_by_link(order.back().track);
- float end_z=neighbors.back()->get_position().z+ep->pos.z;
+ set<Track *>::iterator nb=neighbors.begin();
+ int epi=(*nb)->get_endpoint_by_link(*order.front().track);
+ float start_z=(*nb)->get_endpoint_position(epi).z;
+ ++nb;
+ epi=(*nb)->get_endpoint_by_link(*order.back().track);
+ float end_z=(*nb)->get_endpoint_position(epi).z;
if(smooth)
{
{
cur_slope+=0.025;
- float dz=order.front().track->get_length()*dir*cur_slope;
+ float dz=order.front().track->get_type().get_total_length()*dir*cur_slope;
set_slope(order.front(), start_z, dz);
start_z+=dz;
- total_len-=order.front().track->get_length();
+ total_len-=order.front().track->get_type().get_total_length();
order.erase(order.begin());
- dz=order.back().track->get_length()*dir*cur_slope;
+ dz=order.back().track->get_type().get_total_length()*dir*cur_slope;
set_slope(order.back(), end_z-dz, dz);
end_z-=dz;
- total_len-=order.back().track->get_length();
+ total_len-=order.back().track->get_type().get_total_length();
order.erase(--order.end());
}
}
float cur_z=start_z;
- for(TrackOrderSeq::iterator i=order.begin(); i!=order.end(); ++i)
+ for(list<TrackOrder>::iterator i=order.begin(); i!=order.end(); ++i)
{
- float dz=i->track->get_length()*(end_z-start_z)/total_len;
+ float dz=i->track->get_type().get_total_length()*(end_z-start_z)/total_len;
set_slope(*i, cur_z, dz);
cur_z+=dz;
}
- for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
(*i)->check_slope();
update_wrap();
mode=NONE;
wrap_pos=center;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
i->track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z));
i->track->set_rotation(i->rot);
}
- for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
(*i)->check_slope();
angle=0;
update_wrap();
//snapped=0;
- for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
- for(MTrackSeq::iterator j=tracks.begin(); j!=tracks.end(); ++j)
+ for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(vector<MTrack>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
j->track->break_link(**i);
- const TrackSeq <racks=designer.get_layout()->get_tracks();
- for(TrackSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
+ const set<Track *> <racks=designer.get_layout()->get_tracks();
+ for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
{
bool ok=true;
- for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
+ for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
ok=(j->track!=*i);
if(!ok) continue;
- for(MTrackSeq::iterator j=tracks.begin(); j!=tracks.end(); ++j)
+ for(vector<MTrack>::iterator j=tracks.begin(); j!=tracks.end(); ++j)
j->track->snap_to(**i, true);
}
Point delta(gpointer.x-move_origin.x, gpointer.y-move_origin.y, 0);
wrap_pos=Point(center.x+delta.x, center.y+delta.y, center.z);
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
i->track->set_position(Point(wrap_pos.x+i->pos.x, wrap_pos.y+i->pos.y, wrap_pos.z+i->pos.z));
i->track->set_rotation(i->rot);
}
- const TrackSeq <racks=designer.get_layout()->get_tracks();
+ const set<Track *> <racks=designer.get_layout()->get_tracks();
MTrack *snapped=0;
- for(TrackSeq::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i)
+ for(set<Track *>::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i)
{
bool ok=true;
- for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
+ for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j)
ok=(j->track!=*i);
if(!ok) continue;
- for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && !snapped); ++j)
+ for(vector<MTrack>::iterator j=tracks.begin(); (j!=tracks.end() && !snapped); ++j)
if(j->track->snap_to(**i, false))
snapped=&*j;
}
float c=cos(da);
float s=sin(da);
const Point &sp=snapped->track->get_position();
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
if(&*i==snapped)
continue;
rot_origin=a;
wrap_rot=angle;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
float c=cos(angle);
float s=sin(angle);
signal_status.emit(ss.str());
wrap_pos.z=center.z+dz;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
i->track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z+dz));
- for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
+ for(set<Track *>::iterator i=neighbors.begin(); i!=neighbors.end(); ++i)
(*i)->check_slope();
}
}
tracks.clear();
if(selection)
{
- const Selection::TrackSet &stracks=selection->get_tracks();
+ const set<Track *> &stracks=selection->get_tracks();
tracks.insert(tracks.end(), stracks.begin(), stracks.end());
}
wrap.clear();
float min_x=0,max_x=0;
float min_y=0,max_y=0;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
Track3D *t3d=designer.get_layout_3d()->get_track(i->track);
center=Point((min_x+max_x)/2, (min_y+max_y)/2, 0);
wrap_pos=center;
wrap_rot=0;
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
const Point &tp=i->track->get_position();
i->pos=Point(tp.x-center.x, tp.y-center.y, tp.z);
void Manipulator::update_neighbors()
{
neighbors.clear();
- for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(vector<MTrack>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- const Track::EndpointSeq &epl=i->track->get_endpoints();
- for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j)
+ const vector<Track *> &links=i->track->get_links();
+ for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
{
- if(!j->link)
+ if(!*j)
continue;
- if(find(neighbors.begin(), neighbors.end(), j->link)!=neighbors.end())
+ if(neighbors.count(*j))
continue;
bool ok=true;
- for(MTrackSeq::iterator k=tracks.begin(); (k!=tracks.end() && ok); ++k)
- ok=(k->track!=j->link);
+ for(vector<MTrack>::iterator k=tracks.begin(); (k!=tracks.end() && ok); ++k)
+ ok=(k->track!=*j);
if(ok)
- neighbors.push_back(j->link);
+ neighbors.insert(*j);
}
}
}
MTrack(Marklin::Track *);
};
- typedef std::list<MTrack> MTrackSeq;
struct TrackOrder
{
TrackOrder(Marklin::Track *t, bool r): track(t), rev(r) { }
};
- typedef std::list<TrackOrder> TrackOrderSeq;
struct TrackWrap
{
Designer &designer;
Selection *selection;
- MTrackSeq tracks;
+ std::vector<MTrack> tracks;
Marklin::Point center;
std::list<TrackWrap> wrap;
float angle;
float rot_origin;
int elev_origin;
- Marklin::TrackSeq neighbors;
+ std::set<Marklin::Track *> neighbors;
sigc::connection selection_changed_conn;
void selection_changed();
#include "3d/layout.h"
#include "measure.h"
+using namespace std;
using namespace Marklin;
using namespace Msp;
void Measure::snap_to_tracks(Point &pt, float &dir)
{
- const TrackSeq <racks=designer.get_layout()->get_tracks();
- for(TrackSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
+ const set<Track *> <racks=designer.get_layout()->get_tracks();
+ for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
if((*i)->snap(pt, dir))
return;
}
void Selection::select_more()
{
- TrackSet new_tracks;
- for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ set<Track *> new_tracks;
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- const Track::EndpointSeq &epl=(*i)->get_endpoints();
- for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j)
- if(j->link)
- new_tracks.insert(j->link);
+ const vector<Track *> &links=(*i)->get_links();
+ for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
+ if(*j)
+ new_tracks.insert(*j);
}
bool changed=false;
- for(TrackSet::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
+ for(set<Track *>::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i)
if(tracks.insert(*i).second)
changed=true;
void Selection::select_linked()
{
bool changed=false;
- TrackSeq queue(tracks.begin(), tracks.end());
+ list<Track *> queue(tracks.begin(), tracks.end());
while(!queue.empty())
{
Track *track=queue.front();
queue.erase(queue.begin());
- const Track::EndpointSeq &epl=track->get_endpoints();
- for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j)
- if(j->link && tracks.insert(j->link).second)
+ const vector<Track *> &links=track->get_links();
+ for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
+ if(*j && tracks.insert(*j).second)
{
- queue.push_back(j->link);
+ queue.push_back(*j);
changed=true;
}
}
- for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- const Track::EndpointSeq &epl=(*i)->get_endpoints();
- for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j)
- if(j->link && tracks.insert(j->link).second)
+ const vector<Track *> &links=(*i)->get_links();
+ for(vector<Track *>::const_iterator j=links.begin(); j!=links.end(); ++j)
+ if(*j && tracks.insert(*j).second)
changed=true;
}
class Selection
{
public:
- typedef std::set<Marklin::Track *> TrackSet;
-
sigc::signal<void> signal_changed;
- const TrackSet &get_tracks() const { return tracks; }
+ const std::set<Marklin::Track *> &get_tracks() const { return tracks; }
Marklin::Track *get_track() const;
unsigned size() const { return tracks.size(); }
void clear();
void select_more();
void select_linked();
private:
- TrackSet tracks;
+ std::set<Marklin::Track *> tracks;
};
#endif
#include <limits>
#include <SDL.h>
#include <GL/gl.h>
-#include <msp/core/error.h>
+#include <msp/core/except.h>
#include <msp/core/getopt.h>
#include <msp/gl/matrix.h>
#include <msp/gl/transform.h>
#include "engineer.h"
#include "mainpanel.h"
#include "trainpanel.h"
+#include "trainproperties.h"
using namespace std;
using namespace Marklin;
placing_train(0),
placing_block(0),
placing_entry(0),
- simulate(false)
+ simulate(false),
+ train_prop(0),
+ train_prop_stale(false)
{
string res;
bool debug=false;
catalogue.load("tracks.dat");
- const list<string> &args=getopt.get_args();
+ const vector<string> &args=getopt.get_args();
if(args.empty())
throw UsageError("No layout given");
layout.load(args.front());
- control.signal_sensor_event.connect(sigc::mem_fun(this, &Engineer::sensor_event));
-
trfc_mgr=new TrafficManager(control, layout);
trfc_mgr->signal_block_reserved.connect(sigc::mem_fun(this, &Engineer::block_reserved));
+ const map<unsigned, Sensor *> &sensors=control.get_sensors();
+ for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ i->second->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Engineer::sensor_event), i->second));
+
view_all();
}
delete trfc_mgr;
}
-void Engineer::add_train(unsigned addr)
+Train *Engineer::add_train(unsigned addr)
{
- if(control.get_locomotive(addr))
- return;
+ /*if(control.get_locomotive(addr))
+ return 0;*/
- Locomotive *loco=new Locomotive(control, addr);
- Train *train=new Train(*trfc_mgr, *loco);
- train->set_name(format("Train %d", trfc_mgr->get_trains().size()));
+ if(addr==0)
+ {
+ train_prop=new TrainProperties(*this, ui_res, 0);
+ train_prop->signal_ok.connect(sigc::mem_fun(this, &Engineer::dismiss_train_prop));
+ train_prop_stale=false;
- TrainPanel *tpanel=new TrainPanel(*this, ui_res, *train);
- int y=main_panel->get_geometry().y;
- for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
- y-=(*i)->get_geometry().h;
- tpanel->set_position(0, y-tpanel->get_geometry().h);
- train_panels.push_back(tpanel);
+ return 0;
+ }
+ else
+ {
+ Locomotive *loco=new Locomotive(control, addr);
+ Train *train=new Train(*trfc_mgr, *loco);
+ train->set_name(format("Train %d", trfc_mgr->get_trains().size()));
+
+ //train_prop=new TrainProperties(ui_res, *train);
- placing_train=train;
- placing_block=0;
- status_text="Select train location";
+ TrainPanel *tpanel=new TrainPanel(*this, ui_res, *train);
+ int y=main_panel->get_geometry().y;
+ for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
+ y-=(*i)->get_geometry().h;
+ tpanel->set_position(0, y-tpanel->get_geometry().h);
+ train_panels.push_back(tpanel);
+
+ placing_train=train;
+ placing_block=0;
+ status_text="Select train location";
+
+ return train;
+ }
}
int Engineer::main()
if(!screen)
throw Exception("Couldn't create window");
+ SDL_EnableUNICODE(1);
+
glEnableClientState(GL_VERTEX_ARRAY);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- Parser::load(ui_res, "engineer.res");
+ DataFile::load(ui_res, "engineer.res");
main_panel=new MainPanel(*this, ui_res);
main_panel->set_position(0, screen_h-main_panel->get_geometry().h);
pointer_motion(event.motion.x, screen_h-1-event.motion.y);
break;
case SDL_KEYDOWN:
- key_press(event.key.keysym.sym, event.key.keysym.mod);
+ key_press(event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
break;
case SDL_QUIT:
exit(0);
Track &track=(*i)->get_track();
if(track.get_turnout_id())
{
- Turnout *trnt=control.get_turnout(track.get_turnout_id());
- if(trnt)
- (*i)->render_route(trnt->get_route());
- else
- (*i)->render_route(-1);
+ Turnout &trnt=control.get_turnout(track.get_turnout_id());
+ (*i)->render_route(trnt.get_route());
}
else
(*i)->render_route(-1);
if(placing_train && placing_block)
{
- float rot=placing_entry->track->get_rotation()+placing_entry->track_ep->rot;
- Point pos=placing_entry->track->get_endpoint_position(*placing_entry->track_ep);
+ const Marklin::Block::Endpoint &bep=placing_block->get_endpoints()[placing_entry];
+ float rot=bep.track->get_endpoint_direction(bep.track_ep);
+ Point pos=bep.track->get_endpoint_position(bep.track_ep);
GL::push_matrix();
GL::translate(pos.x, pos.y, pos.z+0.03);
GL::rotate(rot*180/M_PI+180, 0, 0, 1);
main_panel->render();
for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
(*i)->render();
+ if(train_prop)
+ train_prop->render();
- const GL::Font &font=ui_res.get_font("dejavu-12");
+ if(train_prop_stale)
+ {
+ delete train_prop;
+ train_prop=0;
+ }
+
+ const GL::Font &font=ui_res.get_default_font();
GL::load_identity();
GL::translate(340, 10, 0);
GL::scale_uniform(font.get_default_size());
SDL_GL_SwapBuffers();
}
-void Engineer::key_press(unsigned, unsigned)
+void Engineer::key_press(unsigned key, unsigned mod, wchar_t ch)
{
+ if(train_prop)
+ train_prop->key_press(key, mod, ch);
}
void Engineer::button_press(int x, int y, unsigned btn)
{
if(main_panel->get_geometry().is_inside(x, y))
{
- main_panel->button_press(x, y, btn);
+ main_panel->button_press(x, y-main_panel->get_geometry().y, btn);
return;
}
for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
(*i)->button_press(x, y, btn);
return;
}
+ if(train_prop && train_prop->get_geometry().is_inside(x, y))
+ {
+ train_prop->button_press(x, y, btn);
+ return;
+ }
if(placing_train)
{
}
else if(btn==3)
{
- const Block::EndpointSeq &endpoints=placing_block->get_endpoints();
- Block::EndpointSeq::const_iterator i;
- for(i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(&*i==placing_entry)
- break;
- ++i;
- if(i==endpoints.end())
- i=endpoints.begin();
- placing_entry=&*i;
+ const vector<Block::Endpoint> &endpoints=placing_block->get_endpoints();
+ placing_entry=(placing_entry+1)%endpoints.size();
}
}
else
Track3D *track=pick_track(x, y);
if(track)
{
- Turnout *turnout=control.get_turnout(track->get_track().get_turnout_id());
- if(turnout)
- turnout->set_route(1-turnout->get_route());
+ if(unsigned tid=track->get_track().get_turnout_id())
+ {
+ Turnout &turnout=control.get_turnout(tid);
+ turnout.set_route(1-turnout.get_route());
+ }
else if(simulate)
{
- Sensor *sensor=control.get_sensor(track->get_track().get_sensor_id());
- if(sensor)
- control.signal_sensor_event.emit(track->get_track().get_sensor_id(), !sensor->get_state());
+ if(unsigned sid=track->get_track().get_sensor_id())
+ {
+ Sensor &sensor=control.get_sensor(sid);
+ control.signal_sensor_event.emit(sid, !sensor.get_state());
+ }
}
}
}
{
if(main_panel->get_geometry().is_inside(x, y))
{
- main_panel->button_release(x, y, btn);
+ main_panel->button_release(x, y-main_panel->get_geometry().y, btn);
return;
}
for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i)
(*i)->button_release(x, y, btn);
return;
}
+ if(train_prop && train_prop->get_geometry().is_inside(x, y))
+ {
+ train_prop->button_release(x, y, btn);
+ return;
+ }
}
void Engineer::pointer_motion(int x, int y)
(*i)->pointer_motion(x, y);
return;
}
+ if(train_prop && train_prop->get_geometry().is_inside(x, y))
+ {
+ train_prop->pointer_motion(x, y);
+ return;
+ }
Track3D *track=pick_track(x, y);
if(track && placing_train)
if(placing_block)
set_block_color(*placing_block, Color(1, 1, 1));
placing_block=block;
- placing_entry=&block->get_endpoints().front();
+ placing_entry=0;
set_block_color(*placing_block, Color(0.5, 1, 0.7));
}
}
void Engineer::set_block_color(const Block &block, const Color &color)
{
- const TrackSet &tracks=block.get_tracks();
- for(TrackSet::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ const set<Track *> &tracks=block.get_tracks();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
layout_3d.get_track(*i)->set_color(color);
}
-void Engineer::sensor_event(unsigned addr, bool state)
+void Engineer::sensor_event(bool state, Sensor *sensor)
{
- cout<<"sensor_event "<<state<<" @ "<<addr<<'\n';
- const Track3DSeq <racks=layout_3d.get_tracks();
- for(Track3DSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
- if((*i)->get_track().get_sensor_id()==addr)
+ const list<Track3D *> <racks=layout_3d.get_tracks();
+ for(list<Track3D *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
+ if((*i)->get_track().get_sensor_id()==sensor->get_address())
{
if(state)
(*i)->set_color(Color(1, 0.5, 0.3));
void Engineer::block_reserved(const Block &block, const Train *train)
{
- if(Sensor *sensor=control.get_sensor(block.get_sensor_id()))
- if(sensor->get_state())
+ if(unsigned sid=block.get_sensor_id())
+ {
+ Sensor &sensor=control.get_sensor(sid);
+ cout<<block.get_sensor_id()<<' '<<&sensor<<' '<<sensor.get_state()<<'\n';
+ if(sensor.get_state())
return;
+ }
if(train)
set_block_color(block, Color(1, 1, 0.3));
return layout_3d.pick_track(xx, yy, size);
}
+void Engineer::dismiss_train_prop()
+{
+ train_prop_stale=true;
+}
+
Application::RegApp<Engineer> Engineer::reg;
class MainPanel;
class TrainPanel;
+class TrainProperties;
class Engineer: public Msp::Application
{
~Engineer();
Marklin::Control &get_control() { return control; }
- void add_train(unsigned);
+ Marklin::Train *add_train(unsigned);
int main();
void quit() { exit(0); }
private:
Marklin::TrafficManager *trfc_mgr;
Marklin::Train *placing_train;
Marklin::Block *placing_block;
- const Marklin::Block::Endpoint *placing_entry;
+ unsigned placing_entry;
bool simulate;
+ TrainProperties *train_prop;
+ bool train_prop_stale;
void tick();
- void key_press(unsigned, unsigned);
+ void key_press(unsigned, unsigned, wchar_t);
void button_press(int, int, unsigned);
void button_release(int, int, unsigned);
void pointer_motion(int, int);
void view_all();
void set_block_color(const Marklin::Block &, const Marklin::Color &);
- void sensor_event(unsigned, bool);
+ void sensor_event(bool, Marklin::Sensor *);
void block_reserved(const Marklin::Block &, const Marklin::Train *);
void project_3d();
Marklin::Track3D *pick_track(int, int);
+ void dismiss_train_prop();
static Msp::Application::RegApp<Engineer> reg;
};
{
set_size(200, 100);
+ add(*(lbl_addr=new GLtk::Label(res, lexical_cast(train.get_locomotive().get_address(), "%2d"))));
+ lbl_addr->set_style("digital");
+ lbl_addr->set_geometry(GLtk::Geometry(10, geom.h-34, 35, 34));
+
add(*(lbl_name=new GLtk::Label(res, train.get_name())));
lbl_name->set_style("digital");
- lbl_name->set_geometry(GLtk::Geometry(10, geom.h-34, 140, 24));
+ lbl_name->set_geometry(GLtk::Geometry(45, geom.h-34, geom.w-55, 24));
train.signal_name_changed.connect(sigc::mem_fun(lbl_name, &GLtk::Label::set_text));
- GLtk::Button *btn;
-
- add(*(btn=new GLtk::Button(res, "Name")));
- btn->set_geometry(GLtk::Geometry(150, geom.h-34, 40, 24));
-
add(*(sld_speed=new GLtk::HSlider(res)));
sld_speed->set_geometry(GLtk::Geometry(10, geom.h-49, 180, 10));
sld_speed->set_range(0, 14);
add(*(lbl_speed=new GLtk::Label(res, " 0")));
lbl_speed->set_style("digital");
- lbl_speed->set_geometry(GLtk::Geometry(10, geom.h-75, 36, 24));
+ lbl_speed->set_geometry(GLtk::Geometry(10, geom.h-75, 35, 24));
train.get_locomotive().signal_speed_changed.connect(sigc::mem_fun(this, &TrainPanel::loco_speed_changed));
+
+ GLtk::Button *btn;
+
+ add(*(btn=new GLtk::Button(res, "Edit")));
+ btn->set_geometry(GLtk::Geometry(geom.w-50, 10, 40, 24));
}
void TrainPanel::speed_slider_changed(double v)
private:
Engineer &engineer;
Marklin::Train &train;
+ Msp::GLtk::Label *lbl_addr;
Msp::GLtk::Label *lbl_name;
Msp::GLtk::HSlider *sld_speed;
Marklin::Locomotive *loco;
#include <msp/gltk/button.h>
+#include <msp/strings/lexicalcast.h>
+#include "engineer.h"
#include "trainproperties.h"
using namespace Msp;
using namespace Marklin;
-TrainProperties::TrainProperties(GLtk::Resources &r, Train &t):
+TrainProperties::TrainProperties(Engineer &e, GLtk::Resources &r, Train *t):
Panel(r),
+ engineer(e),
train(t)
{
set_size(200, 75);
- add(*(ent_name=new GLtk::Entry(res, train.get_name())));
- ent_name->set_geometry(GLtk::Geometry(5, geom.h-25, geom.w-10, 20));
+ add(*(ent_addr=new GLtk::Entry(res)));
+ ent_addr->set_geometry(GLtk::Geometry(10, geom.h-25, 40, 20));
- add(*(ent_name=new GLtk::Entry(res, train.get_name())));
- ent_name->set_geometry(GLtk::Geometry(5, geom.h-50, geom.w-10, 20));
+ add(*(ent_name=new GLtk::Entry(res, "Train")));
+ ent_name->set_geometry(GLtk::Geometry(10, geom.h-50, geom.w-20, 20));
GLtk::Button *btn;
add(*(btn=new GLtk::Button(res, "OK")));
- btn->set_geometry(GLtk::Geometry(geom.w-45, 5, 40, 25));
+ btn->set_style("green");
+ btn->set_geometry(GLtk::Geometry(geom.w-40, 10, 30, 25));
+ btn->signal_clicked.connect(sigc::mem_fun(this, &TrainProperties::ok_clicked));
add(*(btn=new GLtk::Button(res, "Cncl")));
- btn->set_geometry(GLtk::Geometry(geom.w-90, 5, 40, 25));
+ btn->set_style("red");
+ btn->set_geometry(GLtk::Geometry(geom.w-80, 10, 30, 25));
+}
+
+void TrainProperties::ok_clicked()
+{
+ if(train)
+ {
+ }
+ else
+ {
+ train=engineer.add_train(lexical_cast<unsigned>(ent_addr->get_text()));
+ train->set_name(ent_name->get_text());
+ }
+ signal_ok.emit();
}
#include <msp/gltk/panel.h>
#include <libmarklin/train.h>
+class Engineer;
+
class TrainProperties: public Msp::GLtk::Panel
{
public:
- TrainProperties(Msp::GLtk::Resources &, Marklin::Train &);
+ sigc::signal<void> signal_ok;
+
+ TrainProperties(Engineer &, Msp::GLtk::Resources &, Marklin::Train *);
private:
- Marklin::Train &train;
- Msp::GLtk::Entry *ent_id;
+ Engineer &engineer;
+ Marklin::Train *train;
+ Msp::GLtk::Entry *ent_addr;
Msp::GLtk::Entry *ent_name;
+
+ void ok_clicked();
};
#endif
#include "control.h"
#include "block.h"
+#include "tracktype.h"
#include "trafficmanager.h"
#include "turnout.h"
namespace Marklin {
-Block::Block(TrafficManager &tm, Track *start):
+Block::Block(TrafficManager &tm, Track &start):
trfc_mgr(tm),
id(next_id++),
sensor_id(0),
train(0)
{
- tracks.insert(start);
+ tracks.insert(&start);
- if(start->get_sensor_id())
- {
- sensor_id=start->get_sensor_id();
- const Track::EndpointSeq &eps=start->get_endpoints();
- for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
- endpoints.push_back(Endpoint(start, &*i));
- }
- else
- {
- TrackSeq queue;
- queue.push_back(start);
+ list<Track *> queue;
+ queue.push_back(&start);
- while(!queue.empty())
- {
- Track *track=queue.front();
- queue.erase(queue.begin());
+ while(!queue.empty())
+ {
+ Track *track=queue.front();
+ queue.erase(queue.begin());
- const Track::EndpointSeq &eps=track->get_endpoints();
- for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
- if(i->link && tracks.count(i->link)==0)
+ const vector<Track *> &links=track->get_links();
+ for(unsigned i=0; i<links.size(); ++i)
+ if(links[i] && !tracks.count(links[i]))
+ {
+ if(links[i]->get_sensor_id()==start.get_sensor_id())
{
- if(!i->link->get_sensor_id())
- {
- queue.push_back(i->link);
- tracks.insert(i->link);
- }
- else
- endpoints.push_back(Endpoint(track, &*i));
+ queue.push_back(links[i]);
+ tracks.insert(links[i]);
}
- }
+ else
+ endpoints.push_back(Endpoint(track, i));
+ }
}
- unsigned n=0;
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i, ++n)
+ for(unsigned i=0; i<endpoints.size(); ++i)
{
- unsigned route=1<<n;
- i->routes|=route;
+ unsigned route=1<<i;
+ endpoints[i].routes|=route;
set<Track *> visited;
- find_routes(i->track, i->track_ep, route, visited);
+ find_routes(*endpoints[i].track, endpoints[i].track_ep, route, visited);
}
}
-const Block::Endpoint *Block::get_endpoint_by_link(const Block *other) const
+int Block::get_endpoint_by_link(const Block &other) const
{
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->link==other)
- return &*i;
+ for(unsigned i=0; i<endpoints.size(); ++i)
+ if(endpoints[i].link==&other)
+ return i;
- return 0;
+ return -1;
}
-const Block::Endpoint *Block::traverse(const Endpoint *ep) const
+int Block::traverse(unsigned epi) const
{
- Track *track=ep->track;
- const Track::Endpoint *track_ep=ep->track_ep;
+ if(epi>=endpoints.size())
+ throw InvalidParameterValue("Endpoint index out of range");
+
+ const Endpoint &ep=endpoints[epi];
+ Track *track=ep.track;
+ unsigned track_ep=ep.track_ep;
while(1)
{
unsigned tid=track->get_turnout_id();
if(tid)
{
- Turnout *turnout=trfc_mgr.get_control().get_turnout(tid);
- if(turnout)
- cur_route=turnout->get_route();
+ Turnout &turnout=trfc_mgr.get_control().get_turnout(tid);
+ cur_route=turnout.get_route();
}
- const Track::Endpoint *other_ep=track->traverse(track_ep, cur_route);
- if(!other_ep)
+ int other_ep=track->traverse(track_ep, cur_route);
+ if(other_ep<0)
return 0;
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->track==track && i->track_ep==other_ep)
- return &*i;
+ for(unsigned i=0; i<endpoints.size(); ++i)
+ if(endpoints[i].track==track && endpoints[i].track_ep==static_cast<unsigned>(other_ep))
+ return i;
- track_ep=other_ep->link->get_endpoint_by_link(track);
- track=other_ep->link;
+ Track *next=track->get_link(other_ep);
+ track_ep=next->get_endpoint_by_link(*track);
+ track=next;
if(tracks.count(track)==0)
- return 0;
+ return -1;
}
}
void Block::check_link(Block &other)
{
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
{
if(i->link)
continue;
- for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
- if(j->track==i->track_ep->link && j->track_ep->link==i->track && !j->link)
+ for(vector<Endpoint>::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
+ if(j->track==i->track->get_link(i->track_ep) && j->track->get_link(j->track_ep)==i->track && !j->link)
{
i->link=&other;
j->link=this;
}
}
+Block *Block::get_link(unsigned epi) const
+{
+ if(epi>=endpoints.size())
+ throw InvalidParameterValue("Endpoint index out of range");
+ return endpoints[epi].link;
+}
+
bool Block::reserve(const Train *t)
{
if(!t || !train)
if((*tracks.begin())->get_sensor_id())
cout<<", sensor="<<(*tracks.begin())->get_sensor_id();
cout<<'\n';
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
{
cout<<" Endpoint, link=";
if(i->link)
}
}
-void Block::find_routes(Track *track, const Track::Endpoint *track_ep, unsigned route, std::set<Marklin::Track *> &visited)
+void Block::find_routes(Track &track, unsigned track_ep, unsigned route, set<Track *> &visited)
{
- visited.insert(track);
+ visited.insert(&track);
- const Track::EndpointSeq &eps=track->get_endpoints();
- for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i)
+ const vector<Marklin::Endpoint> &eps=track.get_type().get_endpoints();
+ for(unsigned i=0; i<eps.size(); ++i)
{
- if(&*i==track_ep) continue;
- if(!i->link) continue;
- if(!(i->routes&track_ep->routes)) continue;
- if(visited.count(i->link)) continue;
-
- if(tracks.count(i->link))
- find_routes(i->link, i->link->get_endpoint_by_link(track), route, visited);
+ if(i==track_ep) continue;
+ Track *link=track.get_link(i);
+ if(link) continue;
+ if(visited.count(link)) continue;
+ if(!(eps[i].routes&eps[track_ep].routes)) continue;
+
+ if(tracks.count(link))
+ find_routes(*link, link->get_endpoint_by_link(track), route, visited);
else
{
- for(EndpointSeq::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
- if(j->track==track && j->track_ep==&*i)
+ for(vector<Endpoint>::iterator j=endpoints.begin(); j!=endpoints.end(); ++j)
+ if(j->track==&track && j->track_ep==i)
j->routes|=route;
}
}
unsigned Block::next_id=1;
-Block::Endpoint::Endpoint(Track *t, const Track::Endpoint *e):
+Block::Endpoint::Endpoint(Track *t, unsigned e):
track(t),
track_ep(e),
link(0),
public:
struct Endpoint
{
- Track *track;
- const Track::Endpoint *track_ep;
- Block *link;
+ Track *track;
+ unsigned track_ep;
+ Block *link;
unsigned routes;
- Endpoint(Track *, const Track::Endpoint *);
+ Endpoint(Track *, unsigned);
};
- typedef std::list<Endpoint> EndpointSeq;
- Block(TrafficManager &, Track *);
- unsigned get_sensor_id() const { return sensor_id; }
- const TrackSet &get_tracks() const { return tracks; }
- const EndpointSeq &get_endpoints() const { return endpoints; }
- const Endpoint *get_endpoint_by_link(const Block *) const;
- const Endpoint *traverse(const Endpoint *) const;
- void check_link(Block &);
- bool reserve(const Train *);
- void print_debug();
private:
TrafficManager &trfc_mgr;
unsigned id;
unsigned sensor_id;
- TrackSet tracks;
- EndpointSeq endpoints;
+ std::set<Track *> tracks;
+ std::vector<Endpoint> endpoints;
const Train *train;
- void find_routes(Track *, const Track::Endpoint *, unsigned, TrackSet &);
+public:
+ Block(TrafficManager &, Track &);
+ unsigned get_sensor_id() const { return sensor_id; }
+ const std::set<Track *> &get_tracks() const { return tracks; }
+ const std::vector<Endpoint> &get_endpoints() const { return endpoints; }
+ int get_endpoint_by_link(const Block &) const;
+ int traverse(unsigned) const;
+ void check_link(Block &);
+ Block *get_link(unsigned) const;
+ bool reserve(const Train *);
+ void print_debug();
+private:
+ void find_routes(Track &, unsigned, unsigned, std::set<Track *> &);
static unsigned next_id;
};
-#include <fstream>
-#include <msp/parser/parser.h>
+#include <msp/core/refptr.h>
+#include <msp/datafile/parser.h>
#include "catalogue.h"
-#include "track.h"
+#include "tracktype.h"
using namespace std;
using namespace Msp;
namespace Marklin {
-Track *Catalogue::get_track(unsigned art_nr)
+Catalogue::~Catalogue()
{
- TrackMap::const_iterator i=tracks.find(art_nr);
+ for(map<unsigned, TrackType *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ delete i->second;
+}
- if(i!=tracks.end())
- return i->second;
+TrackType &Catalogue::get_track(unsigned art_nr)
+{
+ map<unsigned, TrackType *>::const_iterator i=tracks.find(art_nr);
+ if(i==tracks.end())
+ throw KeyError("Unknown track type");
- return 0;
+ return *i->second;
}
void Catalogue::load(const string &fn)
{
- ifstream in(fn.c_str());
- if(!in)
- throw Exception("File not found");
+ IO::File in(fn.c_str());
- Parser::Parser parser(in, fn);
+ DataFile::Parser parser(in, fn);
Loader loader(*this);
loader.load(parser);
}
-Catalogue::~Catalogue()
-{
- for(TrackMap::iterator i=tracks.begin(); i!=tracks.end(); ++i)
- delete i->second;
-}
Catalogue::Loader::Loader(Catalogue &c):
cat(c)
void Catalogue::Loader::track(unsigned art_no)
{
- TrackMap::iterator i=cat.tracks.find(art_no);
+ map<unsigned, TrackType *>::iterator i=cat.tracks.find(art_no);
if(i!=cat.tracks.end())
throw Exception("Duplicate track number");
- Track *trk=new Track(art_no);
- try
- {
- load_sub(*trk);
- }
- catch(const Msp::Exception &)
- {
- delete trk;
- throw;
- }
- cat.tracks.insert(TrackMap::value_type(trk->get_article_number(), trk));
+ RefPtr<TrackType> trk=new TrackType(art_no);
+ load_sub(*trk);
+ unsigned art_nr=trk->get_article_number();
+ cat.tracks.insert(map<unsigned, TrackType *>::value_type(art_nr, trk.release()));
}
} // namespace Marklin
#define LIBMARKLIN_CATALOGUE_H_
#include <map>
-#include <msp/parser/loader.h>
+#include <msp/datafile/loader.h>
namespace Marklin {
-class Track;
+class TrackType;
class Catalogue
{
public:
- class Loader: public Msp::Parser::Loader
+ class Loader: public Msp::DataFile::Loader
{
public:
Loader(Catalogue &);
void track(unsigned);
};
- typedef std::map<unsigned, Track *> TrackMap;
+private:
+ std::map<unsigned, TrackType *> tracks;
- Track *get_track(unsigned);
- const TrackMap &get_tracks() const { return tracks; }
- void load(const std::string &);
+public:
~Catalogue();
-private:
- TrackMap tracks;
+
+ TrackType &get_track(unsigned);
+ const std::map<unsigned, TrackType *> &get_tracks() const { return tracks; }
+ void load(const std::string &);
};
} // namespace Marklin
#include <termios.h>
#include <sys/poll.h>
#include <iostream>
-#include <msp/core/error.h>
+#include <msp/core/except.h>
#include <msp/time/units.h>
#include <msp/time/utils.h>
#include "command.h"
command(string(1, CMD_POWER_OFF));
}
-Turnout *Control::get_turnout(unsigned id) const
-{
- TurnoutMap::const_iterator i=turnouts.find(id);
- if(i!=turnouts.end())
- return i->second;
-
- return 0;
-}
-
-Locomotive *Control::get_locomotive(unsigned id) const
-{
- for(LocomotiveSeq::const_iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
- if((*i)->get_address()==id)
- return *i;
- return 0;
-}
-
-Sensor *Control::get_sensor(unsigned id) const
-{
- SensorMap::const_iterator i=sensors.find(id);
- if(i!=sensors.end())
- return i->second;
-
- return 0;
-}
-
void Control::open(const string &dev)
{
serial_fd=::open(dev.c_str(), O_RDWR);
return queue.back();
}
-void Control::add_turnout(Turnout *t)
+void Control::add_turnout(Turnout &t)
{
- if(turnouts.count(t->get_address())==0)
- turnouts.insert(TurnoutMap::value_type(t->get_address(), t));
+ turnouts[t.get_address()]=&t;
}
-void Control::add_locomotive(Locomotive *l)
+Turnout &Control::get_turnout(unsigned id) const
{
- if(find(locomotives.begin(), locomotives.end(), l)==locomotives.end())
- locomotives.push_back(l);
+ map<unsigned, Turnout *>::const_iterator i=turnouts.find(id);
+ if(i==turnouts.end())
+ throw KeyError("Unknown turnout");
+
+ return *i->second;
}
-void Control::add_sensor(Sensor *s)
+void Control::add_locomotive(Locomotive &l)
{
- if(sensors.count(s->get_address())==0)
- {
- sensors.insert(SensorMap::value_type(s->get_address(), s));
- poll_sensors=true;
- }
+ locomotives[l.get_address()]=&l;
+}
+
+Locomotive &Control::get_locomotive(unsigned id) const
+{
+ map<unsigned, Locomotive *>::const_iterator i=locomotives.find(id);
+ if(i==locomotives.end())
+ throw KeyError("Unknown locomotive");
+
+ return *i->second;
+}
+
+void Control::add_sensor(Sensor &s)
+{
+ sensors[s.get_address()]=&s;
+ poll_sensors=true;
+}
+
+Sensor &Control::get_sensor(unsigned id) const
+{
+ map<unsigned, Sensor *>::const_iterator i=sensors.find(id);
+ if(i==sensors.end())
+ throw KeyError("Unknown sensor");
+
+ return *i->second;
}
void Control::tick()
{
const Time::TimeStamp t=Time::now();
+ for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ i->second->tick();
+
if(t>next_event_query)
{
next_event_query=t+300*Time::msec;
}
}
+Time::Timer::Slot &Control::set_timer(const Time::TimeDelta &dt)
+{
+ return timer.add(dt);
+}
+
Control::~Control()
{
- for(SensorMap::iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ for(map<unsigned, Sensor *>::iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ delete i->second;
+ for(map<unsigned, Turnout *>::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
delete i->second;
- for(TurnoutMap::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
+ for(map<unsigned, Locomotive *>::iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
delete i->second;
- for(LocomotiveSeq::iterator i=locomotives.begin(); i!=locomotives.end(); ++i)
- delete *i;
close(serial_fd);
}
#include <list>
#include <string>
+#include <msp/time/timer.h>
#include <msp/time/timestamp.h>
#include "constants.h"
#include "sensor.h"
class Control
{
+private:
+ int serial_fd;
+ bool p50_enabled;
+ bool power;
+ std::list<Command> queue;
+ std::map<unsigned, Turnout *> turnouts;
+ std::map<unsigned, Locomotive *> locomotives;
+ std::map<unsigned, Sensor *> sensors;
+ Msp::Time::TimeStamp next_event_query;
+ bool poll_sensors;
+ bool debug;
+ Msp::Time::Timer timer;
+
public:
sigc::signal<void, unsigned, bool> signal_turnout_event;
sigc::signal<void, unsigned, bool> signal_sensor_event;
Control();
void set_power(bool);
- void set_debug(bool d) { debug=d; }
bool get_power() const { return power; }
- const TurnoutMap &get_turnouts() const { return turnouts; }
- Turnout *get_turnout(unsigned) const;
- Locomotive *get_locomotive(unsigned) const;
- Sensor *get_sensor(unsigned) const;
+ void set_debug(bool d) { debug=d; }
+ //const TurnoutMap &get_turnouts() const { return turnouts; }
+ const std::map<unsigned, Sensor *> &get_sensors() const { return sensors; }
unsigned get_queue_length() const { return queue.size(); }
void open(const std::string &);
Command &command(const std::string &);
- void add_turnout(Turnout *);
- void add_locomotive(Locomotive *);
- void add_sensor(Sensor *);
+ void add_turnout(Turnout &);
+ Turnout &get_turnout(unsigned) const;
+ void add_locomotive(Locomotive &);
+ Locomotive &get_locomotive(unsigned) const;
+ void add_sensor(Sensor &);
+ Sensor &get_sensor(unsigned) const;
void tick();
+ Msp::Time::Timer::Slot &set_timer(const Msp::Time::TimeDelta &);
~Control();
private:
- int serial_fd;
- bool p50_enabled;
- bool power;
- std::list<Command> queue;
- TurnoutMap turnouts;
- LocomotiveSeq locomotives;
- SensorMap sensors;
- Msp::Time::TimeStamp next_event_query;
- bool poll_sensors;
- bool debug;
-
void read_all(int, char *, int);
std::string read_reply(Cmd);
void event_query_done(Error, const std::string &);
--- /dev/null
+#ifndef MARKLIN_ENDPOINT_H_
+#define MARKLIN_ENDPOINT_H_
+
+namespace Marklin {
+
+struct Endpoint
+{
+ float x, y;
+ float dir; // Direction outwards from the endpoint
+ unsigned routes;
+
+ Endpoint(): x(0), y(0), dir(0), routes(0) { }
+ Endpoint(float x_, float y_, float d, unsigned r): x(x_), y(y_), dir(d), routes(r) { }
+};
+
+} // namespace Marklin
+
+#endif
-#include <algorithm>
#include <fstream>
-#include <msp/parser/parser.h>
+#include <msp/core/refptr.h>
+#include <msp/datafile/parser.h>
#include "catalogue.h"
#include "layout.h"
+#include "tracktype.h"
using namespace std;
using namespace Msp;
catalogue(c)
{ }
-void Layout::add_track(Track *t)
+void Layout::add_track(Track &t)
{
- if(find(tracks.begin(), tracks.end(), t)==tracks.end())
- {
- tracks.push_back(t);
+ if(tracks.insert(&t).second)
signal_track_added.emit(t);
- }
}
-void Layout::remove_track(Track *t)
+void Layout::remove_track(Track &t)
{
- TrackSeq::iterator i=remove_if(tracks.begin(), tracks.end(), bind1st(equal_to<Track *>(), t));
- if(i!=tracks.end())
+ if(tracks.count(&t))
{
- tracks.erase(i, tracks.end());
+ tracks.erase(&t);
signal_track_removed.emit(t);
}
}
void Layout::check_links()
{
- for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
(*i)->break_links();
- for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
- for(TrackSeq::iterator j=i; j!=tracks.end(); ++j)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator j=i; j!=tracks.end(); ++j)
if(j!=i)
(*i)->snap_to(**j, true);
}
void Layout::load(const string &fn)
{
- ifstream in(fn.c_str());
- if(!in)
- throw Exception("Couldn't open file");
+ IO::File in(fn);
+ IO::Buffered inb(in);
filename=fn;
- Parser::Parser parser(in, fn);
+ DataFile::Parser parser(inb, fn);
Loader loader(*this);
loader.load(parser);
check_links();
- for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
(*i)->check_slope();
}
if(base.size())
out<<"base \""<<base<<"\";\n";
- for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
- out<<"track "<<(*i)->get_article_number()<<"\n{\n";
+ out<<"track "<<(*i)->get_type().get_article_number()<<"\n{\n";
const Point &p=(*i)->get_position();
out<<"\tposition "<<p.x<<' '<<p.y<<' '<<p.z<<";\n";
out<<"\trotation "<<(*i)->get_rotation()<<";\n";
Layout::~Layout()
{
- for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
delete *i;
}
void Layout::Loader::track(unsigned art_nr)
{
- Track *tmpl=layout.catalogue.get_track(art_nr);
- if(!tmpl)
- throw Exception("Unknown track");
+ TrackType &type=layout.catalogue.get_track(art_nr);
- Track *trk=tmpl->copy();
- try
- {
- load_sub(*trk);
- }
- catch(Msp::Exception &e)
- {
- delete trk;
- throw;
- }
- layout.tracks.push_back(trk);
- layout.signal_track_added.emit(trk);
+ RefPtr<Track> trk=new Track(type);
+ load_sub(*trk);
+ layout.add_track(*trk.release());
}
} // namespace Marklin
#define LIBMARKLIN_LAYOUT_H_
#include <sigc++/sigc++.h>
-#include <msp/parser/loader.h>
+#include <msp/datafile/loader.h>
#include "route.h"
#include "track.h"
class Layout
{
public:
- class Loader: public Msp::Parser::Loader
+ class Loader: public Msp::DataFile::Loader
{
public:
Loader(Layout &);
void track(unsigned);
};
- sigc::signal<void, Track *> signal_track_added;
- sigc::signal<void, Track *> signal_track_removed;
+ sigc::signal<void, Track &> signal_track_added;
+ sigc::signal<void, Track &> signal_track_removed;
Layout(Catalogue &);
- const TrackSeq &get_tracks() const { return tracks; }
- void add_track(Track *);
- void remove_track(Track *);
+ const std::set<Track *> &get_tracks() const { return tracks; }
+ void add_track(Track &);
+ void remove_track(Track &);
void check_links();
void load(const std::string &);
int save(const std::string &);
Catalogue &catalogue;
std::string filename;
std::string base;
- TrackSeq tracks;
- RouteSeq routes;
+ std::set<Track *> tracks;
+ //RouteSeq routes;
};
} // namespace Marklin
reverse(false),
funcs(0)
{
- control.add_locomotive(this);
+ control.add_locomotive(*this);
refresh_status();
}
if(speed)
{
- (new Time::Timer((500+speed*150)*Time::msec))->signal_timeout.connect(sigc::mem_fun(this, &Locomotive::reverse_timeout));
+ control.set_timer((500+speed*150)*Time::msec).signal_timeout.connect(sigc::mem_fun(this, &Locomotive::reverse_timeout));
set_speed(0);
}
else
void status_reply(Error, const std::string &);
bool reverse_timeout();
};
-typedef std::list<Locomotive *> LocomotiveSeq;
} // namespace Marklin
#define LIBMARKLIN_ROUTE_H_
#include <list>
+#include <map>
+#include <set>
#include <string>
-#include "track.h"
namespace Marklin {
+class Track;
+class Turnout;
+
class Route
{
public:
typedef std::map<unsigned, unsigned> TurnoutMap;
Route();
- const TurnoutMap &get_turnouts() const { return turnouts; }
+ const std::map<unsigned, Turnout *> &get_turnouts() const { return turnouts; }
void add_track(Track *);
~Route();
private:
std::string name;
- TrackSeq tracks;
- TurnoutMap turnouts;
+ std::set<Track *> tracks;
+ std::map<unsigned, Turnout *> turnouts;
};
-typedef std::list<Route *> RouteSeq;
} // namespace Marklin
+#include <msp/time/utils.h>
+#include <msp/time/units.h>
#include "control.h"
#include "sensor.h"
+using namespace Msp;
+
namespace Marklin {
Sensor::Sensor(Control &c, unsigned a):
addr(a),
state(false)
{
- control.add_sensor(this);
+ control.add_sensor(*this);
control.signal_sensor_event.connect(sigc::mem_fun(this, &Sensor::sensor_event));
}
void Sensor::sensor_event(unsigned a, bool s)
{
- if(a==addr && s!=state)
+ if(a==addr)
+ {
+ if(s)
+ {
+ off_timeout=Time::TimeStamp();
+ if(s!=state)
+ {
+ state=s;
+ signal_state_changed.emit(state);
+ }
+ }
+ else
+ off_timeout=Time::now()+Time::sec;
+ }
+}
+
+void Sensor::tick()
+{
+ if(off_timeout)
{
- state=s;
- signal_state_changed.emit(state);
+ const Time::TimeStamp t=Time::now();
+ if(t>off_timeout)
+ {
+ off_timeout=Time::TimeStamp();
+ if(state)
+ {
+ state=false;
+ signal_state_changed.emit(state);
+ }
+ }
}
}
#include <list>
#include <map>
-#include <sigc++/sigc++.h>
+#include <sigc++/signal.h>
+#include <msp/time/timestamp.h>
namespace Marklin {
Sensor(Control &, unsigned);
unsigned get_address() const { return addr; }
bool get_state() const { return state; }
+ void tick();
private:
Control &control;
unsigned addr;
bool state;
+ Msp::Time::TimeStamp off_timeout;
void sensor_event(unsigned, bool);
};
-typedef std::list<Sensor *> SensorSeq;
-typedef std::map<unsigned, Sensor *> SensorMap;
} // namespace Marklin
#include <cmath>
#include "track.h"
+#include "tracktype.h"
using namespace std;
using namespace Msp;
namespace Marklin {
-Track::Track(unsigned a):
- art_nr(a),
+Track::Track(const TrackType &t):
+ type(t),
rot(0),
slope(0),
flex(false),
turnout_id(0),
- sensor_id(0)
+ sensor_id(0),
+ links(t.get_endpoints().size())
{ }
Track::~Track()
{
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->link)
- {
- Track *trk=i->link;
- i->link=0;
- trk->break_link(*this);
- }
+ break_links();
}
void Track::set_position(const Point &p)
void Track::set_slope(float s)
{
- if(endpoints.size()!=2) return;
+ if(links.size()!=2) return;
slope=s;
- endpoints.back().pos.z=slope;
}
-const Track::Endpoint *Track::get_endpoint_by_link(Track *other) const
+void Track::set_flex(bool f)
{
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->link==other)
- return &*i;
+ flex=f;
+}
- return 0;
+void Track::set_turnout_id(unsigned i)
+{
+ turnout_id=i;
}
-Point Track::get_endpoint_position(const Endpoint &ep) const
+void Track::set_sensor_id(unsigned i)
{
- float c=cos(rot);
- float s=sin(rot);
- return Point(pos.x+c*ep.pos.x-s*ep.pos.y, pos.y+s*ep.pos.x+c*ep.pos.y, pos.z+ep.pos.z);
+ sensor_id=i;
}
-float Track::get_length() const
+int Track::get_endpoint_by_link(const Track &other) const
{
- float len=parts.front().length;
- if(parts.front().radius)
- len*=parts.front().radius;
- return len;
+ for(unsigned i=0; i<links.size(); ++i)
+ if(links[i]==&other)
+ return i;
+
+ return -1;
}
-float Track::get_total_length() const
+Point Track::get_endpoint_position(unsigned epi) const
{
- float len=0;
- for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
- {
- float l=i->length;
- if(i->radius)
- l*=i->radius;
- len+=l;
- }
- return len;
+ const vector<Endpoint> &eps=type.get_endpoints();
+ if(epi>=eps.size())
+ throw InvalidParameterValue("Endpoint index out of range");
+
+ const Endpoint &ep=eps[epi];
+
+ float c=cos(rot);
+ float s=sin(rot);
+
+ Point p(pos.x+c*ep.x-s*ep.y, pos.y+s*ep.x+c*ep.y, pos.z);
+ if(eps.size()==2 && epi==1)
+ p.z+=slope;
+ return p;
}
-unsigned Track::get_n_routes() const
+float Track::get_endpoint_direction(unsigned epi) const
{
- unsigned n=1;
- for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i)
- if(i->route>=n)
- n=i->route+1;
- return n;
+ const vector<Endpoint> &eps=type.get_endpoints();
+ if(epi>=eps.size())
+ throw InvalidParameterValue("Endpoint index out of range");
+
+ const Endpoint &ep=eps[epi];
+
+ return rot+ep.dir;
}
bool Track::snap_to(Track &other, bool link)
{
float limit=(link && !flex) ? 1e-6 : 1e-4;
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ const vector<Endpoint> &eps=type.get_endpoints();
+ const vector<Endpoint> &other_eps=other.get_type().get_endpoints();
+
+ for(unsigned i=0; i<eps.size(); ++i)
{
- Point epp=get_endpoint_position(*i);
- for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j)
+ Point epp=get_endpoint_position(i);
+
+ for(unsigned j=0; j<other_eps.size(); ++j)
{
- if(j->link)
+ if(other.get_link(j))
continue;
- Point epp2=other.get_endpoint_position(*j);
+ Point epp2=other.get_endpoint_position(j);
float dx=epp2.x-epp.x;
float dy=epp2.y-epp.y;
if(dx*dx+dy*dy<limit)
{
- set_rotation(other.rot+j->rot-i->rot+M_PI);
- set_position(Point(epp2.x-(i->pos.x*cos(rot)-i->pos.y*sin(rot)), epp2.y-(i->pos.y*cos(rot)+i->pos.x*sin(rot)), other.pos.z+j->pos.z-i->pos.z));
+ set_rotation(other.rot+other_eps[j].dir-eps[i].dir+M_PI);
+ set_position(Point(epp2.x-(eps[i].x*cos(rot)-eps[i].y*sin(rot)), epp2.y-(eps[i].y*cos(rot)+eps[i].x*sin(rot)), epp2.z));
+
if(link)
{
- if(i->link)
- break_link(*i->link);
- i->link=&other;
- j->link=this;
+ if(links[i])
+ break_link(*links[i]);
+ links[i]=&other;
+ other.links[j]=this;
}
+
return true;
}
}
bool Track::snap(Point &pt, float &d) const
{
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
+ const vector<Endpoint> &eps=type.get_endpoints();
+
+ for(unsigned i=0; i<eps.size(); ++i)
{
- Point epp=get_endpoint_position(*i);
+ Point epp=get_endpoint_position(i);
float dx=pt.x-epp.x;
float dy=pt.y-epp.y;
if(dx*dx+dy*dy<1e-4)
{
pt=epp;
- d=rot+i->rot;
+ d=rot+eps[i].dir;
return true;
}
}
void Track::break_link(Track &trk)
{
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->link==&trk)
+ for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
+ if(*i==&trk)
{
- i->link=0;
+ *i=0;
trk.break_link(*this);
return;
}
void Track::break_links()
{
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if(i->link)
+ for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
+ if(Track *trk=*i)
{
- Track *trk=i->link;
- i->link=0;
+ *i=0;
trk->break_link(*this);
}
}
+Track *Track::get_link(unsigned i) const
+{
+ if(i>links.size())
+ throw InvalidParameterValue("Link index out of range");
+
+ return links[i];
+}
+
void Track::check_slope()
{
- if(endpoints.size()!=2)
+ if(links.size()!=2)
return;
- Track *link1=endpoints.front().link;
- Track *link2=endpoints.back().link;
- if(link1 && link2)
+ if(links[0] && links[1])
{
- const Endpoint *ep1=link1->get_endpoint_by_link(this);
- const Endpoint *ep2=link2->get_endpoint_by_link(this);
- pos.z=link1->pos.z+ep1->pos.z;
- slope=(link2->pos.z+ep2->pos.z)-pos.z;
+ Point epp0=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
+ Point epp1=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
+ pos.z=epp0.z;
+ slope=epp1.z-pos.z;
}
else
{
slope=0;
- if(link1)
+ if(links[0])
{
- const Endpoint *ep=link1->get_endpoint_by_link(this);
- pos.z=link1->pos.z+ep->pos.z;
+ Point epp=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
+ pos.z=epp.z;
}
- else if(link2)
+ else if(links[1])
{
- const Endpoint *ep=link2->get_endpoint_by_link(this);
- pos.z=link2->pos.z+ep->pos.z;
+ Point epp=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
+ pos.z=epp.z;
}
}
-
- endpoints.back().pos.z=slope;
}
-const Track::Endpoint *Track::traverse(const Endpoint *ep, unsigned route) const
+int Track::traverse(unsigned i, unsigned route) const
{
- if(ep->routes&(1<<route))
+ const vector<Endpoint> &eps=type.get_endpoints();
+ if(i>=eps.size())
+ throw InvalidParameterValue("Endpoint index out of range");
+
+ const Endpoint &ep=eps[i];
+
+ if(ep.routes&(1<<route))
{
// Find the other endpoint for this route
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if((i->routes&(1<<route)) && &*i!=ep)
- return &*i;
+ for(unsigned j=0; j<eps.size(); ++j)
+ if((eps[j].routes&(1<<route)) && j!=i)
+ return j;
}
else
{
// Find an endpoint that's connected to this one and has the requested route
- for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
- if((i->routes&(1<<route)) && (i->routes&ep->routes))
- return &*i;
+ for(unsigned j=0; j<eps.size(); ++j)
+ if((eps[j].routes&(1<<route)) && (eps[j].routes&ep.routes))
+ return j;
}
- return 0;
+ return -1;
}
Track *Track::copy() const
{
- Track *trk=new Track(*this);
- for(EndpointSeq::iterator i=trk->endpoints.begin(); i!=trk->endpoints.end(); ++i)
- i->link=0;
- trk->turnout_id=0;
- trk->sensor_id=0;
+ Track *trk=new Track(type);
+ trk->set_position(pos);
+ trk->set_rotation(rot);
+ trk->set_slope(slope);
+ trk->set_flex(flex);
return trk;
}
-/*** private ***/
-
-void Track::collect_endpoints()
-{
- endpoints.clear();
-
- for(PartSeq::iterator i=parts.begin(); i!=parts.end(); ++i)
- i->collect_endpoints(endpoints);
- endpoints.back().pos.z=slope;
-
- for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end();)
- {
- bool rm=false;
- for(EndpointSeq::iterator j=i; j!=endpoints.end();)
- {
- if(j==i)
- {
- ++j;
- continue;
- }
- float dx=i->pos.x-j->pos.x;
- float dy=i->pos.y-j->pos.y;
- if(dx*dx+dy*dy<0.0001)
- {
- float da=i->rot-j->rot;
- if(da<-M_PI)
- da+=M_PI*2;
- if(da>M_PI)
- da-=M_PI*2;
- if(da<-3 || da>3)
- rm=true;
- i->routes|=j->routes;
- j=endpoints.erase(j);
- }
- else
- ++j;
- }
- if(rm)
- i=endpoints.erase(i);
- else
- ++i;
- }
-}
-
/*******************
** Track::Loader
*/
Track::Loader::Loader(Track &t):
track(t)
{
- add("description", &Track::description);
- add("part", &Loader::part);
add("position", &Loader::position);
add("rotation", &Track::rot);
add("slope", &Track::slope);
add("flex", &Track::flex);
}
-Track::Loader::~Loader()
-{
- track.collect_endpoints();
-}
-
-void Track::Loader::part()
-{
- Part p;
- load_sub(p);
- track.parts.push_back(p);
-}
-
void Track::Loader::position(float x, float y, float z)
{
track.pos=Point(x, y, z);
}
-/*******************
-** Track::Part
-*/
-
-Track::Part::Part():
- x(0),
- y(0),
- dir(0),
- length(0),
- radius(0),
- route(0),
- dead_end(false)
-{ }
-
-void Track::Part::collect_endpoints(EndpointSeq &epl)
-{
- epl.push_back(Endpoint(Point(x, y, 0), dir+M_PI, 1<<route));
- if(dead_end)
- return;
- else if(radius)
- {
- float a=(radius<0)?-length:length;
- float c=cos(a);
- float s=sin(a);
- float rx=radius*sin(dir);
- float ry=-radius*cos(dir);
- epl.push_back(Endpoint(Point(x+c*rx-s*ry-rx, y+c*ry+s*rx-ry, 0), dir+a, 1<<route));
- }
- else
- epl.push_back(Endpoint(Point(x+cos(dir)*length, y+sin(dir)*length, 0), dir, 1<<route));
-}
-
-Track::Part::Loader::Loader(Part &p):
- part(p)
-{
- add("start", &Loader::start);
- add("length", &Part::length);
- add("radius", &Part::radius);
- add("route", &Part::route);
- add("dead_end", &Part::dead_end);
-}
-
-Track::Part::Loader::~Loader()
-{
- if(part.radius)
- {
- part.length*=M_PI/180;
- part.radius/=1000;
- }
- else
- part.length/=1000;
-
- part.x/=1000;
- part.y/=1000;
- part.dir*=M_PI/180;
-}
-
-void Track::Part::Loader::start(float x, float y, float d)
-{
- part.x=x;
- part.y=y;
- part.dir=d;
-}
-
} // namespace Marklin
#include <list>
#include <set>
-#include <msp/parser/loader.h>
+#include <msp/datafile/loader.h>
#include "geometry.h"
namespace Marklin {
+class TrackType;
+
class Track
{
public:
- class Loader: public Msp::Parser::Loader
+ class Loader: public Msp::DataFile::Loader
{
+ private:
+ Track &track;
+
public:
Loader(Track &);
Track &get_object() { return track; }
- ~Loader();
private:
- Track &track;
-
- void part();
void position(float, float, float);
};
- struct Endpoint
- {
- Point pos;
- float rot;
- Track *link;
- unsigned routes;
-
- Endpoint(const Point &p, float r, unsigned o): pos(p), rot(r), link(0), routes(o) { }
- };
- typedef std::list<Endpoint> EndpointSeq;
-
- struct Part
- {
- class Loader: public Msp::Parser::Loader
- {
- public:
- Loader(Part &);
- Part &get_object() { return part; }
- ~Loader();
- private:
- Part ∂
-
- void start(float, float, float);
- };
-
- float x,y;
- float dir;
- float length;
- float radius;
- unsigned route;
- bool dead_end;
-
- Part();
- void collect_endpoints(EndpointSeq &);
- };
- typedef std::list<Part> PartSeq;
+private:
+ const TrackType &type;
+ Point pos;
+ float rot;
+ float slope;
+ bool flex;
+ unsigned turnout_id;
+ unsigned sensor_id;
+ std::vector<Track *> links;
- Track(unsigned);
+public:
+ Track(const TrackType &);
~Track();
- void set_position(const Point &);
- void set_rotation(float);
- void set_slope(float);
- void set_flex(bool f) { flex=f; }
- void set_turnout_id(unsigned i) { turnout_id=i; }
- void set_sensor_id(unsigned i) { sensor_id=i; }
- const Point &get_position() const { return pos; }
- float get_rotation() const { return rot; }
- unsigned get_article_number() const { return art_nr; }
- const PartSeq &get_parts() const { return parts; }
- const EndpointSeq &get_endpoints() const { return endpoints; }
- const Endpoint *get_endpoint_by_link(Track *) const;
- Point get_endpoint_position(const Endpoint &) const;
- const std::string &get_description() const { return description; }
- float get_slope() const { return slope; }
- bool get_flex() const { return flex; }
- float get_length() const;
- float get_total_length() const;
- unsigned get_turnout_id() const { return turnout_id; }
- unsigned get_sensor_id() const { return sensor_id; }
- unsigned get_n_routes() const;
- bool snap_to(Track &, bool);
- bool snap(Point &, float &) const;
- void break_link(Track &);
- void break_links();
- void check_slope();
- const Endpoint *traverse(const Endpoint *, unsigned) const;
+
+ const TrackType &get_type() const { return type; }
+ void set_position(const Point &);
+ const Point &get_position() const { return pos; }
+ void set_rotation(float);
+ float get_rotation() const { return rot; }
+ void set_slope(float);
+ float get_slope() const { return slope; }
+ void set_flex(bool);
+ bool get_flex() const { return flex; }
+ void set_turnout_id(unsigned);
+ unsigned get_turnout_id() const { return turnout_id; }
+ void set_sensor_id(unsigned);
+ unsigned get_sensor_id() const { return sensor_id; }
+ int get_endpoint_by_link(const Track &) const;
+ Point get_endpoint_position(unsigned) const;
+ float get_endpoint_direction(unsigned) const;
+ bool snap_to(Track &, bool);
+ bool snap(Point &, float &) const;
+ void break_link(Track &);
+ void break_links();
+ const std::vector<Track *> &get_links() const { return links; }
+ Track *get_link(unsigned) const;
+ void check_slope();
+ int traverse(unsigned, unsigned) const;
/**
Creates a copy of the track. The new track will be almost identical, but
*/
Track *copy() const;
private:
- unsigned art_nr;
- std::string description;
- PartSeq parts;
- EndpointSeq endpoints;
- Point pos;
- float rot;
- float slope;
- bool flex;
- unsigned turnout_id;
- unsigned sensor_id;
// Direct copying not allowed due to links. See the copy() function.
- //Track(const Track &);
+ Track(const Track &);
Track &operator=(const Track &);
-
- void collect_endpoints();
};
-typedef std::list<Track *> TrackSeq;
-typedef std::set<Track *> TrackSet;
} // namespace Marklin
--- /dev/null
+#include <cmath>
+#include "trackpart.h"
+
+using namespace std;
+
+namespace Marklin {
+
+TrackPart::TrackPart():
+ x(0),
+ y(0),
+ dir(0),
+ length(0),
+ radius(0),
+ route(0),
+ dead_end(false)
+{ }
+
+void TrackPart::collect_endpoints(vector<Endpoint> &eps)
+{
+ eps.push_back(Endpoint(x, y, dir+M_PI, 1<<route));
+
+ if(dead_end)
+ ;
+ else if(radius)
+ {
+ float a=((radius<0) ? -length : length);
+ float c=cos(a);
+ float s=sin(a);
+ float rx=radius*sin(dir);
+ float ry=-radius*cos(dir);
+ eps.push_back(Endpoint(x+c*rx-s*ry-rx, y+c*ry+s*rx-ry, dir+a, 1<<route));
+ }
+ else
+ eps.push_back(Endpoint(x+cos(dir)*length, y+sin(dir)*length, dir, 1<<route));
+}
+
+
+TrackPart::Loader::Loader(TrackPart &p):
+ part(p)
+{
+ add("start", &Loader::start);
+ add("length", &TrackPart::length);
+ add("radius", &TrackPart::radius);
+ add("route", &TrackPart::route);
+ add("dead_end", &TrackPart::dead_end);
+}
+
+void TrackPart::Loader::finish()
+{
+ if(part.radius)
+ {
+ part.length*=M_PI/180;
+ part.radius/=1000;
+ }
+ else
+ part.length/=1000;
+
+ part.x/=1000;
+ part.y/=1000;
+ part.dir*=M_PI/180;
+}
+
+void TrackPart::Loader::start(float x, float y, float d)
+{
+ part.x=x;
+ part.y=y;
+ part.dir=d;
+}
+
+} // namespace Marklin
--- /dev/null
+#ifndef MARKLIN_TRACKPART_H_
+#define MARKLIN_TRACKPART_H_
+
+#include <msp/datafile/loader.h>
+#include "endpoint.h"
+
+namespace Marklin {
+
+struct TrackPart
+{
+ class Loader: public Msp::DataFile::Loader
+ {
+ private:
+ TrackPart ∂
+
+ public:
+ Loader(TrackPart &);
+ TrackPart &get_object() { return part; }
+ private:
+ virtual void finish();
+
+ void start(float, float, float);
+ };
+
+ float x, y;
+ float dir;
+ float length;
+ float radius;
+ unsigned route;
+ bool dead_end;
+
+ TrackPart();
+ void collect_endpoints(std::vector<Endpoint> &);
+};
+
+} // namespace Marklin
+
+#endif
--- /dev/null
+#include <cmath>
+#include "tracktype.h"
+
+using namespace std;
+
+namespace Marklin {
+
+TrackType::TrackType(unsigned a):
+ art_nr(a)
+{ }
+
+float TrackType::get_total_length() const
+{
+ float len=0;
+ for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ {
+ float l=i->length;
+ if(i->radius)
+ l*=i->radius;
+ len+=l;
+ }
+ return len;
+}
+
+unsigned TrackType::get_n_routes() const
+{
+ unsigned n=1;
+ for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ if(i->route>=n)
+ n=i->route+1;
+ return n;
+}
+
+void TrackType::collect_endpoints()
+{
+ endpoints.clear();
+
+ for(vector<TrackPart>::iterator i=parts.begin(); i!=parts.end(); ++i)
+ i->collect_endpoints(endpoints);
+
+ for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end();)
+ {
+ bool rm=false;
+ for(vector<Endpoint>::iterator j=i+1; j!=endpoints.end();)
+ {
+ float dx=i->x-j->x;
+ float dy=i->y-j->y;
+ if(dx*dx+dy*dy<0.0001)
+ {
+ float da=i->dir-j->dir;
+ if(da<-M_PI)
+ da+=M_PI*2;
+ if(da>M_PI)
+ da-=M_PI*2;
+ if(da<-3.1 || da>3.1)
+ rm=true;
+ i->routes|=j->routes;
+ j=endpoints.erase(j);
+ }
+ else
+ ++j;
+ }
+
+ if(rm)
+ i=endpoints.erase(i);
+ else
+ ++i;
+ }
+}
+
+
+TrackType::Loader::Loader(TrackType &t):
+ ttype(t)
+{
+ add("description", &TrackType::description);
+ add("part", &Loader::part);
+}
+
+void TrackType::Loader::finish()
+{
+ ttype.collect_endpoints();
+}
+
+void TrackType::Loader::part()
+{
+ TrackPart p;
+ load_sub(p);
+ ttype.parts.push_back(p);
+}
+
+} // namespace Marklin
--- /dev/null
+#ifndef LIBMARKLIN_TRACKTYPE_H_
+#define LIBMARKLIN_TRACKTYPE_H_
+
+#include <msp/datafile/loader.h>
+#include "endpoint.h"
+#include "trackpart.h"
+
+namespace Marklin {
+
+class TrackType
+{
+public:
+ class Loader: public Msp::DataFile::Loader
+ {
+ private:
+ TrackType &ttype;
+
+ public:
+ Loader(TrackType &);
+ TrackType &get_object() { return ttype; }
+ private:
+ virtual void finish();
+
+ void part();
+ void position(float, float, float);
+ };
+
+private:
+ unsigned art_nr;
+ std::string description;
+ std::vector<TrackPart> parts;
+ std::vector<Endpoint> endpoints;
+
+public:
+ TrackType(unsigned);
+
+ unsigned get_article_number() const { return art_nr; }
+ const std::string &get_description() const { return description; }
+ float get_total_length() const;
+ unsigned get_n_routes() const;
+ const std::vector<TrackPart> &get_parts() const { return parts; }
+ const std::vector<Endpoint> &get_endpoints() const { return endpoints; }
+
+private:
+ void collect_endpoints();
+};
+
+} // namespace Marklin
+
+#endif
control(c),
layout(l)
{
- const TrackSeq &tracks=layout.get_tracks();
+ const set<Track *> &tracks=layout.get_tracks();
- TrackSet used_tracks;
- for(TrackSeq::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ set<Track *> used_tracks;
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
{
if(unsigned tid=(*i)->get_turnout_id())
- {
- Turnout *t=control.get_turnout(tid);
- if(!t)
- t=new Turnout(control, tid);
- //t->signal_route_changed.connect(sigc::mem_fun(*i, &Track::set_current_route));
- }
+ new Turnout(control, tid);
if(unsigned sid=(*i)->get_sensor_id())
- {
- Sensor *s=control.get_sensor(sid);
- if(!s)
- s=new Sensor(control, sid);
- }
+ new Sensor(control, sid);
+
if(used_tracks.count(*i)==0)
{
- Block *block=new Block(*this, *i);
+ Block *block=new Block(*this, **i);
blocks.push_back(block);
used_tracks.insert(block->get_tracks().begin(), block->get_tracks().end());
}
{
for(BlockSeq::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
{
- const TrackSet &tracks=(*i)->get_tracks();
+ const set<Track *> &tracks=(*i)->get_tracks();
if(tracks.count(const_cast<Track *>(t)))
return *i;
}
private:
Control &control;
Layout &layout;
- BlockSeq blocks;
- TrainSeq trains;
+ std::list<Block *> blocks;
+ std::list<Train *> trains;
void turnout_route_changed(unsigned, Turnout *);
};
target_speed(0)
{
trfc_mgr.add_train(this);
- trfc_mgr.get_control().signal_sensor_event.connect(sigc::mem_fun(this, &Train::sensor_event));
+
+ const map<unsigned, Sensor *> &sensors=trfc_mgr.get_control().get_sensors();
+ for(map<unsigned, Sensor *>::const_iterator i=sensors.begin(); i!=sensors.end(); ++i)
+ i->second->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Train::sensor_event), i->second));
}
void Train::set_name(const string &n)
loco.set_speed(speed);
}
-void Train::place(Block *block, const Block::Endpoint *entry)
+void Train::place(Block *block, unsigned entry)
{
- for(BlockRefSeq::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
+ for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end();)
{
i->block->reserve(0);
i=rsv_blocks.erase(i);
}
- for(BlockRefSeq::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
+ for(list<BlockRef>::iterator i=cur_blocks.begin(); i!=cur_blocks.end();)
{
i->block->reserve(0);
i=cur_blocks.erase(i);
bool Train::free_block(Block *block)
{
- for(BlockRefSeq::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
+ for(list<BlockRef>::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
if(i->block==block)
{
while(i!=rsv_blocks.end())
return false;
}
-void Train::sensor_event(unsigned addr, bool state)
+void Train::sensor_event(bool state, Sensor *sensor)
{
if(!loco.get_speed())
return;
+ unsigned addr=sensor->get_address();
+
if(state)
{
- BlockRefSeq::iterator i;
+ list<BlockRef>::iterator i;
for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i)
if(i->block->get_sensor_id() && i->block->get_sensor_id()!=addr)
break;
else
{
cout<<"Finding blocks to free\n";
- BlockRefSeq::iterator i;
+ list<BlockRef>::iterator i;
for(i=cur_blocks.begin(); i!=cur_blocks.end(); ++i)
if(i->block->get_sensor_id()==addr)
break;
{
cout<<"found\n";
++i;
- for(BlockRefSeq::iterator j=cur_blocks.begin(); j!=i; ++j)
+ for(list<BlockRef>::iterator j=cur_blocks.begin(); j!=i; ++j)
j->block->reserve(0);
cur_blocks.erase(cur_blocks.begin(), i);
cout<<cur_blocks.size()<<" cur_blocks\n";
bool result=false;
unsigned size=rsv_blocks.size();
- while(size<5)
+ while(size<3)
{
- const Block::Endpoint *exit=last->block->traverse(last->entry);
- if(exit && exit->link->reserve(this))
+ int exit=last->block->traverse(last->entry);
+ if(exit>=0)
{
- rsv_blocks.push_back(BlockRef(exit->link, exit->link->get_endpoint_by_link(last->block)));
- last=&rsv_blocks.back();
- ++size;
- result=true;
+ Block *link=last->block->get_link(exit);
+ if(link)
+ {
+ rsv_blocks.push_back(BlockRef(link, link->get_endpoint_by_link(*last->block)));
+ last=&rsv_blocks.back();
+ ++size;
+ result=true;
+ }
}
else
break;
namespace Marklin {
class Locomotive;
+class Sensor;
class TrafficManager;
class Train: public sigc::trackable
{
-public:
- sigc::signal<void, const std::string &> signal_name_changed;
-
- Train(TrafficManager &, Locomotive &);
- void set_name(const std::string &);
- void set_speed(unsigned);
- const std::string &get_name() const { return name; }
- Locomotive &get_locomotive() const { return loco; }
- void place(Block *, const Block::Endpoint *);
- bool free_block(Block *);
- void tick();
private:
struct BlockRef
{
Block *block;
- const Block::Endpoint *entry;
+ unsigned entry;
- BlockRef(Block *s, const Block::Endpoint *e): block(s), entry(e) { }
+ BlockRef(Block *s, unsigned e): block(s), entry(e) { }
};
- typedef std::list<BlockRef> BlockRefSeq;
TrafficManager &trfc_mgr;
std::string name;
Locomotive &loco;
- BlockRefSeq cur_blocks;
- BlockRefSeq rsv_blocks;
+ std::list<BlockRef> cur_blocks;
+ std::list<BlockRef> rsv_blocks;
unsigned target_speed;
- void sensor_event(unsigned, bool);
+public:
+ sigc::signal<void, const std::string &> signal_name_changed;
+
+ Train(TrafficManager &, Locomotive &);
+ void set_name(const std::string &);
+ void set_speed(unsigned);
+ const std::string &get_name() const { return name; }
+ Locomotive &get_locomotive() const { return loco; }
+ void place(Block *, unsigned);
+ bool free_block(Block *);
+ void tick();
+private:
+ void sensor_event(bool, Sensor *);
bool reserve_more();
};
typedef std::list<Train *> TrainSeq;
addr(a),
route(0)
{
- control.add_turnout(this);
+ control.add_turnout(*this);
control.signal_turnout_event.connect(sigc::mem_fun(this, &Turnout::turnout_event));
route=r;
command(true);
- (new Time::Timer(200*Time::msec))->signal_timeout.connect(sigc::mem_fun(this, &Turnout::switch_timeout));
+ control.set_timer(200*Time::msec).signal_timeout.connect(sigc::mem_fun(this, &Turnout::switch_timeout));
signal_route_changed.emit(route);
}
bool switch_timeout();
void turnout_event(unsigned, bool);
};
-typedef std::list<Turnout *> TurnoutSeq;
-typedef std::map<unsigned, Turnout *> TurnoutMap;
} // namespace Marklin
-#include <fstream>
#include <iostream>
#include <map>
#include <msp/core/getopt.h>
-#include <msp/parser/loader.h>
-#include <msp/parser/parser.h>
+#include <msp/datafile/loader.h>
+#include <msp/datafile/parser.h>
using namespace std;
using namespace Msp;
ShoppingList(int, char **);
void print(ostream &);
private:
- class InventoryLoader: public Parser::Loader
+ class InventoryLoader: public DataFile::Loader
{
public:
InventoryLoader(ShoppingList &);
void track(unsigned, unsigned);
};
- class LayoutLoader: public Parser::Loader
+ class LayoutLoader: public DataFile::Loader
{
public:
LayoutLoader(ShoppingList &);
void ShoppingList::load_inventory(const string &fn)
{
- ifstream in(fn.c_str());
- Parser::Parser parser(in, fn);
+ IO::File in(fn);
+ DataFile::Parser parser(in, fn);
InventoryLoader il(*this);
il.load(parser);
}
void ShoppingList::load_layout(const string &fn)
{
- ifstream in(fn.c_str());
- Parser::Parser parser(in, fn);
+ IO::File in(fn);
+ DataFile::Parser parser(in, fn);
LayoutLoader ll(*this);
ll.load(parser);
}