Index: src/train_cmd.cpp =================================================================== --- src/train_cmd.cpp (revision 19022) +++ src/train_cmd.cpp (working copy) @@ -3193,9 +3193,37 @@ uint hash = (y_diff + 7) | (x_diff + 7); if (hash & ~15) return NULL; - /* Slower check using multiplication */ - if (x_diff * x_diff + y_diff * y_diff > 25) return NULL; + /* + * Slower check using multiplication. + * + * The vehicle 'distance' has to account for a wagon on diagonal tracks + * and one on non diagonal track. In this case the distance on one axis + * is 5 and on the other it's 1. Using Pythogoras that gives a distance + * of 5**2 + 1**2 = 26, which is the minimum safe distance (squared). + * The 5 in this formula coincides with half the distance on straight + * track plus 1. + * + * As we can have shorter vehicles we need to calculate the minimum + * distance for them, which is multiplication expensive, so we first + * do a simple sweep by comparing the distance of the trains. Note that + * this also uses Pythagoras and we 'just' remove the sqrt from both + * sides of the equation. + */ + int distance_squared = x_diff * x_diff + y_diff * y_diff; + /* Check for the simply case to prevent costly calculations. */ + if (distance_squared > 25) return NULL; + /* Step 1: calculate the distance between the centers. Wagons are + * always centered by (x + 1) / 2, so we use that here too. */ + int center_distance = + (Train::From(v)->tcache.cached_veh_length + 1) / 2 + + (tcc->v->tcache.cached_veh_length + 1) / 2; + /* Step 2: calculate distance (for the longest axis), which is + * half the distance plus 1. */ + int min_distance = (center_distance + 1) / 2 + 1; + /* Step 3: compare the distance of the wagon with the minimum distance. */ + if (distance_squared > min_distance * min_distance) return NULL; + /* Happens when there is a train under bridge next to bridge head */ if (abs(v->z_pos - tcc->v->z_pos) > 5) return NULL;