代码之家  ›  专栏  ›  技术社区  ›  Johan

C网络拓扑结构M值

  •  1
  • Johan  · 技术社区  · 7 年前

    我使用NetTopologySuite作为SqlGeometries的.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值创建点/坐标/线串?

    2 回复  |  直到 7 年前
        1
  •  2
  •   TJ Rockefeller    7 年前

    默认坐标序列为 CoordinateArraySequence 目前不支持 M 价值观,但看起来 DotSpatialAffineCoordinateSequence 支持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);
            }
        }
    }
    
        2
  •  0
  •   TJ Rockefeller    7 年前

    是的,它是 缺陷 的默认实现中缺少的功能 ICoordinateSequence . 看起来他们已经开始进行更改以支持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);
        }
    

    然后依次调用 GetOrdinate SetOrdinate 在里面 CoordinateArraySequence

        /// <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);
            }
        }
    

    你可以看到,当你打电话 设置纵坐标 具有 Ordinate.M 什么都没准备好,打电话的时候 获得坐标 具有 纵坐标m 它总是会回来的。

    如果你真的想使用nettopologysuite,你可以从这里开始回购。 https://github.com/NetTopologySuite/NetTopologySuite 并进行支持所需的更新 M 默认情况下是值,但我认为有很多事情需要更改。如果你更新了它,我相信维护nettopologysuite github repo的人会很感激一个包含任何更改的pull请求。

    推荐文章