/// <summary> /// Initializes a new instance of the <see cref="RawCoordinateSequenceFactory"/> class. /// </summary> /// <param name="ordinateGroups"> /// A sequence of zero or more <see cref="Ordinates"/> flags representing ordinate values /// that should be allocated together. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="ordinateGroups"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when a given flag appears in more than one element of /// <paramref name="ordinateGroups"/>. /// </exception> /// <remarks> /// Any flags not represented in <paramref name="ordinateGroups"/>, and any spatial or /// measure dimensions beyond the 16th, will be allocated together, SoA-style. /// <para/> /// Elements without any bits set will be silently ignored. /// </remarks> public RawCoordinateSequenceFactory(IEnumerable <Ordinates> ordinateGroups) { if (ordinateGroups is null) { throw new ArgumentNullException(nameof(ordinateGroups)); } var seenOrdinates = Ordinates.None; var ordinateGroupsList = new List <Ordinates>(); foreach (var ordinateGroup in ordinateGroups) { if ((ordinateGroup & seenOrdinates) != Ordinates.None) { throw new ArgumentException("Each ordinate may show up in at most one group.", nameof(ordinateGroups)); } seenOrdinates |= ordinateGroup; if (OrdinatesUtility.OrdinatesToDimension(ordinateGroup) < 2) { // it would have been equally correct to omit this continue; } _ordinatesInGroups |= ordinateGroup; ordinateGroupsList.Add(ordinateGroup); } _ordinateGroups = ordinateGroupsList.ToArray(); }
/// <summary> /// Writes a binary encoded PostGIS of the given <paramref name="geometry"/> to to an array of bytes. /// </summary> /// <param name="geometry">The geometry</param> /// <param name="ordinates">The ordinates of each geometry's coordinate. <see cref="Ordinates.XY"/> area always written.</param> /// <returns>An array of bytes.</returns> private byte[] Write(IGeometry geometry, Ordinates ordinates) { var coordinateSpace = 8 * OrdinatesUtility.OrdinatesToDimension(ordinates); var bytes = GetBytes(geometry, coordinateSpace); Write(geometry, ordinates, new MemoryStream(bytes)); return(bytes); }
/// <summary> /// Writes out a given <see cref="Geometry"/> to a byte array. /// </summary> /// <param name="geometry">The <see cref="Geometry"/> to write.</param> /// <returns>The byte array.</returns> public byte[] Write(Geometry geometry) { var maxCoords = HandleOrdinates == Ordinates.None ? Ordinates.XYZM : HandleOrdinates; int coordinateSpace = 8 * OrdinatesUtility.OrdinatesToDimension(maxCoords & CheckOrdinates(geometry)); byte[] bytes = GetBytes(geometry, coordinateSpace); Write(geometry, new MemoryStream(bytes)); return(bytes); }
/// <summary> /// Creates an instance of this class /// </summary> /// <param name="coordinates">The coordinates</param> /// <param name="ordinates"></param> public DotSpatialAffineCoordinateSequence(IReadOnlyCollection <Coordinate> coordinates, Ordinates ordinates) : base(coordinates?.Count ?? 0, OrdinatesUtility.OrdinatesToDimension(ordinates & Ordinates.XYZM), OrdinatesUtility.OrdinatesToMeasures(ordinates & Ordinates.XYZM)) { coordinates = coordinates ?? Array.Empty <Coordinate>(); _xy = new double[2 * coordinates.Count]; if (HasZ) { _z = new double[coordinates.Count]; } if (HasM) { _m = new double[coordinates.Count]; } var xy = MemoryMarshal.Cast <double, XYStruct>(_xy); using (var coordinatesEnumerator = coordinates.GetEnumerator()) { for (int i = 0; i < xy.Length; i++) { if (!coordinatesEnumerator.MoveNext()) { ThrowForInconsistentCount(); } var coordinate = coordinatesEnumerator.Current; xy[i].X = coordinate.X; xy[i].Y = coordinate.Y; if (_z != null) { _z[i] = coordinate.Z; } if (_m != null) { _m[i] = coordinate.M; } } if (coordinatesEnumerator.MoveNext()) { ThrowForInconsistentCount(); } } void ThrowForInconsistentCount() => throw new ArgumentException("IReadOnlyCollection<T>.Count is inconsistent with IEnumerable<T> implementation.", nameof(coordinates)); }
/// <summary> /// Constructs a sequence of a given size, populated with new Coordinates. /// </summary> /// <param name="size">The size of the sequence to create.</param> /// <param name="ordinates">The kind of ordinates.</param> public DotSpatialAffineCoordinateSequence(int size, Ordinates ordinates) : base(size, OrdinatesUtility.OrdinatesToDimension(ordinates & Ordinates.XYZM), OrdinatesUtility.OrdinatesToMeasures(ordinates & Ordinates.XYZM)) { _xy = new double[2 * size]; if (HasZ) { _z = NullOrdinateArray(size); } if (HasM) { _m = NullOrdinateArray(size); } }
private static Ordinate[] ToOrdinateArray(Ordinates ordinates) { var result = new Ordinate[OrdinatesUtility.OrdinatesToDimension(ordinates)]; int nextIndex = 0; for (int i = 0; i < 32; i++) { if (ordinates.HasFlag((Ordinates)(1 << i))) { result[nextIndex++] = (Ordinate)i; } } return(result); }
/// <summary> /// Creates a sequence based on the given coordinate sequence. /// </summary> /// <param name="coordSeq">The coordinate sequence.</param> /// <param name="ordinates">The ordinates to copy</param> public DotSpatialAffineCoordinateSequence(CoordinateSequence coordSeq, Ordinates ordinates) : base(coordSeq?.Count ?? 0, OrdinatesUtility.OrdinatesToDimension(ordinates & Ordinates.XYZM), OrdinatesUtility.OrdinatesToMeasures(ordinates & Ordinates.XYZM)) { if (coordSeq is DotSpatialAffineCoordinateSequence dsCoordSeq) { _xy = (double[])dsCoordSeq._xy.Clone(); if (HasZ) { _z = ((double[])dsCoordSeq._z?.Clone()) ?? NullOrdinateArray(Count); } if (HasM) { _m = ((double[])dsCoordSeq._m?.Clone()) ?? NullOrdinateArray(Count); } } else { _xy = new double[2 * Count]; if (HasZ) { _z = new double[Count]; } if (HasM) { _m = new double[Count]; } var xy = MemoryMarshal.Cast <double, XYStruct>(_xy); for (int i = 0; i < xy.Length; i++) { xy[i].X = coordSeq.GetX(i); xy[i].Y = coordSeq.GetY(i); if (_z != null) { _z[i] = coordSeq.GetZ(i); } if (_m != null) { _m[i] = coordSeq.GetM(i); } } } }
/// <summary> /// Creates a <see cref="ICoordinateSequence" /> of the specified size and ordinates. /// For this to be useful, the <see cref="ICoordinateSequence" /> implementation must be mutable. /// </summary> /// <param name="size">The number of coordinates</param> /// <param name="ordinates"> /// The ordinates each coordinate has. <see cref="Ordinates.XY"/> is fix, <see cref="Ordinates.Z"/> and <see cref="Ordinates.M"/> can be set. /// </param> /// <returns></returns> public ICoordinateSequence Create(int size, Ordinates ordinates) { return(Create(size, OrdinatesUtility.OrdinatesToDimension(ordinates))); }