/// <summary>
        /// Creates a shape based on the specified geometry.  This shape will be standing alone,
        /// all by itself.
        /// </summary>
        /// <param name="geometry">The geometry to create a shape from.</param>
        /// <param name="copyAttributes">The <see cref="IGeometry.UserData"/> will be copied to the <see cref="DSShape.Attributes"/>.</param>
        /// <returns>A <see cref="DSShape"/> representing the <paramref name="geometry"/></returns>
        public static DSShape ToDotSpatialShape(this IGeometry geometry, bool copyAttributes = false)
        {
            if (geometry is IPolygonal)
                geometry = OrientationEnsured((IPolygonal)geometry);

            var coords = geometry.Coordinates;
            var vertices = new double[geometry.NumPoints * 2];
            var z = new double[geometry.NumPoints];
            var hasZ = false;
            double[] m = null; //new double[geometry.NumPoints];
            var hasM = false;

            var shape = new DSShape
                            {
                                MinZ = double.MaxValue,
                                MaxZ = double.MinValue,
                                MinM = double.MaxValue,
                                MaxM = double.MinValue
                            };

            for (var i = 0; i < coords.Length; i++)
            {
                var c = coords[i];
                vertices[i * 2] = c.X;
                vertices[i * 2 + 1] = c.Y;

                if (!Double.IsNaN(c.Z))
                {
                    z[i] = c.Z;
                    shape.MinZ = shape.MinZ < c.Z ? shape.MinZ : c.Z;
                    shape.MaxZ = shape.MaxZ < c.Z ? shape.MaxZ : c.Z;
                    hasZ = true;
                }
                /*
                if (!Double.IsNaN(c.M))
                {
                    m[i] = c.M;
                    shape.MinM = shape.MinM < c.M ? shape.MinM : c.M;
                    shape.MaxM = shape.MaxM < c.M ? shape.MaxM : c.M;
                    hasZ = true;
                }
                 */
            }

            if (!hasZ)
            {
                z = null;
                shape.MinZ = shape.MaxZ = double.NaN;
            }
            if (!hasM)
            {
                m = null;
                shape.MinM = shape.MaxM = double.NaN;
            }

            shape.Range = ShapeRangeFromGeometry(geometry, vertices, 0);
            shape.Vertices = vertices;
            shape.Z = z;
            shape.M = m;

            if (geometry.UserData != null && copyAttributes)
            {
                var ud = geometry.UserData as object[];
                shape.Attributes = ud ?? new[] { geometry.UserData };
            }
            return shape;
        }
        /// <summary>
        /// Creates a shape based on the specified geometry.  This shape will be standing alone,
        /// all by itself.
        /// </summary>
        /// <param name="geometry">The geometry to create a shape from.</param>
        /// <param name="copyAttributes">The <see cref="IGeometry.UserData"/> will be copied to the <see cref="DSShape.Attributes"/>.</param>
        /// <returns>A <see cref="DSShape"/> representing the <paramref name="geometry"/></returns>
        public static DSShape ToDotSpatialShape(this IGeometry geometry, bool copyAttributes = false)
        {
            if (geometry is IPolygonal)
            {
                geometry = OrientationEnsured((IPolygonal)geometry);
            }

            var coords   = geometry.Coordinates;
            var vertices = new double[geometry.NumPoints * 2];
            var z        = new double[geometry.NumPoints];
            var hasZ     = false;

            double[] m    = null; //new double[geometry.NumPoints];
            var      hasM = false;

            var shape = new DSShape
            {
                MinZ = double.MaxValue,
                MaxZ = double.MinValue,
                MinM = double.MaxValue,
                MaxM = double.MinValue
            };

            for (var i = 0; i < coords.Length; i++)
            {
                var c = coords[i];
                vertices[i * 2]     = c.X;
                vertices[i * 2 + 1] = c.Y;

                if (!Double.IsNaN(c.Z))
                {
                    z[i]       = c.Z;
                    shape.MinZ = shape.MinZ < c.Z ? shape.MinZ : c.Z;
                    shape.MaxZ = shape.MaxZ < c.Z ? shape.MaxZ : c.Z;
                    hasZ       = true;
                }

                /*
                 * if (!Double.IsNaN(c.M))
                 * {
                 *  m[i] = c.M;
                 *  shape.MinM = shape.MinM < c.M ? shape.MinM : c.M;
                 *  shape.MaxM = shape.MaxM < c.M ? shape.MaxM : c.M;
                 *  hasZ = true;
                 * }
                 */
            }

            if (!hasZ)
            {
                z          = null;
                shape.MinZ = shape.MaxZ = double.NaN;
            }
            if (!hasM)
            {
                m          = null;
                shape.MinM = shape.MaxM = double.NaN;
            }

            shape.Range    = ShapeRangeFromGeometry(geometry, vertices, 0);
            shape.Vertices = vertices;
            shape.Z        = z;
            shape.M        = m;

            if (geometry.UserData != null && copyAttributes)
            {
                var ud = geometry.UserData as object[];
                shape.Attributes = ud ?? new[] { geometry.UserData };
            }
            return(shape);
        }