Path: blob/main/tools/contributed/sumopy/coremodules/landuse/maps.py
169689 views
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo1# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.2# SUMOPy module3# Copyright (C) 2012-2021 University of Bologna - DICAM4# This program and the accompanying materials are made available under the5# terms of the Eclipse Public License 2.0 which is available at6# https://www.eclipse.org/legal/epl-2.0/7# This Source Code may also be made available under the following Secondary8# Licenses when the conditions for such availability set forth in the Eclipse9# Public License 2.0 are satisfied: GNU General Public License, version 210# or later which is available at11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1314# @file maps.py15# @author Joerg Schweizer16# @date 20121718# size limit at 1280x128019# http://maps.googleapis.com/maps/api/staticmap?size=500x500&path=color:0x000000|weight:10|44.35789,11.3093|44.4378,11.3935&format=GIF&maptype=satellite&scale=220# https://console.cloud.google.com/google/maps-apis21import os22import sys23import numpy as np24import wx25import urllib26from collections import OrderedDict27import agilepy.lib_base.classman as cm28import agilepy.lib_base.arrayman as am29import agilepy.lib_base.xmlman as xm3031import matplotlib.pyplot as plt32from coremodules.misc.matplottools import *3334##from agilepy.lib_base.processes import Process35from coremodules. network import netconvert36from agilepy.lib_base.processes import Process, CmlMixin, P3738import csv3940from matplotlib import cm as cmp41from mpl_toolkits.mplot3d import Axes3D42try:43from scipy import interpolate44is_scipy = True45except:46is_scipy = False4748IS_MAPSUPPORT = True49try:50from PIL import ImageFilter, Image, ImageChops, ImagePath, ImageDraw51except:52print "WARNING: Maps requires PIL module."53IS_MAPSUPPORT = False5455try:56import pyproj5758except:59try:60from mpl_toolkits.basemap import pyproj6162except:63print "WARNING: Maps requires pyproj module."64IS_MAPSUPPORT = False65# print __doc__66# raise676869URL_GOOGLEMAP = "https://maps.googleapis.com/maps/api/staticmap?"707172def download_googlemap(filepath, bbox, proj, size=640, filetype='gif', maptype='satellite'):73print 'download_googlemap', bbox74# https://developers.google.com/maps/documentation/static-maps/intro#Paths75x_sw, y_sw = bbox[0]76x_ne, y_ne = bbox[1]7778# 01 1179#80#81# 00 1082lon00, lat00 = proj(x_sw, y_sw, inverse=True)83lon10, lat10 = proj(x_ne, y_sw, inverse=True)84lon11, lat11 = proj(x_ne, y_ne, inverse=True)85lon01, lat01 = proj(x_sw, y_ne, inverse=True)8687size_x = size_y = size/288url = URL_GOOGLEMAP+"size=%dx%d&visible=%.6f,%.6f|%.6f,%.6f&format=%s&maptype=%s&scale=2"\89% (size_x, size_y, lat00, lon00, lat11, lon11, filetype.upper(), maptype)90print ' url=', url91urllib.urlretrieve(url, filepath)9293bbox_lonlat = np.array([[lon00, lat00], [lon11, lat11]])94return bbox_lonlat959697def download_googlemap_bb(filepath, bbox, proj, apikey, size=640, filetype='gif', maptype='satellite', color="0xff0000ff"):98print 'download_googlemap_bb', bbox99# https://developers.google.com/maps/documentation/static-maps/intro#Paths100x_sw, y_sw = bbox[0]101x_ne, y_ne = bbox[1]102103# 01 11104#105#106# 00 10107lon00, lat00 = proj(x_sw, y_sw, inverse=True)108lon10, lat10 = proj(x_ne, y_sw, inverse=True)109lon11, lat11 = proj(x_ne, y_ne, inverse=True)110lon01, lat01 = proj(x_sw, y_ne, inverse=True)111112size_x = size_y = size/2113114# 3115#116# 0 2117#118# 1119dhx = (x_ne-x_sw)/2120dhy = (y_ne-y_sw)/2121lon0, lat0 = proj(x_sw, y_sw+dhy, inverse=True)122lon1, lat1 = proj(x_sw+dhx, y_sw, inverse=True)123lon2, lat2 = proj(x_ne, y_sw+dhy, inverse=True)124lon3, lat3 = proj(x_sw+dhx, y_ne, inverse=True)125126url = URL_GOOGLEMAP+"key=%s&size=%dx%d&format=%s&maptype=%s&scale=2&path=color:%s|weight:3" % (127apikey, size_x, size_y, filetype.upper(), maptype, color)128url += "|%.6f,%.6f" % (lat0, lon0)129url += "|%.6f,%.6f" % (lat2, lon2)130url += "|%.6f,%.6f" % (lat10, lon10)131url += "|%.6f,%.6f" % (lat1, lon1)132url += "|%.6f,%.6f" % (lat3, lon3)133url += "|%.6f,%.6f" % (lat01, lon01)134url += "|%.6f,%.6f" % (lat00, lon00)135url += "|%.6f,%.6f" % (lat10, lon10)136url += "|%.6f,%.6f" % (lat11, lon11)137url += "|%.6f,%.6f" % (lat3, lon3)138139#url = URL_GOOGLEMAP+"key=%s&size=%dx%d&format=%s&maptype=%s&scale=2&path=color:%s|weight:5"%(apikey,size_x,size_y,filetype.upper(),maptype,color)140#url += "|%.6f,%.6f"%(lat00,lon00)141#url += "|%.6f,%.6f"%(lat10,lon10)142#url += "|%.6f,%.6f"%(lat11,lon11)143#url += "|%.6f,%.6f"%(lat01,lon01)144#url += "|%.6f,%.6f"%(lat00,lon00)145146# urllib.urlretrieve (URL_GOOGLEMAP+"size=%dx%d&format=%s&maptype=%s&scale=2&path=color:0xff0000ff|weight:1|%.5f,%.5f|%.5f,%.5f|%.5f,%.5f|%.5f,%.5f"\147# %(size_x,size_y,filetype,maptype,lat00,lon00, lat11,lon11, lat01,lon01, lat10,lon10), filepath)148print ' url=', url149urllib.urlretrieve(url, filepath)150bbox_lonlat = np.array([[lon00, lat00], [lon11, lat11]])151return bbox_lonlat152153154def estimate_angle(filepath):155156im = Image.open(filepath).convert("RGB")157print 'estimate_angle image', filepath, "%dx%d" % im.size, im.mode, im.getbands()158imr, img, imb = im.split()159160# calculate width and height of bbox in pixel from measured rectangle161#wr = int(np.sqrt((rect[1][0]-rect[0][0])**2+(rect[1][1]-rect[0][1])**2))162#wr_check = int(np.sqrt((rect[2][0]-rect[3][0])**2+(rect[2][1]-rect[3][1])**2))163#hr = int(np.sqrt((rect[3][0]-rect[0][0])**2+(rect[3][1]-rect[0][1])**2))164#h_check = int(np.sqrt((rect[2][0]-rect[1][0])**2+(rect[2][1]-rect[1][1])**2))165166xcb = im.size[0]/2167ycb = im.size[1]/2168wx = im.size[0]169wy = im.size[1]170hx = wx/2171hy = wy/2172173# create an image and draw a rectanle with coordinates from bbox174#bbox = [(xcb-wr/2,ycb-hr/2), (xcb+wr/2,ycb-hr/2), (xcb+wr/2,ycb+hr/2), (xcb-wr/2,ycb+hr/2),(xcb-wr/2,ycb-hr/2)]175im_bbox = ImageChops.constant(im, 0)176draw = ImageDraw.Draw(im_bbox)177draw.line([(0, hy), (wx, hy)], fill=255)178draw.line([(hx, 0), (hx, wy)], fill=255)179del draw180181# rotate im_bbox with different angles182# and correlate with the red component of the image in filepath183# which contains a geo-referenced red rectangle184angles = np.arange(-3.0, 3.0, 0.01)185matches = np.zeros(len(angles))186for i in xrange(len(angles)):187im_bbox_rot = im_bbox.rotate(angles[i]) # gimp 1.62188im_corr = ImageChops.multiply(imr, im_bbox_rot)189# im_corr.show()190im_corr_arr = np.asarray(im_corr)191matches[i] = np.sum(im_corr_arr)/255192# print ' angles[i],matches[i]',angles[i],matches[i]193194angle_opt = angles[np.argmax(matches)]195print ' angle_opt', angle_opt196197ys = np.arange(0, int(0.2*wy), 1)198matches = np.zeros(len(ys))199for y in xrange(len(ys)):200im_bbox = ImageChops.constant(im, 0)201draw = ImageDraw.Draw(im_bbox)202draw.line([(0, y), (wx, y)], fill=255)203draw.line([(0, wy-y), (wx, wy-y)], fill=255)204del draw205im_bbox_rot = im_bbox.rotate(angle_opt)206im_corr = ImageChops.multiply(imr, im_bbox_rot)207# im_corr.show()208im_corr_arr = np.asarray(im_corr)209matches[y] = np.sum(im_corr_arr)/255210# print ' y,matches[y]',y,matches[y]211212y_opt = ys[np.argmax(matches)]213print ' y_opt', y_opt214215if 0:216im_bbox = ImageChops.constant(im, 0)217draw = ImageDraw.Draw(im_bbox)218draw.line([(0, y_opt), (wx, y_opt)], fill=255)219draw.line([(0, wy-y_opt), (wx, wy-y_opt)], fill=255)220im_bbox_rot = im_bbox.rotate(angle_opt)221im_bbox_rot.show()222im.show()223224# assuming rectangle:225bbox = [(y_opt, y_opt), (wx-y_opt, y_opt), (wx-y_opt, wy-y_opt), (y_opt, wy-y_opt), (y_opt, y_opt)]226print ' bbox', bbox227return -angle_opt, bbox228229230class MapsImporter(Process):231def __init__(self, maps, logger=None, **kwargs):232print 'MapsImporter.__init__', maps, maps.parent.get_ident()233self._init_common('mapsimporter', name='Background maps importer',234logger=logger,235info='Downloads and converts background maps.',236)237self._maps = maps238239attrsman = self.set_attrsman(cm.Attrsman(self))240#self.net = attrsman.add( cm.ObjConf( network.Network(self) ) )241# self.status = attrsman.add(cm.AttrConf(242# 'status', 'preparation',243# groupnames = ['_private','parameters'],244# perm='r',245# name = 'Status',246# info = 'Process status: preparation-> running -> success|error.'247# ))248249self.width_tile = attrsman.add(cm.AttrConf('width_tile', kwargs.get('width_tile', 500.0),250groupnames=['options'],251choices=OrderedDict([("500", 500.0),252("1000", 1000.0),253("2000", 2000.0),254("4000", 4000.0),255("8000", 8000.0),256]),257perm='rw',258name='Tile width',259unit='m',260info='Tile width in meter of quadratic tile. This is the real width of one tile that will be downloaded.',261))262263self.size_tile = attrsman.add(cm.AttrConf('size_tile', kwargs.get('size_tile', 1280),264groupnames=['options'],265perm='r',266name='Tile size',267info='Tile size in pixel. This is the size of one tile that will be downloaded and determins the map resolution. Maximum is 1280.',268))269270self.n_tiles = attrsman.add(cm.FuncConf('n_tiles', 'get_n_tiles', 0,271groupnames=['options'],272name='Number of tiles',273#info = 'Delete a row.',274))275276# self.add_option( 'maptype',kwargs.get('maptype','satellite'),277# choices = ['satellite',]278# perm='rw',279# name = 'Map type',280# info = 'Type of map to be downloaded.',281# )282# self.add_option( 'filetype',kwargs.get('filetype','png'),283# choices = ['png',]284# perm='rw',285# name = 'File type',286# info = 'Image file format to be downloaded.',287# )288289# self.add_option( 'mapserver',kwargs.get('mapserver','google'),290# choices = ['google',]291# perm='rw',292# name = 'Map server',293# info = 'Map server from where to download. Some servers require username and password.',294# )295296# self.add_option( 'username',kwargs.get('username',''),297# perm='rw',298# name = 'User',299# info = 'User name of map server (if required).',300# )301302self.apikey = attrsman.add(cm.AttrConf('apikey', kwargs.get('apikey', ''),303groupnames=['options'],304perm='rw',305name='API key',306info='API key for google maps. API key can be obtained from Google at https://cloud.google.com/maps-platform/?refresh=1&pli=1#get-started.',307))308309# self.add_option( 'password',kwargs.get('password',''),310# perm='rw',311# name = 'User',312# info = 'User name of map server (if required).',313# )314315self.is_remove_orig = attrsman.add(cm.AttrConf('is_remove_orig', kwargs.get('is_remove_orig', True),316groupnames=['options'],317perm='rw',318name='Remove originals',319info='Remove original files. Original, untransformed files are not necessary, but can be kept.',320))321322def get_n_tiles(self):323"""324The number of tiles to be downloaded. Please do not download more han 300 tiles, otherwise map server is likely to be offended.325"""326return self._maps.get_n_tiles(self.width_tile)327328def do(self):329self.update_params()330331print 'MapsImporter.do'332# self._maps.download(maptype = self.maptype, mapserver = self.mapserver,333# filetype = 'png', rootfilepath = None,334# width_tile = self.width_tile, size_tile = self.size_tile,335# is_remove_orig = True):336self._maps.download(maptype='satellite', mapserver='google',337filetype='png', rootfilepath=None, apikey=self.apikey,338width_tile=self.width_tile, size_tile=self.size_tile,339is_remove_orig=self.is_remove_orig)340#import_xml(self, rootname, dirname, is_clean_nodes = True)341# self.run_cml(cml)342# if self.status == 'success':343return True344345def update_params(self):346"""347Make all parameters consistent.348example: used by import OSM to calculate/update number of tiles349from process dialog350"""351pass352353354class Maps(am.ArrayObjman):355def __init__(self, landuse, **kwargs):356357self._init_objman(ident='maps',358parent=landuse,359name='Maps',360info='Information on background maps.',361**kwargs)362self._init_attributes()363364def _init_attributes(self):365# print 'maps._init_attributes'366367# self.add(cm.AttrConf( 'width_tile',500,368# groupnames = ['state'],369# perm='r',370# name = 'Tile width',371# unit = 'm',372# info = 'Tile width in meter of quadratic tile. This is the real wdith of one tile that will be downloaded.',373# ))374375# self.add(cm.AttrConf( 'size_tile',1280,376# groupnames = ['state'],377# perm='r',378# name = 'Tile size',379# info = 'Tile size in pixel. This is the size of one tile that will be downloaded.',380# ))381382if self.has_attrname('width_tile'):383# no longer attributes384self.delete('width_tile')385self.delete('size_tile')386# put r/w permissione to older version387# self.get_config('width_tile').set_perm('rw')388# self.get_config('size_tile').set_perm('rw')389390self.add_col(am.ArrayConf('bboxes', np.zeros((2, 2), dtype=np.float32),391groupnames=['state'],392perm='r',393name='BBox',394unit='m',395info='Bounding box of map in network coordinate system (lower left coord, upper right coord).',396is_plugin=True,397))398399self.add_col(am.ArrayConf('filenames', None,400dtype=np.object,401groupnames=['state'],402perm='rw',403metatype='filepath',404name='File',405info='Image file name.',406))407408def write_decals(self, fd, indent=4, rootdir=None, delta=np.zeros(3, dtype=np.float32)):409print 'write_decals', len(self)410net = self.parent.get_net()411if rootdir is None:412rootdir = os.path.dirname(net.parent.get_rootfilepath())413414#proj = pyproj.Proj(str(net.get_projparams()))415#offset = net.get_offset()416#width_tile = self.width_tile.value417#size_tile = self.size_tile.value418419for filename, bbox in zip(self.filenames.get_value(), self.bboxes.get_value()):420#x0, y0 = proj(bbox_lonlat[0][0], bbox_lonlat[0][1])421#x1, y1 = proj(bbox_lonlat[1][0],bbox_lonlat[1][1])422#bbox = np.array([[x0, y0, 0.0],[x1, y1 ,0.0]],np.float32)423424#bbox_tile = [[x_sw,y_sw ],[x_ne,y_ne]]425#x0,y0 = bbox_abs[0]+offset426#x1,y1 = bbox_abs[1]+offset427428#bbox = np.array([[x0, y0, 0.0],[x1, y1 ,0.0]],np.float32)429# print ' bbox decal',bbox430xc, yc = 0.5*(bbox[0]+bbox[1])-delta[:2]431zc = 0.0432width_tile = bbox[1, 0] - bbox[0, 0]433# print ' xc,yc',xc,yc434# print ' width_tile',width_tile,bbox435if filename == os.path.basename(filename):436# filename does not contain path info437filepath = filename # os.path.join(rootdir,filename)438else:439# filename contains path info (can happen if interactively inserted)440filepath = filename441442calxml = '<decal filename="%s" centerX="%.2f" centerY="%.2f" centerZ="0.00" width="%.2f" height="%.2f" altitude="0.00" rotation="0.00" tilt="0.00" roll="0.00" layer="0.00"/>\n' % (443filepath, xc, yc, width_tile, width_tile)444fd.write(indent*' '+calxml)445446def clear_all(self):447"""448Remove all map information.449"""450self.clear_rows()451# here we could also delete files ??452453def update_netoffset(self, deltaoffset):454"""455Called when network offset has changed.456Children may need to adjust theur coordinates.457"""458bboxes = self.bboxes.get_value()459bboxes[:, :, :2] = bboxes[:, :, :2] + deltaoffset460461def get_n_tiles(self, width_tile):462"""463Estimates number of necessary tiles.464"""465net = self.parent.get_net()466bbox_sumo, bbox_lonlat = net.get_boundaries()467x0 = bbox_sumo[0] # -0.5*width_tile468y0 = bbox_sumo[1] # -0.5*width_tile469width = bbox_sumo[2]-x0470height = bbox_sumo[3]-y0471nx = int(width/width_tile+0.5)472ny = int(height/width_tile+0.5)473return nx*ny474475def download(self, maptype='satellite', mapserver='google', apikey=None,476filetype='png', rootfilepath=None,477width_tile=1000.0, size_tile=1280,478is_remove_orig=True):479480self.clear_rows()481net = self.parent.get_net()482if rootfilepath is None:483rootfilepath = net.parent.get_rootfilepath()484485bbox_sumo, bbox_lonlat = net.get_boundaries()486487offset = net.get_offset()488# latlon_sw=np.array([bbox_lonlat[1],bbox_lonlat[0]],np.float32)489# latlon_ne=np.array([bbox_lonlat[3],bbox_lonlat[2]],np.float32)490491x0 = bbox_sumo[0] # -0.5*width_tile492y0 = bbox_sumo[1] # -0.5*width_tile493width = bbox_sumo[2]-x0494height = bbox_sumo[3]-y0495496print 'download to', rootfilepath497498# '+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'499#params_proj="+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"500params_proj = net.get_projparams()501proj = pyproj.Proj(str(params_proj))502# print ' params_proj',params_proj,IS_MAPSUPPORT503# these values are measured manually and are only valid for size_tile = 256/640504# width_tile_eff= width_tile#*float(2*size_tile)/238.0#500m 1205.0*width_tile#m 1208505# height_tile_eff = width_tile#*float(2*size_tile)/238.0# 500m1144.0*width_tile#m 1140506507nx = int(width/width_tile+0.5)508ny = int(height/width_tile+0.5)509print ' offset', offset510print ' bbox_sumo', bbox_sumo511print ' width_tile', width_tile, 'm'512print ' Will download %dx%d= %d maps' % (nx, ny, nx*ny)513#latlon_tile = np.array([(latlon_ne[0]-latlon_sw[0])/ny, (latlon_ne[1]-latlon_sw[1])/nx])514#filepaths = []515#centers = []516#517#518# 0 1519# 3 2520#521# 0 1 2 3522523angle = None524bbox = None525ids_map = []526for ix in xrange(nx):527for iy in xrange(ny):528529# tile in SUMO network coords. These are the saved coords530x_tile = x0+ix*width_tile531y_tile = y0+iy*width_tile532print ' x_tile,y_tile', x_tile, y_tile533bb = np.array([[x_tile, y_tile], [x_tile+width_tile, y_tile+width_tile]], np.float32)534535# tile in absolute coordinates. Coords used for download536x_sw = x_tile-offset[0]537y_sw = y_tile-offset[1]538539x_ne = x_sw+width_tile540y_ne = y_sw+width_tile541bbox_tile = [[x_sw, y_sw], [x_ne, y_ne]]542543filepath = rootfilepath+'_map%04dx%04d.%s' % (ix, iy, filetype)544# print ' filepath=',filepath545546if angle is None:547download_googlemap_bb(filepath, bbox_tile, proj, apikey,548size=size_tile,549filetype=filetype, maptype=maptype)550if os.path.getsize(filepath) > 2000: # download OK551angle, bbox = estimate_angle(filepath)552# sys.exit(0)553else:554print 'WARNING in download: no file downloaded from mapserver'555return ids_map556557bbox_tile_lonlat = download_googlemap_bb(filepath, bbox_tile, proj, apikey,558size=size_tile, filetype=filetype,559maptype=maptype, color="0x0000000f")560561if os.path.getsize(filepath) < 2000: # download failed562print 'WARNING in download: no file downloaded from mapserver'563return ids_map564565print ' bbox_tile', bbox_tile566print ' bbox_tile_lonlat', bbox_tile_lonlat567568im = Image.open(filepath).convert("RGB")569if 1:570print ' downloaded image', filepath, "%dx%d" % im.size, im.mode, im.getbands()571print ' x_sw,y_sw', x_sw, y_sw572print ' x_ne,y_ne', x_ne, y_ne573574# print ' start rotation'575im_rot = im.rotate(angle) # gimp 1.62576# im_rot.show()577region = im_rot.crop([bbox[0][0], bbox[0][1], bbox[2][0], bbox[2][1]])578regsize = region.size579print ' regsize', regsize580im_crop = Image.new('RGB', (regsize[0], regsize[1]), (0, 0, 0))581im_crop.paste(region, (0, 0, regsize[0], regsize[1]))582im_tile = im_crop.resize((1024, 1024))583# im_crop.show()584outfilepath = rootfilepath+'_rot%04dx%04d.%s' % (ix, iy, filetype)585586# print 'save ',outfilepath,"%dx%d" % im_crop.size,im_crop.getbands()587im_tile.save(outfilepath, filetype.upper())588589# print ' bb_orig=',bb590print ' bb_orig', bb591#lon0, lat0 = proj(x_tile-offset[0], y_tile-offset[1])592#lon1, lat1 = proj(x_tile+width_tile-offset[0], y_tile+width_tile-offset[1])593594# print ' bb',bb.shape,bb595# print ' outfilepath',outfilepath,os.path.basename(outfilepath)596# print ' saved bbox',np.array([[x_tile-offset[0], y_tile-offset[1]],[x_tile+width_tile-offset[0], y_tile+width_tile-offset[1]]],np.float32)597# print ' saved bbox',bbox_tile_lonlat598id_map = self.add_row(filenames=os.path.basename(outfilepath),599# bbox_tile,#bbox_tile_lonlat#np.array([[lon0, lat0],[lon1, lat1]],np.float32),600bboxes=bb,601)602ids_map.append(id_map)603604if is_remove_orig:605# remove original file606os.remove(filepath)607608return ids_map609610611class CsvElevationsImport(PlotoptionsMixin, CmlMixin, Process):612def __init__(self, landuse, rootname=None, rootdirpath=None, netfilepath=None,613is_clean_nodes=False, logger=None, **kwargs):614615self._init_common('csvelevationsimporter', name='Elevations csv import',616logger=logger,617info='Imports the elevations .csv file with 3 colums (Longitudes, Latitudes, Elevations), starting from the first lane',618)619self._landuse = landuse620621self.init_cml('netconvert')622623attrsman = self.get_attrsman()624self.add_option('elevationscsv_filepath', '/home/cristian/scenarios_cri/Elevation/bo_elevations2.csv',625groupnames=['options'], # this will make it show up in the dialog626cml='--csv-elevation-file',627perm='rw',628name='Elevations file',629wildcards='Elevations CSV file(*.csv)|*.csv*',630metatype='filepath',631info='Elevations CSV file in',632)633634self.interpolation_radius = attrsman.add(cm.AttrConf('interpolation_radius', kwargs.get('interpolation_radius', 150.),635groupnames=['options'],636name='Interpolation radius',637info='In order to find the quote of an unknown ponit, will be interpolated the elevation points around him within this radius.\638If it count zero, the point wil have the quote equal to the nearest elevation point. ',639))640641# self.method_interp = attrsman.add(cm.AttrConf( 'method_interp', kwargs.get('method_interp', 'cubic'),642## groupnames = ['options'],643## choices = ['linear', 'cubic', 'quintic'],644## name = 'Interpolation method',645## info = 'Elevation interpolation method.',646# ))647648self.x_offset = attrsman.add(cm.AttrConf('x_offset', kwargs.get('x_offset', -679244.),649groupnames=['options'],650perm='rw',651name='Longitude offset',652unit='m',653info='Longitude Offset for the importation phase.',654))655656self.y_offset = attrsman.add(cm.AttrConf('y_offset', kwargs.get('y_offset', -4924610.),657groupnames=['options'],658perm='rw',659name='Latitude offset',660unit='m',661info='Latitude Offset for the importation phase.',662))663664self.is_plot_elevations = attrsman.add(cm.AttrConf('is_plot_elevations', kwargs.get('is_plot_elevations', False),665groupnames=['options'],666perm='rw',667name='Plot Elevations',668info='Plot point elevations.',669))670671# Match elevations672673self.is_match_to_nodes = attrsman.add(cm.AttrConf('is_match_to_nodes', kwargs.get('is_match_to_nodes', True),674groupnames=['options'],675perm='rw',676name='Match to node',677info='Match the elevations to the network nodes.',678))679680# self.is_match_to_nodes_shape = attrsman.add(cm.AttrConf( 'is_match_to_nodes_shape',kwargs.get('is_match_to_nodes_shape',True),681## groupnames = ['options'],682# perm='rw',683## name = 'Match to node shapes',684## info = 'Match the elevations to the network nodes shapes.',685# ))686687# self.is_match_to_edge = attrsman.add(cm.AttrConf( 'is_match_to_node',kwargs.get('is_match_to_node',True),688## groupnames = ['options'],689# perm='rw',690## name = 'Match to node',691## info = 'Matche the elevations to the network nodes.',692# ))693694self.is_match_to_edges = attrsman.add(cm.AttrConf('is_match_to_edges', kwargs.get('is_match_to_edges', True),695groupnames=['options'],696perm='rw',697name='Match to edge ',698info='Match the elevations to the network edges.',699))700701self.is_match_to_zones = attrsman.add(cm.AttrConf('is_match_to_zones', kwargs.get('is_match_to_zones', True),702groupnames=['options'],703perm='rw',704name='Match to zones',705info='Match the elevations to the assignment zones.',706))707708# self.is_match_to_zones_shape = attrsman.add(cm.AttrConf( 'is_match_to_zones_shape',kwargs.get('is_match_to_zones_shape',True),709## groupnames = ['options'],710# perm='rw',711## name = 'Match to node shapes',712## info = 'Match the elevations to the network nodes shapes.',713# ))714715self.is_match_to_facilities = attrsman.add(cm.AttrConf('is_match_to_facilities', kwargs.get('is_match_to_facilities', True),716groupnames=['options'],717perm='rw',718name='Match to facilities',719info='Match the elevations to the facilities.',720))721722# self.is_match_to_facilities_shape = attrsman.add(cm.AttrConf( 'is_match_to_facilities_shape',kwargs.get('is_match_to_facilities_shape',True),723## groupnames = ['options'],724# perm='rw',725## name = 'Match to facility shapes',726## info = 'Match the elevations to the facility shapes.',727# ))728729self.add_plotoptions(**kwargs)730self.add_save_options(**kwargs)731attrsman.delete('plottype')732attrsman.delete('length_arrowhead')733734def do(self):735736net = self._landuse.parent.net737738with open(self.elevationscsv_filepath, 'r') as csvFile:739reader = csv.reader(csvFile)740i = 1741longitudes = []742latitudes = []743elevations = []744ids_point = []745for row in reader:746747longitudes.append(float(row[0]))748latitudes.append(float(row[1]))749elevations.append(float(row[2]))750ids_point.append(i)751i += 1752753ids_point = np.array(ids_point)754longitudes = np.array(longitudes) + self.x_offset755latitudes = np.array(latitudes) + self.y_offset756elevations = np.array(elevations)757758csvFile.close()759#################################################################################760quote = self.evaluate_quote(longitudes, latitudes, elevations, 2000., 10000.)761quote = self.evaluate_quote(longitudes, latitudes, elevations, 4000., 7000.)762quote = self.evaluate_quote(longitudes, latitudes, elevations, 7000., 11000.)763quote = self.evaluate_quote(longitudes, latitudes, elevations, 10000., 3000.)764###################################################765766if self.is_match_to_nodes:767nodes = net.nodes768ids_node = nodes.get_ids()769coords = nodes.coords[ids_node]770for coord, id_node in zip(coords, ids_node):771772quote = self.evaluate_quote(longitudes, latitudes, elevations, coord[0], coord[1])773774nodes.coords[id_node] = [coord[0], coord[1], quote]775# print 'node_coord', nodes.coords[id_node]776777shapes = nodes.shapes[ids_node]778for shape, id_node in zip(shapes, ids_node):779for coord, i in zip(shape, range(len(shape))):780# print coord781# print np.stack((longitudes, latitudes), axis = -1)782quote = self.evaluate_quote(longitudes, latitudes, elevations, coord[0], coord[1])783nodes.shapes[id_node][i] = [coord[0], coord[1], quote]784# print 'node_shape', nodes.shapes[id_node]785786# coord[0]787# coord[1]788789if self.is_match_to_edges:790edges = net.edges791ids_edge = edges.get_ids()792shapes = edges.shapes[ids_edge]793for shape, id_edge in zip(shapes, ids_edge):794positive_climb = 0.795negative_climb = 0.796for coord, i in zip(shape, range(len(shape))):797# print coord798# print np.stack((longitudes, latitudes), axis = -1)799quote = self.evaluate_quote(longitudes, latitudes, elevations, coord[0], coord[1])800801edges.shapes[id_edge][i] = [coord[0], coord[1], quote]802print edges.shapes[id_edge][i]803if i > 0 and (quote-quote_pre) > 0:804positive_climb += (quote-quote_pre)805elif i > 0 and (quote-quote_pre) < 0:806negative_climb += (-quote + quote_pre)807quote_pre = quote808# print 'edge_shape', edges.shapes[id_edge][i]809slope = (edges.shapes[id_edge][-1][2]-edges.shapes[id_edge][0][2])/edges.lengths[id_edge]810edges.average_slopes[id_edge] = slope811edges.positive_climbs[id_edge] = positive_climb812edges.negative_climbs[id_edge] = negative_climb813# print 'slope', slope814815# if self.is_match_to_zones:816##817# if self.is_match_to_facilities:818819#######################820if self.is_plot_elevations:821fig = plt.figure()822ax = fig.add_subplot(111)823## import matplotlib824## import matplotlib.pyplot as plt825## cm = matplotlib.cm.get_cmap('RdYlBu')826# plt.subplot(111)827## plt.scatter(longitudes, latitudes, c=elevations, s=20, vmax = 70)828# plt.colorbar()829# plt.show()830plot_point_results_on_map(self, net, ax, longitudes, latitudes, values=elevations,831title='Elevations', valuelabel='[m]',832)833plt.show()834############################################835836return True837838def evaluate_quote(self, longitudes, latitudes, elevations, x_point, y_point):839840dists = np.sqrt(np.sum((np.stack((longitudes, latitudes), axis=-1) - [x_point, y_point])**2, 1))841842if is_scipy:843print 'use scipy to interpolate'844#tck = interpolate.splrep(x, y, s=0)845#xnew = np.linspace(np.min(x), np.max(x), 200)846#ynew = interpolate.splev(xnew, tck, der=0)847# if 1:848849nearest_longitudes = longitudes[(dists < self.interpolation_radius)]850nearest_latitudes = latitudes[(dists < self.interpolation_radius)]851nearest_elevations = elevations[(dists < self.interpolation_radius)]852## nearest_longitudes = longitudes[(longitudes < x_point + self.interpolation_radius)&(longitudes > x_point - self.interpolation_radius)&(latitudes < y_point + self.interpolation_radius)&(latitudes > y_point - self.interpolation_radius)]853## nearest_latitudes = latitudes[(longitudes < x_point + self.interpolation_radius)&(longitudes > x_point - self.interpolation_radius)&(latitudes < y_point + self.interpolation_radius)&(latitudes > y_point - self.interpolation_radius)]854## nearest_elevations = elevations[(longitudes < x_point + self.interpolation_radius)&(longitudes > x_point - self.interpolation_radius)&(latitudes < y_point + self.interpolation_radius)&(latitudes > y_point - self.interpolation_radius)]855print[x_point, y_point], nearest_longitudes, nearest_latitudes, nearest_elevations856if len(nearest_longitudes) > 15:857858f_inter = interpolate.SmoothBivariateSpline(859nearest_longitudes, nearest_latitudes, nearest_elevations,) # kind = self.method_interp )860## #############################################861## xnew = np.linspace(x_point-self.interpolation_radius/2, x_point+self.interpolation_radius/2,200)862## ynew = np.linspace(y_point-self.interpolation_radius/2, y_point+self.interpolation_radius/2,200)863## X, Y = np.meshgrid(xnew, ynew)864## Z = f_inter(xnew, ynew)865##866##867## fig = plt.figure()868## ax = fig.gca(projection='3d')869##870##871# Plot the surface.872# surf = ax.plot_surface(X, Y, Z, cmap=cmp.coolwarm,873# linewidth=0, antialiased=False)874##875## fig.colorbar(surf, shrink=0.5, aspect=5)876# plt.savefig('/home/cristian/scenarios_cri/Elevation/interpolation_%d'%(xnew[0]))877# plt.show()878#############################################879quote = f_inter(x_point, y_point)880else:881quote = elevations[np.argmin(dists)]882print 'nearest quote'883else:884885nearest_quotes = elevations[(dists < 100)]886nearest_dists = dists[(dists < 100)]887numerator = 0.0888denominator = 0.0889for near_quote, near_dist in zip(nearest_quotes, nearest_dists):890numerator += near_quote/(10**(near_dist/10))891denominator += 1/(10**(near_dist/10))892# print numerator, denominator893if denominator != 0:894quote = numerator/denominator895else:896quote = elevations[np.argmin(dists)]897print 'nearest quote'898899return quote900901902if __name__ == '__main__':903############################################################################904###905pass906907908