C#净拓扑匹配M值

C#净拓扑匹配M值,c#,.net-core,nettopologysuite,C#,.net Core,Nettopologysuite,我使用NetTopologySuite作为SQLGeometrics的.net核心替代品。它似乎不支持点或坐标中的M值,尽管它有M个属性。例如,以下简单代码: using NetTopologySuite.Geometries; using System.Diagnostics; namespace PlaygroundCore { class Program { static void Main(string[] args) {

我使用NetTopologySuite作为SQLGeometrics的.net核心替代品。它似乎不支持点或坐标中的M值,尽管它有M个属性。例如,以下简单代码:

using NetTopologySuite.Geometries;
using System.Diagnostics;

namespace PlaygroundCore
{
    class Program
    {
        static void Main(string[] args)
        {
            var p3 = new Point(1, 2, 3);
            p3.Y = 8;
            p3.M = 1;
            var m = p3.M;

            Debug.WriteLine(p3);
            Debug.WriteLine(p3.M);
            Debug.WriteLine(m);
        }
    }
}
输出

POINT (1 8 3)
NaN
NaN
M值似乎被完全拒绝。这是实现中的一个bug吗?有没有办法用M值创建点/坐标/线串?

是的,这是默认实现的
ICoordinateSequence
中缺少的一个bug功能。看起来他们已经开始进行更改以支持M值,但这些更改并没有在任何地方进行。下面是代码中不支持M值的至少一个区域,它最终导致了您看到的问题

当引用p3.M时,它使用这些get和set方法

    public double M
    {
        get
        {
            if (CoordinateSequence == null)
                throw new ArgumentOutOfRangeException("M called on empty Point");
            return CoordinateSequence.GetOrdinate(0, Ordinate.M);
        }
        set => CoordinateSequence.SetOrdinate(0, Ordinate.M, value);
    }
然后依次调用
coordinarraysequence中的
getorigin
setorigin

    /// <summary>
    /// Returns the ordinate of a coordinate in this sequence.
    /// Ordinate indices 0 and 1 are assumed to be X and Y.
    /// Ordinate indices greater than 1 have user-defined semantics
    /// (for instance, they may contain other dimensions or measure values).
    /// </summary>
    /// <param name="index">The coordinate index in the sequence.</param>
    /// <param name="ordinate">The ordinate index in the coordinate (in range [0, dimension-1]).</param>
    /// <returns></returns>
    public double GetOrdinate(int index, Ordinate ordinate)
    {
        switch (ordinate)
        {
            case Ordinate.X:
                return Coordinates[index].X;
            case Ordinate.Y:
                return Coordinates[index].Y;
            case Ordinate.Z:
                return Coordinates[index].Z;
            default:
                return double.NaN;
        }
    }

    /// <summary>
    /// Sets the value for a given ordinate of a coordinate in this sequence.
    /// </summary>
    /// <param name="index">The coordinate index in the sequence.</param>
    /// <param name="ordinate">The ordinate index in the coordinate (in range [0, dimension-1]).</param>
    /// <param name="value">The new ordinate value.</param>
    public void SetOrdinate(int index, Ordinate ordinate, double value)
    {
        switch (ordinate)
        {
            case Ordinate.X:
                Coordinates[index].X = value;
                break;
            case Ordinate.Y:
                Coordinates[index].Y = value;
                break;
            case Ordinate.Z:
                Coordinates[index].Z = value;
                break;
            //default:
            //    //throw new ArgumentException("invalid ordinate index: " + ordinate);
        }
    }
//
///返回此序列中坐标的纵坐标。
///纵坐标指数0和1假定为X和Y。
///大于1的纵坐标索引具有用户定义的语义
///(例如,它们可能包含其他标注或测量值)。
/// 
///序列中的坐标索引。
///坐标中的坐标索引(范围[0,维度-1])。
/// 
公共双坐标(整数索引,坐标)
{
开关(纵坐标)
{
案例X:
返回坐标[index].X;
案例Y:
返回坐标[index].Y;
案例Z:
返回坐标[index].Z;
违约:
返回double.NaN;
}
}
/// 
///设置此序列中坐标的给定坐标的值。
/// 
///序列中的坐标索引。
///坐标中的坐标索引(范围[0,维度-1])。
///新的纵坐标值。
公共空坐标(整数索引、坐标坐标、双值)
{
开关(纵坐标)
{
案例X:
坐标[索引]。X=值;
打破
案例Y:
坐标[索引]。Y=值;
打破
案例Z:
坐标[index].Z=值;
打破
//默认值:
////抛出新的ArgumentException(“无效的纵坐标索引:“+纵坐标”);
}
}
正如您所看到的,当您使用
origin.M
调用
setorigin
时,没有设置任何内容,而使用
origin.M
调用
getorigin
时,它将始终返回NaN


如果你真的想使用NetTopologySuite,你可以从这里开始回购,并在默认情况下进行必要的更新,以支持
M
值,但我认为有许多事情需要更改。如果您确实更新了它,我相信维护NetTopologySuite GitHub repo的家伙们会很乐意接受包含任何更改的pull请求。

默认坐标序列是
CoordinaryArraySequence
,目前不支持
m
值,但看起来
DotSpatialAffineCoordinateSequence
确实支持M值。要使
M
值起作用,我必须执行以下操作

using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using System.Diagnostics;

namespace NetTopologyTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //This sequence has to be initialized with ordinates XYZM. If you construct it
            //with just XYZ values, then you can't add M values to it later.
            var coordinateSequence = new DotSpatialAffineCoordinateSequence(new[] { 1.0, 2.0 }, new[] { 3.0 }, new[] { 4.0 });
            var sequenceFactory = new DotSpatialAffineCoordinateSequenceFactory(GeoAPI.Geometries.Ordinates.XYZM);
            var geometryFactory = new GeometryFactory(sequenceFactory);
            var p3 = new Point(coordinateSequence, geometryFactory);
            p3.Y = 8;
            p3.M = 1;
            var m = p3.M;

            Debug.WriteLine(p3);
            Debug.WriteLine(p3.M);
            Debug.WriteLine(m);
        }
    }
}

这不是一个bug,它取决于坐标序列(工厂)可以处理什么。(默认)CooeDateSequence和irs工厂可以处理atm三,第三个是Z。感谢TJ提供的替代解决方案@FOBER迈尔在实现一个接口(在这种情况下,I点)时,我会考虑它,如果不是一个bug,至少是坏的/不需要的设计,具有一个可调用的SETER,但不是一个接口属性的吸气剂。不管引擎盖下面是什么,因为这是用户可以公开看到的。@Johan,您更喜欢
NotSupportedException
?我见过很多只部分实现的公共接口。@FObermaier我更喜欢正确的实现。当它是一个官方的Microsoft.NET nuget包(Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite)时,我希望它能按预期工作。好吧,这就解释了问题。我可能错了,但NetTopologySuite不是使其与实体框架核心一起工作的唯一选项(即,能够从数据库中获取和保存几何图形)吗?