Code Monkey home page Code Monkey logo

nettopologysuite.io.shapefile's Introduction

NetTopologySuite.IO.ShapeFile

The ShapeFile IO module for NTS.

Important note

The development of this project has been discontinued. Please consider NetTopologySuite.IO.Esri as a replacement.

nettopologysuite.io.shapefile's People

Contributors

airbreather avatar dguidi avatar fobermaier avatar frankhommers avatar jarobbins avatar kristofdegrave avatar stijnherreman avatar xivk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nettopologysuite.io.shapefile's Issues

DbaseFileReader default encoding error and so on...

question 1:
var reader= new DbaseFileReader(file,encoding);
throw an error and that the object not instance ;
question 2:
for example code;
while (reader.Read())
{
var f = new Feature() { Geometry = reader.Geometry };
f.Attributes = new AttributesTable();
int num = reader.DbaseHeader.NumFields;

                for (int i = 0; i < num; ++i)
                {
                    _name = reader.DbaseHeader.Fields[i].Name;
                    object val = reader.GetValue(i+1);//here is bug,attrbiute table not match column name index
                }

};
question 3:
ShapefileDataWriter can't setting default encoding

Shapefiles in-memory

Hello,

is it possible to get the shapefile parts in-memory somehow ? I would like to create the shapefile with all its parts and zip them afterwards, so the user will only download the zip file. Now, it would be useful if I could skip the writing to the harddisk all together. Any idea?

Thanks

Read a shapefile in Xamarin.Forms

i want to read a shapefile but file not existing ?
ShapeDataReader reader = new ShapeDataReader("mapsuiSample.MURS.shp");
var mbr = reader.ShapefileBounds;
var result = reader.ReadByMBRFilter(mbr);
var coll = result.GetEnumerator();
while (coll.MoveNext())
var item = coll.Current;

Shapefile writer performance improvements?

From @xivk on February 28, 2017 9:32

I'm working on a tool for a client of mine converting OSM data into a shapefile that can easily consumed for routing and analytics.

Basically I have 2 steps:

  1. Building a routerdb with Itinero.
  2. Writing the result as a shapefile.

Now Itinero can handle the entire world, the planet OSM file, and build a database for the entire world. I don't think it's even possible to attempt writing this to a shapefile but I am having performance issues, for example for a country like germany it takes about 10 hours (!) to write a shapefile with all german roads. Doing this in Itinero-only takes about 30 mins.

I have checked and the bottleneck clearly is the shapefile writer.

So I'm wondering, is it possible to improve the performance of writing a shapefile? Can anyone give me some pointers on where to get started? For example, why does it iterate twice over the source? Any way to compress the result? Germany now give me a shapefile of 70GB (!).

I'm more than willing to contribute the improvements to NTS as usual, but any help getting started would be appreciated.

Copied from original issue: NetTopologySuite/NetTopologySuite#154

Redo everything

Following from #42, we should probably just redo all the shapefile reading code.

It would be nice not to use any of the code from the other library so that we can provide a library that's licensed under BSD-3-clause instead of LGPL.

How to change the way a Shapefile is decoded when reading from it?

Hello NetTopologySuite-Team,
I got a question about reading Shapefiles (.shp) with NetTopologySuite.IO.
Is there any way to set the Encoding for the file to be read? All the Shapefiles I get are encoded using Windows-1252. But because I'm using DotNetCore it tries to encode every file as UTF-8 which is problematic with any special characters like ß, ü, ä, ö and so on which just return a "?" as a character instead.

Can someone please provide me with an example of how to read a shp File encoded in Windows-1252 correctly?

I don't need to write any changes to the Shapefile just read the data in the correcly encoded format.

I've attached a Shapefile where this problem occurs.
SCHLAG.zip

Open a shapefile which contains faulty data

From @laetitiamh on September 7, 2016 14:58

Hi!

I am trying to open a shapefile that contains building outlines using NetTopologySuite.IO.ShapefileReader.
I only get around 700 of the 5000+ buildings as a result as the reading stops early because of a faulty linear ring "Number of points must be 0 or >3". This shapefile is automatically generated and contains some errors. I can open the same file in a tool like http://mapshaper.org/ and I can see all the outlines.

The ShapefileEnumerator::MoveNext will return false when it encounters such an exception and as a result the ShapeFileReader::ReadAll will abort the foreach loop.
Could we specifiy as an option to the ShapefileReader to continue reading until the end of the file even when it finds faulty geometries?

Thank you very much!

Copied from original issue: NetTopologySuite/NetTopologySuite#121

ShapefileStreamProviderRegistry does ProjectionStream get used?

Hello, Thanks for open sourcing this library.

I've been trying to open a shapefile in memory via ShapefileStreamProviderRegistry. The shapefile has .prj file, but the resultant ShapefileDataReader does not seem to have the CRS info present in the projection file. In fact, the Geometry field of the ShapefileDataReader instance is null (opening the shapefile using filepath also created a datareader with null geometry as well).

Browsing through the source code, I'm not able to find a place where ProjectionStream field of the StreamProviderRegistry is used, I'm wondering if the projection stream is read when opening the file?

Best,

ShapeFileDataReader Unable to parse shape file properly

From @Labbe21 on October 30, 2017 15:35

I have a shape file generated with QGIS as a zip with dbf, prj, shp and shx files within it.

That file decoding is fine with QGIS Tool and https://mygeodata.cloud/converter/

However, ShapefileDataReader is not able to read all columns as expected.
Most of columns are parsed as ""\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" with various number of occurences of "\0" while some columns are ok.

There is the file I'm trying to parse: https://ufile.io/p0zl3

I am using the last version of NetTopologySuite.

Could someone please help me with this issue, I'm running out of ideas to fix this problem.

Copied from original issue: NetTopologySuite/NetTopologySuite#202

NuGet: StrongNamed assembly

Hello,

It looks like the NetTopologySuite NuGet package is signed, but this package is not. When trying to read shapefiles, it now throws this exception:

Could not load file or assembly 'NetTopologySuite.IO.ShapeFile.Extended, Version=1.15.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)

Could we have the NuGet package for this library signed?

Thanks!

Ryan

dbf error

when i write attribute column length more than 254 that string intercepted,can't write over length 254

on the other hand.ShapefileDataWriter About Chinese random encoding error

DbaseFileHeader.Fields index off by one vs ShapeFileDataReader.GetValue

I am upgrading from an older version of NTS and my code for reading the attribute tables does not work.

I use DbaseFileHeader.Fields to find the field indices and then use ShapeFileDataReader.GetValue(idx) to read the value from the attribute table.
Using the new NTS I'm getting some strange behavior:
Index 0 in DbaseFileHeader.Fields returns the first field in the attribute table (i.e. ObjectId) as expected.
But ShapeFileDataReader.GetValue(0) returns the geometry object, and index 1 returns the ObjectId value.
Is this by design?


GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModels.Fixed),3006);
            
            var features = new List<Feature>();
            using ( ShapefileDataReader shapeFileDataReader = new ShapefileDataReader(shpFilename, factory))
            {
        
                ShapefileHeader shpHeader = shapeFileDataReader.ShapeHeader;
                
                DbaseFileHeader header = shapeFileDataReader.DbaseHeader;
                while (shapeFileDataReader.Read())
                {
                    Feature feature = new Feature();
                    AttributesTable attributesTable = new AttributesTable();
                    IGeometry geometry = (Geometry)shapeFileDataReader.Geometry;
                    for (int i = 0; i < header.NumFields; i++)
                    {
                        DbaseFieldDescriptor fldDescriptor = header.Fields[i];
                        attributesTable.Add(fldDescriptor.Name, shapeFileDataReader.GetValue(i)); 
                    }
                    feature.Geometry = geometry;
                    feature.Attributes = attributesTable;
                    features.Add(feature);
                }
                shapeFileDataReader.Close();
            }

Thanks

How can I save a Shapefile from a deserialized FeatureCollection?

Hi guys,
I'm working on a project that has to be able to serialize and deserialize many FeatureCollection. I'm using the System.Test.Json.JsonSerializer with the GeoJsonConverterFactory to do so, but I can't write any ShapeFile from the deserialized collections. It has something to do with some attibutes getting deserialized as decimal (they were double). Or could the deserialized StjFeature cause the problem? The error occurs while getting the header via ShapeFileDataWriter.GetHeader(features.First(), features.Count).
image
image
The regular Feature shows different types compared to the StjFeature (the pictures show different FeatureCollection).

I can not read a specific .shp

I can not read a specific .shp. The ReadNextNonNullShape function of ShapeMBREnumeratorBase returns a negative number for CurrShapeIndex = Reader.ReadInt32BE () - 1; in shape number 11
SHP_ETRS89.zip

Incorrect handling of dots in the file name

Hi! Thank you for the tool, it is very useful.
However, I faced a problem, ShapefileDataWriter incorrectly handles dots in the provided filename.
The ShapefileDataWriter documentation says:

<param name="fileName">File path without any extension</param>

So I pass there:
"C:\\TestOutput\\Dr. J.J.P. Oudsingel\\Dr. J.J.P. Oudsingel Surfaces"

However, it produces a file named "Dr. J.J.P.shp"

I believe this is because of calls to Path.ChangeExtension(path, ".shp") in the ShapefileStreamProviderRegistry constructor.
If you require a shapefile name without any extension, maybe the better idea would be to replace Path.ChangeExtension(path, ".shp") to simple path + ".shp"?
If you'd like, I can make a PR with these changes.

Creating a Dbase column with a length larger 254 (1 byte) results in strange behavior

When writing the length of a column in a DbaseFieldHeader you get some strange behavior. The max size of the length in dbase is 1 byte = 254. If we would add a column with a length of 255, this would result into a column with the length of 1. For me it would be logical that in this case the length would be set to its maximum: 254 of 1 byte

writer.Write((byte)_fieldDescriptions[i].Length);

create shapefile incorrect

open failure when used arcgis platform open shapefile
display graphic scaling ratio inormal (arcgis 10.2.2)

How to read AttributeTable

I want get ShapeFile's AttributeTable ,I did it this way

ShapefileDataReader dataReader = new ShapefileDataReader(shapepath, Factory, Encoding.UTF8);
for (int i = 1; i < fieldNames.Length; i++)
                    {
                        attributesTable.Add(fieldNames[i], dataReader.GetValue(i));
                    }

but Why dataReader's depth is 0,result in an empty reference exception to be thrown.My shp can be read in ArcMap.Is My method wrong? What is the general way to read AttributeTable?

merge shapefile

how to write geometry collection to single shapefile,has multi dbf rows

Value cannot be null. Parameter name: key

Hi all
I'm currently try to export wkt poligons to Shapefile, but when i go to write features, like that:
`// Use the dataWriter to write the shape file with geometry and data
ShapefileDataWriter dataWriter = new ShapefileDataWriter(shapeFileName, outGeomFactory, encoding);

// Header
DbaseFileHeader outDbaseHeader = ShapefileDataWriter.GetHeader(features[0], features.Count, encoding);
dataWriter.Header = outDbaseHeader;

// Write feature
dataWriter.Write(features); //Exception is thrown here`

I have an exception, always when i do dataWriter.Write(features);

Exception is:
{System.TypeInitializationException: The type initializer for 'NetTopologySuite.IO.DbaseEncodingUtility' threw an exception. ---> System.ArgumentNullException: Value cannot be null. Parameter name: key at System.Collections.Generic.Dictionary2[TKey,TValue].FindEntry (TKey key) [0x00008] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:380
at System.Collections.Generic.Dictionary2[TKey,TValue].ContainsKey (TKey key) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2019-08/android/release/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:286 at NetTopologySuite.IO.DbaseEncodingUtility.AddLdidEncodingPair (System.Byte ldid, System.Text.Encoding encodingToAdd) [0x0000c] in <0e9c02ea98264091a344714de10def9b>:0 at NetTopologySuite.IO.DbaseEncodingUtility.RegisterEncodings (System.Object[][] ldidCodePagePairs) [0x00027] in <0e9c02ea98264091a344714de10def9b>:0 at NetTopologySuite.IO.DbaseEncodingUtility..cctor () [0x00799] in <0e9c02ea98264091a344714de10def9b>:0 --- End of inner exception stack trace --- at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_generic_class_init(intptr) at NetTopologySuite.IO.DbaseFileHeader.GetLdidFromEncoding (System.Text.Encoding encoding) [0x00000] in <0e9c02ea98264091a344714de10def9b>:0 at NetTopologySuite.IO.DbaseFileHeader.WriteHeader (System.IO.BinaryWriter writer) [0x0009b] in <0e9c02ea98264091a344714de10def9b>:0 at NetTopologySuite.IO.DbaseFileWriter.Write (NetTopologySuite.IO.DbaseFileHeader header) [0x00066] in <0e9c02ea98264091a344714de10def9b>:0 at NetTopologySuite.IO.ShapefileDataWriter.Write (System.Collections.Generic.IEnumerable1[T] featureCollection) [0x00086] in <0e9c02ea98264091a344714de10def9b>:0
at GeoAraba.Helpers.Wkt2ShapeHelper.Transform (System.String wkt, System.String name) [0x00180] in D:\Workspace\VisualStudio\d-1815_geoaraba\GeoAraba\GeoAraba.Shared\Helpers\Wkt2ShapeHelper.cs:95 }`

I'm really lost, and desperate. Please, someone help me with this issue?

Thanks in advance.

Inconsistency determining and writing Int32 in the DBaseFileHeader

In the DBaseFileHeader, we determine with the following logic if the Type is an Int32 or Int64:

case 'N': // numeric
if (DecimalCount == 0)
{
if (Length < 10)
return typeof (int);
return typeof (long);
}
return typeof(double);

If we create a Header based on a feature, the following logic is used:

case 'N': // numeric
if (DecimalCount == 0)
{
if (Length < 10)
return typeof (int);
return typeof (long);
}
return typeof(double);

With the following values:
private const int DoubleLength = 18;
private const int DoubleDecimals = 8;
private const int IntLength = 10;
private const int LongLength = 18;
private const int IntDecimals = 0;

This means an Int32 is defined with a length of 10 when writting. If you would read this header again, using the DBaseFieldDescriptor logic, it would be turn into an Int64 instead of an Int32.

DbaseFileWriter DBF write DateTime Attribute issue with the Year.

From @tdyen on April 9, 2018 3:40

In DbaseFileWriter.cs if you Write a DateTime attribute for DateTime.MinValue then the year is 1 so it writes 1 char not 4 and you get this code triggered

   // Check if the correct amount of bytes was written
        if (bytesWritten != recordLength)
            throw new ShapefileException("Error writing Dbase record");

So this method here

  private void Write(DateTime date)
    {
        foreach (var c in date.Year.ToString(NumberFormatInfo.InvariantInfo))
            _writer.Write(c);

ought to be something like this, though I haven't tested it

  private void Write(DateTime date)
    {
        foreach (var c in date.ToString("yyyy", NumberFormatInfo.InvariantInfo))
            _writer.Write(c);

Copied from original issue: NetTopologySuite/NetTopologySuite#226

MultiLineHandler.GeometryInstantiationErrorHandling is broken

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;
}

The default is ThrowException, this works. Null also works, it ends up creating an empty multilinestring. Empty and TryFix don't work, they modify sequences[s] but this modified data is not used in the later code. factory.CreateLineString(points) throws because there is still only one point in points.

I assume this wasn't fully tested when introduced in NetTopologySuite/NetTopologySuite@9942331
Replacing sequences[s] with points makes Empty return an empty linestring, and makes TryFix return a linestring with two coordinates at the same position. This was probably the intent of the original code.

API review

Hi,

I'm looking to migrate away from an internal shapefile library (very old NTS fork + modifications), to this module. While figuring out how to use the API, I've also reviewed it and found that there is room for improvement. Most notably, IEnumerable<T> should be added to the non-Extended classes, but it's not a quick fix that I can do in a small PR. ShapefileDataReader currently outputs an ICustomTypeDescriptor backed by an internal type, which is not ideal.

A number of things that I would like to improve on:

  • implement IEnumerable<T>
  • make use of more modern types (e.g. no ArrayList to hold attributes) and pull this API out of the .NET 1.x era
  • get rid of code duplication between the two .dbf readers, the actual parsing logic is copy-pasted
  • if possible, consolidate the Extended classes into the non-Extended classes
  • remove IDataReader implementation, doesn't really make sense and some methods have nonsense implementations (e.g. return 0; no matter the method arguments)
  • introduce async IO
  • improve unit tests, they're confusingly structured and one in particular even refers to local data with [TestCase(@"D:\Daten\Geofabrik\roads.shp")]

I should be able to do a good part of the necessary work, but I would like input from the current maintainers before going ahead.

Below is the public API of the read-related classes that I reviewed. I have not (yet) gone over write-related classes because they're not the focus of the project I work on. (The list was compiled by hand, so there may be errors.)

Public API

.dbf

NetTopologySuite.IO.DbaseFileReader

Implements: System.Collections.IEnumerable

DbaseFileReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry)
DbaseFileReader(string path)
DbaseFileReader(string path, System.Text.Encoding encoding)
System.Collections.IEnumerator GetEnumerator()
NetTopologySuite.IO.DbaseFileHeader GetHeader()

NetTopologySuite.IO.ShapeFile.Extended.DBaseReader

Implements: System.IDisposable, System.Collections.Generic.IEnumerable<NetTopologySuite.Features.IAttributesTable>

DbaseReader(NetTopologySuite.IO.Streams.IStreamProvider streamProvider)
DbaseReader(string filename)
void Dispose()
System.Collections.Generic.IEnumerator<NetTopologySuite.Features.IAttributesTable> GetEnumerator()
NetTopologySuite.Features.IAttributesTable ReadEntry(int index)

.shp

NetTopologySuite.IO.ShapefileReader

Implements: System.Collections.IEnumerable

ShapefileReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry shapeStreamProviderRegistry, NetTopologySuite.Geometries.GeometryFactory geometryFactory)
ShapefileReader(string filename)
ShapefileReader(string filename, NetTopologySuite.Geometries.GeometryFactory geometryFactory)
System.Collections.IEnumerator GetEnumerator()
NetTopologySuite.Geometries.GeometryCollection ReadAll()
NetTopologySuite.IO.ShapefileHeader Header { get; }

NetTopologySuite.IO.ShapeFile.Extended.ShapeReader

Implements: System.IDisposable

ShapeReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry)
ShapeReader(string shapefilePath)
void Dispose()
System.Collections.Generic.IEnumerable<NetTopologySuite.Geometries.Geometry> ReadAllShapes(NetTopologySuite.Geometries.GeometryFactory geoFactory)
System.Collections.Generic.IEnumerable<NetTopologySuite.IO.Handlers.MBRInfo> ReadMBRs()
NetTopologySuite.Geometries.Geometry ReadShapeAtIndex(int index, NetTopologySuite.Geometries.GeometryFactory geoFactory)
NetTopologySuite.Geometries.Geometry ReadShapeAtOffset(long shapeOffset, NetTopologySuite.Geometries.GeometryFactory geoFactory)
NetTopologySuite.IO.ShapefileHeader ShapefileHeader { get; }

.dbf + .shp

NetTopologySuite.IO.ShapefileDataReader

Implements: System.Data.IDataReader, System.IDisposable, System.Collections.IEnumerable

ShapefileDataReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry, NetTopologySuite.Geometries.GeometryFactory geometryFactory)
ShapefileDataReader(string filename, NetTopologySuite.Geometries.GeometryFactory geometryFactory)
ShapefileDataReader(string filename, NetTopologySuite.Geometries.GeometryFactory geometryFactory, System.Text.Encoding encoding)
void Close()
void Dispose()
bool GetBoolean(int i)
byte GetByte(int i)
long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
char GetChar(int i)
long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
System.Data.IDataReader GetData(int i)
string GetDataTypeName(int i)
System.DateTime GetDateTime(int i)
decimal GetDecimal(int i)
double GetDouble(int i)
System.Collections.IEnumerator GetEnumerator()
System.Type GetFieldType(int i)
float GetFloat(int i)
System.Guid GetGuid(int i)
short GetInt16(int i)
int GetInt32(int i)
long GetInt64(int i)
string GetName(int i)
int GetOrdinal(string name)
System.Data.DataTable GetSchemaTable()
string GetString(int i)
object GetValue(int i)
int GetValues(object[] values)
bool IsDBNull(int i)
bool NextResult()
bool Read()
void Reset()
NetTopologySuite.IO.DbaseFileHeader DbaseHeader { get; }
int Depth { get; }
int FieldCount { get; }
NetTopologySuite.Geometries.Geometry Geometry { get; }
bool IsClosed { get; }
int RecordCount { get; }
int RecordsAffected { get; }
NetTopologySuite.IO.ShapefileHeader ShapeHeader { get; }
object this[int i] { get; }
object this[string name] { get; }

NetTopologySuite.IO.ShapeFile.Extended.ShapeDataReader

Implements: System.IDisposable

ShapeDataReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry)
ShapeDataReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index)
ShapeDataReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index, NetTopologySuite.Geometries.GeometryFactory geoFactory)
ShapeDataReader(NetTopologySuite.IO.Streams.IStreamProviderRegistry streamProviderRegistry, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index, NetTopologySuite.Geometries.GeometryFactory geoFactory, bool buildIndexAsync)
ShapeDataReader(string shapeFilePath)
ShapeDataReader(string shapeFilePath, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index)
ShapeDataReader(string shapeFilePath, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index, NetTopologySuite.Geometries.GeometryFactory geoFactory)
ShapeDataReader(string shapeFilePath, NetTopologySuite.Index.ISpatialIndex<NetTopologySuite.IO.Handlers.ShapeLocationInFileInfo> index, NetTopologySuite.Geometries.GeometryFactory geoFactory, bool buildIndexAsync)
void Dispose()
System.Collections.Generic.IEnumerable<NetTopologySuite.IO.ShapeFile.Extended.Entities.IShapefileFeature> ReadByMBRFilter(NetTopologySuite.Geometries.Envelope envelope, [bool testGeometriesActuallyInMBR = False])
NetTopologySuite.Geometries.Envelope ShapefileBounds { get; }

Chinese character transcoding error

In DbaseFileHeader class line 311
string name = DbaseEncodingUtility.Latin1.GetString(buffer, 0, buffer.Length);
when the field value is Chinese character, it cant get the correct value.
it should be use the Detected encoding from line 294
var encoding = DetectEncoding(ldid, cpgStreamProvider);
to encoding the value,
string name = encoding.GetString(buffer, 0, buffer.Length);
then it get the correct value

Shapefile IO refactoring

I want to change the way the shapefile read/write works now:

  • Have a package for this only without dragging along the rest. Now you also get, Postgis and MsSqlSpatial using the NetTopologySuite.IO package. Perhaps even with only one dependency, NetTopologySuite.IO and nothing else.
  • Refactor to support some netstandard version.
  • Remove code that has nothing to do with shapefile writing/reading.

Anyone have any feedback? Should I do this outside of the main NTS project, create a project/package in a new repo?

ShapefileReader.MoveNext() is aborted prematurely

I was dealing with some shapefiles with possibly incorrect data for some shapes and I came across a situation where there are two polygons. One contains only 2 points (which is invalid) followed by a second valid polygon of 21 points. However on this situation the enumerator is aborted prematurely before the end of the file, due to the catch() block (ShapefileReader.cs line 138)

try
{
	int recordNumber = _shpBinaryReader.ReadInt32BE();
	int contentLength = _shpBinaryReader.ReadInt32BE();
	_geometry = _handler.Read(_shpBinaryReader, contentLength, _parent._geometryFactory);
}
catch (Exception ex)
{
	// actually we should remove this crap...
	Trace.WriteLine(ex.Message);
	return false;                  // <-----------------   will ignore further valid shapes
}

I would suggest to proceed the enumeration until the end of the file is reached, so possibly valid shapes are not ignored.

System.NotSupportedException: 'Unsupported DBF reader Type 13

I'm starting with NetTopologySuite and I'm trying to read an .shp that I created from geojson.io to do some tests, it gave me an .zip file which contains 4 files (.dbf, .prj, .shp and .shx).

When I try to read the .shp alone I'm having the error: "System.IO.FileNotFoundException: '.../POLYGON.dbf'".

When I try to read the .shp with the .dbf in the same folder I'm having the error: "System.NotSupportedException: 'Unsupported DBF reader Type 13'".

I tried to open this .shp in QGIS and it worked.
I tried to read other .shp files from other sources with my code and it worked.

Code:
ShapeDataReader reader = new ShapeDataReader("...\\POLYGON.shp");

File:
polygon.zip

NetTopologySuite.IO.ShapeFile version: 1.15.3

Writing shape files with streams throws System.ObjectDisposedException 'Cannot access a closed file.'

From @majorbenks on March 16, 2018 8:35

I tried to use ShapefileDataWriter with a ShapefileStreamProviderRegistry. I open four FileStreams and wrap them in an object implementing IShapefileStreamProvider adding them to a ShapefileStreamProviderRegistry. When I run my code, a System.ObjectDisposedException 'Cannot access a closed file.' is thrown. My code works fine when I use a file path instead of streams.

Hier is my the code:

            using (var shpStream = File.Create(Path.Combine(pathWithoutFilename, $"{fileNameWithoutEnding}.shp")))
            {
                using (var shxStream = File.Create(Path.Combine(pathWithoutFilename, $"{fileNameWithoutEnding}.shx")))
                {
                    using (var dbfStream = File.Create(Path.Combine(pathWithoutFilename, $"{fileNameWithoutEnding}.dbf")))
                    {
                        using (var prjStream = File.Create(Path.Combine(pathWithoutFilename, $"{fileNameWithoutEnding}.prf")))
                        {
                            var registry = new ShapefileStreamProviderRegistry(
                                            new ShapeFileStreamProvider(shpStream, StreamTypes.Shape),
                                            new ShapeFileStreamProvider(shxStream, StreamTypes.Index),
                                            new ShapeFileStreamProvider(dbfStream, StreamTypes.Data));

                            // Create the projection file
                            using (var streamWriter = new StreamWriter(prjStream))
                            {
                                streamWriter.Write(shapeFilePrjString);
                            }

                            // Create the shapefile
                            var outGeomFactory = GeometryFactory.Default;
                            var writer = new ShapefileDataWriter(registry, outGeomFactory, Encoding.UTF8);
                            var outDbaseHeader = ShapefileDataWriter.GetHeader(features[0], features.Count);
                            writer.Header = outDbaseHeader;
                            writer.Write(features);
                        }
                    }
                }
            }

This is the stack trace:

at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.Flush(Boolean flushToDisk)
at System.IO.FileStream.Flush()
at System.IO.BinaryWriter.Flush()
at System.IO.BinaryWriter.get_BaseStream()
at NetTopologySuite.IO.DbaseFileWriter.Write(DbaseFileHeader header)
at NetTopologySuite.IO.ShapefileDataWriter.Write(IList1 featureCollection) at Softec.GIS.GeometrieDatenImportExport.FileAccess.SaveToShapeFile(String pathWithoutFilename, String fileNameWithoutEnding, String shapeFilePrjString, IList1 features) in C:\Projekte\Softec.GIS.GeometrieDatenImportExport.Console\Softec.GIS.GeometrieDatenImportExport\FileAccess.cs:line 72
at Softec.GIS.GeometrieDatenImportExport.ShapeExporter.ExportToShapeFile(List`1 models, String pathWithoutFilename, String fileNameWithoutEnding) in C:\Projekte\Softec.GIS.GeometrieDatenImportExport.Console\Softec.GIS.GeometrieDatenImportExport\ShapeExporter.cs:line 82
at Softec.GIS.GeometrieDatenImportExport.Console.Program.Main(String[] args) in C:\Projekte\Softec.GIS.GeometrieDatenImportExport.Console\Softec.GIS.GeometrieDatenImportExport.Console\Program.cs:line 31

Google research suggests, that the stream is closed somewhere, but I can't figure out where. I don't close it anywhere. Can anyone help? Or is this a bug?

I'm using NetTopologySuite v1.14.0, NetTopologySuite.IO. v1.14.0.1, NET FW 4.6.1, WIN 10 Pro and it is a console application.

Copied from original issue: NetTopologySuite/NetTopologySuite#223

System.OverflowException when reading empty header

If we write a feature without attributes, we get an System.OverflowException : Arithmetic operation resulted in an overflow when reading the header again. the error occurs on the following line:

_fieldDescriptions = new DbaseFieldDescriptor[_numFields];

This is because the _numFields is -1 and this is because of the calculation above, where the _headerLength is 0 and FileDescriptorSize defaults to 32.
_numFields = (_headerLength - FileDescriptorSize - 1) / FileDescriptorSize;

Currently the header length is only set when adding or removing columns to the header.
Add Column

_headerLength = 33 + 32 * _fieldDescriptions.Length;

Remove Column
_headerLength = 33 + 32 * _fieldDescriptions.Length;

My proposed solution is to check the headerLength when writing and set it to 33 when it is 0.

Exception in .Net core application reading from shapefile

Hi!
I am trying to convert a .net standard applikation to .net core and get a runtime exception from the IO.ShapeFile library. I have added the nuget NetTopologySuite.IO.Shapefile in VS code, and my target framework is netcoreapp2.0. VS Code says everything is compatible.

The exception is thrown when reading a shapefile:

  GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModels.Fixed),3006);
            
            var features = new List<Feature>();
            using ( ShapefileDataReader shapeFileDataReader = new ShapefileDataReader(shpFilename, factory))  {

It seems like maybe the DbaseEncodeUtility tries to load .Net 4.1 assemblies for System.Text.Encoding?

{System.IO.FileNotFoundException: Could not load file or assembly 'System.Text.Encoding.CodePages, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'System.Text.Encoding.CodePages, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at NetTopologySuite.IO.DbaseEncodingUtility.GetEncodingForCodePageName(String name)
   at NetTopologySuite.IO.DbaseEncodingUtility..cctor() in D:\Development\Source\Repos\NTS.IO\NetTopologySuite.IO.ShapeFile\NetTopologySuite.IO.GeoTools\Dbase\DbaseEncodingUtility.cs:line 14

Or am I doing something wrong?

Thanks

How to get coordinate system of shapefile?

I am reading in a shape file using to test my code:

           var reader = new ShapeDataReader(path);
            var bounds = reader.ShapefileBounds;
            foreach (var thing in reader.ReadByMBRFilter(bounds))
            {
                var attrs = thing.Attributes;
                var geo = thing.Geometry;
                if (geo != null)
                {
                    var coords = geo.Coordinates;
                }
            }

path is the path to the .shp file. Is this correct? Or should I be using ShapefileDataReader? I've seen examples online of both.

One thing is that I can't figure out how to get the coordinate system via code. I need to project it to WGS84. The srid on the geometry is 0 so I'm not sure how to get the information I need. Do I need to do something special to read the .prj file to get the information I need?

Fix failing tests

Running all the NUnit tests from a clean clone on VS2017, most of them fail on my machine.

Some of the failures are because the tests are run on netcoreapp2.0 (so using netstandard2.0), which doesn't handhold as much as the "fat" .NET targets and has a few different defaults around encodings.

Whitespaces in cpg file prevents to detect correct encoding.

In this line you're trying to use content of cpg file as is. But whitespaces, line endings, etc prevents to detect correct encoding.

E.g. these lines will lead to ArgumentException which will lead to default encoding instead of desirable.

Encoding.GetEncoding("UTF-8/r/n")
Encoding.GetEncoding("UTF-8 ")

Suggestion - trim leading and trailing whitespaces.

Reading shape files

From @trailway on July 19, 2016 17:57

I recently encountered some shape files which the reader does not handle. It can be debated whether the files are correct but they do work in ArcMap! What happens is that the content length does not include M content which is present (although it's presence is benign because the value says that it is not meaningful). This makes the reader fail because it walks through shape geometry using content length, i.e. it expects the next element to begin at the location just after the location where the previous element ended. This works in ArcMap because they use the shape index. I think that using the shape index (which is a required file) is a more stable approach.

Copied from original issue: NetTopologySuite/NetTopologySuite#112

how to set shpfile Dimension type

var writer =new ShapefileDataWriter(fullpath, factory,writeEncoding);
writer.Header = ShapefileDataWriter.GetHeader(lines[0], lines.Count);

default is 3D coordinates? i need to 2d

ShapeHandler.GeometryInstantiationErrorHandling cannot be set when using ShapefileReader

NetTopologySuite/NetTopologySuite@19f2f40 introduced ShapeHandler.GeometryInstantiationErrorHandling, but this property is only accessible through an instance of a handler. When using ShapefileReader, the handler is a private field of the ShapefileEnumerator class, making it impossible to change the value of this property.

Relevant code:

public GeometryInstantiationErrorHandlingOption GeometryInstantiationErrorHandling { get; set; }

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;
}

'key is null' when trying to read a shapefile in Android

Hello!
I am working out how to read shapefiles cross platform (UWP and Android) in a Xamarin.Forms application (.netstandard 2.0). But I am encountering an issue:

System.ArgumentNullException
  Message=Value cannot be null.
Parameter name: key

this exception is thrown in the line

var shapeFileReader = Shapefile.CreateDataReader(shapeFile,
   new NetTopologySuite.Geometries.GeometryFactory(
      new NetTopologySuite.Geometries.PrecisionModel(1000000.0)));

where 'shapeFile' is a string with the path /data/user/0/com.companyname.shapefileforms/cache/ShapeFiles/countries (so without file extensions).

This code works fine when run as UWP app but not when run within Android. Tested with version 8.1, 9 and 10.

I attached the whole Project. This error occurs in ShapeFileForms.MainPage.xaml.cs in the Method ClickOnMap, line 83.
I can not step into this line in the debugger, I guess because I installed this module through nuget instead of copying in its source code?

It would be awesome if we could work this out together, although I am quite new to this and pobably won't be of much help :/

Thank you very much!

ShapeFileForms.zip

DateTime value with Time in ShapeFile

Hi,

I'm trying to create ShapeFile which contains time-specific values.

At first, I tried to just add DateTime fields to Attributes table just using:
attributesTable.Add("DateTime", myObject.MyDateTimeField));,

but according to ShapeFileDataWriter:
else if (type == typeof(DateTime)) header.AddColumn(name, 'D', DateLength, DateDecimals);
and DbFileWriter:

else if (columnValue is DateTime)
  {
          Write((DateTime)columnValue);
    }
...
/// <summary>
        /// </summary>
        /// <param name="date"></param>
        private void Write(DateTime date)
        {
            foreach (char c in date.Year.ToString(NumberFormatInfo.InvariantInfo))
                _writer.Write(c);

            if (date.Month < 10)
                _writer.Write('0');
            foreach (char c in date.Month.ToString(NumberFormatInfo.InvariantInfo))
                _writer.Write(c);

            if (date.Day < 10)
                _writer.Write('0');
            foreach (char c in date.Day.ToString(NumberFormatInfo.InvariantInfo))
                _writer.Write(c);
        }

DateTime is always converted to Date format.

So I started to search how to place Time in dbf file, and found in documentation that there is a Timestamp field which has @ symbol.
I tried to change symbol in shape file header, but I See that there are a few places that should be fixed to use Timestamp field.

My question is: In actual code is there a way to place in .shp/.dbf files not only date but also a time and mark it as @ timestamp?
Is there a reason why it's not supported? Is my documentation wrong or is there any other reason?

If there just never be any need to use timestamp before could I contribute and add that functionality? :)

ShapefileDataWriter can't save MulitPoint geometry

This example:
var geomFactory = new GeometryFactory();

var features = new List<IFeature>();
var attrTbl = new AttributesTable();
attrTbl.Add("Id", 10);
var coordinates = new Coordinate[2];
coordinates[0] = new Coordinate(123.0, 023.0);
coordinates[1] = new Coordinate(123.0, 100.0);
var mPoint = geomFactory.CreateMultiPointFromCoords(coordinates);
var ft = new Feature(mPoint, attrTbl);
features.Add(ft);

var shpWriter = new ShapefileDataWriter("outShape.shp", geomFactory);
var header = ShapefileDataWriter.GetHeader(features[0], features.Count);
shpWriter.Header = header;
shpWriter.Write(features);

Failes int the last Write call with exception:
System.ArgumentException: Expected geometry that implements 'IPoint', but was 'MultiPoint'

This is because the call from Write to Shapefile.GetShapeType() with the first geometry returns
PointZM bacause the call to GetNonEmptyGeometry uses GetGeometryN() to get the first point in the mulitpoint and returns it.

The function GetNonEmptyGeometry() could return the geometry itself if it is not null in this case or maby Shapefile.GetShapeType() could not use it to filter geometry.

set encoding bug

set encoding error:
this my code sample:
ShapefileDataWriter.GetHeader(features[0], features.Count,Encoding.UTF8);
error msg:
Setting the encoding is only allowed once, either by means of the constructor or this property setter

and chinese random code error

Reader was disposed, cannot read from a disposed reader

having an issue where i would like to read from a shape file, dispose the reader but hold the shape file information to do something with later. something like:

        private static IEnumerable<NetTopologySuite.IO.ShapeFile.Extended.Entities.IShapefileFeature> ProcessShapeFile(string shapeFilePath)
        {
            using (ShapeDataReader reader = new ShapeDataReader(shapeFilePath))
            {
                NetTopologySuite.Geometries.Envelope mbr = reader.ShapefileBounds;
                return reader.ReadByMBRFilter(mbr).ToList();
            }
        }

and then later, in another method that

var feats = ProcessShapeFile(path);
foreach (NetTopologySuite.IO.ShapeFile.Extended.Entities.IShapefileFeature f in feats)
                {
string clevelVal = f.Attributes["attName"];
...
}

on the attribute line, i get the following error:

System.InvalidOperationException: Reader was disposed, cannot read from a disposed reader
Stack Trace:
DbaseReader.ReadEntry(Int32 index)
<.ctor>b__1()
Lazy1.CreateValue() Lazy1.LazyInitValue()
Lazy`1.get_Value()
IFeature.get_Attributes()

is there any way to get what i'm looking for here, or can i not centralize the shape file loading/disposing like i'm hoping to?

[BUG] UTF-8 read encoding error

Describe
UTF-8 shapefile loaded with wrong encoding.

Code Snippet

using (var reader = new ShapefileDataReader("shape.shp", new GeometryFactory(),
    Encoding.UTF8))
{
    reader.Read();
}

Investigation
NetTopologySuite.IO.DbaseFileReader.CreateStreamProviderRegistry method gets called atShapefileDataReader constructor.
It passes encoding.EncodingName to ByteStreamProvider argument with "Unicode (UTF-8)" value.

Later, when parsing the header in NetTopologySuite.IO.DbaseFileHeader.GetEncoding()

try
{
    // The following line throws exception
    // 'Unicode (UTF-8)' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
    return DbaseEncodingUtility.GetEncodingForCodePageName(cpgText);
}
catch
{
    return DefaultEncoding;
}

I think DbaseEncodingUtility.GetEncodingForCodePageName should be called with "UTF-8" argument.

Registering encoding provider
Calling Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); does not fixes my issue.

Quick fix
Setting the default header encoding.

DbaseFileHeader.DefaultEncoding = Encoding.UTF8;

System.NotSupportedException : Memory stream is not expandable.

When writting a shape to a stream, I get the following error:

System.NotSupportedException : Memory stream is not expandable.

After doing some investigation I have found what the cause of this could be:

: base(provider.Buffer, 0, writable ? provider.MaxLength : provider.Length, writable, true)

In here a new MemoryStream instance is created. When it is a user defined MemoryStream, you aren't able to let the stream grow.

See here a private _expandable property being set.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,108

When setting the capacity, you will see that this is checked and will result into the exception described in the title.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,283

To solve this you could use the default contstructor, or the constructor where you only pass the capacity of the stream.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,70

NetTopologySuite.IO.ShapeFile with Xamarin.Mac - ArgumentNullException

Im trying to read shp-files in a Xamarin.Mac project with NetTopologySuite.IO.Shapefile 2.0.0.
Project is targeting Xamarin.Mac Full NET 4.8.

Calling _reader = new ShapefileDataReader(file, _geometryFactory, System.Text.Encoding.Default); results in ArgumentNullException, see stacktrace below.

With a plain .NET Core 3.0 project, everything is fine.

Any ideas?

System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument argument) in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/System.Memory/src/System/ThrowHelper.cs:27
System.Collections.Generic.Dictionary<System.Text.Encoding,byte>.FindEntry(System.Text.Encoding key) in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:380
System.Collections.Generic.Dictionary<System.Text.Encoding,byte>.ContainsKey(System.Text.Encoding key) in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:286
NetTopologySuite.IO.DbaseEncodingUtility.AddLdidEncodingPair(byte ldid, System.Text.Encoding encodingToAdd) in 
NetTopologySuite.IO.DbaseEncodingUtility.RegisterEncodings(object[][] ldidCodePagePairs) in 
NetTopologySuite.IO.DbaseEncodingUtility..cctor() in 
NetTopologySuite.IO.DbaseFileHeader.GetEncoding(NetTopologySuite.IO.Streams.ByteStreamProvider provider) in 
NetTopologySuite.IO.DbaseFileHeader.DetectEncoding(byte ldid, NetTopologySuite.IO.Streams.ByteStreamProvider cpgFile) in 
NetTopologySuite.IO.DbaseFileHeader.ReadHeader(System.IO.BinaryReader reader, NetTopologySuite.IO.Streams.ByteStreamProvider cpgStreamProvider) in 
NetTopologySuite.IO.DbaseFileReader.GetHeader() in 
NetTopologySuite.IO.ShapefileDataReader..ctor(string filename, NetTopologySuite.Geometries.GeometryFactory geometryFactory, System.Text.ASCIIEncoding encoding) in 
QvShape.Reader..ctor(string file) in /Users/tomflemming/QuoVadis/Qvx1/CodeFromExternal/NetTopologySuite/QvShape/Reader.cs:26
QvShape.Reader.Test() in /Users/tomflemming/QuoVadis/Qvx1/CodeFromExternal/NetTopologySuite/QvShape/Reader.cs:83
QvxAppShared.QvxApp..ctor(Eto.Mac.Platform platform, string[] args) in /Users/tomflemming/QuoVadis/Qvx1/QvxShared/App/QvxApp.cs:49
QvxAppShared.Mac.Program.Main(string[] args) in /Users/tomflemming/QuoVadis/Qvx1/QvxMac/Program.cs:16

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.