|
|
|
|
@ -29,7 +29,7 @@
|
|
|
|
|
|
|
|
|
|
#rename to common.py? |
|
|
|
|
from bitstring import BitArray |
|
|
|
|
import copy,code |
|
|
|
|
import copy,csv,code |
|
|
|
|
|
|
|
|
|
language="de"#currently supported: de, en (both partially) |
|
|
|
|
|
|
|
|
|
@ -43,6 +43,40 @@ def ordinal(num):
|
|
|
|
|
# the second parameter is a default. |
|
|
|
|
suffix = SUFFIXES.get(num % 10, 'th') |
|
|
|
|
return str(num) + suffix |
|
|
|
|
class lcl: |
|
|
|
|
def __init__(self,lcldir): |
|
|
|
|
self.points= self.dat_to_dict(lcldir+'POINTS.DAT','ISO 8859-15','LCD') |
|
|
|
|
self.poffsets= self.dat_to_dict(lcldir+'POFFSETS.DAT','ISO 8859-15','LCD') |
|
|
|
|
self.names= self.dat_to_dict(lcldir+'NAMES.DAT','ISO 8859-15','NID') |
|
|
|
|
self.roads=self.dat_to_dict(lcldir+'ROADS.DAT','ISO 8859-15','LCD') |
|
|
|
|
self.segments=self.dat_to_dict(lcldir+'SEGMENTS.DAT','ISO 8859-15','LCD') |
|
|
|
|
self.allocated_codes=self.dat_to_dict(lcldir+'LOCATIONCODES.DAT','ISO 8859-15','LCD') |
|
|
|
|
self.areas=self.dat_to_dict(lcldir+'ADMINISTRATIVEAREA.DAT','ISO 8859-15','LCD') |
|
|
|
|
def lcn_allocated(self,LCN): |
|
|
|
|
return bool(self.allocated_codes[LCN]["ALLOCATED"]) |
|
|
|
|
def get_poffsets(self,LCD): |
|
|
|
|
return self.poffsets[LCD] |
|
|
|
|
def get_segment(self,LCD): |
|
|
|
|
return self.segments[LCD] |
|
|
|
|
def get_road(self,LCD): |
|
|
|
|
return self.roads[LCD] |
|
|
|
|
def get_area(self,LCD): |
|
|
|
|
return self.areas[LCD] |
|
|
|
|
def get_point(self,LCD): |
|
|
|
|
return self.points[LCD] |
|
|
|
|
def get_name(self,NID): |
|
|
|
|
return self.names[NID]["NAME"] |
|
|
|
|
def dat_to_dict(self,filename,encoding,id_col_name): |
|
|
|
|
csv_reader = csv.reader(open(filename), delimiter=';', quotechar='"') |
|
|
|
|
header=csv_reader.next() |
|
|
|
|
ret_dict={} |
|
|
|
|
for row in csv_reader: |
|
|
|
|
# decode ISO 8859-15 back to Unicode, cell by cell: #TODO read encoding from README.DAT |
|
|
|
|
unirow=[unicode(cell, encoding) for cell in row] |
|
|
|
|
linedict=dict(zip(header,unirow)) |
|
|
|
|
id_num=int(linedict[id_col_name]) |
|
|
|
|
ret_dict[id_num]=linedict |
|
|
|
|
return ret_dict |
|
|
|
|
class tmc_event: |
|
|
|
|
def __init__(self,ecn,tableobj): |
|
|
|
|
self.tableobj=tableobj |
|
|
|
|
@ -160,13 +194,63 @@ class tmc_event:
|
|
|
|
|
def __repr__(self): |
|
|
|
|
return "ecn:%i"%self.ecn |
|
|
|
|
class tmc_location: |
|
|
|
|
#def get_extent_location(self,extent,direction): |
|
|
|
|
#__recursion_get_extent_location(self,extent,direction) |
|
|
|
|
#def __recursion_get_extent_location(self,loc,extent,direction): #direction: 0:pos, 1:neg |
|
|
|
|
def __ref_locs(self,lcn,name_string=""): |
|
|
|
|
if(lcn==34196):#europe |
|
|
|
|
return(name_string) |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
loc_dict=self.lcl_obj.get_area(lcn) |
|
|
|
|
aref=int(loc_dict[u'POL_LCD']) |
|
|
|
|
loc_name=self.lcl_obj.get_name(int(self.loc_dict['N1ID'])) |
|
|
|
|
return(self.__ref_locs(aref,name_string+","+loc_name)) |
|
|
|
|
except KeyError: |
|
|
|
|
return(name_string) |
|
|
|
|
def __getitem__(self,item): |
|
|
|
|
return self.loc_dict[item] |
|
|
|
|
def __init__(self,lcn,lcl_obj): |
|
|
|
|
self.lcn=lcn |
|
|
|
|
self.lcl_obj=lcl_obj |
|
|
|
|
self.reflocs=self.__ref_locs(lcn) |
|
|
|
|
self.is_valid=False |
|
|
|
|
self.loc_dict={} |
|
|
|
|
self.has_koord=False |
|
|
|
|
self.linRef=None |
|
|
|
|
if self.lcl_obj.lcn_allocated(lcn): |
|
|
|
|
try: |
|
|
|
|
self.loc_dict=self.lcl_obj.get_point(lcn) |
|
|
|
|
self.is_valid=True |
|
|
|
|
self.ltype=self.loc_dict[u'CLASS']+self.loc_dict[u'TCD'] |
|
|
|
|
try: |
|
|
|
|
self.subtype=int(self.loc_dict[u'STCD']) |
|
|
|
|
except ValueError:#should not happen, all rows have int |
|
|
|
|
self.subtype=0 |
|
|
|
|
print("location subtype %s is invalid in location %i"%(self.loc_dict[u'STCD'],lcn)) |
|
|
|
|
self.roadnumber="" |
|
|
|
|
self.roadname=self.lcl_obj.get_name(int(self.loc_dict['RNID'])) |
|
|
|
|
self.first_name=self.lcl_obj.get_name(int(self.loc_dict['N1ID'])) |
|
|
|
|
self.second_name=self.lcl_obj.get_name(int(self.loc_dict['N2ID'])) |
|
|
|
|
if not self.loc_dict['ROA_LCD']==u"": |
|
|
|
|
self.linRef=tmc_location(int(self.loc_dict['ROA_LCD']),tableobj) |
|
|
|
|
self.negative_offset=int(self.lcl_obj.get_poffsets(lcd)[u"NEG_OFF_LCD"]) |
|
|
|
|
self.positive_offset=int(self.lcl_obj.get_poffsets(lcd)[u"POS_OFF_LCD"]) |
|
|
|
|
try: |
|
|
|
|
#koords stored in WGS84 format with decimal degrees multiplied with 10^5 |
|
|
|
|
self.xkoord=int(self.loc_dict[u"XCOORD"])/100000.0 |
|
|
|
|
self.ykoord=int(self.loc_dict[u"YCOORD"])/100000.0 |
|
|
|
|
self.koord_str="%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
self.koord_str_google="{lat: %f, lng: %f}"%(self.ykoord,self.xkoord) |
|
|
|
|
self.google_maps_link="https://www.google.de/maps/place/%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
self.has_koord=True |
|
|
|
|
except ValueError: |
|
|
|
|
self.has_koord=False |
|
|
|
|
self.is_valid=True |
|
|
|
|
if not lcn==34196:#Europe does not have an area reference |
|
|
|
|
self.aref=tmc_location(int(self.loc_dict['POL_LCD']),tableobj) |
|
|
|
|
except KeyError: |
|
|
|
|
print("point '%i' not found"%lcn) |
|
|
|
|
elif self.tableobj.log or self.tableobj.debug: |
|
|
|
|
print("lcn not allocated %i"%lcn) |
|
|
|
|
def get_extent_location(self,loc,extent,direction): #direction: 0:pos, 1:neg |
|
|
|
|
#print(loc.lcn) |
|
|
|
|
#print(extent) |
|
|
|
|
#print(direction) |
|
|
|
|
if extent==0 or not loc.is_valid: |
|
|
|
|
return loc |
|
|
|
|
else: |
|
|
|
|
@ -177,20 +261,6 @@ class tmc_location:
|
|
|
|
|
offset_loc=tmc_location(int(offset),self.tableobj) |
|
|
|
|
#return __recursion_get_extent_location(offset_loc,extent-1,direction) |
|
|
|
|
return offset_loc.get_extent_location(offset_loc,extent-1,direction) |
|
|
|
|
def __ref_locs(self,lcn,name_string=""): |
|
|
|
|
#if not self.is_valid: #not used, since not called from outside |
|
|
|
|
# return "" |
|
|
|
|
if(lcn==34196):#europe |
|
|
|
|
return(name_string) |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
locarray=self.tableobj.lcl_dict[lcn] |
|
|
|
|
aref=int(locarray[6]) |
|
|
|
|
loc_name=locarray[4] |
|
|
|
|
return(self.__ref_locs(aref,name_string+","+loc_name)) |
|
|
|
|
#return(loc_name) |
|
|
|
|
except KeyError: |
|
|
|
|
return(name_string) |
|
|
|
|
def __str__(self): |
|
|
|
|
if not self.is_valid: |
|
|
|
|
return "invalid lcn:%i"%(self.lcn) |
|
|
|
|
@ -218,52 +288,117 @@ class tmc_location:
|
|
|
|
|
#return '%s,%i:%s, geo:<a href="%s">%s</a>'%(self.ltype,self.subtype,name,self.google_maps_link,self.koord_str) |
|
|
|
|
else: |
|
|
|
|
return "%s,%i:%s"%(self.ltype,self.subtype,name) |
|
|
|
|
#if self.ltype[0]=="A":#area |
|
|
|
|
#return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
#elif self.ltype[0]=="L":#line |
|
|
|
|
#return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
#elif self.ltype[0]=="P":#point |
|
|
|
|
#return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
def __init__(self,lcn,tableobj): |
|
|
|
|
self.tableobj=tableobj |
|
|
|
|
self.reflocs=self.__ref_locs(lcn) |
|
|
|
|
self.lcn=lcn |
|
|
|
|
self.has_koord=False |
|
|
|
|
self.linRef=None |
|
|
|
|
self.is_valid=False |
|
|
|
|
try: |
|
|
|
|
loc_array=tableobj.lcl_dict[lcn] |
|
|
|
|
self.ltype=loc_array[0] |
|
|
|
|
try: |
|
|
|
|
self.subtype=int(loc_array[1]) |
|
|
|
|
except ValueError:#should not happen, all rows have int |
|
|
|
|
self.subtype=0 |
|
|
|
|
print("location subtype %s is invalid in location %i"%(loc_array[1],lcn)) |
|
|
|
|
self.roadnumber=loc_array[2] |
|
|
|
|
self.roadname=loc_array[3] |
|
|
|
|
self.first_name=loc_array[4] |
|
|
|
|
self.second_name=loc_array[5] |
|
|
|
|
if not loc_array[7]=="": |
|
|
|
|
self.linRef=tmc_location(int(loc_array[7]),tableobj) |
|
|
|
|
self.negative_offset=loc_array[8] |
|
|
|
|
self.positive_offset=loc_array[9] |
|
|
|
|
try: |
|
|
|
|
#koords stored in WGS84 format with decimal degrees multiplied with 10^5 |
|
|
|
|
self.xkoord=int(loc_array[27])/100000.0 |
|
|
|
|
self.ykoord=int(loc_array[28])/100000.0 |
|
|
|
|
self.koord_str="%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
self.koord_str_google="{lat: %f, lng: %f}"%(self.ykoord,self.xkoord) |
|
|
|
|
self.google_maps_link="https://www.google.de/maps/place/%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
self.has_koord=True |
|
|
|
|
except ValueError: |
|
|
|
|
self.has_koord=False |
|
|
|
|
self.is_valid=True |
|
|
|
|
if not lcn==34196:#Europe does not have an area reference |
|
|
|
|
self.aref=tmc_location(int(loc_array[6]),tableobj) |
|
|
|
|
except KeyError: |
|
|
|
|
#print("location '%i' not found"%lcn) |
|
|
|
|
self.is_valid=False |
|
|
|
|
##LOCATIONCODE;TYPE;SUBTYPE;ROADNUMBER;ROADNAME;FIRST_NAME;SECOND_NAME;AREA_REFERENCE;LINEAR_REFERENCE;NEGATIVE_OFFSET;POSITIVE_OFFSET;URBAN;INTERSECTIONCODE;INTERRUPTS_ROAD;IN_POSITIVE;OUT_POSITIVE;IN_NEGATIVE;OUT_NEGATIVE;PRESENT_POSITIVE;PRESENT_NEGATIVE;EXIT_NUMBER;DIVERSION_POSITIVE;DIVERSION_NEGATIVE;VERÄNDERT;TERN;NETZKNOTEN_NR;NETZKNOTEN2_NR;STATION;X_KOORD;Y_KOORD;POLDIR;ADMIN_County;ACTUALITY;ACTIVATED;TESTED;SPECIAL1;SPECIAL2;SPECIAL3;SPECIAL4;SPECIAL5;SPECIAL6;SPECIAL7;SPECIAL8;SPECIAL9;SPECIAL10 |
|
|
|
|
#~ class tmc_location: |
|
|
|
|
#~ def __init__(self,lcn,tableobj): |
|
|
|
|
#~ self.tableobj=tableobj |
|
|
|
|
#~ self.lcl_obj=tableobj.lcl_obj |
|
|
|
|
#~ self.reflocs=self.__ref_locs(lcn) |
|
|
|
|
#~ self.lcn=lcn |
|
|
|
|
#~ self.has_koord=False |
|
|
|
|
#~ self.linRef=None |
|
|
|
|
#~ self.is_valid=False |
|
|
|
|
#~ if self.lcl_obj.lcn_allocated(lcn): |
|
|
|
|
#~ pass |
|
|
|
|
#~ elif self.tableobj.log or self.tableobj.debug: |
|
|
|
|
#~ print("lcn not allocated %i"%lcn) |
|
|
|
|
#~ try: |
|
|
|
|
#~ loc_array=tableobj.lcl_dict[lcn] |
|
|
|
|
#~ self.ltype=loc_array[0] |
|
|
|
|
#~ try: |
|
|
|
|
#~ self.subtype=int(loc_array[1]) |
|
|
|
|
#~ except ValueError:#should not happen, all rows have int |
|
|
|
|
#~ self.subtype=0 |
|
|
|
|
#~ print("location subtype %s is invalid in location %i"%(loc_array[1],lcn)) |
|
|
|
|
#~ self.roadnumber=loc_array[2] |
|
|
|
|
#~ self.roadname=loc_array[3] |
|
|
|
|
#~ self.first_name=loc_array[4] |
|
|
|
|
#~ self.second_name=loc_array[5] |
|
|
|
|
#~ if not loc_array[7]=="": |
|
|
|
|
#~ self.linRef=tmc_location(int(loc_array[7]),tableobj) |
|
|
|
|
#~ self.negative_offset=loc_array[8] |
|
|
|
|
#~ self.positive_offset=loc_array[9] |
|
|
|
|
#~ try: |
|
|
|
|
#~ #koords stored in WGS84 format with decimal degrees multiplied with 10^5 |
|
|
|
|
#~ self.xkoord=int(loc_array[27])/100000.0 |
|
|
|
|
#~ self.ykoord=int(loc_array[28])/100000.0 |
|
|
|
|
#~ self.koord_str="%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
#~ self.koord_str_google="{lat: %f, lng: %f}"%(self.ykoord,self.xkoord) |
|
|
|
|
#~ self.google_maps_link="https://www.google.de/maps/place/%f,%f"%(self.ykoord,self.xkoord) |
|
|
|
|
#~ self.has_koord=True |
|
|
|
|
#~ except ValueError: |
|
|
|
|
#~ self.has_koord=False |
|
|
|
|
#~ self.is_valid=True |
|
|
|
|
#~ if not lcn==34196:#Europe does not have an area reference |
|
|
|
|
#~ self.aref=tmc_location(int(loc_array[6]),tableobj) |
|
|
|
|
#~ except KeyError: |
|
|
|
|
#~ #print("location '%i' not found"%lcn) |
|
|
|
|
#~ self.is_valid=False |
|
|
|
|
#~ ##LOCATIONCODE;TYPE;SUBTYPE;ROADNUMBER;ROADNAME;FIRST_NAME;SECOND_NAME;AREA_REFERENCE;LINEAR_REFERENCE;NEGATIVE_OFFSET;POSITIVE_OFFSET;URBAN;INTERSECTIONCODE;INTERRUPTS_ROAD;IN_POSITIVE;OUT_POSITIVE;IN_NEGATIVE;OUT_NEGATIVE;PRESENT_POSITIVE;PRESENT_NEGATIVE;EXIT_NUMBER;DIVERSION_POSITIVE;DIVERSION_NEGATIVE;VERÄNDERT;TERN;NETZKNOTEN_NR;NETZKNOTEN2_NR;STATION;X_KOORD;Y_KOORD;POLDIR;ADMIN_County;ACTUALITY;ACTIVATED;TESTED;SPECIAL1;SPECIAL2;SPECIAL3;SPECIAL4;SPECIAL5;SPECIAL6;SPECIAL7;SPECIAL8;SPECIAL9;SPECIAL10 |
|
|
|
|
|
|
|
|
|
#~ #def get_extent_location(self,extent,direction): |
|
|
|
|
#~ #__recursion_get_extent_location(self,extent,direction) |
|
|
|
|
#~ #def __recursion_get_extent_location(self,loc,extent,direction): #direction: 0:pos, 1:neg |
|
|
|
|
#~ def get_extent_location(self,loc,extent,direction): #direction: 0:pos, 1:neg |
|
|
|
|
#~ #print(loc.lcn) |
|
|
|
|
#~ #print(extent) |
|
|
|
|
#~ #print(direction) |
|
|
|
|
#~ if extent==0 or not loc.is_valid: |
|
|
|
|
#~ return loc |
|
|
|
|
#~ else: |
|
|
|
|
#~ offset=loc.positive_offset if direction==0 else loc.negative_offset |
|
|
|
|
#~ if offset=="": |
|
|
|
|
#~ return loc |
|
|
|
|
#~ else: |
|
|
|
|
#~ offset_loc=tmc_location(int(offset),self.tableobj) |
|
|
|
|
#~ #return __recursion_get_extent_location(offset_loc,extent-1,direction) |
|
|
|
|
#~ return offset_loc.get_extent_location(offset_loc,extent-1,direction) |
|
|
|
|
#~ def __ref_locs(self,lcn,name_string=""): |
|
|
|
|
#~ #if not self.is_valid: #not used, since not called from outside |
|
|
|
|
#~ # return "" |
|
|
|
|
#~ if(lcn==34196):#europe |
|
|
|
|
#~ return(name_string) |
|
|
|
|
#~ else: |
|
|
|
|
#~ try: |
|
|
|
|
#~ locarray=self.tableobj.lcl_dict[lcn] |
|
|
|
|
#~ aref=int(locarray[6]) |
|
|
|
|
#~ loc_name=locarray[4] |
|
|
|
|
#~ return(self.__ref_locs(aref,name_string+","+loc_name)) |
|
|
|
|
#~ #return(loc_name) |
|
|
|
|
#~ except KeyError: |
|
|
|
|
#~ return(name_string) |
|
|
|
|
#~ def __str__(self): |
|
|
|
|
#~ if not self.is_valid: |
|
|
|
|
#~ return "invalid lcn:%i"%(self.lcn) |
|
|
|
|
#~ elif self.ltype=="P1" and self.subtype==1:#autobahnkreuz TODO:only add if name does not already contain "Kreuz" |
|
|
|
|
#~ name="Kreuz "+self.first_name |
|
|
|
|
#~ elif self.ltype=="P1" and self.subtype==2:#autobahndreieck TODO:only add if name does not already contain "Dreieck" |
|
|
|
|
#~ name="Dreieck "+self.first_name |
|
|
|
|
#~ elif not self.roadname=="": |
|
|
|
|
#~ name="STR:"+self.roadname#TODO remove debug |
|
|
|
|
#~ elif not self.first_name=="": |
|
|
|
|
#~ name=self.first_name |
|
|
|
|
#~ else: |
|
|
|
|
#~ name="NO NAME lcn:%i"%(self.lcn) |
|
|
|
|
#~ return "%s,%i:%s"%(self.ltype,self.subtype,name)#no geo |
|
|
|
|
#~ def __repr__(self): |
|
|
|
|
#~ if not self.is_valid: |
|
|
|
|
#~ return "invalid lcn:%i"%(self.lcn) |
|
|
|
|
#~ #elif self.ltype[0:2] == "P1": #junction |
|
|
|
|
#~ elif self.first_name=="":#no first name-> use aref name |
|
|
|
|
#~ name=self.aref |
|
|
|
|
#~ else: |
|
|
|
|
#~ name=self.roadname+","+self.first_name |
|
|
|
|
#~ if self.has_koord: |
|
|
|
|
#~ return "%s,%i:%s, geo:%s"%(self.ltype,self.subtype,name,self.koord_str) |
|
|
|
|
#~ #return '%s,%i:%s, geo:<a href="%s">%s</a>'%(self.ltype,self.subtype,name,self.google_maps_link,self.koord_str) |
|
|
|
|
#~ else: |
|
|
|
|
#~ return "%s,%i:%s"%(self.ltype,self.subtype,name) |
|
|
|
|
#~ #if self.ltype[0]=="A":#area |
|
|
|
|
#~ #return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
#~ #elif self.ltype[0]=="L":#line |
|
|
|
|
#~ #return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
#~ #elif self.ltype[0]=="P":#point |
|
|
|
|
#~ #return "%s:%s"%(self.ltype,self.first_name) |
|
|
|
|
|
|
|
|
|
class tmc_dict: |
|
|
|
|
"dict of tmc messages sorted by location (LCN) and update class, automatically deletes/updates invalid(ated) items" |
|
|
|
|
@ -511,8 +646,6 @@ class tmc_message:
|
|
|
|
|
def __str__(self): |
|
|
|
|
return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str() |
|
|
|
|
def __repr__(self): |
|
|
|
|
#event_name=self.ecl_dict[self.tmc_event][1] |
|
|
|
|
#message_string="TMC-message,event:%s location:%i,reflocs:%s, station:%s"%(event_name,self.tmc_location,self.ref_locs(self.tmc_location,""),self.RDS_data[PI]["PSN"]) |
|
|
|
|
return "single:%i,complete:%i,event:%i location:%s"%(self.is_single,self.is_complete,self.event.ecn,self.location) |
|
|
|
|
def getDate(self): |
|
|
|
|
if self.hastime: |
|
|
|
|
@ -575,7 +708,6 @@ class tmc_message:
|
|
|
|
|
self.data_arr=BitArray() |
|
|
|
|
self.mgm_list=[] |
|
|
|
|
self.location=tmc_location(tmc_z,tableobj) |
|
|
|
|
self.tmc_location=self.location#decrepated |
|
|
|
|
#self.event=int(tmc_y&0x7ff) #Y10-Y0 |
|
|
|
|
self.event=tmc_event(int(tmc_y&0x7ff),self.tableobj) #Y10-Y0 |
|
|
|
|
self.events=[self.event] |
|
|
|
|
|