# 如何使用System.Spatial.GeographyPoint

How to use System.Spatial.GeographyPoint
2021-06-10
•  译文(汉语)
•  原文(英语)

`IPoint`是,提供了一个接口`Latitude``Longitude`,这两个类型的`double`.

``````  public static double CalculateDistance(IPoint pointA, IPoint pointB)
{
var gp1 = GeographyPoint.Create(pointA.Latitude, pointA.Longitude);
var gp2 = GeographyPoint.Create(pointB.Latitude, pointB.Longitude);

return gp1.Distance(gp2) ?? 0;
}
``````

`NotImplementedException`on结尾`point1.Distance(point2)`.该消息以法语显示,但基本上显示为"未注册任何操作.请使用属性SpatialImplementation.CurrentImplementation.Operations提供操作".

``````public static double CalculateDistance(IPoint pointA, IPoint pointB)
{
var gp1 = GeographyPoint.Create(pointA.Latitude, pointA.Longitude);
var gp2 = GeographyPoint.Create(pointB.Latitude, pointB.Longitude);

return SpatialImplementation.CurrentImplementation.Operations.Distance(gp1, gp2);
}
``````

Msdn对此并不十分冗长.

• 如果只需要计算点之间的距离,则只需复制C#中Haversine公式Vincenty公式的实现即可.

• 如果您需要DB上的空间,请使用Entity Framework 5/6.

• 如果需要在C#中进行进一步的空间运算,请使用NetTopologySuite之类的东西.有一个NuGet,它的使用非常简单.

"该库上的大多数类都是抽象的,因此要由您来实现大部分."-嗯,一点都不正确.创建实例(文档很烂)有点麻烦.对于除点以外的任何内容,您都需要`SpatialBuilder.Create()`获取构建器,然后使用`GeographyPipeline``GeometryPipeline`.

I need a function to calculate distance between point A and point B.

Namespace `System.Spatial` seems to be exactly what I need, but I can't figure how to use it.

`IPoint` is an interface that provides `Latitude` and `Longitude`, both of type `double`.

First try :

``````  public static double CalculateDistance(IPoint pointA, IPoint pointB)
{
var gp1 = GeographyPoint.Create(pointA.Latitude, pointA.Longitude);
var gp2 = GeographyPoint.Create(pointB.Latitude, pointB.Longitude);

return gp1.Distance(gp2) ?? 0;
}
``````

That ends with a `NotImplementedException`on `point1.Distance(point2)`. The message is in french, but basically it says "No operation registered. Please provide operation using property SpatialImplementation.CurrentImplementation.Operations".

Ok, I will try this then :

``````public static double CalculateDistance(IPoint pointA, IPoint pointB)
{
var gp1 = GeographyPoint.Create(pointA.Latitude, pointA.Longitude);
var gp2 = GeographyPoint.Create(pointB.Latitude, pointB.Longitude);

return SpatialImplementation.CurrentImplementation.Operations.Distance(gp1, gp2);
}
``````

Now I got a `NullReferenceException` on `SpatialImplementation.CurrentImplementation.Operations`.

Msdn is not much verbose about this.

Anyone can explain how to get these implementations ?

Talk1:
How are you calling that method, and have you implemented `IPoint` interface with a class ?
Talk2:
Sure I have implemented it. It just provides latitude and longitude. The errors are exactly what I said. I'm calling this from unit test for now.
Solutions1

IMHO you shouldn't use `System.Spatial`. It's an half-baked library created for OData interoperability with Spatial, namely for WCF Data-Services.

You can check here for more information. Also, most of the classes on that library are abstract, hence up-to-you to be implement most-of-it.

Also, and even worse, they're incompatible with Entity Framework spatial support.

I'm not sure what kind of project you're on but I would suggest these guidelines:

• if you just need to calculate distances between points just copy an implementation of the Haversine Formula or Vincenty's Formula in C#.

• if you need spatial on DB just go with Entity Framework 5/6.

• if you need further spatial operations in c# use something like NetTopologySuite. There's a NuGet for it and it's really simple to use.

Talk1:
I dont need db support, at least for now. All caculation are made in-memory. I used the algorithm from this answer and it seems to give correct result : stackoverflow.com/a/6545031/607162. That said, I had preffered a .net provided algorithm.
Talk2:
You can reference the SqlGeography/SqlGeometry types which are included on the Sql Server 2008/2012 types library, even without using a Database. They work perfectly fine on c#.
Talk3:
"most of the classes on that library are abstract, hence up-to-you to be implement most-of-it." - Hmm, not true at all. It is a bit of pain to create instances (and the docs suck). For anything but points, you need to do `SpatialBuilder.Create()` to get a builder then use the `GeographyPipeline` or `GeometryPipeline`.