如何将 geoshape/geotrace/geopoint 转换为 GeoJSON?
How can I convert a geoshape/geotrace/geopoint to GeoJSON?
我正在使用 API 访问使用 kobotoolbox 收集的空间数据。 api returns 空间数据作为 geoshape/geotrace/geopoint,但我需要将该数据转换为 Geojson,以便我可以使用传单将它们显示在我的地图上。
这里是 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;'
非常感谢!
“geoshape”看起来不像任何 well-known vector data format,而是看起来像一串 ;
分隔的 4 元素向量,而这些向量又是 space 分隔的数字。
一些天真的解析是有序的。
首先将字符串拆分为字符串数组 with 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
。我们可以通过提供一个按 spaces:
拆分的函数,将每个字符串变成 Array
of Number
s
function spaceSeparatedStringToArray(str) {
return str.split(' ');
}
...以及另一个将包含数字文本表示的 String
强制转换为 Number
的函数,例如...
function stringToNumber(str) {
return Number(str);
}
...现在让我们输入 some Array.prototype.map()
magic and some method chaining magic,创建一个函数,其中输入是 space 分隔的字符串,输出是 Array
的 Number
s:
function stringToNumber(str) { return Number(str); }
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(stringToNumber);
}
有时将传递给 map()
(或 reduce()
或 filter()
等)的辅助函数定义为 anonymous lambda-functions 会更好,例如:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(function(str){ return Number(str) });
}
如果需要,您可以使用 arrow function syntax:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(str=>Number(str) );
}
并且由于我们使用的是Number
as a function,我们可以直接将其用作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
每个向量以仅保留前两个分量。这使用 array destructuring:
let vectors = geoshape
.split(';')
.map((str)=>str.split(' ').map(Number))
.map(([x,y,w,z])=>[x,y]);
看到了吗?我定义了一个接受单个参数的 lambda 函数,假设它是一个长度为 4 的(数字)数组,解构该数组,然后 returns 一个包含前两个元素的新数组。它也可以像这样工作:
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
在 ([x,y])=>[y,x]
:
let coords = geoshape
.split(';')
.filter(str=> str!=='')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[y,x]);
现在转到 geojson.org and read 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);
看到一个working example here。还有,请,不要盲目复制粘贴代码。请务必阅读链接的文档和资源,并了解发生了什么。
我正在使用 API 访问使用 kobotoolbox 收集的空间数据。 api returns 空间数据作为 geoshape/geotrace/geopoint,但我需要将该数据转换为 Geojson,以便我可以使用传单将它们显示在我的地图上。
这里是 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;'
非常感谢!
“geoshape”看起来不像任何 well-known vector data format,而是看起来像一串 ;
分隔的 4 元素向量,而这些向量又是 space 分隔的数字。
一些天真的解析是有序的。
首先将字符串拆分为字符串数组 with 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
。我们可以通过提供一个按 spaces:
Array
of Number
s
function spaceSeparatedStringToArray(str) {
return str.split(' ');
}
...以及另一个将包含数字文本表示的 String
强制转换为 Number
的函数,例如...
function stringToNumber(str) {
return Number(str);
}
...现在让我们输入 some Array.prototype.map()
magic and some method chaining magic,创建一个函数,其中输入是 space 分隔的字符串,输出是 Array
的 Number
s:
function stringToNumber(str) { return Number(str); }
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(stringToNumber);
}
有时将传递给 map()
(或 reduce()
或 filter()
等)的辅助函数定义为 anonymous lambda-functions 会更好,例如:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(function(str){ return Number(str) });
}
如果需要,您可以使用 arrow function syntax:
function spaceSeparatedStringToArrayOfNumbers(str) {
return str.split(' ').map(str=>Number(str) );
}
并且由于我们使用的是Number
as a function,我们可以直接将其用作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
每个向量以仅保留前两个分量。这使用 array destructuring:
let vectors = geoshape
.split(';')
.map((str)=>str.split(' ').map(Number))
.map(([x,y,w,z])=>[x,y]);
看到了吗?我定义了一个接受单个参数的 lambda 函数,假设它是一个长度为 4 的(数字)数组,解构该数组,然后 returns 一个包含前两个元素的新数组。它也可以像这样工作:
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
在 ([x,y])=>[y,x]
:
let coords = geoshape
.split(';')
.filter(str=> str!=='')
.map((str)=>str.split(' ').map(Number))
.map(([x,y])=>[y,x]);
现在转到 geojson.org and read 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);
看到一个working example here。还有,请,不要盲目复制粘贴代码。请务必阅读链接的文档和资源,并了解发生了什么。