import math import geojson class GeoJSON(): def __init__(self, v): self.data = v.data self.refX, self.refY = self.getMapReference() self.startX, self.startY = self.getStartReference() self.refLat, self.refLng = self.getRefLat() self.geojson = self.createGeoJSON() def getMapReference(self): """ Retrieve reference map coordinates from Vissim parameters Input: None Output: x, y coordinates """ x = float(self.data.xpath('./netPara/refPointMap')[0].attrib['x']) y = float(self.data.xpath('./netPara/refPointMap')[0].attrib['y']) return x, y def getStartReference(self): """ Retrieve reference start coordinates from Vissim parameters Input: None Output: x, y coordinates """ x = float(self.data.xpath('./netPara/refPointNet')[0].attrib['x']) y = float(self.data.xpath('./netPara/refPointNet')[0].attrib['y']) return x, y def metersToLatLng(self, x, y): """ Convert xy points to latlng. Input: x, y Output: WGS84 lat/lng """ extent = 20015085 # height/width in meters of the VISSIM map lng = x * 180 / float(extent) y = y * 180 / float(extent) lat = math.atan(math.exp(y*(math.pi/180.0))) * (360 / math.pi) - 90 return lat, lng def getRefLat(self): refLat, refLng = self.metersToLatLng(self.refX, self.refY) return refLat, refLng def scaledMetersToNode(self, xy): """ Remove Mercator scaling factor and reference point. Input: scaled xy Output: latlng node """ scaleX, scaleY = xy scaleX, scaleY = float(scaleX), float(scaleY) scale = 1 / math.cos(math.radians(self.refLat)) x = (scaleX * scale) + self.refX - self.startX y = (scaleY * scale) + self.refY - self.startY lat, lng = self.metersToLatLng(x, y) return lat, lng def createGeoJSON(self): """ Get list of link geometries and properties to be converted. Input: Vissim object Output: list of links """ features = [] for link in self.data.xpath('./links/link'): geos = [] linkNum = link.attrib['no'] for geo in link.xpath('./geometry/points3D/point3D'): x, y = geo.attrib['x'], geo.attrib['y'] latLng = self.scaledMetersToNode((x, y)) geos.append(latLng) linkNum = link.attrib['no'] laneNum = str(len(link.xpath('./lanes/lane'))) multiLine = geojson.MultiLineString(coordinates=geos) features.append(geojson.Feature(id=linkNum, geometry=multiLine, properties={'lane': laneNum, 'id': linkNum})) return geojson.FeatureCollection(features) def export(self, filename): """ Export GeoJSON object to file Input: filename Output: written file """ f = open(filename, 'w') f.writelines(geojson.dumps(self.geojson)) f.close()