def __init__(self, code, name, offset, relative_to=None): self.code = code self.name = name self._offset = offset self.relative_to = relative_to self.platforms = SortedDict() self.placed = SortedDict() self.label_direction = None self.label_offset = Vector(0, 0)
def load(self, filename): self.stations = SortedDict() self.lines = SortedDict() self.extents = [0, 0, 0, 0] self.outbounds = [] draw_last = [] draw_first = [] with open(filename) as fh: for lineno, line in enumerate(fh): line = line.strip() if line and line[0] != "#": # Get the parts parts = line.split() type, parts = parts[0], parts[1:] # What kind of line is it? if type == "line": # Line definition code = parts[0] colors = [( int(part[0:2], 16) / 255.0, int(part[2:4], 16) / 255.0, int(part[4:8], 16) / 255.0, ) for part in parts[1].split(",")] self.lines[code] = Line(code, colors) # Track segment elif type in ("track", "subtrack"): # It's a station-to-station description station_code, platform_number = parts[0].split("-", 1) dest_code, dest_number = parts[1].split("-", 1) station = self.stations[station_code] # Check for reverses leaves_start = False if platform_number[-1] == "!": leaves_start = True platform_number = platform_number[:-1] finishes_end = False if dest_number[-1] == "!": finishes_end = True dest_number = dest_number[:-1] # Add it try: self.add_outbound( station.platforms[platform_number], self.stations[dest_code]. platforms[dest_number], self.lines[parts[2]], leaves_start=leaves_start, finishes_end=finishes_end, subtrack=(type == "subtrack"), ) except: print "Error context: %s, %s" % (station, parts) raise # Station/waypoint record elif type in ("station", "waypoint", "depot", "sidings", "disstation"): # It's a station or points definition code = parts[0] index = 1 while "," not in parts[index]: index += 1 name = " ".join(parts[1:index]) # Work out the coordinates coord_parts = parts[index].split(",") coords = Vector(*map(float, coord_parts[-2:])) * 10 if len(coord_parts) == 3: relative_to = self.stations[coord_parts[0]] else: relative_to = None if type == "station": station_class = Station elif type == "depot": station_class = Depot elif type == "sidings": station_class = Sidings elif type == "disstation": station_class = DisusedStation else: station_class = Points last_station = self.stations[code] = station_class( code, name, coords, relative_to=relative_to, ) self.extents[0] = min(coords.x, self.extents[0]) self.extents[1] = max(coords.x, self.extents[1]) self.extents[2] = min(coords.y, self.extents[2]) self.extents[3] = max(coords.y, self.extents[3]) # Platform record elif type == "platform": # Add a platform to the last station direction = getattr(Direction, parts[1]) try: line = self.lines[parts[2]] except (IndexError, KeyError): line = self.lines["error"] try: platform_side_code = parts[3] platform_side = { "L": Segment.PLATFORM_LEFT, "R": Segment.PLATFORM_RIGHT, "B": Segment.PLATFORM_BOTH, "N": Segment.PLATFORM_NONE, }[platform_side_code.upper()] except IndexError: platform_side = Segment.PLATFORM_BOTH self.stations[code].add_platform( parts[0], direction, line, platform_side) # Drawing order modifiers elif type == "draw": if parts[0] == "first": draw_first.append(last_station) elif parts[0] == "last": draw_last.append(last_station) else: raise ValueError("Unknown draw position %r" % parts[0]) # Label placement modifiers elif type == "label": last_station.label_direction = getattr( Direction, parts[0]) elif type == "label_offset": last_station.label_offset = Vector( map(int, parts[0].split(","))) # Unknown else: raise ValueError("Unknown line type %r" % type) # Now reorder those with special draw clauses for station in draw_first: self.stations.insert(0, station.code, station) for station in draw_last: self.stations.insert(len(self.stations), station.code, station)