private static CoordinateSequence CreateSequence(Ordinates ordinateFlags, double[] xy) { // get the number of dimension to verify size of provided ordinate values array int dimension = RequiredDimension(ordinateFlags); // inject additional values double[] ordinateValues = InjectZM(ordinateFlags, xy); // get the required size of the sequence int size = Math.DivRem(ordinateValues.Length, dimension, out int remainder); if (remainder != 0) { throw new ArgumentException("ordinateFlags and number of provided ordinate values don't match"); } // create a sequence capable of storing all ordinate values. var res = GetCSFactory(ordinateFlags) .Create(size, RequiredDimension(ordinateFlags), OrdinatesUtility.OrdinatesToMeasures(ordinateFlags)); // fill in values int k = 0; for (int i = 0; i < ordinateValues.Length; i += dimension) { for (int j = 0; j < dimension; j++) { res.SetOrdinate(k, j, ordinateValues[i + j]); } k++; } return(res); }
/// <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(); }
protected static ICoordinateSequence AddCoordinateToSequence(ICoordinateSequence sequence, ICoordinateSequenceFactory factory, double x, double y, double?z, double?m) { // Create a new sequence var newSequence = factory.Create(sequence.Count + 1, sequence.Ordinates); // Copy old values var ordinates = OrdinatesUtility.ToOrdinateArray(sequence.Ordinates); for (var i = 0; i < sequence.Count; i++) { foreach (var ordinate in ordinates) { newSequence.SetOrdinate(i, ordinate, sequence.GetOrdinate(i, ordinate)); } } // new coordinate newSequence.SetOrdinate(sequence.Count, Ordinate.X, x); newSequence.SetOrdinate(sequence.Count, Ordinate.Y, y); if (z.HasValue) { newSequence.SetOrdinate(sequence.Count, Ordinate.Z, z.Value); } if (m.HasValue) { newSequence.SetOrdinate(sequence.Count, Ordinate.M, m.Value); } return(newSequence); }
/// <summary> /// Gets an array of <see cref="System.Double"/> ordinate values /// </summary> /// <param name="ordinate">The ordinate index</param> /// <returns>An array of ordinate values</returns> public override double[] GetOrdinates(Ordinate ordinate) { if (IsEmpty) { return(new double[0]); } var ordinateFlag = OrdinatesUtility.ToOrdinatesFlag(ordinate); if ((_shell.CoordinateSequence.Ordinates & ordinateFlag) != ordinateFlag) { return(CreateArray(NumPoints, Coordinate.NullOrdinate)); } var result = new double[NumPoints]; var ordinates = _shell.GetOrdinates(ordinate); Array.Copy(ordinates, 0, result, 0, ordinates.Length); var offset = ordinates.Length; foreach (var linearRing in _holes) { ordinates = linearRing.GetOrdinates(ordinate); Array.Copy(ordinates, 0, result, offset, ordinates.Length); offset += ordinates.Length; } return(result); }
/// <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)); }
private static IGeometry CreatePoint(Ordinates ordinates, bool empty) { if (empty) { return(Factory.CreatePoint((ICoordinateSequence)null)); } var seq = CsFactory.Create(1, ordinates); foreach (var o in OrdinatesUtility.ToOrdinateArray(ordinates)) { seq.SetOrdinate(0, o, RandomOrdinate(o, Factory.PrecisionModel)); } return(Factory.CreatePoint(seq)); }
/// <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); }
public override double[] GetOrdinates(Ordinate ordinate) { if (IsEmpty) { return(new double[0]); } var ordinateFlag = OrdinatesUtility.ToOrdinatesFlag(ordinate); if ((_points.Ordinates & ordinateFlag) != ordinateFlag) { return(CreateArray(_points.Count, Coordinate.NullOrdinate)); } return(CreateArray(_points, ordinate)); }
/// <summary> /// Function to return a coordinate sequence that is ensured to be closed. /// </summary> /// <param name="sequence">The base sequence</param> /// <param name="factory">The factory to use in case we need to create a new sequence</param> /// <returns>A closed coordinate sequence</returns> private static ICoordinateSequence EnsureClosedSequence(ICoordinateSequence sequence, ICoordinateSequenceFactory factory) { //This sequence won't serve a valid linear ring if (sequence.Count < 3) { return(null); } //The sequence is closed var start = sequence.GetCoordinate(0); var lastIndex = sequence.Count - 1; var end = sequence.GetCoordinate(lastIndex); if (start.Equals2D(end)) { return(sequence); } // The sequence is not closed // 1. Test for a little offset, in that case simply correct x- and y- ordinate values const double eps = 1E-7; if (start.Distance(end) < eps) { sequence.SetOrdinate(lastIndex, Ordinate.X, start.X); sequence.SetOrdinate(lastIndex, Ordinate.Y, start.Y); return(sequence); } // 2. Close the sequence by adding a new point, this is heavier var newSequence = factory.Create(sequence.Count + 1, sequence.Ordinates); var ordinates = OrdinatesUtility.ToOrdinateArray(sequence.Ordinates); for (var i = 0; i < sequence.Count; i++) { foreach (var ordinate in ordinates) { newSequence.SetOrdinate(i, ordinate, sequence.GetOrdinate(i, ordinate)); } } foreach (var ordinate in ordinates) { newSequence.SetOrdinate(sequence.Count, ordinate, sequence.GetOrdinate(0, ordinate)); } return(newSequence); }
/// <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); } } } }
public override double[] GetOrdinates(Ordinate ordinate) { if (IsEmpty) { return(new double[0]); } var ordinateFlag = OrdinatesUtility.ToOrdinatesFlag(ordinate); if ((_coordinates.Ordinates & ordinateFlag) != ordinateFlag) { return new[] { Coordinate.NullOrdinate } } ; return(new [] { _coordinates.GetOrdinate(0, ordinate) }); }
private static IGeometry CreateMultiPoint(Ordinates ordinates, bool empty) { if (empty) { return(Factory.CreateMultiPoint((ICoordinateSequence)null)); } int numPoints = Rnd.Next(75, 101); var seq = CsFactory.Create(numPoints, ordinates); for (int i = 0; i < numPoints; i++) { foreach (var o in OrdinatesUtility.ToOrdinateArray(ordinates)) { seq.SetOrdinate(i, o, RandomOrdinate(o, Factory.PrecisionModel)); } } return(Factory.CreateMultiPoint(seq)); }
/// <summary> /// Transforms a <see cref="MultiPoint" /> object. /// </summary> /// <param name="factory"></param> /// <param name="points"></param> /// <param name="transform"></param> /// <returns></returns> public static IMultiPoint TransformMultiPoint(IGeometryFactory factory, IMultiPoint points, IMathTransform transform) { //We assume the first point holds all the ordinates var ordinateFlags = ((IPoint)points.GetGeometryN(0)).CoordinateSequence.Ordinates; var ordinates = OrdinatesUtility.ToOrdinateArray(ordinateFlags); var coordSequence = factory.CoordinateSequenceFactory.Create(points.NumPoints, ordinateFlags); for (var i = 0; i < points.NumGeometries; i++) { var seq = ((IPoint)points.GetGeometryN(i)).CoordinateSequence; foreach (var ordinate in ordinates) { coordSequence.SetOrdinate(i, ordinate, seq.GetOrdinate(i, ordinate)); } } var transPoints = transform.Transform(coordSequence); return(factory.CreateMultiPoint(transPoints)); }
private static void TestCoordinateSequences(ICoordinateSequence orig, ICoordinateSequence trans) { Assert.AreNotSame(orig, trans, "Seqences are same"); Assert.AreEqual(orig.Count, trans.Count, "Sequences have different lengths"); Assert.AreEqual(orig.Ordinates, trans.Ordinates, "Sequences provide different ordinates"); var ordinates = OrdinatesUtility.ToOrdinateArray(orig.Ordinates); for (var i = 0; i < orig.Count; i++) { foreach (var ordinate in ordinates) { var v1 = orig.GetOrdinate(i, ordinate); var v2 = trans.GetOrdinate(i, ordinate); if (double.IsNaN(v1)) { Assert.IsTrue(double.IsNaN(v2)); continue; } if (double.IsPositiveInfinity(v1)) { Assert.IsTrue(double.IsPositiveInfinity(v2)); continue; } if (double.IsNegativeInfinity(v1)) { Assert.IsTrue(double.IsNegativeInfinity(v2)); continue; } Assert.AreNotEqual(v1, v2, "Sequences provide equal value for '{0}'", ordinate); } } }
private static void DoTest(ICoordinateSequence forward, ICoordinateSequence reversed) { const double eps = 1e-12; Assert.AreEqual(forward.Count, reversed.Count, "Coordinate sequences don't have same size"); Assert.AreEqual(forward.Ordinates, reversed.Ordinates, "Coordinate sequences don't serve same ordinate values"); var ordinates = OrdinatesUtility.ToOrdinateArray(forward.Ordinates); int j = forward.Count; for (int i = 0; i < forward.Count; i++) { j--; foreach (var ordinate in ordinates) { Assert.AreEqual(forward.GetOrdinate(i, ordinate), reversed.GetOrdinate(j, ordinate), eps, string.Format("{0} values are not within tolerance", ordinate)); } var cf = forward.GetCoordinate(i); var cr = reversed.GetCoordinate(j); Assert.IsFalse(ReferenceEquals(cf, cr), "Coordinate sequences deliver same coordinate instances"); Assert.IsTrue(cf.Equals(cr), "Coordinate sequences do not provide equal coordinates"); } }
/// <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))); }
private static bool HasOrdinate(ICoordinateSequence seq, Ordinate ordinate) { return((seq.Ordinates & OrdinatesUtility.ToOrdinatesFlag(new[] { ordinate })) != Ordinates.None); }
/// <summary> /// Creates a <see cref="ICoordinateSequence" /> of the specified size and dimension. /// For this to be useful, the <see cref="ICoordinateSequence" /> implementation must be mutable. /// </summary> /// <param name="size"></param> /// <param name="dimension">the dimension of the coordinates in the sequence /// (if user-specifiable, otherwise ignored)</param> /// <returns>A coordinate sequence</returns> public ICoordinateSequence Create(int size, int dimension) { return(new DotSpatialAffineCoordinateSequence(size, OrdinatesUtility.DimensionToOrdinates(dimension))); }