# 数据内容
# 数字线化图(Digital Line Graphic:DLG)
# 基于实体,可以单独选择
# 是与现有线划基本一致的矢量数据集,且保存各要素间的空间关系和相关的属性信息
# 数字栅格地形图(Digital Raster Graphic:DRG)
# 纸质地形图数字化产品,不能单独选择,常用于背景
# 数字高程模型(Digital Elevation Model:DEM)
# 它是自然地貌高程值的集合,能够反映较稳定地貌形态,主要用来描述地形
# 主要分为ASTER-GDEM(精度大约在30米)、SRTM1(精度大约在30米)、SRTM3(精度大约在90米)
# 数字正射影像(Digital Orthophoto Map:DOM)
# 影像数据,来源于卫星影像、航空影像,先生产DEM,以DEM为数据源生产DOM,它是DEM经正射纠正的产品
# 因为DEM不包括人工地物的高程,所以DOM中人工地物是存在投影变形的
# 比如说高大的房屋、烟囱等,在DOM中还是能看到明显的倾斜
# 数字表面模型(Digital Surface Model:DSM)
# 是指包含了地表建筑物、桥梁和树木等高度的地面高程模型
# 和DEM相比,DEM只包含了地形的高程信息,并未包含其它地表信息
# DSM是在DEM的基础上,进一步涵盖了除地面以外的其它地表信息的高程
# 在一些对建筑物高度有需求的领域,得到了很大程度的重视
倾斜摄影
无人机倾斜摄影可生成数字正射影像(DOM)、数字高程模型(DEM)、数字表面模型(DSM)
倾斜摄影的主要目的是创建实景三维模型,航摄时有不同方向的航摄影像,比较常见的是五镜头倾斜摄影
# 无人机搭载激光雷达和倾斜摄影的区别
地面点点位数据
# 激光雷达采集的点云数据是直接通过激光发射器获取的地面点点位数据
# 倾斜摄影是通过照片密集匹配和空三加密得到的地面点点位数据
# 前者是直接获取,后者是空三加密后得到
点位精度
# 倾斜摄影点位精度是不如激光扫描精度的,它获取到的数据主要是模型数据,纹理较好,易于判别画图
# 激光雷达精度高,数据成果是离散点云数据,纹理一般
总结
# 倾斜摄影精度较低(厘米级),纹理好,无法过滤植被,模型画图(适合各类地物)
# 激光雷达精度高(毫米级),离散,纹理一般,可以过滤植被,切片画图(适合房屋等人工建筑)
# 数据格式
矢量数据(shp)、正射/高程影像数据(tif)、点云(las)、倾斜摄影模形(osgb)
Fbx和obj都支持目前主流的三维模型软件,是通用的3d文件格式,不同的是,fbx格式可以带材质的
# TIF
# TIF文件为栅格图像文件,后缀为tif或tiff,是ogc规范的一种,全称GeoTiff
# 通常需要用GIS软件查看tif栅格影像数据的坐标系信息,因为它的坐标系信息写在数据文件内部
# tif可以有8位,24位等深度,一般真彩色是24位,而地形数据只有一个高度值,采用 8 位
# 目前很多卫星影像数据、地形数据的存储格式都是tif
# DEM
dem有两种格式,NSDTF和USGS
SGS-DEM # USGS是美国地质调查局的英文缩写,是一种公开格式的DEM数据格式标准,使用范围较广格式的
NSDTF-DEM # 是我国国家标准地球空间数据交换格式,是属于格网数据交换格式,一般的GIS软件都不支持
# SHP
可以通过shapefile-js (opens new window)等诸多开源库进行转换到 GeoJSON 进行使用,通常包含以下文件:
主文件(.shp 必须) # 存储坐标数据
索引文件(.shx 必须) # 存储坐标数据的索引信息
属性表文件(.dbf 必须) # 存储属性数据
投影文件(.prj) # 投影描述,存储空间坐标系信息
编码文件(.cpg) # 存储文件(.dbf文件)的编码信息,此文件作用不大
- shapefile的文件大小有限制
# shapefile文件组中每个文件的大小不能超过2GB。相应的,dbf文件不能超过2GB,shp文件不能超过2GB
- shape属性出现点ZM
# 在ArcGIS中,我们常用的几何类型有点、线、面、体,但在这之外,可能会遇到带ZM的类型
# 与点类似,但比点多两个字段,Z值是用来存储高程属性信息,M值是用来存储其他属性信息,如温度、浓度等
# GeoJSON
GeoJSON 是一种使用JSON的格式来表示简单的地理特征以及它们的非空间属性的方式
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83775386582222, 35.24980190252168]
},
"properties": {
"name": "DOUBLE OAKS CENTER",
"address": "1326 WOODWARD AV"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-80.83827000459532, 35.25674709224663]
},
"properties": {
"name": "DOUBLE OAKS NEIGHBORHOOD PARK",
"address": "2605 DOUBLE OAKS RD"
}
}
]
}
注意
- 面(Polygon)比线多了一层[],并且第一个点跟最后一个点是相同的,因为我们日常接触的面还会有中间带孔洞的形式,例如行政区划中很特殊的现象——飞地
- GeometryCollection 对象没有"coordinates"成员,而是有一个名为"geometries"的成员。"geometries"的值是一个数组。该数组的每个元素都是一个 GeoJSON Geometry 对象。此数组可能为空
# EsriJSON
EsriJSON是由Esri公司定义的一种GeoJSON格式的扩展,用于表示地理空间要素及其属性信息。与标准的GeoJSON相比,Esri JSON增加了一些属性和元素,以支持Esri ArcGIS产品族的规范。
- 转换方式
//https://github.com/terraformer-js/terraformer/blob/main/packages/arcgis/README.md
npm install @terraformer/arcgis
//EsriJSON转GeoJSON
import { arcgisToGeoJSON } from "@terraformer/arcgis"
arcgisToGeoJSON({
"x":-122.6764,
"y":45.5165,
"spatialReference": {
"wkid": 4326
}
});
>> { "type": "Point", "coordinates": [ -122.6764, 45.5165 ] }
//GeoJSON转EsriJSON
import { geojsonToArcGIS } from "@terraformer/arcgis"
geojsonToArcGIS({
"type": "Point",
"coordinates": [45.5165, -122.6764]
})
>> { "x":-122.6764, "y":45.5165, "spatialReference": { "wkid": 4326 } }
- EsriJSON的格式
//要素(Feature)
// GeoJSON
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
// EsriJSON
{
"attributes": {
"OBJECTID": 1,
"Name": "Sample",
"Type": "Building"
},
"geometry": {
"rings": [[[0,0],[0,10],[10,10],[10,0],[0,0]]],
"spatialReference": { "wkid": 4326 }
}
}
//Point(点)
// GeoJSON
"geometry":{
"type":"Point",
"coordinates":[105.380859375,31.57853542647338]
}
// EsriJSON
{
"x": -122.690899,
"y": 45.512296
}
//MultiPoint(多点)
// GeoJSON
"geometry":{
"type":"MultiPoint",
"coordinates":[
[105.380859375,31.57853542647338],
[105.580859375,31.52853542647338]
]
}
// EsriJSON
{
"points": [[-122.68,45.50],[-122.70,45.52],[-122.68,45.53]],
"spatialReference": { "wkid": 4326 }
}
//LineString(线)
// GeoJSON - 依次连接点
"geometry":{
"type":"LineString",
"coordinates":[
[105.6005859375,30.65681556429287],
[107.9516601562,31.98944183792288],
[109.3798828125,30.03105542654020],
[107.7978515625,29.93589521337244]
]
}
// EsriJSON
{
"paths": [
[[0,0],[5,5],[10,10]]
],
"spatialReference": { "wkid": 4326 }
}
//MultiLineString(多线)
// GeoJSON
"geometry":{
"type":"MultiLineString",
"coordinates":
[
[
[105.6005859375,30.65681556429287],
[107.9516601569,31.98944183792288],
[109.3798828125,30.03105542654020],
[107.7978515625,29.93589521332444]
],
[
[109.3798828125,30.03105542654020],
[107.1978515625,31.23589521337244]
]
]
}
// EsriJSON
{
"paths": [
[[0,0],[5,5],[10,10]],
[[15,15],[20,25],[30,30]]
],
"spatialReference": { "wkid": 4326 }
}
//Polygon(面)
// GeoJSON
"geometry":{
"type": "Polygon",
"coordinates":
[
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
]
]
}
// EsriJSON
{
"rings": [
[[0,0],[0,10],[10,10],[10,0],[0,0]]
],
"spatialReference": { "wkid": 4326 }
}
//MultiPolygon(多面)
// GeoJSON
"geometry": {
"type": "MultiPolygon",
"coordinates":
[
[
[
[109.2041015625,30.088107753367257],
[115.02685546875,30.088107753367257],
[115.02685546875,32.7872745269555],
[109.2041015625,32.7872745269555],
[109.2041015625,30.088107753367257]
]
],
[
[
[112.9833984375,26.82407078047018],
[116.69677734375,26.82407078047018],
[116.69677734375,29.036960648558267],
[112.9833984375,29.036960648558267],
[112.9833984375,26.82407078047018]
]
]
]
}
# WKB/WKT
WKT(Well-known Text) # 使用文本表达几何对象的一种标记语言
WKB(Well-known Binary) # 使用二进制表达几何对象的一种标记语言
下图分表是使用WKT与GeoJSON分别描述同一几何的差异:
注意
可以看出其主要还是为了表达几何对象,相较 GeoJSON 而言,其无法存储属性数据
这种数据格式在很多数据库中都用以表达几何数据类型,格式转换工具 (opens new window)
# KML
KML文件本质上是一个XML文件,用以描述地图中的关键数据,如路径、标记位置、叠加图层等信息的简单地图,不包含高程、地形地貌等复杂信息
- KML文件定义了几个特殊的元素标签:
Placemark # 标记或路径
Linestring # 路劲的坐标点
Point # 标记位置的坐标
Coordinates # 经纬度坐标
- 一个KML文件如下所示
<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Folder>
<name>高速公路</name>
<Placemark>
<name>卫岗隧道</name>
<Style>
<LineStyle>
<color>ffff0000</color>
</LineStyle>
<PolyStyle>
<fill>0</fill>
</PolyStyle>
</Style>
<LineString>
<coordinates>118.8385657,32.0429378 118.8338431,32.0439411</coordinates>
</LineString>
</Placemark>
<Placemark>
<name>南京长江隧道</name>
<Style>
<LineStyle>
<color>ffff0000</color>
</LineStyle>
<PolyStyle>
<fill>0</fill>
</PolyStyle>
</Style>
<LineString>
<coordinates>118.67057150000001,32.0543862 118.6921381</coordinates>
</LineString>
</Placemark>
</Folder>
<Folder>
<name>市级地名</name>
<Placemark>
<name>南京市</name>
<Point><coordinates>118.79126,32.06042</coordinates></Point>
</Placemark>
<Placemark>
<name>马鞍山市</name>
<Point><coordinates>118.49952,31.69933</coordinates></Point>
</Placemark>
</Folder>
# .dwg与.dxf
dwg文件 # AutoCAD的图形文件格式,是二维或三维图形档案。其与dxf文件是可以互相转化的
dxf文件 # AutoCAD推出与其它软件平台之间进行数据交换的一种开放的矢量数据格式
# .gdb与.mdb
gdb # 文件地理数据库,是在文件系统文件夹中保存的各种类型的GIS数据集的集合
mdb # 个人地理数据库,是以access数据库为基础的,可以存储不超过2G的文件,只适合Windows
# .osgb
# 倾斜模型,Open Scene Gragh Binary是OSGB的全称,一般是二进制存贮的、带有嵌入式链接纹理数据
# .obj(人工建模)
# Obj是三维模型的一个万能格式,大部分三维软件都支持,obj文件一般包含obj、mtl、纹理图片三个文件
# 地形分类标准
# 0°~0.5°为平原 => 0.00872686779075879
# 0.5°~2°为微斜坡 => 0.03492076949174773
# 2°~5°为缓斜坡 => 0.08748866352592401
# 5°~15°为斜坡 => 0.2679491924311227
# 15°~35°为陡坡 => 0.7002075382097097
# 35°~55°为峭坡 => 1.4281480067421144
# 55°~90°为垂直壁 => 以上
# Geohash
Geohashing 是一种地理编码方法,用于将地理坐标(纬度和经度)编码为一小段数字和字母,以不同的分辨率在地图上划定一个区域(称为像元)。字符串中的字符越多,位置越精确。在线转换 (opens new window)
# 用一个变长的字符串表示一个区域
# 整个世界被分割成4*8=32个网格,中国主要出于w网格
# 每个网格使用一个base32的字母表示(字符可以是0到9和 A 到 Z,不包括 “A”,“I”,“L”和 “O”)
# 每个区域再分成32个子区域。编码长度越长,越精确
注意
转换精度(precision)可以在1到12之间选择精度,长度为12的最高精度的 geohash 产生的单元覆盖不到一平方米的土地
# 举例说明将经纬度(116.389550, 39.928167)转成geohash的过程:
- 对纬度39.928167进行逼近编码,这里使用的是6位geohash来说明一个转换流程
# 区间[-90,90]二分为[-90,0),[0,90],称为左右区间,可以确定39.928167属于右区间[0,90],标记为1
# 接着将区间[0,90]二分为 [0,45),[45,90],可以确定39.928167属于左区间 [0,45),给标记为0
# 递归上述过程,随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167
- 如果给定的纬度x(39.928167)属于左区间,则记录0,如果属于右区间则记录1,如下图
- 同理,地球经度区间是[-180,180],可以对经度116.389550进行编码
- 通过计算,纬度产生的编码为1 1 0 1 0 0 1 0 1 1 0 0 0 1 0,经度的编码为1 0 1 1 1 0 0 0 1 1 0 0 0 1 1
- 合并:偶数位放经度,奇数位放纬度,把2串编码组合生成新串如下图
- 将11100 11101 00100 01111 0000 01101转成十进制(28、29、4、15,0,13)十进制对应的base32编码就是wx4g0e,如下图
- 同理,将编码转换成经纬度的解码算法与之相反
# 转换方法
- 经纬度二分法,将10进制经度或纬度转为经度或纬度二进制排列
/**
* 经纬度二分法,将10进制经度或纬度转为经度或纬度二进制排列
*
* @param lower 经度、纬度最小值
* @param upper 经度、纬度最大值
* @param value 27.967758178710938 或 131.22276306152344
* @param length 二分到多少位
* @return
*/
private def toBinary(lower: Double, upper: Double, value: Double, length: Int): Array[Char]=
{
val binaryArray: Array[Char] = new Array[Char](length)
var min: Double = lower
var max: Double = upper
for (i <- 0 until length) {
val mid: Double = (max + min) / 2
if (value < mid) {
binaryArray(i) = '0'
max = mid
} else {
binaryArray(i) = '1'
min = mid
}
}
binaryArray
}
- 10进制的纬经度 ===>>> 7位geohash的base32字符
/**
* 10进制的纬经度 ===>>> 7位geohash的base32字符
* @param longitude 经度 131.22276306152344
* @param latitude 纬度 27.967758178710938
* @param bits 7位(我需要将经纬度转成7位的base32字符串)
* @return
*/
def getGeoHash7(longitude: Double, latitude: Double, bits: Int): String = {
val length: Int = bits * 5 / 2
var longitudeLength: Int = length
val b: Boolean = bits % 2 != 0
if (b) {
longitudeLength += 1
}
val longitudeArray: Array[Char] = toBinary(-180, 180, longitude, longitudeLength)
val latitudeArray: Array[Char] = toBinary(-90, 90, latitude, length)
val geoHash: StringBuffer = new StringBuffer(longitudeLength + length)
// 将经纬度的二进制串拼接起来,经度在偶数位,纬度在奇数位
for (i <- 0 until length) {
geoHash.append(longitudeArray.charAt(i))
geoHash.append(latitudeArray.charAt(i))
}
if (b) {
geoHash.append(longitudeArray.charAt(length))
}
// 将经纬度二进制串拼接成一个35位的二进制串
var i: Int = 0
val result: StringBuffer = new StringBuffer(bits)
while (i < length * 2) {
val j: Int = i + 5
val index: Int = Integer.parseInt(geoHash.substring(i, j), 2)
// 去base32中查询
result.append(BASE32(index))
i = j
}
result.toString
}
- 将7位geohash的base32字符串转成35位二进制的排列
/**
* 经纬度二分法,将7位geohash的base32字符串转为35二进制
*
* @param geoHash
* @return
*/
def decodeToBinary(geoHash: String): String = {
val result: StringBuffer = new StringBuffer(geoHash.length * 5)
for (c <- geoHash) {
val bits: String = Integer.toBinaryString(BASE32.indexOf(c))
for (i <- 0 until 5 - bits.length) {
result.append('0')
}
result.append(bits)
}
result.toString
}
- 将二进制的纬度或经度字符串转成10进制的纬度或经度
/**
* 将二进制的纬度或经度字符串转成10进制的纬度或经度
* @param bStr 二进制的纬度或经度字符串 10100111110001101 , 110111010101000001
* @param min 对应纬度、经度的最小值
* @param max 对应纬度、经度的最大值
* @return 27.967758178710938 或 131.22276306152344
*/
def getGeohashMid(bStr: String, min: Double, max: Double): Double = {
if (bStr == null || bStr.length < 1) {
return (min + max) / 2
}
if (bStr.charAt(0) == '1') {
getGeohashMid(bStr.substring(1), (min + max) / 2, max)
} else {
getGeohashMid(bStr.substring(1), min, (min + max) / 2)
}
}
- 获取7位geohash的base32字符串对应的(纬度二进制串,经度二进制串)
/**
* 获取7位geohash的base32字符串对应的经纬度二进制串
*
* @param geoHash geoHash值
* @return (纬度,经度)
*/
def geohash2LatLong(geoHash: String): (String, String) = {
val bCoordinate: String = decodeToBinary(geoHash)
// 纬度
val bLat: StringBuilder = new StringBuilder
// 经度
val bLon: StringBuilder = new StringBuilder
for (i <- 0 until bCoordinate.length) {
if (i % 2 == 0) {
// 偶数位填到经度上面
bLon.append(bCoordinate.charAt(i))
} else {
// 奇数位填到纬度上面
bLat.append(bCoordinate.charAt(i))
}
}
val lat: String = bLat.toString()
val lon: String = bLon.toString()
(lat, lon)
// (10100111110001101,110111010101000001)
}
- 获取7位geohash的base32字符串对应经纬度
/**
* 获取geohash对应经纬度
* @param geoHash geohash值
* @return (纬度,经度)
*/
def getPointByGeoHash(geoHash: String): (Double, Double) = {
// 将geoHash转为经纬度二进制字符串
val (lat, lon) = geohash2LatLong(geoHash)
val latValue = getGeohashMid(lat, -90d, 90d)
val lonValue = getGeohashMid(lon, -180d, 180d)
(latValue, lonValue)
}
# 卫星数据
卫星星历,又称为两行轨道数据(TLE,Two-Line Orbital Element)
四大卫星导航系统
美国的GPS(24颗卫星),中国的BDS(百斗,28颗),俄罗斯的Glonass(格洛纳斯),欧洲的Galileo(伽利略)
# 重要的几个网站
- Space-Track (opens new window)
- https://celestrak.com/ (opens new window)
- 卫星跟踪 (opens new window)
- 卫星计算js (opens new window)
- 卫星计算c# (opens new window)
# tle数据说明
BEIDOU 3
//01:行号 1
//03-07:卫星ID,NORAD_CAT_ID, 36287
//08:保密级别 U
//10-11:发射年份 10
//12-14:发射编号 001
//15-17:发射编号 A
//19-20:TLE数据发布时间年份 21
//21-32:TLE数据发布时间第几天 187.60806788
//34-43:平均运动的一阶时间导数,用来计算每一天平均运动的变化带来的轨道漂移
// 提供给轨道计算软件预测卫星的位置。两行式轨道数据使用这个数据校准卫星的位置
//45-52:平均运动的二阶时间导数,用来计算每一天平均运动的变化带来的轨道漂移
// 提供给轨道计算软件预测卫星的位置
//54-61:BSTAR阻力系数,用于大气阻力对卫星运动的影响
//63:美国空军空间指挥中心内部使用的为1;美国空军空间指挥中心以外公开使用标识为0
//65-68:星历编号,TLE数据按新发现卫星的先后顺序的编号
//69:校验和,指这一行的所有非数字字符,按照“字母、空格、句点、正号= 0
// 负号=1”的规则换算成0和1后,将这一行中原来的全部数字加起来,以10为模计算后所得的和
// 校验和可以检查出90%的数据存储或传送错误。按十进制加起来的个位数字的校验和,用于精确纠正误差
1 36287U 10001A 21187.60806788 -.00000272 00000-0 00000-0 0 9992
//01:行号 1
//03-07:卫星ID,NORAD_CAT_ID, 36287
//09-16:轨道面与赤道面夹角 1.9038
//18-25:升交点赤经,升交点赤经是指卫星由南到北穿过地球赤道平面时
// 与地球赤道平面的交点,经度47.2796 纬度0
//27-33:轨道偏心率 0.0005620 圆形为0
//35-42:近地点幅角 82.9429
//44-51:平近点角 153.9116
//53-63:每天环绕地球的圈数 1.00269947 , 周期1,436.12 分钟
//64-68: 发射以来飞行的圈数 4204
//69:校验和
2 36287 1.9038 47.2796 0005620 82.9429 153.9116 1.00269947 42045
# 轨道参数
轨道根数(或称轨道要素或轨道参数)是描述在牛顿运动定律和牛顿万有引力定律的作用下的天体或航天器,在其开普勒轨道上运动时,确定其轨道所必要的六个参数。
传统使用的轨道根数,是在开普勒定律之后发展出来的,称为开普勒元素,主要有六个参数:
离心率(e) # 也就是椭圆两焦点的距离和长轴比值。对于圆,它就是0
半长轴(a) # 是椭圆长轴的一半。对于圆,也就是半径
轨道倾角(i) # 这个是轨道平面和地球赤道平面的夹角。对于位于赤道上空的同步静止卫星来说,倾角就是0
升交点黄经(Ω) # 卫星从南半球到北半球时和赤道的交点叫升交点。此点和春分点对于地心的张角叫升交点赤经
近日点辐角(ω) # 这是近地点和升交点对地心的张角,这个值则确定了轨道在轨道平面里的位置
在指定历元的平近点角(Mo)(或是近日点通过时间(To)) # 卫星位置随时间的变化需要一个初值
离心率和半长轴决定了轨道的形状,轨道倾角和升交点黄经决定了卫星轨道平面在空间的位置
# 坐标系
- ECI:earth centered inertial惯性坐标系
# 坐标原点取在地心,X轴指向春分点,Z轴指向北极,Y轴与前者构成右手系
# 该系不与地球一同转动,因此可以应用牛顿定律
- ECEF:地固坐标系
# 该坐标系以地球质心为原点,Z轴向北沿地球自转轴方向,X轴指向经纬度的(0,0)位置
# 右手系Y轴指向90度经线。该系与地球一同转动
# 地球坐标系固定在地球上而随地球一起在空间做公转和自转运动
# 因此地球上任一固定点在地球坐标系的坐标就不会由于地球旋转而变化
# 地心地固直角坐标系和大地坐标系都属于这种坐标系
# 气象数据
MICAPS系统的数据结构 (opens new window)
# 气象风场UV,风向说明
用角度表示风向,是把圆周分成360度,北风(N)是0度(即360度),东风(E)是90度,南风(S)是180度,西风(W)是270度,其余的风向都可以由此计算出来
# U和V表示
U是东西风上的分量,西风为正。V是南北风上的分量,南风为正
空间数据表达 →