+ if(!from.get_turnout_id())
+ throw InvalidParameterValue("Can't divert from a non-turnout");
+ if(routes.empty())
+ return false;
+
+ int path = -1;
+ unsigned from_ep = 0;
+ list<RouteRef>::iterator route = routes.begin();
+ BlockIter block = cur_blocks.back();
+ set<const Track *> visited;
+
+ // Follow our routes to find out where we're entering the turnout
+ while(1)
+ {
+ block = block.next(route->route);
+
+ const Block::Endpoint &entry_ep = block->get_endpoints()[block.entry()];
+
+ if(visited.count(entry_ep.track))
+ return false;
+ visited.insert(entry_ep.track);
+
+ if(!advance_route(route, *entry_ep.track))
+ return false;
+
+ if(entry_ep.track==&from)
+ {
+ if(block->get_train()==this && !free_block(*block))
+ return false;
+
+ from_ep = entry_ep.track_ep;
+ path = route->route->get_turnout(from.get_turnout_id());
+ break;
+ }
+ }
+
+ // Check that more than one path is available
+ unsigned ep_paths = from.get_type().get_endpoints()[from_ep].paths;
+ if(!(ep_paths&(ep_paths-1)))
+ return false;
+
+ // Choose some other path
+ for(int i=0; ep_paths>>i; ++i)
+ if((ep_paths&(1<<i)) && i!=path)
+ {
+ path = i;
+ break;
+ }
+
+ TrackIter track = TrackIter(&from, from_ep).next(path);
+ if(!track)
+ return false;
+
+ unsigned ep = track->get_endpoint_by_link(from);
+
+ set<Track *> tracks;
+ for(list<RouteRef>::iterator i=routes.begin(); i!=routes.end(); ++i)
+ tracks.insert(i->route->get_tracks().begin(), i->route->get_tracks().end());
+ Route *diversion = 0;
+ try
+ {
+ diversion = Route::find(*track, ep, tracks);
+ }
+ catch(const Msp::Exception &)
+ {
+ return false;
+ }
+
+ diversion->set_name("Diversion");
+ diversion->add_track(from);
+ diversion->set_turnout(from.get_turnout_id(), path);
+
+ if(!is_valid_diversion(*diversion, from, from_ep))
+ {
+ delete diversion;
+ return false;
+ }
+
+ // Follow the diversion route until we get back to the original route
+ list<RouteRef>::iterator end = routes.end();
+ while(1)