我正在使用API访问使用kobotoolbox收集的空间数据。 API 将空间数据作为地理形状/地理跟踪/地理点返回,但我需要将该数据隐藏到 Geojson,以便我可以使用传单在地图上显示它们。
这是地理形状'-6.725577650887138 39.10606026649475 0.0 0.0;-6.72631550943841 39.10506717860699 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.725577650887138 39.10606026649475 0.0 0.0;'
的示例字符串
提前非常感谢!
这个"geoshape"看起来不像任何众所周知的矢量数据格式,而看起来像一串;
分隔的 4 元素向量,而这些向量又是空格分隔的数字。
一些幼稚的解析是有序的。
首先使用String.prototype.split()
将字符串拆分为字符串数组:
let geoshape = '-6.725577650887138 39.10606026649475 0.0 0.0;-6.72631550943841 39.10506717860699 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.725577650887138 39.10606026649475 0.0 0.0;';
let points = geoshape.split(';');
现在points
是String
Array
。我们可以通过提供一个用空格拆分字符串的函数来将这些字符串中的每一个转换为Number
s 的Array
:
function spaceSeparatedStringToArray(str) {
return str.split(' ');
}
。以及另一个将包含数字文本表示的String
强制到Number
中的函数,例如......
function stringToNumber(str) {
return Number(str);
}
。现在让我们加入一些Array.prototype.map()
魔术和一些方法链接魔术,以创建一个函数,其中输入是空格分隔的字符串,输出是Number
的Array
:
function stringToNumber(str) { return Number(str); }
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(stringToNumber);
}
有时最好将传递给map()
(或reduce()
或filter()
等)的辅助函数定义为匿名lambda函数,例如:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(function(str){ return Number(str) });
}
如果需要,可以改用箭头函数语法:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(str=>Number(str) );
}
由于我们将Number
用作函数,因此我们可以直接将其用作map()
的参数:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(Number);
}
现在我们有了这个函数,让我们回到开头,并将该函数应用于每个;
分隔的子字符串:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(Number);
}
let geoshape = '-6.725577650887138 39.10606026649475 0.0 0.0;-6.72631550943841 39.10506717860699 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.725577650887138 39.10606026649475 0.0 0.0;';
let points = geoshape.split(';');
let vectors = points.map(spaceSeparatedStringToArrayOfNumbers);
让我们更改它以添加更多的 lambda 和方法链接以及箭头语法:
let vectors = geoshape.split(';').map((str)=>str.split(' ').map(Number));
此外,由于 GeoJSON 格式期望每个坐标作为 2 分量向量而不是 4 分量向量,因此让我们再次map
每个向量以仅保留前两个分量。这使用数组解构:
let vectors = geoshape
.split(';')
.map((str)=>str.split(' ').map(Number))
.map(([x,y,w,z])=>[x,y]);
看?我定义了一个 lambda 函数,它接受单个参数,假设它是一个长度为 4 的数组(数字),解构数组,然后返回一个包含前两个元素的新数组。它也可以像这样工作:
let coords = geoshape
.split(';')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[x,y]);
您的示例数据以;
结尾,这会导致空字符串,因此我也会将其过滤掉:
let coords = geoshape
.split(';')
.filter(str=> str!=='')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[x,y]);
我假设你在达累斯萨拉姆工作,而不是在巴达霍斯工作,所以让我们通过在([x,y])=>[y,x]
中交换x
和y
来翻转纬度和经度(也见 https://macwright.com/lonlat/):
let coords = geoshape
.split(';')
.filter(str=> str!=='')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[y,x]);
现在转到 geojson.org 并阅读 RFC 7946 以了解如何指定 GeoJSON 数据结构。我们已经有了 LineString 几何图形的坐标,所以它所需要的只是一些换行:
let geojsonFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": coords
}
};
如果示例数据集是具有外部船体且没有内部船体的多边形(请阅读 OGC SFA 以了解"船体"在此上下文中的含义),则可以将坐标包装在额外的内联数组中,并将Polygon
指定为几何类型:
let geojsonFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [ coords ]
}
};
现在你可以把它喂给L.geoJson
,例如
let line = L.geoJson(geojsonFeature).addTo(map);
最后,为了它,我将把所有东西压缩在一起:
let geoshape = '-6.725577650887138 39.10606026649475 0.0 0.0;-6.72631550943841 39.10506717860699 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.725577650887138 39.10606026649475 0.0 0.0;';
let leafletLine = L.geoJson({
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": geoshape
.split(';')
.filter(str=> str!=='')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[y,x])
}
}).addTo(map);
在此处查看工作示例。拜托,拜托,不要盲目复制粘贴代码。请阅读链接的文档和资源,并了解发生了什么。