Commit b949bd01448fe80d59d15abbac47a4335a9bb951

Authored by Edmar Moretti
1 parent 2940ba44
Exists in master and in 1 other branch docker

Código python para cálculo de melhor caminho

ferramentas/melhorcaminho/LEIAME 0 → 100755
... ... @@ -0,0 +1,87 @@
  1 +para execução do script é necessário executar as seguintes linhas no terminal
  2 +
  3 +sudo apt-get install python-pip python-dev build-essential
  4 +sudo pip install --upgrade pip
  5 +sudo pip install gdal scikit-image pyyaml
  6 +
  7 +É necessário instalar tbm o YAML no PHP:
  8 +
  9 +sudo pecl install yaml
  10 +
  11 +Depois de instalado é necessário incluir no php.ini:
  12 +
  13 +extension=yaml.so
  14 +
  15 +e reiniciar o apache
  16 +
  17 +
  18 +--------------------------------------------------------------------------------
  19 +O script lê os parâmetros a partir de um arquivo yaml cujo nome é definido ao executar o programa
  20 +
  21 +Para executar o arquivo é necessário invocá-lo no terminal:
  22 +
  23 +./better_path.py /path/to/source.yaml
  24 +
  25 +
  26 +--------------------------------------------------------------------------------
  27 +Exemplo de arquivo YAML:
  28 +
  29 +cost_surface_path: /home/diego/Documentos/better_path/sources/cost_surfaces/MS_Custo_LT.tif
  30 +pathresult: /home/diego/Documentos/better_path/p01
  31 +processes:
  32 + p1:
  33 + calculation_type: best_path_lut
  34 + lut:
  35 + - {min: 0.33, max: 0.795255, nv: 0.31}
  36 + - {min: 0, max: 0.2, nv: 0.1}
  37 + file_prefix: custo1
  38 + start_coord: [-37.95350887511466, -11.943630837101258]
  39 + stop_coord: [-45.14970144166611, -12.302899835863277]
  40 + p2:
  41 + calculation_type: best_path_within_buffer
  42 + buffer_km: 10
  43 + file_prefix: custo2
  44 + start_coord: [-37.95350887511466, -11.943630837101258]
  45 + stop_coord: [-45.14970144166611, -12.302899835863277]
  46 + p3:
  47 + calculation_type: informed_path_cost
  48 + informed_path: /home/diego/Documentos/better_path/sources/user_lines/caminho_usuario.shp
  49 + file_prefix: custo3
  50 + start_coord: [-37.95350887511466, -11.943630837101258]
  51 + stop_coord: [-45.14970144166611, -12.302899835863277]
  52 + p4:
  53 + calculation_type: cartesian_straight_line_cost
  54 + file_prefix: custo4
  55 + start_coord: [-37.95350887511466, -11.943630837101258]
  56 + stop_coord: [-45.14970144166611, -12.302899835863277]
  57 + p5:
  58 + calculation_type: best_path
  59 + file_prefix: custo5
  60 + start_coord: [-37.95350887511466, -11.943630837101258]
  61 + stop_coord: [-45.14970144166611, -12.302899835863277]
  62 +
  63 +
  64 +--------------------------------------------------------------------------------
  65 +Descrição dos parâmetros:
  66 +
  67 +cost_surface_path: arquivo raster com o valor do custo em cada pixel
  68 +pathresult: pasta onde serão guardados os resultados
  69 +processes: lista de processos que serão executados
  70 +
  71 + xxxx: nome do processo (apenas para referência do programa)
  72 +
  73 + calculation_type: tipo de cálculo que será executado no processo
  74 + file_prefix: prefixo que será usado nos arquivos resultantes do processo
  75 + lut: parâmetros de reclassificação indicando o range e o valor reclassificado
  76 + start_coord: ponto A
  77 + stop_coord: ponto B
  78 + ou
  79 + informed_path: arquivo shapefile com uma linha (opcional)
  80 +
  81 + buffer_km: buffer de entorno da linha reta entre A e B que será considerado no cálculo do caminho (opcional)
  82 +
  83 +
  84 +--------------------------------------------------------------------------------
  85 +Resultado:
  86 +
  87 +Os arquivos shapefile e o arquivo result.yaml são gerados na pasta de destino especificada no arquivo de parâmetros
... ...
ferramentas/melhorcaminho/better_path.py 0 → 100755
... ... @@ -0,0 +1,383 @@
  1 +#!/usr/bin/python
  2 +# -*- coding: utf-8 -*-
  3 +"""
  4 +Created on Mon Feb 9 00:02:35 2015
  5 +
  6 +@author: Diego Moreira Carvalho
  7 +@email: moreira.geo@gmail.com
  8 +"""
  9 +
  10 +
  11 +import os, sys
  12 +import numpy as np
  13 +import yaml
  14 +from osgeo import gdal, ogr, osr
  15 +from skimage.graph import route_through_array
  16 +
  17 +
  18 +BASE_PATH = os.path.dirname(__file__)
  19 +RASTERIZE_COLOR_FIELD = "color"
  20 +noDataValue = -9999
  21 +
  22 +
  23 +INFORMED_PATH_COST = 'informed_path_cost'
  24 +CARTESIAN_STRAIGHT_LINE_COST = 'cartesian_straight_line_cost'
  25 +BEST_PATH = 'best_path'
  26 +BEST_PATH_WITHIN_BUFFER = 'best_path_within_buffer'
  27 +BEST_PATH_LUT = 'best_path_lut'
  28 +
  29 +TYPES_CALCULATIONS = [INFORMED_PATH_COST,CARTESIAN_STRAIGHT_LINE_COST, BEST_PATH,
  30 + BEST_PATH_WITHIN_BUFFER, BEST_PATH_LUT]
  31 +
  32 +def cleanDirectories():
  33 + dirs = [os.path.join(BASE_PATH,'tmp/raster/'),os.path.join(BASE_PATH,'tmp/shp/')]
  34 + for d in dirs:
  35 + filelist = [ f for f in os.listdir(d) if os.path.isfile(os.path.join(d,f))]
  36 + for f in filelist:
  37 + os.remove(os.path.join(d,f))
  38 +
  39 +def coord2pixelOffset(rasterfn,x,y):
  40 + raster = gdal.Open(rasterfn)
  41 + geotransform = raster.GetGeoTransform()
  42 + originX = geotransform[0]
  43 + originY = geotransform[3]
  44 + pixelWidth = geotransform[1]
  45 + pixelHeight = geotransform[5]
  46 + xOffset = int((x - originX)/pixelWidth)
  47 + yOffset = int((y - originY)/pixelHeight)
  48 +
  49 + return xOffset,yOffset
  50 +
  51 +def pixelsOffset2coord(rasterfn,pixels):
  52 + raster = gdal.Open(rasterfn)
  53 + geotransform = raster.GetGeoTransform()
  54 + coords = []
  55 + for lin, col in pixels:
  56 + Xgeo = (geotransform[0] + col*geotransform[1] + lin*geotransform[2] +
  57 + (geotransform[1] + lin*geotransform[2])/2)
  58 + Ygeo = (geotransform[3] + lin*geotransform[5] + col*geotransform[4] +
  59 + (geotransform[5] + col*geotransform[4])/2)
  60 + coords.append([Xgeo,Ygeo])
  61 +
  62 + return coords
  63 +
  64 +
  65 +def raster2array(rasterfn):
  66 + raster = gdal.Open(rasterfn)
  67 + band = raster.GetRasterBand(1)
  68 + array = band.ReadAsArray()
  69 + return array
  70 +
  71 +def array2raster(newRasterfn,rasterfn,array, dataType=None, zeroAsNoData=False):
  72 + raster = gdal.Open(rasterfn)
  73 + band =raster.GetRasterBand(1)
  74 + if not dataType:
  75 + dataType = band.DataType
  76 +
  77 + outRaster = createRaster(rasterfn,newRasterfn, dataType)
  78 +
  79 + outband = outRaster.GetRasterBand(1)
  80 + outband.SetNoDataValue(noDataValue)
  81 + if zeroAsNoData:
  82 + array[array==0] = noDataValue
  83 + outband.WriteArray(array)
  84 +
  85 + outband.FlushCache()
  86 + return outRaster
  87 +
  88 +def createCartesianLineGeom(p0,p1):
  89 + line = ogr.Geometry(ogr.wkbLineString)
  90 + line.AddPoint(p0[0], p0[1])
  91 + line.AddPoint(p1[0], p1[1])
  92 + return line
  93 +
  94 +def createCartesianLineStringGeom(points):
  95 + line = ogr.Geometry(ogr.wkbLineString)
  96 + for i in points:
  97 + line.AddPoint(i[0], i[1])
  98 + return line
  99 +
  100 +
  101 +def getFirstLine(vectorFilePath):
  102 + driver = ogr.GetDriverByName("ESRI Shapefile")
  103 + dataSource = driver.Open(vectorFilePath, 0)
  104 + layer = dataSource.GetLayer()
  105 + for f in layer:
  106 + geom = f.GetGeometryRef()
  107 + return createCartesianLineStringGeom(geom.GetPoints())
  108 +
  109 +def createShape(path, geom, projection):
  110 + layer_name = os.path.basename(path).split('.')[0]
  111 + drv = ogr.GetDriverByName( "ESRI Shapefile" )
  112 + dst_ds = drv.CreateDataSource(path)
  113 + if dst_ds:
  114 + print "Failed to create feature in shapefile.\n"
  115 + return False
  116 +
  117 + dst_layer = dst_ds.CreateLayer(str(layer_name), srs=projection, geom_type = geom.GetGeometryType() )
  118 + field_def = ogr.FieldDefn(RASTERIZE_COLOR_FIELD, ogr.OFTReal)
  119 + dst_layer.CreateField(field_def)
  120 + source_layer_def = dst_layer.GetLayerDefn()
  121 + field_index = source_layer_def.GetFieldIndex(RASTERIZE_COLOR_FIELD)
  122 +
  123 + feat = ogr.Feature( source_layer_def)
  124 + feat.SetField(field_index, 1)
  125 + feat.SetGeometry(geom)
  126 + if dst_layer.CreateFeature(feat) != 0:
  127 + print "Failed to create feature in shapefile.\n"
  128 + return False
  129 + return True
  130 +
  131 +
  132 +def createRaster(rasterLayerModelPath, outputRasterPath, bandType=gdal.GDT_Byte):
  133 + s_raster = gdal.Open(rasterLayerModelPath)
  134 + s_driver = s_raster.GetDriver()
  135 +
  136 + geotransform = s_raster.GetGeoTransform()
  137 + s_origin_x = geotransform[0]
  138 + s_origin_y = geotransform[3]
  139 + s_pixel_width = geotransform[1]
  140 + s_pixel_height = geotransform[5]
  141 + s_x_rotation = geotransform[2]
  142 + s_y_rotation = geotransform[4]
  143 +
  144 + s_colls = s_raster.RasterXSize
  145 + s_rows = s_raster.RasterYSize
  146 + target_ds = s_driver.Create(outputRasterPath, s_colls, s_rows, 1, bandType)
  147 + target_ds.SetGeoTransform(( s_origin_x, s_pixel_width, s_x_rotation,
  148 + s_origin_y, s_y_rotation, s_pixel_height,
  149 + ))
  150 + target_ds.SetProjection(s_raster.GetProjectionRef())
  151 + return target_ds
  152 +
  153 +def calculateProximity(src_filename, dst_filename):
  154 + src_ds = gdal.Open( src_filename)
  155 + srcband = src_ds.GetRasterBand(1)
  156 + target_ds = createRaster(src_filename, dst_filename,gdal.GDT_Int32 )
  157 + dstband = target_ds.GetRasterBand(1)
  158 + options = []
  159 + options.append( 'DISTUNITS=PIXEL' )
  160 + options.append( 'NODATA=noDataValue')
  161 + gdal.ComputeProximity( srcband, dstband, options)
  162 + target_ds = None
  163 +
  164 +def rasterize(vectorPath, rasterLayerModelPath, outputRasterPath):
  165 + orig_data_source = ogr.Open(vectorPath)
  166 +
  167 + source_layer = orig_data_source.GetLayer(0)
  168 +
  169 + target_ds = createRaster(rasterLayerModelPath, outputRasterPath)
  170 + # Rasterize
  171 + err = gdal.RasterizeLayer(target_ds, (1,), source_layer,
  172 + burn_values=(0,),
  173 + options=["ATTRIBUTE=%s" % RASTERIZE_COLOR_FIELD,"ALL_TOUCHED=TRUE"])
  174 + if err != 0:
  175 + raise Exception("error rasterizing layer: %s" % err)
  176 +
  177 +def lookUpTable(cost_surface_path, new_cost_surface_path, luts):
  178 + costSurfaceArray = raster2array(cost_surface_path)
  179 + for i in luts:
  180 + costSurfaceArray[np.logical_and(costSurfaceArray >= i['min'], costSurfaceArray <= i['max'])] = i['nv']
  181 + array2raster(new_cost_surface_path, cost_surface_path, costSurfaceArray, None, True)
  182 +
  183 +def createPath(cost_surface_path, startCoord,stopCoord):
  184 +
  185 + costSurfaceArray = raster2array(cost_surface_path)
  186 + # coordinates to array index
  187 + startCoordX = startCoord[0]
  188 + startCoordY = startCoord[1]
  189 + startIndexX,startIndexY = coord2pixelOffset(cost_surface_path,startCoordX,startCoordY)
  190 +
  191 + stopCoordX = stopCoord[0]
  192 + stopCoordY = stopCoord[1]
  193 + stopIndexX,stopIndexY = coord2pixelOffset(cost_surface_path,stopCoordX,stopCoordY)
  194 + # create path
  195 + indices, weight = route_through_array(costSurfaceArray,
  196 + (startIndexY,startIndexX),
  197 + (stopIndexY,stopIndexX),geometric=True,fully_connected=True)
  198 + indiceT = np.array(indices).T
  199 + path = np.zeros_like(costSurfaceArray)
  200 + path[indiceT[0], indiceT[1]] = 1
  201 +
  202 + return path, indices
  203 +
  204 +def calculateCost(item, cost_surface_path, path_result, file_prefix, line, vector_path, raster_path):
  205 + s_raster = gdal.Open(cost_surface_path)
  206 + s_projection = osr.SpatialReference(s_raster.GetProjectionRef())
  207 + costSurfaceArray = raster2array(cost_surface_path)
  208 +
  209 + createShape(vector_path, line, s_projection)
  210 + rasterize(vector_path, cost_surface_path, raster_path)
  211 +
  212 + line_as_array = raster2array(raster_path)
  213 + path_cost = np.sum(costSurfaceArray*line_as_array)
  214 + return {'item': item, 'cost': float(path_cost),
  215 + 'geom': str(line.ExportToWkt())}
  216 +
  217 +def calculateCostInformedPath(cost_surface_path, path_result, file_prefix,
  218 + start_coord, stop_coord, informed_path):
  219 +
  220 + line_raster_path = os.path.join(path_result,'%s_%s.tiff'% (file_prefix, INFORMED_PATH_COST))
  221 + line_vector_path = os.path.join(path_result,'%s_%s.shp'% (file_prefix, INFORMED_PATH_COST))
  222 +
  223 + line = getFirstLine(informed_path)
  224 +
  225 + return calculateCost(INFORMED_PATH_COST, cost_surface_path, path_result, file_prefix,
  226 + line, line_vector_path, line_raster_path)
  227 +
  228 +
  229 +def calculateCostCartesianStraightLine(cost_surface_path, path_result, file_prefix,
  230 + start_coord, stop_coord):
  231 + line_raster_path = os.path.join(path_result,'%s_%s.tiff'% (file_prefix, CARTESIAN_STRAIGHT_LINE_COST))
  232 + line_vector_path = os.path.join(path_result,'%s_%s.shp'% (file_prefix, CARTESIAN_STRAIGHT_LINE_COST))
  233 +
  234 + line = createCartesianLineGeom(start_coord, stop_coord)
  235 +
  236 + return calculateCost(CARTESIAN_STRAIGHT_LINE_COST, cost_surface_path, path_result, file_prefix,
  237 + line, line_vector_path, line_raster_path)
  238 +
  239 +def calculateCostBestPath(cost_surface_path, path_result, file_prefix,
  240 + start_coord, stop_coord):
  241 + line_raster_path = os.path.join(path_result,'%s_%s.tiff'% (file_prefix, BEST_PATH))
  242 + line_vector_path = os.path.join(path_result,'%s_%s.shp'% (file_prefix, BEST_PATH))
  243 +
  244 + pathArray, indices = createPath(cost_surface_path, start_coord, stop_coord) # creates path array
  245 + line = createCartesianLineStringGeom(pixelsOffset2coord(cost_surface_path, indices))
  246 +
  247 + return calculateCost(BEST_PATH, cost_surface_path, path_result, file_prefix,
  248 + line, line_vector_path, line_raster_path)
  249 +
  250 +
  251 +def calculateCostBestPathLUT(cost_surface_path, path_result, file_prefix,
  252 + start_coord, stop_coord, luts):
  253 + line_raster_path = os.path.join(path_result,'%s_%s.tiff'% (file_prefix, BEST_PATH_LUT))
  254 + line_vector_path = os.path.join(path_result,'%s_%s.shp'% (file_prefix, BEST_PATH_LUT))
  255 + new_cost_surface_path = os.path.join(path_result,'%s_lut_cost_%s.tiff'% (file_prefix, BEST_PATH_LUT))
  256 +
  257 + lookUpTable(cost_surface_path, new_cost_surface_path, luts)
  258 +
  259 + pathArray, indices = createPath(new_cost_surface_path, start_coord, stop_coord) # creates path array
  260 + line = createCartesianLineStringGeom(pixelsOffset2coord(cost_surface_path, indices))
  261 +
  262 + return calculateCost(BEST_PATH_LUT, cost_surface_path, path_result, file_prefix,
  263 + line, line_vector_path, line_raster_path)
  264 +
  265 +
  266 +def calculateCostBestPathWithinBuffer(cost_surface_path, path_result, file_prefix,
  267 + start_coord, stop_coord, buffer_km):
  268 + line_raster_path = os.path.join(path_result,'%s_%s.tiff'% (file_prefix, BEST_PATH_WITHIN_BUFFER))
  269 + line_vector_path = os.path.join(path_result,'%s_%s.shp'% (file_prefix, BEST_PATH_WITHIN_BUFFER))
  270 + buffer_vector_path = os.path.join(path_result,'%s_buffer_%s.shp'% (file_prefix, BEST_PATH_WITHIN_BUFFER))
  271 + buffer_cost_path = os.path.join(path_result,'%s_buffer_cost_%s.tiff'% (file_prefix, BEST_PATH_WITHIN_BUFFER))
  272 +
  273 + s_raster = gdal.Open(cost_surface_path)
  274 + s_projection = osr.SpatialReference(s_raster.GetProjectionRef())
  275 + costSurfaceArray = raster2array(cost_surface_path)
  276 +
  277 + base_line = createCartesianLineGeom(start_coord, stop_coord)
  278 +
  279 + createShape(buffer_vector_path, base_line.Buffer(((1.0/60)/1.852)*buffer_km), s_projection)
  280 + rasterize(buffer_vector_path, cost_surface_path, buffer_cost_path)
  281 + buffer_raster_array = raster2array(buffer_cost_path)
  282 +
  283 + costSurface_10km = costSurfaceArray * buffer_raster_array
  284 + array2raster(buffer_cost_path, cost_surface_path, costSurface_10km, None, True)
  285 +
  286 + pathArray, indices = createPath(buffer_cost_path, start_coord, stop_coord) # creates path array
  287 + line = createCartesianLineStringGeom(pixelsOffset2coord(cost_surface_path, indices))
  288 +
  289 + return calculateCost(BEST_PATH_WITHIN_BUFFER, cost_surface_path, path_result, file_prefix,
  290 + line, line_vector_path, line_raster_path)
  291 +
  292 +
  293 +def main(args = None):
  294 + if len(args) == 1:
  295 + return 1
  296 + fileName = args[1]
  297 + if os.path.isfile(fileName):
  298 + parFile = open(fileName)
  299 + contents = parFile.read()
  300 + try:
  301 + parameters = yaml.load(contents)
  302 + except:
  303 + return 1
  304 + parFile.close()
  305 +
  306 + errors = []
  307 + resultList = []
  308 +
  309 + cost_surface_path = parameters['cost_surface_path']
  310 + path_result = parameters['pathresult']
  311 +
  312 + if not os.path.isdir(path_result):
  313 + os.makedirs(path_result)
  314 +
  315 + fileResultsDic = {}
  316 + fileResultsDic['parameters'] = parameters
  317 +
  318 + processes = parameters['processes']
  319 + for k, v in processes.iteritems():
  320 + start_coord = v['start_coord']
  321 + stop_coord = v['stop_coord']
  322 + calculation_type = v['calculation_type']
  323 + file_prefix = v['file_prefix']
  324 + if calculation_type == INFORMED_PATH_COST:
  325 + informed_path = v['informed_path'] if 'informed_path' in v and\
  326 + os.path.isfile(v['informed_path']) else None
  327 + if informed_path:
  328 + result = calculateCostInformedPath(cost_surface_path, path_result, file_prefix,
  329 + start_coord, stop_coord, informed_path)
  330 + result['process'] = '%s_%s'%(k, file_prefix)
  331 + resultList.append(result)
  332 + else:
  333 + errors.append('process: %s - calculation type: %s - \
  334 + Msg: The path is not valid'%(k, calculation_type))
  335 +
  336 + elif calculation_type == CARTESIAN_STRAIGHT_LINE_COST:
  337 + result = calculateCostCartesianStraightLine(cost_surface_path, path_result, file_prefix,
  338 + start_coord, stop_coord)
  339 + result['process'] = '%s_%s'%(k, file_prefix)
  340 + resultList.append(result)
  341 +
  342 + elif calculation_type == BEST_PATH_WITHIN_BUFFER:
  343 + buffer_km = v['buffer_km'] if 'buffer_km' in v and\
  344 + isinstance(v['buffer_km'], (int, long, float)) else None
  345 + if buffer_km:
  346 + result = calculateCostBestPathWithinBuffer(cost_surface_path, path_result, file_prefix,
  347 + start_coord, stop_coord, buffer_km)
  348 + result['process'] = '%s_%s'%(k, file_prefix)
  349 + resultList.append(result)
  350 + else:
  351 + errors.append("process: %s - calculation type: %s - \
  352 + Msg: buffer_km isn't a number"%(k, calculation_type))
  353 + elif calculation_type == BEST_PATH_LUT:
  354 + lut = v['lut'] if 'lut' in v else None
  355 + if lut:
  356 + result = calculateCostBestPathLUT(cost_surface_path, path_result, file_prefix,
  357 + start_coord, stop_coord, lut)
  358 + result['process'] = '%s_%s'%(k, file_prefix)
  359 + resultList.append(result)
  360 + else:
  361 + errors.append("process: %s - calculation type: %s - \
  362 + Msg: lut was not informed "%(k, calculation_type))
  363 + elif calculation_type == BEST_PATH:
  364 + result = calculateCostBestPath(cost_surface_path, path_result, file_prefix,
  365 + start_coord, stop_coord)
  366 + result['process'] = '%s_%s'%(k, file_prefix)
  367 + resultList.append(result)
  368 + else:
  369 + errors.append('process: %s - Msg: Calculation Type: %s is invalid'%(k, calculation_type))
  370 +
  371 +
  372 + fileResultsDic['results'] = resultList
  373 + fileResultsDic['errors'] = errors
  374 +
  375 + strResult = yaml.safe_dump(fileResultsDic)
  376 + fileName = 'result.yaml'
  377 + f = open( os.path.join(path_result, fileName), 'w')
  378 + f.write(strResult)
  379 + f.close()
  380 +
  381 +
  382 +if __name__ == '__main__':
  383 + sys.exit(main(sys.argv))
0 384 \ No newline at end of file
... ...
ferramentas/melhorcaminho/source.yaml 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +cost_surface_path: /var/www_geobahia_17/geodados/MS_Custo_LT.tif
  2 +pathresult: /tmp/ms_tmp/p0
  3 +processes:
  4 + p1:
  5 + calculation_type: best_path_lut
  6 + lut:
  7 + - {min: 0.33, max: 0.795255, nv: 0.31}
  8 + - {min: 0, max: 0.2, nv: 0.1}
  9 + file_prefix: custo1
  10 + start_coord: [-37.95350887511466, -11.943630837101258]
  11 + stop_coord: [-45.14970144166611, -12.302899835863277]
  12 + p2:
  13 + calculation_type: best_path_within_buffer
  14 + buffer_km: 10
  15 + file_prefix: custo2
  16 + start_coord: [-37.95350887511466, -11.943630837101258]
  17 + stop_coord: [-45.14970144166611, -12.302899835863277]
  18 + p3:
  19 + calculation_type: informed_path_cost
  20 + informed_path: /var/www_geobahia_17/caminho_usuario.shp
  21 + file_prefix: custo3
  22 + start_coord: [-37.95350887511466, -11.943630837101258]
  23 + stop_coord: [-45.14970144166611, -12.302899835863277]
  24 + p4:
  25 + calculation_type: cartesian_straight_line_cost
  26 + file_prefix: custo4
  27 + start_coord: [-37.95350887511466, -11.943630837101258]
  28 + stop_coord: [-45.14970144166611, -12.302899835863277]
  29 + p5:
  30 + calculation_type: best_path
  31 + file_prefix: custo5
  32 + start_coord: [-37.95350887511466, -11.943630837101258]
  33 + stop_coord: [-45.14970144166611, -12.302899835863277]
... ...