Track &track = t3d->get_track();
if(track.get_turnout_id())
{
- Block &block = layout.get_block_by_track(track);
+ Block &block = track.get_block();
if(block.get_train() && !block.get_train()->free_block(block))
set_status("Turnout is busy");
else
{
pick_conn.disconnect();
- Block &block = engineer.get_layout().get_block_by_track(*track);
+ Block &block = track->get_block();
while(1)
{
train(0)
{
tracks.insert(&start);
+ start.set_block(this);
list<Track *> queue;
queue.push_back(&start);
{
queue.push_back(links[i]);
tracks.insert(links[i]);
+ links[i]->set_block(this);
}
else
endpoints.push_back(Endpoint(track, i));
Block::~Block()
{
+ set<Track *> trks = tracks;
+ tracks.clear();
+ for(set<Track *>::iterator i=trks.begin(); i!=trks.end(); ++i)
+ (*i)->set_block(0);
+
for(vector<Endpoint>::iterator i=endpoints.begin(); i!=endpoints.end(); ++i)
if(Block *blk = i->link)
{
throw KeyError("Unknown block", lexical_cast(id));
}
-Block &Layout::get_block_by_track(Track &t) const
-{
- for(set<Block *>::const_iterator i=blocks.begin(); i!=blocks.end(); ++i)
- if((*i)->has_track(t))
- return **i;
-
- throw InvalidParameterValue("No block found for track");
-}
-
void Layout::create_blocks()
{
set<Track *> used_tracks;
void Layout::create_blocks(Track &track)
{
+ /* Must collect the blocks in a set first while all tracks are still
+ guaranteed to have blocks and to avoid duplicate deletes */
+ set<Block *> del_blocks;
+
+ del_blocks.insert(&track.get_block());
+
const vector<Track *> &links = track.get_links();
- for(set<Block *>::iterator i=blocks.begin(); i!=blocks.end();)
- {
- bool del = (*i)->has_track(track);
- for(vector<Track *>::const_iterator j=links.begin(); (!del && j!=links.end()); ++j)
- del = (*i)->has_track(**j);
-
- if(del)
- delete *i++;
- else
- ++i;
- }
+ for(vector<Track *>::const_iterator i=links.begin(); i!=links.end(); ++i)
+ if(*i)
+ del_blocks.insert(&(*i)->get_block());
+
+ for(set<Block *>::iterator i=del_blocks.begin(); i!=del_blocks.end(); ++i)
+ delete *i;
create_blocks();
}
void add_block(Block &);
Block &get_block(unsigned) const;
- Block &get_block_by_track(Track &) const;
const std::set<Block *> &get_blocks() const { return blocks; }
void create_blocks();
void create_blocks(Track &);
*/
#include <cmath>
+#include "block.h"
#include "driver.h"
#include "layout.h"
#include "track.h"
Track::Track(Layout &l, const TrackType &t):
layout(l),
type(t),
+ block(0),
rot(0),
slope(0),
flex(false),
layout.remove_track(*this);
}
+void Track::set_block(Block *b)
+{
+ if(b && !b->has_track(*this))
+ throw InvalidParameterValue("Track is not in the Block");
+ if(!b && block && block->has_track(*this))
+ throw InvalidState("Track is still in a Block");
+
+ block = b;
+}
+
+Block &Track::get_block() const
+{
+ if(!block)
+ throw InvalidState("No Block");
+
+ return *block;
+}
+
void Track::set_position(const Point &p)
{
pos = p;
namespace Marklin {
+class Block;
class Layout;
class TrackType;
private:
Layout &layout;
const TrackType &type;
+ Block *block;
Point pos;
float rot;
float slope;
Layout &get_layout() const { return layout; }
const TrackType &get_type() const { return type; }
+ void set_block(Block *);
+ Block &get_block() const;
void set_position(const Point &);
void set_rotation(float);
void set_slope(float);