/// <summary> /// Function to read a <see cref="IPoint"/> from a ShapeFile stream using the specified <paramref name="reader"/>. /// </summary> /// <param name="reader">The reader to use</param> /// <param name="ordinates">The ordinates to read</param> /// <returns>The read point geometry</returns> protected IGeometry ReadPoint(BinaryReader reader, Ordinates ordinates) { var buffer = new CoordinateBuffer(1, ShapeFileConstants.NoDataBorder, true); ReadCoordinates(reader, 1, new[] { 0 }, ordinates, buffer); IGeometry point = _factory.CreatePoint(buffer.ToSequence()); return point; }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="factory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory factory) { int totalRead = 0; ShapeGeometryType type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead); //type = (ShapeGeometryType) EnumUtility.Parse(typeof (ShapeGeometryType), shapeTypeNum.ToString()); if (type == ShapeGeometryType.NullShape) return factory.CreatePoint((Coordinate)null); if (type != ShapeType) throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); CoordinateBuffer buffer = new CoordinateBuffer(1, NoDataBorderValue, true); IPrecisionModel precisionModel = factory.PrecisionModel; double x = precisionModel.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); double y = precisionModel.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); double? z = null, m = null; // Trond Benum: Let's read optional Z and M values if (HasZValue() && totalRead < totalRecordLength) z = ReadDouble(file, totalRecordLength, ref totalRead); if ((HasMValue() || HasZValue()) && (totalRead < totalRecordLength)) m = ReadDouble(file, totalRecordLength, ref totalRead); buffer.AddCoordinate(x, y, z, m); return factory.CreatePoint(buffer.ToSequence(factory.CoordinateSequenceFactory)); }
private static ICoordinateSequence ToDotSpatial(CoordinateBuffer buffer) { double[] z, m; var xy = buffer.ToXYZM(out z, out m); return(new DotSpatialAffineCoordinateSequence(xy, z, m)); }
private static ICoordinateSequence ToPackedFloatArray(CoordinateBuffer buffer) { float[] pa; var dim = buffer.ToPackedArray(out pa); return(new PackedDoubleCoordinateSequence(pa, dim)); }
private static void TestToSequenceMethod(ICoordinateSequenceFactory factory) { var rnd = new Random(8894); var buffer = new CoordinateBuffer(NumCoordinates); for (var i = 0; i < NumCoordinates; i++) { buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); } System.Diagnostics.Trace.WriteLine( string.Format("\nConversion using {0} factory", (factory ?? GeoAPI.GeometryServiceProvider.Instance.DefaultCoordinateSequenceFactory).GetType().Name)); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); var seqCold = buffer.ToSequence(factory); sw.Stop(); System.Diagnostics.Trace.WriteLine( string.Format(" Cold converting sequence of {0} coordinates in {1}ms.", NumCoordinates, sw.ElapsedMilliseconds)); long total = 0; foreach (var rndBuffer in (_randomCoordinateBuffers ?? (_randomCoordinateBuffers = RandomCoordinateBuffers(NumTests)))) { sw.Stop(); sw.Start(); var seqWarm = rndBuffer.ToSequence(factory); sw.Stop(); Assert.AreEqual(rndBuffer.Count, seqWarm.Count); total += sw.ElapsedTicks; } System.Diagnostics.Trace.WriteLine( string.Format(" Warm converting {0} random coordinate buffers in {1}ticks.", NumTests, total)); }
public void TestAddCoordinatesDisallowRepeated() { var buf = new CoordinateBuffer(); buf.AddCoordinate(0, 0); Assert.IsFalse(buf.AddCoordinate(0, 0, allowRepeated: false)); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); }
/// <summary> /// Function to read a <see cref="IMultiPoint"/> from a ShapeFile stream using the specified <paramref name="reader"/>. /// </summary> /// <param name="reader">The reader to use</param> /// <param name="ordinates">The ordinates to read</param> /// <returns>The read polygonal geometry</returns> public IGeometry ReadMultiPoint(BinaryReader reader, Ordinates ordinates) { /*var bbox = */ ReadBoundingBox(reader); // jump boundingbox var numPoints = ReadNumPoints(reader); var buffer = new CoordinateBuffer(numPoints, ShapeFileConstants.NoDataBorder, true); ReadCoordinates(reader, numPoints, new[] { numPoints - 1 }, ordinates, buffer); return _factory.CreateMultiPoint(buffer.ToSequence()); }
public void TestAddCoordinates() { var buf = new CoordinateBuffer(); buf.AddCoordinate(0, 0); Assert.IsTrue(buf.AddCoordinate(0, 0)); Assert.AreEqual(2, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivant geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="factory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory factory) { int totalRead = 0; int shapeTypeNum = ReadInt32(file, totalRecordLength, ref totalRead); var type = (ShapeGeometryType)EnumUtility.Parse(typeof(ShapeGeometryType), shapeTypeNum.ToString()); if (type == ShapeGeometryType.NullShape) { return(factory.CreateMultiPoint(new IPoint[] { })); } if (type != ShapeType) { throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); } // Read and for now ignore bounds. int bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) { double d = ReadDouble(file, totalRecordLength, ref totalRead); boundingBox[boundingBoxIndex] = d; } // Read points var numPoints = ReadInt32(file, totalRecordLength, ref totalRead); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var points = new IPoint[numPoints]; var pm = factory.PrecisionModel; for (var i = 0; i < numPoints; i++) { var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); buffer.AddCoordinate(x, y); buffer.AddMarker(); } // Trond Benum: We have now read all the points, let's read optional Z and M values GetZMValues(file, totalRecordLength, ref totalRead, buffer); var sequences = buffer.ToSequences(factory.CoordinateSequenceFactory); for (var i = 0; i < numPoints; i++) { points[i] = factory.CreatePoint(sequences[i]); } geom = factory.CreateMultiPoint(points); return(geom); }
public void BeginFigure(double x, double y, double?z, double?m) { if (_inFigure) { throw new ApplicationException(); } _coordinateBuffer = new CoordinateBuffer(); //_coordinates = new List<Coordinate>(); AddCoordinate(x, y, z, m); _inFigure = true; }
/// <summary> /// Function to read a <see cref="ILineString"/> or <see cref="IMultiLineString"/> from a ShapeFile stream using the specified <paramref name="reader"/>. /// </summary> /// <param name="reader">The reader to use</param> /// <param name="ordinates">The ordinates to read</param> /// <returns>The read lineal geometry</returns> protected IGeometry ReadLineString(BinaryReader reader, Ordinates ordinates) { /*var bbox = */ ReadBoundingBox(reader); // Jump boundingbox var numParts = ReadNumParts(reader); var numPoints = ReadNumPoints(reader); var indexParts = ReadIndexParts(reader, numParts, numPoints); var buffer = new CoordinateBuffer(numPoints, ShapeFileConstants.NoDataBorder, true); ReadCoordinates(reader, numPoints, indexParts, ordinates, buffer); if (numParts == 1) return _factory.CreateLineString(buffer.ToSequence()); return CreateMultiLineString(buffer.ToSequences()); }
/// <summary> /// Function to read a either a <see cref="IPolygon"/> or an <see cref="IMultiPolygon"/> from a ShapeFile stream using the specified <paramref name="reader"/>. /// </summary> /// <param name="reader">The reader to use</param> /// <param name="ordinates">The ordinates to read</param> /// <returns>The read polygonal geometry</returns> protected IGeometry ReadPolygon(BinaryReader reader, Ordinates ordinates) { /*var bbox = */ ReadBoundingBox(reader); // jump boundingbox var numParts = ReadNumParts(reader); var numPoints = ReadNumPoints(reader); var indexParts = ReadIndexParts(reader, numParts, numPoints); var buffer = new CoordinateBuffer(numPoints, ShapeFileConstants.NoDataBorder, true); ReadCoordinates(reader, numPoints, indexParts, ordinates, buffer); return numParts == 1 ? _factory.CreatePolygon(_factory.CreateLinearRing(buffer.ToSequence()), null) : CreateSingleOrMultiPolygon(buffer); }
public void TestInsertCoordinates() { var buf = new CoordinateBuffer(); Assert.IsTrue(buf.AddCoordinate(0, 0)); Assert.IsTrue(buf.AddCoordinate(10, 10)); Assert.AreEqual(2, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); Assert.IsTrue(buf.InsertCoordinate(0, -10d, -10d)); Assert.AreEqual(3, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); Assert.IsTrue(buf.InsertCoordinate(0, -10d, -10d)); Assert.AreEqual(4, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); }
private static IEnumerable <CoordinateBuffer> RandomCoordinateBuffers(int numBuffers) { var rnd = new Random(numBuffers); var list = new List <CoordinateBuffer>(numBuffers); for (var i = 0; i < numBuffers; i++) { var numCoordinates = rnd.Next(100, 500); var buffer = new CoordinateBuffer(numCoordinates); for (var j = 0; j < numCoordinates; j++) { buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); } list.Add(buffer); } return(list); }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivant geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="geometryFactory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory geometryFactory) { int totalRead = 0; int shapeTypeNum = ReadInt32(file, totalRecordLength, ref totalRead); var type = (ShapeGeometryType) EnumUtility.Parse(typeof(ShapeGeometryType), shapeTypeNum.ToString()); if (type == ShapeGeometryType.NullShape) return geometryFactory.CreateMultiPoint(new IPoint[] { }); if (type != ShapeType) throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); // Read and for now ignore bounds. int bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) { double d = ReadDouble(file, totalRecordLength, ref totalRead); boundingBox[boundingBoxIndex] = d; } // Read points var numPoints = ReadInt32(file, totalRecordLength, ref totalRead); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var points = new IPoint[numPoints]; var pm = geometryFactory.PrecisionModel; for (var i = 0; i < numPoints; i++) { var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); buffer.AddCoordinate(x, y); buffer.AddMarker(); } // Trond Benum: We have now read all the points, let's read optional Z and M values GetZMValues(file, totalRecordLength, ref totalRead, buffer); var sequences = buffer.ToSequences(geometryFactory.CoordinateSequenceFactory); for (var i = 0; i < numPoints; i++) points[i] = geometryFactory.CreatePoint(sequences[i]); geom = geometryFactory.CreateMultiPoint(points); return geom; }
public void TestInsertCoordinatesDisallowRepeated() { var buf = new CoordinateBuffer(); Assert.IsTrue(buf.AddCoordinate(0, 0)); Assert.IsTrue(buf.AddCoordinate(10, 10)); Assert.IsTrue(buf.InsertCoordinate(0, -10d, -10d, allowRepeated: false)); Assert.AreEqual(3, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); Assert.IsFalse(buf.InsertCoordinate(0, -10d, -10d, allowRepeated: false)); Assert.AreEqual(3, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); Assert.IsFalse(buf.InsertCoordinate(1, -10d, -10d, allowRepeated: false)); Assert.AreEqual(3, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); }
public void TestAddMarkers() { var cb = new CoordinateBuffer(10); for (var i = 0; i < 10; i++) { if (i > 0 && i % 5 == 0) { cb.AddMarker(); } cb.AddCoordinate(i, i); } //cb.AddMarker(); var seqs = cb.ToSequences(); Assert.AreEqual(2, seqs.Length); Assert.AreEqual(5, seqs[0].Count); Assert.AreEqual(5, seqs[1].Count); }
/// <summary> /// Creates a single Polygon with holes. /// </summary> /// <param name="buffer"></param> /// <returns></returns> private IGeometry CreateSingleOrMultiPolygon(CoordinateBuffer buffer) { // Support vars var cses = buffer.ToSequences(); var shellRings = new List <ILinearRing>(); var holeRings = new List <ILinearRing>(); var numHoleRings = new Queue <int>(); //Sort for shells and holes foreach (var cs in cses) { var ring = _factory.CreateLinearRing(cs); if (!ring.IsCCW) { shellRings.Add(ring); numHoleRings.Enqueue(holeRings.Count); } else { holeRings.Add(ring); } } numHoleRings.Enqueue(holeRings.Count); if (shellRings.Count == 1) { return(_factory.CreatePolygon(shellRings[0], holeRings.ToArray())); } var polygons = new IPolygon[shellRings.Count]; var offset = numHoleRings.Dequeue(); for (int i = 0; i < shellRings.Count; i++) { var shellRing = shellRings[i]; var numHoles = numHoleRings.Dequeue(); var holes = holeRings.GetRange(offset, numHoles - offset).ToArray(); polygons[i] = _factory.CreatePolygon(shellRing, holes); } return(_factory.CreateMultiPolygon(polygons)); }
private static void TestToSequenceMethod(CoordinateBufferToSequenceConverterHandler converter) { var rnd = new Random(8894); var buffer = new CoordinateBuffer(); for (var i = 0; i < NumCoordinates; i++) { buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); } System.Diagnostics.Trace.WriteLine( string.Format("\nConversion using {0} method", converter.Method.Name)); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); var seqCold = buffer.ToSequence(converter); sw.Stop(); System.Diagnostics.Trace.WriteLine( string.Format(" Cold converting sequence of {0} coordinates in {1}ms.", NumCoordinates, sw.ElapsedMilliseconds)); long total = 0; foreach (var rndBuffer in (_randomCoordinateBuffers ?? (_randomCoordinateBuffers = RandomCoordinateBuffers(NumTests)))) { sw.Stop(); sw.Start(); var seqWarm = rndBuffer.ToSequence(converter); sw.Stop(); Assert.AreEqual(rndBuffer.Count, seqWarm.Count); total += sw.ElapsedTicks; } System.Diagnostics.Trace.WriteLine( string.Format(" Warm converting {0} random coordinate buffers in {1}ticks.", NumTests, total)); }
private static void TestAddCoordinatesOptional(double noDataValue = double.NaN) { Assert.IsFalse(0d.Equals(noDataValue), "noDataValue must not be 0"); Assert.IsFalse(1d.Equals(noDataValue), "noDataValue must not be 1"); var buf = new CoordinateBuffer(noDataValue); buf.AddCoordinate(0, 0, m: noDataValue); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); buf.Clear(); buf.AddCoordinate(0, 0, m: 1); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XYM); buf.Clear(); buf.AddCoordinate(0, 0, noDataValue); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); buf.Clear(); buf.AddCoordinate(0, 0, 1); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XYZ); buf.Clear(); buf.AddCoordinate(0, 0, noDataValue, noDataValue); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XY); buf.Clear(); buf.AddCoordinate(0, 0, 1, 1); Assert.AreEqual(1, buf.Count); CheckDefinedFlags(buf, Ordinates.XYZM); }
private static ICoordinateSequence ToCoordinateArray(CoordinateBuffer buffer) { return new CoordinateArraySequence(buffer.ToCoordinateArray()); }
private static void TestToSequenceMethod(ICoordinateSequenceFactory factory) { var rnd = new Random(8894); var buffer = new CoordinateBuffer(NumCoordinates); for (var i = 0; i < NumCoordinates; i++) buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); System.Diagnostics.Trace.WriteLine( string.Format("\nConversion using {0} factory", (factory ?? GeoAPI.GeometryServiceProvider.Instance.DefaultCoordinateSequenceFactory).GetType().Name)); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); var seqCold = buffer.ToSequence(factory); sw.Stop(); System.Diagnostics.Trace.WriteLine( string.Format(" Cold converting sequence of {0} coordinates in {1}ms.", NumCoordinates, sw.ElapsedMilliseconds)); long total = 0; foreach (var rndBuffer in (_randomCoordinateBuffers ?? (_randomCoordinateBuffers = RandomCoordinateBuffers(NumTests)))) { sw.Stop(); sw.Start(); var seqWarm = rndBuffer.ToSequence(factory); sw.Stop(); Assert.AreEqual(rndBuffer.Count, seqWarm.Count); total += sw.ElapsedTicks; } System.Diagnostics.Trace.WriteLine( string.Format(" Warm converting {0} random coordinate buffers in {1}ticks.", NumTests, total)); }
private static IEnumerable<CoordinateBuffer> RandomCoordinateBuffers(int numBuffers) { var rnd = new Random(numBuffers); var list = new List<CoordinateBuffer>(numBuffers); for (var i = 0; i < numBuffers; i++) { var numCoordinates = rnd.Next(100, 500); var buffer = new CoordinateBuffer(numCoordinates); for (var j = 0; j < numCoordinates; j++) buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); list.Add(buffer); } return list; }
private static void CheckDefinedFlags(CoordinateBuffer buffer, Ordinates defined) { Assert.AreEqual(defined, buffer.DefinedOrdinates, "Defined flags are not set correctly\nExpected: {0}, Actual: {1}", defined, buffer.DefinedOrdinates); }
public void BeginFigure(double x, double y, double? z, double? m) { if (_inFigure) { throw new ApplicationException(); } _coordinateBuffer = new CoordinateBuffer(); //_coordinates = new List<Coordinate>(); AddCoordinate(x, y, z, m); _inFigure = true; }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="factory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory factory) { int totalRead = 0; var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead); if (type == ShapeGeometryType.NullShape) return factory.CreatePolygon(null, null); if (type != ShapeType) throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); // Read and for now ignore bounds. var bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) boundingBox[boundingBoxIndex] = ReadDouble(file, totalRecordLength, ref totalRead); var numParts = ReadInt32(file, totalRecordLength, ref totalRead); var numPoints = ReadInt32(file, totalRecordLength, ref totalRead); var partOffsets = new int[numParts]; for (var i = 0; i < numParts; i++) partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead); var skippedList = new HashSet<int>(); //var allPoints = new List<Coordinate>(); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var pm = factory.PrecisionModel; for (var part = 0; part < numParts; part++) { var start = partOffsets[part]; var finish = (part == numParts - 1) ? numPoints : partOffsets[part + 1]; var length = finish - start; for (var i = 0; i < length; i++) { var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); // Thanks to Abhay Menon! if (!(Coordinate.NullOrdinate.Equals(x) || Coordinate.NullOrdinate.Equals(y))) buffer.AddCoordinate(x, y); else skippedList.Add(start + i); } //Add a marker that we have finished one part of the geometry buffer.AddMarker(); } // Trond Benum: We have now read all the parts, let's read optional Z and M values // and populate Z in the coordinate before we start manipulating the segments // We have to track corresponding optional M values and set them up in the // Geometries via ICoordinateSequence further down. GetZMValues(file, totalRecordLength, ref totalRead, buffer, skippedList); // Get the resulting sequences var sequences = buffer.ToSequences(factory.CoordinateSequenceFactory); var shells = new List<ILinearRing>(); var holes = new List<ILinearRing>(); for (var i = 0; i < sequences.Length; i++) { //Skip garbage input data with 0 points if (sequences[i].Count < 1) continue; var tmp = EnsureClosedSequence(sequences[i], factory.CoordinateSequenceFactory); var ring = factory.CreateLinearRing(tmp); if (ring.IsCCW) holes.Add(ring); else shells.Add(ring); } // Ensure the ring is encoded right if (shells.Count == 0 && holes.Count == 1) { shells.Add(factory.CreateLinearRing(holes[0].CoordinateSequence.Reversed())); holes.Clear(); } // Now we have lists of all shells and all holes var holesForShells = new List<List<ILinearRing>>(shells.Count); for (var i = 0; i < shells.Count; i++) holesForShells.Add(new List<ILinearRing>()); //Thanks to Bruno.Labrecque //Sort shells by area, rings should only be added to the smallest shell, that contains the ring shells.Sort(ProbeLinearRing); // Find holes foreach (var testHole in holes) { var testEnv = testHole.EnvelopeInternal; var testPt = testHole.GetCoordinateN(0); //We have the shells sorted for (var j = 0; j < shells.Count; j++) { var tryShell = shells[j]; var tryEnv = tryShell.EnvelopeInternal; var isContained = tryEnv.Contains(testEnv) && CGAlgorithms.IsPointInRing(testPt, tryShell.Coordinates); // Check if this new containing ring is smaller than the current minimum ring if (isContained) { // Suggested by Brian Macomber and added 3/28/2006: // holes were being found but never added to the holesForShells array // so when converted to geometry by the factory, the inner rings were never created. var holesForThisShell = holesForShells[j]; holesForThisShell.Add(testHole); //Suggested by Bruno.Labrecque //A LinearRing should only be added to one outer shell break; } } } var polygons = new IPolygon[shells.Count]; for (var i = 0; i < shells.Count; i++) polygons[i] = (factory.CreatePolygon(shells[i], holesForShells[i].ToArray())); if (polygons.Length == 1) geom = polygons[0]; else geom = factory.CreateMultiPolygon(polygons); return geom; }
private static ICoordinateSequence ToPackedFloatArray(CoordinateBuffer buffer) { float[] pa; var dim = buffer.ToPackedArray(out pa); return new PackedDoubleCoordinateSequence(pa, dim); }
/* * protected static double[] ReadDoubles(BigEndianBinaryReader reader, int count) * { * var result = new double[count]; * for (var i = 0; i < count; i++) * result[i] = reader.ReadDouble(); * return result; * } */ /// <summary> /// Get the z values and populate each one of them in Coordinate.Z /// If there are M values, return an array with those. /// </summary> /// <param name="file">The reader</param> /// <param name="totalRecordLength">Total number of bytes in this record</param> /// <param name="currentlyReadBytes">How many bytes are read from this record</param> /// <param name="buffer">The coordinate buffer</param> /// <param name="skippedList">A list of indices which have not been added to the buffer</param> protected void GetZMValues(BigEndianBinaryReader file, int totalRecordLength, ref int currentlyReadBytes, CoordinateBuffer buffer, HashSet <int> skippedList = null) { int numPoints = buffer.Capacity; if (HasZValue()) { boundingBox[boundingBoxIndex++] = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); boundingBox[boundingBoxIndex++] = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); int numSkipped = 0; for (int i = 0; i < numPoints; i++) { double z = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); if (skippedList?.Contains(i) != true) { buffer.SetZ(i - numSkipped, z); } else { numSkipped++; } } } // Trond: Note that M value is always optional per the shapefile spec. So we need to test total read record bytes // v.s. read bytes to see if we have them or not // Also: If we have Z we might have M. Per shapefile defn. if ((HasMValue() || HasZValue()) && currentlyReadBytes < totalRecordLength) { boundingBox[boundingBoxIndex++] = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); boundingBox[boundingBoxIndex++] = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); int numSkipped = 0; for (int i = 0; i < numPoints; i++) { double m = ReadDouble(file, totalRecordLength, ref currentlyReadBytes); if (skippedList?.Contains(i) != true) { buffer.SetM(i - numSkipped, m); } else { numSkipped++; } } } if (currentlyReadBytes < totalRecordLength) { int remaining = totalRecordLength - currentlyReadBytes; file.ReadBytes(remaining * 2); } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="geometryFactory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory geometryFactory) { int totalRead = 0; var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead); if (type == ShapeGeometryType.NullShape) return geometryFactory.CreateMultiLineString(null); if (type != ShapeType) throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); // Read and for now ignore bounds. int bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) { double d = ReadDouble(file, totalRecordLength, ref totalRead); boundingBox[boundingBoxIndex] = d; } int numParts = ReadInt32(file, totalRecordLength, ref totalRead); int numPoints = ReadInt32(file, totalRecordLength, ref totalRead); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead); var lines = new List<ILineString>(numParts); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var pm = geometryFactory.PrecisionModel; for (var part = 0; part < numParts; part++) { var start = partOffsets[part]; var finish = part == numParts - 1 ? numPoints : partOffsets[part + 1]; var length = finish - start; for (var i = 0; i < length; i++) { var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); buffer.AddCoordinate(x, y); } buffer.AddMarker(); } // Trond Benum: We have now read all the parts, let's read optional Z and M values // and populate Z in the coordinate before we start manipulating the segments // We have to track corresponding optional M values and set them up in the // Geometries via ICoordinateSequence further down. GetZMValues(file, totalRecordLength, ref totalRead, buffer); var sequences = new List<ICoordinateSequence>(buffer.ToSequences(geometryFactory.CoordinateSequenceFactory)); for (var s = 0; s < sequences.Count; s++) { var points = sequences[s]; //Skip garbage input data with 0 points if (points.Count < 1) continue; var createLineString = true; if (points.Count == 1) { switch (GeometryInstantiationErrorHandling) { case GeometryInstantiationErrorHandlingOption.ThrowException: break; case GeometryInstantiationErrorHandlingOption.Empty: sequences[s] = geometryFactory.CoordinateSequenceFactory.Create(0, points.Ordinates); break; case GeometryInstantiationErrorHandlingOption.TryFix: sequences[s] = AddCoordinateToSequence(points, geometryFactory.CoordinateSequenceFactory, points.GetOrdinate(0, Ordinate.X), points.GetOrdinate(0, Ordinate.Y), points.GetOrdinate(0, Ordinate.Z), points.GetOrdinate(0, Ordinate.M)); break; case GeometryInstantiationErrorHandlingOption.Null: createLineString = false; break; } } if (createLineString) { // Grabs m values if we have them var line = geometryFactory.CreateLineString(points); lines.Add(line); } } geom = (lines.Count != 1) ? (IGeometry)geometryFactory.CreateMultiLineString(lines.ToArray()) : lines[0]; return geom; }
private static void TestToSequenceMethod(CoordinateBufferToSequenceConverterHandler converter) { var rnd = new Random(8894); var buffer = new CoordinateBuffer(); for (var i = 0; i < NumCoordinates; i++) buffer.AddCoordinate(rnd.NextDouble(), rnd.NextDouble()); System.Diagnostics.Trace.WriteLine( string.Format("\nConversion using {0} method", converter.Method.Name)); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); var seqCold = buffer.ToSequence(converter); sw.Stop(); System.Diagnostics.Trace.WriteLine( string.Format(" Cold converting sequence of {0} coordinates in {1}ms.", NumCoordinates, sw.ElapsedMilliseconds)); long total = 0; foreach (var rndBuffer in (_randomCoordinateBuffers ?? (_randomCoordinateBuffers = RandomCoordinateBuffers(NumTests)))) { sw.Stop(); sw.Start(); var seqWarm = rndBuffer.ToSequence(converter); sw.Stop(); Assert.AreEqual(rndBuffer.Count, seqWarm.Count); total += sw.ElapsedTicks; } System.Diagnostics.Trace.WriteLine( string.Format(" Warm converting {0} random coordinate buffers in {1}ticks.", NumTests, total)); }
/// <summary> /// Method to read the coordinates block /// </summary> /// <param name="reader">The reader</param> /// <param name="numPoints">The total number of points to read</param> /// <param name="markers">The markers</param> /// <param name="ordinates">The ordinates to read</param> /// <param name="buffer">The buffer to add the coordinates to.</param> private static void ReadCoordinates(BinaryReader reader, int numPoints, int[] markers, Ordinates ordinates, CoordinateBuffer buffer) { var offset = buffer.Count; var j = 0; // Add x- and y-ordinates for (var i = 0; i < numPoints; i++) { //Read x- and y- ordinates buffer.AddCoordinate(reader.ReadDouble(), reader.ReadDouble()); //Check if we have reached a marker if (i != markers[j]) { continue; } //Add a marker buffer.AddMarker(); j++; } // are there any z-ordinates if ((ordinates & Ordinates.Z) == Ordinates.Z) { //Read zInterval /*var zInterval = */ ReadInterval(reader); //Set the z-values for (var i = 0; i < numPoints; i++) { buffer.SetZ(offset + i, reader.ReadDouble()); } } if ((ordinates & Ordinates.M) == Ordinates.M) { //Read m-interval /*var mInterval = */ ReadInterval(reader); //Set the m-values for (var i = 0; i < numPoints; i++) { buffer.SetZ(offset + i, reader.ReadDouble()); } } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="geometryFactory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override IGeometry Read(BigEndianBinaryReader file, int totalRecordLength, IGeometryFactory geometryFactory) { int totalRead = 0; var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead); if (type == ShapeGeometryType.NullShape) { return(geometryFactory.CreatePolygon(null, null)); } if (type != ShapeType) { throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); } // Read and for now ignore bounds. var bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) { boundingBox[boundingBoxIndex] = ReadDouble(file, totalRecordLength, ref totalRead); } var numParts = ReadInt32(file, totalRecordLength, ref totalRead); var numPoints = ReadInt32(file, totalRecordLength, ref totalRead); var partOffsets = new int[numParts]; for (var i = 0; i < numParts; i++) { partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead); } var skippedList = new HS(); //var allPoints = new List<Coordinate>(); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var pm = geometryFactory.PrecisionModel; for (var part = 0; part < numParts; part++) { var start = partOffsets[part]; var finish = (part == numParts - 1) ? numPoints : partOffsets[part + 1]; var length = finish - start; for (var i = 0; i < length; i++) { var x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); var y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); // Thanks to Abhay Menon! if (!(Coordinate.NullOrdinate.Equals(x) || Coordinate.NullOrdinate.Equals(y))) { buffer.AddCoordinate(x, y); } else { skippedList.Add(start + i); } } //Add a marker that we have finished one part of the geometry buffer.AddMarker(); } // Trond Benum: We have now read all the parts, let's read optional Z and M values // and populate Z in the coordinate before we start manipulating the segments // We have to track corresponding optional M values and set them up in the // Geometries via ICoordinateSequence further down. GetZMValues(file, totalRecordLength, ref totalRead, buffer, skippedList); // Get the resulting sequences var sequences = buffer.ToSequences(geometryFactory.CoordinateSequenceFactory); var shells = new List <ILinearRing>(); var holes = new List <ILinearRing>(); for (var i = 0; i < sequences.Length; i++) { var tmp = EnsureClosedSequence(sequences[i], geometryFactory.CoordinateSequenceFactory); var ring = geometryFactory.CreateLinearRing(tmp); if (ring.IsCCW) { holes.Add(ring); } else { shells.Add(ring); } } // Ensure the ring is encoded right if (shells.Count == 0 && holes.Count == 1) { shells.Add(geometryFactory.CreateLinearRing(holes[0].CoordinateSequence.Reversed())); holes.Clear(); } // Now we have lists of all shells and all holes var holesForShells = new List <List <ILinearRing> >(shells.Count); for (var i = 0; i < shells.Count; i++) { holesForShells.Add(new List <ILinearRing>()); } //Thanks to Bruno.Labrecque //Sort shells by area, rings should only be added to the smallest shell, that contains the ring shells.Sort(ProbeLinearRing); // Find holes foreach (var testHole in holes) { var testEnv = testHole.EnvelopeInternal; var testPt = testHole.GetCoordinateN(0); //We have the shells sorted for (var j = 0; j < shells.Count; j++) { var tryShell = shells[j]; var tryEnv = tryShell.EnvelopeInternal; var isContained = tryEnv.Contains(testEnv) && CGAlgorithms.IsPointInRing(testPt, tryShell.Coordinates); // Check if this new containing ring is smaller than the current minimum ring if (isContained) { // Suggested by Brian Macomber and added 3/28/2006: // holes were being found but never added to the holesForShells array // so when converted to geometry by the factory, the inner rings were never created. var holesForThisShell = holesForShells[j]; holesForThisShell.Add(testHole); //Suggested by Bruno.Labrecque //A LinearRing should only be added to one outer shell break; } } } var polygons = new IPolygon[shells.Count]; for (var i = 0; i < shells.Count; i++) { polygons[i] = (geometryFactory.CreatePolygon(shells[i], holesForShells[i].ToArray())); } if (polygons.Length == 1) { geom = polygons[0]; } else { geom = geometryFactory.CreateMultiPolygon(polygons); } return(geom); }
private static ICoordinateSequence ToCoordinateArray(CoordinateBuffer buffer) { return(new CoordinateArraySequence(buffer.ToCoordinateArray())); }
public void TestAddMarkers() { var cb = new CoordinateBuffer(10); for (var i = 0; i < 10; i++) { if (i > 0 && i % 5 == 0) cb.AddMarker(); cb.AddCoordinate(i, i); } //cb.AddMarker(); var seqs = cb.ToSequences(); Assert.AreEqual(2, seqs.Length); Assert.AreEqual(5, seqs[0].Count); Assert.AreEqual(5, seqs[1].Count); }
/// <summary> /// Method to read the coordinates block /// </summary> /// <param name="reader">The reader</param> /// <param name="numPoints">The total number of points to read</param> /// <param name="markers">The markers</param> /// <param name="ordinates">The ordinates to read</param> /// <param name="buffer">The buffer to add the coordinates to.</param> private static void ReadCoordinates(BinaryReader reader, int numPoints, int[] markers, Ordinates ordinates, CoordinateBuffer buffer) { var offset = buffer.Count; var j = 0; // Add x- and y-ordinates for (var i = 0; i < numPoints; i++) { //Read x- and y- ordinates buffer.AddCoordinate(reader.ReadDouble(), reader.ReadDouble()); //Check if we have reached a marker if (i != markers[j]) continue; //Add a marker buffer.AddMarker(); j++; } // are there any z-ordinates if ((ordinates & Ordinates.Z) == Ordinates.Z) { //Read zInterval /*var zInterval = */ ReadInterval(reader); //Set the z-values for (var i = 0; i < numPoints; i++) buffer.SetZ(offset + i, reader.ReadDouble()); } if ((ordinates & Ordinates.M) == Ordinates.M) { //Read m-interval /*var mInterval = */ ReadInterval(reader); //Set the m-values for (var i = 0; i < numPoints; i++) buffer.SetZ(offset + i, reader.ReadDouble()); } }
/// <summary> /// Reads a stream and converts the shapefile record to an equilivent geometry object. /// </summary> /// <param name="file">The stream to read.</param> /// <param name="totalRecordLength">Total length of the record we are about to read</param> /// <param name="factory">The geometry factory to use when making the object.</param> /// <returns>The Geometry object that represents the shape file record.</returns> public override Geometry Read(BigEndianBinaryReader file, int totalRecordLength, GeometryFactory factory) { int totalRead = 0; var type = (ShapeGeometryType)ReadInt32(file, totalRecordLength, ref totalRead); if (type == ShapeGeometryType.NullShape) { return(factory.CreateMultiLineString(null)); } if (type != ShapeType) { throw new ShapefileException(string.Format("Encountered a '{0}' instead of a '{1}'", type, ShapeType)); } // Read and for now ignore bounds. int bblength = GetBoundingBoxLength(); boundingBox = new double[bblength]; for (; boundingBoxIndex < 4; boundingBoxIndex++) { double d = ReadDouble(file, totalRecordLength, ref totalRead); boundingBox[boundingBoxIndex] = d; } int numParts = ReadInt32(file, totalRecordLength, ref totalRead); int numPoints = ReadInt32(file, totalRecordLength, ref totalRead); int[] partOffsets = new int[numParts]; for (int i = 0; i < numParts; i++) { partOffsets[i] = ReadInt32(file, totalRecordLength, ref totalRead); } var lines = new List <LineString>(numParts); var buffer = new CoordinateBuffer(numPoints, NoDataBorderValue, true); var pm = factory.PrecisionModel; for (int part = 0; part < numParts; part++) { int start = partOffsets[part]; int finish = part == numParts - 1 ? numPoints : partOffsets[part + 1]; int length = finish - start; for (int i = 0; i < length; i++) { double x = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); double y = pm.MakePrecise(ReadDouble(file, totalRecordLength, ref totalRead)); buffer.AddCoordinate(x, y); } buffer.AddMarker(); } // Trond Benum: We have now read all the parts, let's read optional Z and M values // and populate Z in the coordinate before we start manipulating the segments // We have to track corresponding optional M values and set them up in the // Geometries via CoordinateSequence further down. GetZMValues(file, totalRecordLength, ref totalRead, buffer); var sequences = new List <CoordinateSequence>(buffer.ToSequences(factory.CoordinateSequenceFactory)); for (int s = 0; s < sequences.Count; s++) { var points = sequences[s]; //Skip garbage input data with 0 points if (points.Count < 1) { continue; } bool createLineString = true; if (points.Count == 1) { switch (GeometryInstantiationErrorHandling) { case GeometryInstantiationErrorHandlingOption.ThrowException: break; case GeometryInstantiationErrorHandlingOption.Empty: sequences[s] = factory.CoordinateSequenceFactory.Create(0, points.Ordinates); break; case GeometryInstantiationErrorHandlingOption.TryFix: sequences[s] = AddCoordinateToSequence(points, factory.CoordinateSequenceFactory, points.GetX(0), points.GetY(0), points.GetZ(0), points.GetM(0)); break; case GeometryInstantiationErrorHandlingOption.Null: createLineString = false; break; } } if (createLineString) { // Grabs m values if we have them var line = factory.CreateLineString(points); lines.Add(line); } } geom = (lines.Count != 1) ? (Geometry)factory.CreateMultiLineString(lines.ToArray()) : lines[0]; return(geom); }
/// <summary> /// Creates a single Polygon with holes. /// </summary> /// <param name="buffer"></param> /// <returns></returns> private IGeometry CreateSingleOrMultiPolygon(CoordinateBuffer buffer) { // Support vars var cses = buffer.ToSequences(); var shellRings = new List<ILinearRing>(); var holeRings = new List<ILinearRing>(); var numHoleRings = new Queue<int>(); //Sort for shells and holes foreach (var cs in cses) { var ring = _factory.CreateLinearRing(cs); if (!ring.IsCCW) { shellRings.Add(ring); numHoleRings.Enqueue(holeRings.Count); } else holeRings.Add(ring); } numHoleRings.Enqueue(holeRings.Count); if (shellRings.Count == 1) return _factory.CreatePolygon(shellRings[0], holeRings.ToArray()); var polygons = new IPolygon[shellRings.Count]; var offset = numHoleRings.Dequeue(); for (int i = 0; i < shellRings.Count; i++) { var shellRing = shellRings[i]; var numHoles = numHoleRings.Dequeue(); var holes = holeRings.GetRange(offset, numHoles - offset).ToArray(); polygons[i] = _factory.CreatePolygon(shellRing, holes); } return _factory.CreateMultiPolygon(polygons); }
private static ICoordinateSequence ToDotSpatial(CoordinateBuffer buffer) { double[] z, m; var xy = buffer.ToXYZM(out z, out m); return new DotSpatialAffineCoordinateSequence(xy, z, m); }