from Event import * import sys import os sys.path.append(os.path.abspath("../data_retrieval")) from retrieve_line import Line from retrieve_station import Station from segment import Segment import math def removeFirstWord(s): ss = s.split() ret = "" first = True for w in ss[1:]: if(not first): ret+=" " first = False ret+=w return(ret) def station_name_equal(s1,s2): return s1==s2 or removeFirstWord(s1)==s2 def distance_coords(c1,c2): latd1 = c1[0] longd1 = c1[1] latd2 = c2[0] longd2 = c2[1] R = 6378.137 lat1 = math.radians(latd1) long1 = math.radians(longd1) lat2 = math.radians(latd2) long2 = math.radians(longd2) #d = 2R × sin⁻¹(√[sin²((θ₂ - θ₁)/2) + cosθ₁ × cosθ₂ × sin²((φ₂ - φ₁)/2)]) d = 2*R*math.asin(math.sqrt(math.sin((lat1-lat2)/2)**2+math.cos(lat1)*math.cos(lat2)*math.sin((long2-long1)/2)**2)) return(d) def list_events(lines,stations): dic_stations = {} for station in stations: dic_stations[station.link]=station events = [] vertex_indices_per_line = {} for line in lines: i=0 #accumulated_distance =0 coords = line.vertices() accumulated_distance =0 for station_on_line in line.stations_on_line: # Search for the vertex that is closest to the station. It will stop # searching when it finds a vertex that is two times as far as the # minimal distance station= dic_stations[station_on_line.link] if not station.link in vertex_indices_per_line.keys(): vertex_indices_per_line[station.link] = {} min_distance = math.inf if(station.coordinates[0]==None or station.coordinates[1]==None): while(accumulated_distance < station_on_line.distance and i+1 < len(coords)): accumulated_distance += distance_coords(coords[i+1],coords[i]) i+=1 vertex_indices_per_line[station.link][line.number]=i dic_stations[station.link].coordinates = coords[i] while i+12*min_distance): break i+=1 #station = dic_stations[station_on_line.link] #while(accumulated_distance < station_on_line.distance and i+1 < len(coords)): # accumulated_distance += distance_coords(coords[i+1],coords[i]) # i+=1 #if not station.link in vertex_indices_per_line.keys(): # vertex_indices_per_line[station.link] = {} #vertex_indices_per_line[station.link][line.number]=i #if(station.coordinates[0]==None or station.coordinates[1]==None): # dic_stations[station.link].coordinates = coords[i] for line_segment in line.segments: i = 0 start_index = None end_index = None for station_on_line in line.stations_on_line: if(station_name_equal(station_on_line.name,line_segment.start)): start_index = i if(station_name_equal(station_on_line.name,line_segment.end)): end_index = i i+=1 if(line_segment.end=="grens" or line_segment.end==""): end_index = -1 if(line_segment.start=="grens" or line_segment.start==""): start_index = 0 if(start_index==None): print(f"{line_segment.start} could not be found on line {line.number}") if(end_index==None): print(f"{line_segment.end} could not be found on line {line.number}") date = line_segment.date gpx_file_path = f"{line.number}.gpx" opening_or_closure = line_segment.opening_or_closure station_events = [] i=0 stations_on_segment = [] if(end_index==-1): stations_on_segment=line.stations_on_line[start_index:] else: stations_on_segment=line.stations_on_line[start_index:end_index+1] for station_on_line in stations_on_segment: station = dic_stations[station_on_line.link] station_event = station_date_to_station_event(station,line_segment.date,line_segment.opening_or_closure,vertex_indices_per_line[station_on_line.link]) if(station_event!=None): station_events.append(station_event) i+=1 #print(f"end_index is on stations {line.stations_on_line[end_index].link}") start_link=line.stations_on_line[start_index].link end_link=line.stations_on_line[end_index].link start_name = dic_stations[start_link].name end_name =dic_stations[end_link].name if("Elten" in end_name): print(end_name) print(start_index,end_index) print(line.stations_on_line[start_index:end_index+1]) start_coord=dic_stations[start_link].coordinates end_coord =dic_stations[end_link].coordinates segmentEvent=LineSegmentEvent(date,station_events,gpx_file_path,\ start_coord,end_coord,start_name,end_name,opening_or_closure) events.append(segmentEvent) for station in dic_stations.values(): if not station.link in vertex_indices_per_line.keys(): continue vertex_indices = vertex_indices_per_line[station.link] for date in station.openings: events.append(StationEvent(date,station.name,station.coordinates,\ "opening",vertex_indices)) for date in station.closures: events.append(StationEvent(date,station.name,station.coordinates, "closure",vertex_indices)) return(events) def station_date_to_station_event(station,date,opening_or_closure,vertex_indices): if(opening_or_closure == "opening" and date in station.openings): station.openings.remove(date) elif(opening_or_closure == "closures" and date in station.closures): station.closures.remove(date) else: #print(f"Station {station.link} has no opening or closure on date {date}") return(None) return(StationEvent(date,station.name,station.coordinates,opening_or_closure,vertex_indices)) month_str_to_num={'jan':1,'feb':2,'mrt':3,'apr':4,'mei':5,'jun':6,'jul':7,\ 'aug':8,'sep':9,'okt':10,'nov':11,'dec':12} def date_sort_key(date): [day,month,year] = date.split() return(int(day)+31*(month_str_to_num[month]+12*int(year))) def event_sort_key(event): return(date_sort_key(event.date)) #This function returns the script given all the information about the lines #and stations. The script is just a list of events. def script(lines_file,stations_file): lines_element = ET.parse(lines_file).getroot() lines = [] for line_element in lines_element: lines.append(Line.fromXML(line_element)) stations_element = ET.parse(stations_file).getroot() stations = [] for station_element in stations_element: stations.append(Station.fromXML(station_element)) events = list_events(lines,stations) events.sort(key=event_sort_key) return(events) events = script("../data/Lines.xml", "../data/Stations.xml") eventsToXml(events)