node 、字符串转xml_1.node-gdal: shapefile in and geojson out

这篇博客介绍了如何利用Node.js、Express、MongoDB和GDAL构建一个简单的GIS Server,该服务器能够将传统GIS数据格式(如Shapefile)转换为GeoJSON并进行RESTful服务响应。文章详细讲解了从数据上传、格式转换到存储的流程,并探讨了为何选择GeoJSON作为数据格式的原因。
摘要由CSDN通过智能技术生成

1ce07d39fc68c240d6d5bcebe4ad4aba.png

前言

这是零起步的第一篇,零不是绝对意义上的零,有Node+Express框架做为基底,其它的事情就只需关注我们要做什么。另外,类似如何新建一个Express应用程序,不是本文重点,请另行找寻资料。从本篇起,会一步步来说明如果最终形成green-gis-server 0.1.0版本代码,中间有些临时想法也会一并介绍,故中间代码并非最终仓库代码,但中间思路必不可少。(仓库地址)

GIS Server的简单诉求

GIS Server,它作为一个服务,必然是要为请求提供资源的,这是它最单纯的目的。同时,作为一个专业的服务,它提供的必然也是专业的资源,简而言之,它要向客户端提供GIS数据。但有所区别的是,文件服务器往往是客户提供文件名,服务器返回对应文件;而GIS服务器,客户会提交更为复杂的请求参数,比如有时请求整个图层(确切说是要素类,Layer=Feature+Symbol+Label+other layer definition),有时通过空间范围或查询条件请求符合条件的部分数据,有时请求多个图层加渲染的动态图片,所以请求方式多而且复杂,这也是为什么OGC要规范WFS、WMS、WMTS等协议与接口的原因,让所有GIS Server之间能够以统一的方式来交互。

惭愧的是,从做05年开始做.net开发,到15年之后彻底的转向了前端开发,XML,Web Service这些再也回不去了,转而代之的是JSON、Express Restful Service。因此,从这个角度出发,GeoJSON是我们实现轻量服务的最佳格式,也是目前前端多个API可以兼容的数据格式,了解的同仁,可以关注下除了Leaflet之外的非GIS API:例如Echarts、d3等等。

综上,在这一篇:最最简单诉求,请求通过要素名称返回对应的GeoJSON数据格式。

GeoJSON

请求通过要素名称返回对应的GeoJSON数据格式,这个需求有很多实现方法,可能最简单就是一个文件服务器,管理一堆GeoJSON文件,用户请求哪个文件名就返回哪个。OK,没问题,广义来说,这也是GIS 服务器,但这个方案可能存在如下问题:

1.大数据量时如何做切片,

2.如何返回符合条件的数据,

3.GeoJSON数据格式并非是传统GIS平台的输出,GeoJSON作为只适合Web的数据格式如何生成和编辑得来。

4.如果这个方案可以接受的话,那还需要大书特书吗

因此,在这一篇,我们需要实现一个能将传统的GIS数据格式作为输入(发布),GeoJSON作为输出(response返回)的解决方案,同时,为将来做切片和查询打下良好基础。

Node+Express+Mongo

Node+Express+Mongo,MEAN架构就查Angular,其实manager是采用Angular来开发的。个人较为推崇该架构。

Node+Express:Node无需解释,Why Express,作为一个要返回Restful数据及资源的服务器,Express是最佳的,更何况切片请求是最为典型Restful风格,选择Express已经完成了工作的一半:不夸张的说,WebStorm自动生成的Express框架,确实已经完成了50%的代码。

Mongo+mongoose:Mongo作为非关系库,一是它存储的就是JSON格式,二是GeoJSON就格式来说是不严谨的,同一GeoJSON中甚至可以同时存储点、线、面等多个形状类型,这对于关系数据库来说,简直不要太难受,而对于Mongo,这就是小case。(当然不推荐在一个GeoJSON中存储多种要素类)除此之外,GeoJSON属性数据(即properties),这部分是非常自由的,没有事先定义,而Mongo几乎就为处理此类数据而生。

mongoose,不多说,Express+Mongo,中间一般都采用mongoose来访问Mongo。

事半功倍,正确的选型是成功的一半。

GDAL

gdal对于经常从事GIS数据格式转换的同仁,一定不会陌生,同时&#

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import os import numpy as np from osgeo import gdal input_folder = 'G:/xianlinhotel/xlh632envi' output_folder = "G:/xianlinhotel/xlh_nir_rg_632envicai" target_width = 1230 target_height = 910 for filename in os.listdir(input_folder): if filename.endswith(".tif"): tif_path = os.path.join(input_folder, filename) tif_dataset = gdal.Open(tif_path) if tif_dataset is not None and tif_dataset.RasterXSize == 1280 and tif_dataset.RasterYSize == 960: data = tif_dataset.ReadAsArray() x_offset = (tif_dataset.RasterXSize - target_width) // 2 y_offset = (tif_dataset.RasterYSize - target_height) // 2 new_data = data[:, y_offset:y_offset+target_height, x_offset:x_offset+target_width] output_path = os.path.join(output_folder, filename) driver = gdal.GetDriverByName("GTiff") new_dataset = driver.Create(output_path, target_width, target_height, tif_dataset.RasterCount, tif_dataset.GetRasterBand(1).DataType) geotransform = tif_dataset.GetGeoTransform() new_geotransform = (geotransform[0] + x_offset * geotransform[1], geotransform[1], geotransform[2], geotransform[3] + y_offset * geotransform[5], geotransform[4], geotransform[5]) new_dataset.SetGeoTransform(new_geotransform) new_dataset.SetProjection(tif_dataset.GetProjection()) for i in range(1, tif_dataset.RasterCount + 1): new_dataset.GetRasterBand(i).WriteArray(new_data[i - 1]) new_dataset = None # 关闭数据集以保存文件和释放资源 print(f"Saved {filename} to {output_path}") else: print(f"{filename} has invalid size or is not a TIFF file.") tif_dataset = None # 关闭数据集以释放资源 详细解释
最新发布
05-30
这是一个Python脚本,用于将指定文件夹中的所有大小为1280x960的TIFF文件裁剪为指定大小并保存到另一个文件夹中。 以下是对代码的详细解释: ```python import os import numpy as np from osgeo import gdal # 定义输入文件夹路径、输出文件夹路径和裁剪后的目标宽度和高度 input_folder = 'G:/xianlinhotel/xlh632envi' output_folder = "G:/xianlinhotel/xlh_nir_rg_632envicai" target_width = 1230 target_height = 910 # 遍历文件夹中的所有文件 for filename in os.listdir(input_folder): if filename.endswith(".tif"): # 如果文件是TIFF文件 tif_path = os.path.join(input_folder, filename) # 构造完整的文件路径 tif_dataset = gdal.Open(tif_path) # 读取TIFF文件 # 如果TIFF文件存在且大小为1280x960 if tif_dataset is not None and tif_dataset.RasterXSize == 1280 and tif_dataset.RasterYSize == 960: data = tif_dataset.ReadAsArray() # 读取TIFF文件中的像素数据 # 计算裁剪后的左上角坐标 x_offset = (tif_dataset.RasterXSize - target_width) // 2 y_offset = (tif_dataset.RasterYSize - target_height) // 2 # 对像素数据进行裁剪 new_data = data[:, y_offset:y_offset+target_height, x_offset:x_offset+target_width] # 构造输出文件路径,并创建输出文件 output_path = os.path.join(output_folder, filename) driver = gdal.GetDriverByName("GTiff") new_dataset = driver.Create(output_path, target_width, target_height, tif_dataset.RasterCount, tif_dataset.GetRasterBand(1).DataType) # 设置输出文件的地理参考和投影信息 geotransform = tif_dataset.GetGeoTransform() new_geotransform = (geotransform[0] + x_offset * geotransform[1], geotransform[1], geotransform[2], geotransform[3] + y_offset * geotransform[5], geotransform[4], geotransform[5]) new_dataset.SetGeoTransform(new_geotransform) new_dataset.SetProjection(tif_dataset.GetProjection()) # 将裁剪后的像素数据写入输出文件 for i in range(1, tif_dataset.RasterCount + 1): new_dataset.GetRasterBand(i).WriteArray(new_data[i - 1]) new_dataset = None # 关闭输出文件以保存和释放资源 print(f"Saved {filename} to {output_path}") else: print(f"{filename} has invalid size or is not a TIFF file.") tif_dataset = None # 关闭输入文件以释放资源 ``` 首先,我们导入了需要使用的模块,包括`os`、`numpy`和`gdal`。其中,`os`模块用于操作文件和文件夹,`numpy`模块用于处理像素数据,`gdal`模块用于读取和写入TIFF文件。 然后,我们定义了输入文件夹路径、输出文件夹路径和裁剪后的目标宽度和高度。这些变量用于在脚本中重复使用。 接下来,我们使用`os.listdir()`函数遍历输入文件夹中的所有文件,并使用`filename.endswith(".tif")`判断文件是否是TIFF文件。如果是TIFF文件,我们构造完整的文件路径并使用`gdal.Open()`函数读取TIFF文件。 然后,我们检查TIFF文件的大小是否为1280x960。如果是,我们使用`gdal.Dataset.ReadAsArray()`函数读取TIFF文件中的像素数据,并计算裁剪后的左上角坐标。我们使用`numpy`模块对像素数据进行裁剪,并构造输出文件路径。然后,我们使用`gdal.GetDriverByName()`函数创建输出文件,并将裁剪后的像素数据写入输出文件。最后,我们关闭输入文件和输出文件以释放资源,并输出保存的文件路径。 如果文件不是TIFF文件或大小不是1280x960,则输出相应的错误信息。 希望这份解释能够帮助您理解这段代码的功能和实现方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值