/// <summary> /// Gets a <see cref="WKTReader"/> to read geometries from WKT with expected ordinates. /// </summary> /// <param name="ordinateFlags">a set of expected ordinates.</param> /// <param name="precisionModel">a precision model.</param> /// <returns>A <see cref="WKTReader"/>.</returns> public static WKTReader GetWKTReader(Ordinates ordinateFlags, PrecisionModel precisionModel) { ordinateFlags |= Ordinates.XY; if ((ordinateFlags & Ordinates.XY) == ordinateFlags) { return(new WKTReader(new NtsGeometryServices(CoordinateArraySequenceFactory.Instance, precisionModel, 0)) { IsOldNtsCoordinateSyntaxAllowed = false, }); } // note: XYZM will go through here too, just like in JTS. if (ordinateFlags.HasFlag(Ordinates.Z)) { return(new WKTReader(new NtsGeometryServices(CoordinateArraySequenceFactory.Instance, precisionModel, 0))); } if (ordinateFlags.HasFlag(Ordinates.M)) { return(new WKTReader(new NtsGeometryServices(PackedCoordinateSequenceFactory.DoubleFactory, precisionModel, 0)) { IsOldNtsCoordinateSyntaxAllowed = false, }); } return(new WKTReader(new NtsGeometryServices(CoordinateArraySequenceFactory.Instance, precisionModel, 0))); }
private static double[] InjectZM(Ordinates ordinateFlags, double[] xy) { int size = xy.Length / 2; int dimension = RequiredDimension(ordinateFlags); double[] res = new double[size * dimension]; int k = 0; for (int i = 0; i < xy.Length; i += 2) { res[k++] = xy[i]; res[k++] = xy[i + 1]; if (ordinateFlags.HasFlag(Ordinates.Z)) { res[k++] = 10; } if (ordinateFlags.HasFlag(Ordinates.M)) { res[k++] = 11; } } return(res); }
/// <summary> /// Writes the binary encoded PostGIS header. /// </summary> /// <param name="type">The PostGIS geometry type.</param> /// <param name="srid">The spatial reference of the geometry</param> /// <param name="emitSrid">Flag indicating that <paramref name="srid"/> should be written</param> /// <param name="ordinates"></param> /// <param name="byteOrder">The byte order specified.</param> /// <param name="writer">The writer to use.</param> private static void WriteHeader(PostGisGeometryType type, int srid, bool emitSrid, Ordinates ordinates, ByteOrder byteOrder, BinaryWriter writer) { writer.Write((byte)byteOrder); // write typeword uint typeword = (uint)type; if (ordinates.HasFlag(Ordinates.Z)) { typeword |= 0x80000000; } if (ordinates.HasFlag(Ordinates.M)) { typeword |= 0x40000000; } emitSrid &= srid > 0; if (emitSrid) { typeword |= 0x20000000; } writer.Write(typeword); if (emitSrid) { writer.Write(srid); } }
private static void Write(CoordinateSequence sequence, Ordinates ordinates, BinaryWriter writer, bool justOne) { if (sequence == null || sequence.Count == 0) { return; } int length = 1; if (!justOne) { length = sequence.Count; writer.Write(length); } bool writeZ = ordinates.HasFlag(Ordinates.Z); bool writeM = ordinates.HasFlag(Ordinates.M); for (int i = 0; i < length; i++) { writer.Write(sequence.GetX(i)); writer.Write(sequence.GetY(i)); if (writeZ) { writer.Write(sequence.GetZ(i)); } if (writeM) { writer.Write(sequence.GetM(i)); } } }
/// <inheritdoc /> public void Filter(CoordinateSequence seq) { for (int i = 0; i < seq.Count; i++) { if (_checkOrdinateFlags.HasFlag(Ordinates.Z) && !_outputOrdinates.HasFlag(Ordinates.Z)) { if (!double.IsNaN(seq.GetZ(i))) { _outputOrdinates |= Ordinates.Z; } } if (_checkOrdinateFlags.HasFlag(Ordinates.M) && !_outputOrdinates.HasFlag(Ordinates.M)) { if (!double.IsNaN(seq.GetM(i))) { _outputOrdinates |= Ordinates.M; if (_alwaysEmitZWithM) { _outputOrdinates |= Ordinates.Z; } } } } }
private static void Write(CoordinateSequence sequence, Ordinates ordinates, ByteOrder byteOrder, BinaryWriter writer, bool justOne) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } // Handle empty multi-coordinate geometries if (sequence.Count == 0) { if (!justOne) { writer.Write(0); return; } } // Get which ordinates to write bool writeZ = ordinates.HasFlag(Ordinates.Z); bool writeM = ordinates.HasFlag(Ordinates.M); // Write length if not points int length = 1; if (!justOne) { length = sequence.Count; writer.Write(length); } // Write empty point else if (sequence.Count == 0) { const long postgisNaN = 9221120237041090560; writer.Write(postgisNaN); writer.Write(postgisNaN); if (writeZ) { writer.Write(postgisNaN); } if (writeM) { writer.Write(postgisNaN); } return; } if (sequence is PackedDoubleCoordinateSequence packedSequence && byteOrder == ByteOrder.LittleEndian == BitConverter.IsLittleEndian) { #if NETSTANDARD2_1 writer.Write(MemoryMarshal.AsBytes <double>(packedSequence.GetRawCoordinates())); #else writer.Write(MemoryMarshal.AsBytes <double>(packedSequence.GetRawCoordinates()).ToArray()); #endif }
/// <summary> /// Gets a <see cref="CoordinateSequenceFactory"/> that can create sequences for ordinates /// defined in the provided bit pattern. /// </summary> /// <param name="ordinateFlags">a bit-pattern of ordinates.</param> /// <returns>a <see cref="CoordinateSequenceFactory"/>.</returns> public static CoordinateSequenceFactory GetCSFactory(Ordinates ordinateFlags) { if (ordinateFlags.HasFlag(Ordinates.M)) { return(PackedCoordinateSequenceFactory.DoubleFactory); } return(CoordinateArraySequenceFactory.Instance); }
/// <summary> /// Reads a <see cref="CoordinateSequence"/> from the stream /// </summary> /// <param name="reader">The binary reader</param> /// <param name="factory">The geometry factory to use for geometry creation.</param> /// <param name="precisionModel">The precision model used to make x- and y-ordinates precise.</param> /// <param name="numPoints">The number of points in the coordinate sequence.</param> /// <param name="receivedOrdinates">The ordinates to read. <see cref="Ordinates.XY"/> are always read.</param> /// <returns>The coordinate sequence</returns> protected CoordinateSequence ReadCoordinateSequence(BinaryReader reader, CoordinateSequenceFactory factory, PrecisionModel precisionModel, int numPoints, Ordinates receivedOrdinates) { var outputOrdinates = receivedOrdinates; if (HandleOrdinates != Ordinates.None) { outputOrdinates &= HandleOrdinates; } var sequence = factory.Create(numPoints, outputOrdinates); bool receivedZ = receivedOrdinates.HasFlag(Ordinates.Z); bool receivedM = receivedOrdinates.HasFlag(Ordinates.M); bool outputtingZ = outputOrdinates.HasFlag(Ordinates.Z) && sequence.HasZ; bool outputtingM = outputOrdinates.HasFlag(Ordinates.M) && sequence.HasM; for (int i = 0; i < numPoints; i++) { sequence.SetX(i, precisionModel.MakePrecise(reader.ReadDouble())); sequence.SetY(i, precisionModel.MakePrecise(reader.ReadDouble())); if (receivedZ) { double z = reader.ReadDouble(); if (outputtingZ) { sequence.SetZ(i, z); } } if (receivedM) { double m = reader.ReadDouble(); if (outputtingM) { sequence.SetM(i, m); } } } return(sequence); }
/// <summary> /// Configures the dimension of the column that the property maps to when targeting SQLite. /// </summary> /// <param name="propertyBuilder"> The builder for the property being configured. </param> /// <param name="ordinates"> The dimension ordinates. </param> /// <returns> The same builder instance so that multiple calls can be chained. </returns> public static PropertyBuilder ForSqliteHasDimension( [NotNull] this PropertyBuilder propertyBuilder, Ordinates ordinates) { Check.NotNull(propertyBuilder, nameof(propertyBuilder)); string dimension = null; if (ordinates.HasFlag(Ordinates.Z)) { dimension += "Z"; } if (ordinates.HasFlag(Ordinates.M)) { dimension += "M"; } propertyBuilder.Metadata.Sqlite().Dimension = dimension; return(propertyBuilder); }
/// <summary> /// Configures the dimension of the column that the property maps to when targeting SQLite. /// </summary> /// <param name="propertyBuilder"> The builder for the property being configured. </param> /// <param name="ordinates"> The dimension ordinates. </param> /// <returns> The same builder instance so that multiple calls can be chained. </returns> public static PropertyBuilder HasGeometricDimension( [NotNull] this PropertyBuilder propertyBuilder, Ordinates ordinates) { Check.NotNull(propertyBuilder, nameof(propertyBuilder)); string dimension = null; if (ordinates.HasFlag(Ordinates.Z)) { dimension += "Z"; } if (ordinates.HasFlag(Ordinates.M)) { dimension += "M"; } propertyBuilder.Metadata.SetGeometricDimension(dimension); return(propertyBuilder); }
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> /// Reads a <see cref="CoordinateSequence"/> from the stream /// </summary> /// <param name="reader">The binary reader</param> /// <param name="factory">The geometry factory to use for geometry creation.</param> /// <param name="precisionModel">The precision model used to make x- and y-ordinates precise.</param> /// <param name="numPoints">The number of points in the coordinate sequence.</param> /// <param name="receivedOrdinates">The ordinates to read. <see cref="Ordinates.XY"/> are always read.</param> /// <returns>The coordinate sequence</returns> protected CoordinateSequence ReadCoordinateSequence(BinaryReader reader, CoordinateSequenceFactory factory, PrecisionModel precisionModel, int numPoints, Ordinates receivedOrdinates) { var outputOrdinates = receivedOrdinates; if (HandleOrdinates != Ordinates.None) { outputOrdinates &= HandleOrdinates; } bool receivedZ = receivedOrdinates.HasFlag(Ordinates.Z); bool receivedM = receivedOrdinates.HasFlag(Ordinates.M); if (factory is PackedCoordinateSequenceFactory packedFactory && packedFactory.Type == PackedCoordinateSequenceFactory.PackedType.Double && reader is BiEndianBinaryReader biReader && biReader.Endianess == ByteOrder.LittleEndian == BitConverter.IsLittleEndian) { int dimension = 2; int measure = 0; if (receivedZ) { dimension++; } if (receivedM) { dimension++; measure++; } byte[] bytes = reader.ReadBytes(8 * numPoints * dimension); double[] doubles = MemoryMarshal.Cast <byte, double>(bytes).ToArray(); return(packedFactory.Create(doubles, dimension, measure)); } var sequence = factory.Create(numPoints, outputOrdinates); bool outputtingZ = outputOrdinates.HasFlag(Ordinates.Z) && sequence.HasZ; bool outputtingM = outputOrdinates.HasFlag(Ordinates.M) && sequence.HasM; for (int i = 0; i < numPoints; i++) { sequence.SetX(i, precisionModel.MakePrecise(reader.ReadDouble())); sequence.SetY(i, precisionModel.MakePrecise(reader.ReadDouble())); if (receivedZ) { double z = reader.ReadDouble(); if (outputtingZ) { sequence.SetZ(i, z); } } if (receivedM) { double m = reader.ReadDouble(); if (outputtingM) { sequence.SetM(i, m); } } } return(sequence); }