将GeoJson要素映射到特性



我正试图将GeoJSON FeatureCollection中的多多边形映射到一个NetTopologySuite类型的多多边形属性。

这就是我得到的:

GeoJSON:

{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"bbox":[13.55188823869398,44.440081209521175,16.6289966237125,46.16059787999315],"type":"MultiPolygon","coordinates":[[[[15.395583981629768,44.57162377024533],[15.387003350545871,44.481720735232564],[15.261789625068943,44.48813408824978],[15.270172550335417,44.578048939581144],[15.395583981629768,44.57162377024533]]],[[[15.896964543940912,44.544415530182626],[16.022240457648902,44.53723684127118],[16.14748751000305,44.52990760944508],[16.137724258293254,44.440081209521175],[16.012673860640266,44.44739698760816],[15.88759478603406,44.45456249478511],[15.76248761526664,44.46157767625901],[15.771660353342368,44.55144362101705],[15.896964543940912,44.544415530182626]]],[[[15.152955209351642,44.674242834298695],[15.027294842687972,44.6803775578638],[15.035349165740053,44.770301745657044],[15.161209210808025,44.764155656145604],[15.152955209351642,44.674242834298695]]],[[[15.395583981629768,44.57162377024533],[15.40420062719178,44.661519892738035],[15.52978449007481,44.65493177334668],[15.538636545464684,44.74480883793866],[15.664392732134285,44.73805721601009],[15.655341665136223,44.64819262251561],[15.646328471445097,44.55832105973176],[15.520969484947091,44.56504779340633],[15.395583981629768,44.57162377024533]]],[[[15.906373586831855,44.63426143624865],[15.780871560861883,44.641302492390295],[15.790121463337991,44.731154339362874],[15.915822144904903,44.7241002616354],[15.906373586831855,44.63426143624865]]],[[[14.909464652174844,44.77629632941221],[14.783556270565919,44.78213936065267],[14.791243042374749,44.8720788835874],[14.917352248635115,44.86622499380096],[14.909464652174844,44.77629632941221]]],[[[15.40420062719178,44.661519892738035],[15.278590669072724,44.667956929679484],[15.28704418791397,44.75785810878928],[15.295533315163146,44.84775252708752],[15.421542808951754,44.84129159985158],[15.412853498605203,44.751409152650304],[15.40420062719178,44.661519892738035]]],[[[15.295533315163146,44.84775252708752],[15.169497988826626,44.854061767894706],[15.17782174856998,44.943961219958226],[15.304058260811797,44.937640234683336],[15.295533315163146,44.84775252708752]]],[[[15.67348189503577,44.82791488944938],[15.547525868962715,44.83467903673759],[15.55645268017813,44.92454241922587],[15.682609378238029,44.91776569199236],[15.67348189503577,44.82791488944938]]],[[[15.574419653120414,45.10424893283504],[15.447831530393547,45.11089856282971],[15.456668762059818,45.20075425647369],[15.583460263041763,45.19409216255446],[15.574419653120414,45.10424893283504]]],[[[15.084394984513631,45.309708772973096],[15.076133963305915,45.21982378925574],[14.94923765800067,45.2258745480123],[14.941215654803312,45.13597182321009],[14.814498911953551,45.1418585743132],[14.822316698924032,45.23177234906947],[14.695371707066238,45.237517145249605],[14.703017502529459,45.32743542422996],[14.710695871844338,45.4173474925388],[14.8380521975077,45.41158102170872],[14.830167727940616,45.321679814539486],[14.957293763601468,45.315770914953696],[14.965384175175874,45.40566097472601],[15.092691175810298,45.39958739941671],[15.084394984513631,45.309708772973096]]],[16.19120538066795,46.06345399526351],[16.062454717796655,46.07086579545412]]]]},"properties":{"code":"1167","maptype":"Distribution","category":"Species","isocode":"HR","refgrid":"EEA 10x10km","sensitive":"non-sensitive"}}],"fileName":"Test"}

我的型号:

public class Species
{
public int Id { get; set; }
public string Name { get; set; }
//property to which I want to map the MultiPolygon feature from GeoJSON. This is a NetToplogySuite type.
public MultiPolygon Range { get; set; }
}

我尝试使用NetTopologySuite和GeoJSON.Net库来进行GeoJSON转换和映射,但没有走多远。我在控制器中收到GeoJSON作为字符串:

using NetTopologySuite.IO;
using NetTopologySuite.Geometries;
using GeoJSON.Net.Feature;
using GeoJSON.Net;
public void GeoJson(string json)
{
Species newSpecies = new Species();
var reader = new GeoJsonReader();
var featureCollection = reader.Read<FeatureCollection>(json);
if (featureCollection == null)
{
return;
}
// loop through all the parsed features
for (int featureIndex = 0;
featureIndex < featureCollection.Features.Count;
featureIndex++)
{
// get json feature
var jsonFeature = featureCollection.Features[featureIndex];
Geometry geom = null;
// get geometry type to create appropriate geometry
switch (jsonFeature.Geometry.Type)
{
case GeoJSONObjectType.Point:
break;
case GeoJSONObjectType.MultiPoint:
break;
case GeoJSONObjectType.LineString:
break;
case GeoJSONObjectType.MultiLineString:
break;
case GeoJSONObjectType.Polygon:
break;
case GeoJSONObjectType.MultiPolygon:
{
//this is where I want to convert GeoJSON MultiPolygon to a NetToplogySuite MultiPolygon but I'm don't know how. Basically I want to map the newSpecies.Range to the MultiPolygon jsonFeature. 
}
break;
case GeoJSONObjectType.GeometryCollection:
break;
case GeoJSONObjectType.Feature:
break;
case GeoJSONObjectType.FeatureCollection:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}

有什么想法吗?

谢谢!

在阅读了互联网上几乎所有的页面后,我重构了你的答案,因为(我认为(这是一个复制粘贴错误。除了添加到.之外,我永远找不到你使用firstLevelCoordinateList的目的

所以,我重构了你的代码。这个版本可能包含GeoJSON.Net的痕迹,但我后来尝试删除它的痕迹,并将其完全基于NetTopologySuite。然而,后来出现了另一种解决方案。。。

using GeoJSON.Net;
using GeoJSON.Net.Contrib.EntityFramework;
using GeoJSON.Net.Feature;
using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using RekylService.ExternalSync.DataPortal.Imports.Interfaces;
using System.Collections.Generic;
using System.Linq;
using LineString = GeoJSON.Net.Geometry.LineString;
using MultiLineString = GeoJSON.Net.Geometry.MultiLineString;
using MultiPoint = GeoJSON.Net.Geometry.MultiPoint;
using MultiPolygon = GeoJSON.Net.Geometry.MultiPolygon;
using Point = GeoJSON.Net.Geometry.Point;
using NTS = NetTopologySuite;
namespace Parser
{
public class GeoShapeJsonParser
{
public ICollection<Geometry> ParseGeoShapes(string data)
{
var reader = new NTS.IO.GeoJsonReader();
var featureCollection = reader.Read<FeatureCollection>(data);
if (featureCollection == null)
return null;
var geoFactory = NTS.NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var shapes = new List<Geometry>();
foreach (var shape in featureCollection.Features)
{
if (shape.Type == GeoJSONObjectType.MultiPolygon)
{
var multipolygon = shape.Geometry as MultiPolygon;
var ringList = new List<NTS.Geometries.LinearRing>();
var polygonList = new List<NTS.Geometries.Polygon>();
foreach (var xpolygon in multipolygon.Coordinates) //I had a name conflict, hence xpolygon instead of polygon ;)
{
foreach (var lineString in xpolygon.Coordinates) //the first lineString is the shell, and the ones following are holes
{
var linearRingCoordinates = new List<NTS.Geometries.Coordinate>();
foreach (var coordinate in lineString.Coordinates)
{
var coordinates = new NTS.Geometries.Coordinate(coordinate.Longitude, coordinate.Latitude);
linearRingCoordinates.Add(coordinates);
}
var ring = geoFactory.CreateLinearRing(linearRingCoordinates.ToArray());
ringList.Add(ring);
}
var polygon = geoFactory.CreatePolygon(ringList.First(), ringList.Skip(1).ToArray()); //this takes the first ring as outer shell and the rest as holes
polygonList.Add(polygon);
}
shapes.Add(geoFactory.CreateMultiPolygon(polygonList.ToArray()));
}
}
return shapes;

此解决方案还考虑多边形中的孔。不过,踢来了(现在是100%NetTopologySuite,所有形状(:

public class GeoShapeJsonParser
{
public ICollection<Geometry> ParseGeoShapes(string data)
{
var reader = new GeoJsonReader();
var featureCollection = reader.Read<FeatureCollection>(data);
var shapes = new List<Geometry>();
foreach (var feature in featureCollection)
shapes.AddRange(Extract(feature));
}
public IEnumerable<Geometry> Extract(IFeature feature)
{
var extract = new List<Geometry>();
new GeometryExtracter<Point>(extract).Filter(feature.Geometry);
new GeometryExtracter<MultiPoint>(extract).Filter(feature.Geometry);
new GeometryExtracter<LineString>(extract).Filter(feature.Geometry);
new GeometryExtracter<MultiLineString>(extract).Filter(feature.Geometry);
new GeometryExtracter<LinearRing>(extract).Filter(feature.Geometry);
new GeometryExtracter<Polygon>(extract).Filter(feature.Geometry);
new GeometryExtracter<MultiPolygon>(extract).Filter(feature.Geometry);
return extract;
}

这绝对是解析所有几何形状的最好、最短、最快的方法。我对这个主题缺乏相关文档感到惊讶。

为了将其保存到SQL server,在使用"the extracted geometry object".ToText()发送之前,我将每个形状制作成WKT。

在存储库中,我将它们作为DbGeography.FromText("the extracted geometry object")分配给字段。

这是我经过几天的反复尝试后编写的解决方案。基本上,geoJSON以字符串的形式输入,使用Newtonsoft.JSON的Parse方法转换为JSON,然后使用geoJSON.NET的GeoJsonReader转换为FetureCollection。然后,我循环浏览所有解析的功能并创建适当的几何图形。在这种情况下,我只对多多边形功能感兴趣,我将其从NetTopologySuite转换为多多边形类型。

using NetTopologySuite.IO;
using NetTopologySuite.Geometries;
using GeoJSON.Net.Feature;
using GeoJSON.Net;
[HttpPost]
public void GeoJson(string json) {
var test = json;
var item = JObject.Parse(json);
Species newSpecies = new Species();
var reader = new GeoJsonReader();
var featureCollection = reader.Read < FeatureCollection > (json);
if (featureCollection == null) {
return;
}
// loop through all the parsed features
for (int featureIndex = 0; featureIndex < featureCollection.Features.Count; featureIndex++) {
// get json feature
var jsonFeature = featureCollection.Features[featureIndex];
// get geometry type to create appropriate geometry
switch (jsonFeature.Geometry.Type) {
case GeoJSONObjectType.Point:
break;
case GeoJSONObjectType.MultiPoint:
break;
case GeoJSONObjectType.LineString:
break;
case GeoJSONObjectType.MultiLineString:
break;
case GeoJSONObjectType.Polygon:
break;
case GeoJSONObjectType.MultiPolygon:
{
var multipoly = jsonFeature.Geometry as GeoJSON.Net.Geometry.MultiPolygon;
var polygonList = new List < Polygon > ();
foreach(var firstLevel in multipoly.Coordinates) {
var firstLevelCoordinateList = new List < List < Coordinate >> ();
foreach(var secondLevel in firstLevel.Coordinates) {
var secondLevelCoordinateList = new List < Coordinate > ();
foreach(var thirdLevel in secondLevel.Coordinates) {
var coordinates = new Coordinate(thirdLevel.Longitude, thirdLevel.Latitude);
secondLevelCoordinateList.Add(coordinates);
}
var coordArr = new Coordinate[secondLevelCoordinateList.Count];
for (int i = 0; i < secondLevelCoordinateList.Count; i++) {
coordArr[i] = secondLevelCoordinateList[i];
}
var poly = new GeometryFactory().CreatePolygon(coordArr);
polygonList.Add(poly);
firstLevelCoordinateList.Add(secondLevelCoordinateList);
}
}
var polyArr = new Polygon[polygonList.Count];
for (int i = 0; i < polygonList.Count; i++) {
polyArr[i] = polygonList[i];
}
//NetTopologySuite Multipolygon property
newSpecies.Range = new GeometryFactory().CreateMultiPolygon(polyArr);
}
break;
case GeoJSONObjectType.GeometryCollection:
break;
case GeoJSONObjectType.Feature:
break;
case GeoJSONObjectType.FeatureCollection:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}

最新更新