[英]Concatenate two C# DbGeography Polygons into a single multipolygon
I have downloaded a map with Swedish districts as Shape files from an official source. 我从官方来源下载了带有瑞典地区的地图作为Shape文件。 I then used QGIS to convert the data into
geojson
and then converted the geojson
to DbGeography
like this: 然后我用QGIS将数据转换成
geojson
,然后转化的geojson
到DbGeography
这样的:
https://stackoverflow.com/a/49225753/3850405 https://stackoverflow.com/a/49225753/3850405
Map source: 地图来源:
https://www.lantmateriet.se/sv/Kartor-och-geografisk-information/Kartor/oppna-data/hamta-oppna-geodata/#faq:gsd-distriktsindelning https://www.lantmateriet.se/sv/Kartor-och-geografisk-information/Kartor/oppna-data/hamta-oppna-geodata/#faq:gsd-distriktsindelning
The districts can have two or more areas but are not multipolygon
but polygon
where each area share the same key (code). 这些区域可以具有两个或多个区域,但不是
multipolygon
polygon
,而是每个区域共享相同键(代码)的polygon
。 Using other official sources I have gotten a multipolygon
directly but not from this source. 使用其他官方资料,我直接得到了一个
multipolygon
,但不是从这个资料中得到的。 When I save it to my database I would like to do it right and only have the code and name properties once and store it as a multipolygon
. 当我将其保存到数据库中时,我想做的正确,只具有一次code和name属性,并将其存储为
multipolygon
。 I use Entity Framework to store the information to my database. 我使用实体框架将信息存储到数据库中。
How can I concatenate the two or more polygons into a multipolygon? 如何将两个或多个多边形连接成一个多边形?
Example for Stora Hammars distrikt with code 101019
. 代码为
101019
Stora Hammars 101019
。
Current code: 当前代码:
Model: 模型:
/// <summary>
/// GSD means Geografiska Sverigedata and is available via Lantmäteriet in Sweden.
/// </summary>
public class GSDDistrict
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Code { get; set; }
public string Name { get; set; }
public string ObjectId { get; set; }
public string ObjectVer { get; set; }
public DateTime ValidFrom { get; set; }
public DbGeography Area { get; set; }
}
Method: 方法:
public void AddGsdDistricts()
{
using (var reader = File.OpenText($"{path}\\GIS\\lantmateriet-gsd-distriktsindelning.geojson"))
{
var json = reader.ReadToEnd();
var featureCollection = JsonConvert.DeserializeObject<GeoJSON.Net.Feature.FeatureCollection>(json);
foreach (var feature in featureCollection.Features)
{
var code = feature.Properties["DISTRKOD"].ToString();
var gsdDistrict = new GSDDistrict();
string geoJson = JsonConvert.SerializeObject(feature.Geometry);
var dbGeography = JsonConvert.DeserializeObject<DbGeography>(geoJson, new DbGeographyGeoJsonConverter());
gsdDistrict.Area = dbGeography;
gsdDistrict.Area = gsdDistrict.Area.MakePolygonValid();
if (db.GSDDistricts.All(x => x.Code != code))
{
gsdDistrict.Code = feature.Properties["DISTRKOD"].ToString();
gsdDistrict.Name = feature.Properties["DISTRNAMN"].ToString();
gsdDistrict.ObjectId = feature.Properties["OBJEKT_ID"].ToString();
gsdDistrict.ObjectVer = feature.Properties["OBJEKT_VER"].ToString();
gsdDistrict.ValidFrom = DateTime.ParseExact(feature.Properties["GALLERFRAN"].ToString(), "yyyy/MM/dd", CultureInfo.InvariantCulture);
db.GSDDistricts.Add(gsdDistrict);
//Yes this will be slow but the method will only run once
db.SaveChanges();
Program.LogWithGreenConsoleColour($"Added geo data for {gsdDistrict.Name}");
}
else if (db.GSDDistricts.Any(x => x.Code == code && x.Area.Disjoint(gsdDistrict.Area)))
{
//Add the other area here
Program.LogWithGreenConsoleColour($"Here");
}
}
if (db.ChangeTracker.HasChanges())
{
db.SaveChanges();
Program.LogWithGreenConsoleColour($"Saved geo data GSD District from Lantmäteriet to database");
}
}
}
The MakePolygonValid()
extension method is to solve ring orientation error due to that SQL Server uses left-handed orientation and almost all sources in Sweden use right-handed orientation. MakePolygonValid()
扩展方法用于解决环形定向错误,因为SQL Server使用左手定向,瑞典的几乎所有源都使用右手定向。 The extension method is described here: 扩展方法如下:
https://stackoverflow.com/a/49454154/3850405 https://stackoverflow.com/a/49454154/3850405
Turns out I did not have to convert it into a multipolygon
at all. 事实证明,我根本不需要将其转换为
multipolygon
。 The key was DbGeography.Union
. 关键是
DbGeography.Union
。
https://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.union(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.union(v=vs.110).aspx
else if (db.GSDDistricts.Any(x => x.Code == code && x.Area.Disjoint(gsdDistrict.Area)))
{
var district = db.GSDDistricts.FirstOrDefault(x => x.Code == code);
Program.LogWithGreenConsoleColour($"Adding another area for {district.Name}");
district.Area = district.Area.Union(gsdDistrict.Area);
db.SaveChanges();
}
Looks like this when loaded into Google Maps, red line instead of teal above. 加载到Google Maps中时看起来像这样,用红线代替上面的蓝绿色。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.