NetTopologySuite / NetTopologySuite.IO.Esri

BSD 3-Clause "New" or "Revised" License
31 stars 16 forks source link

Issue in ReadGeometry with a Multipolygon ESRI shapefile #9

Closed fraferrando closed 1 year ago

fraferrando commented 1 year ago

Hi!

first of all, thank you for your library. I'm inexperienced with ESRI shapefile. I'm using your library to try to open an ESRI shapefile, modify its attributes and save a new one. I have found this issue with a MultiPolygon ESRI shapefile and at the moment I'm trying to understand what it is wrong.. I'm calling Shapefile.ReadAllFeatures on the shapefile attached below.. MultiPolygon ReadGeometry(Stream shapeBinary) throws an exception.

If you have any suggestions you are more then welcome.

Thank you, bye Francesca tmpA6A6.zip Exception

fraferrando commented 1 year ago

Hi kubaszostak,

i have not found a solution yet but what i have noticed is that it is probably a question of decimal digits...

Because Multypoligon tmpA6A6 crashes While Multypoligon tmp3509 works

points in tmpA6A6 where it crashes 11.9797646969949998 44.88052525112210134

11.97958996594410053 44.88039510494419915

11.97940691328200025 44.88051933463930254

11.97958164432600014 44.88064948109619934

11.9797646969949998 44.88052525112210134

points in tmp3509 where it works 11.98410995573788007 44.87705361570291984

11.98413715530627499 44.87705443978246223

11.98412541839736356 44.87681169189863084

11.98409970871640873 44.87681083371183632

11.98410995573788007 44.87705361570291984 tmpA6A6 [tmp3509.zip](https://github.com/NetTopologySuite/NetTopologySuite.IO.Esri/files/10093292/tmp3509.zip) .zip

KubaSzostak commented 1 year ago

Hi Francesca, I've updated the code and now you can read your shapefiles:

var options = new ShapefileReaderOptions()
{
    GeometryBuilderMode = GeometryBuilderMode.IgnoreInvalidShapes
};
var shpPath = TestShapefiles.PathTo("Issues/009/tmpA6A6/Rx/PPPP29_0.shp");
var features = Shapefile.ReadAllFeatures(shpPath, options);
Assert.AreEqual(50, features.Count());

Console.WriteLine("Invalid shape geometries:");
foreach (var feature in features)
{
    if (!feature.Geometry.IsValid)
    {
        Console.WriteLine(string.Join(", ", feature.Attributes.GetValues()));
    }
}

You can also fix invalid geometries by using GeometryBuilderMode.FixInvalidShapes option. It will work for tmpA6A6 file, but not for tmp3509. The latter contains self-intersecting polygon shells, so it can't be fixed automatically.

image

KubaSzostak commented 1 year ago

This also fixes Cannot read a polygon with a hole from a ShapeFile #70 issue.

fraferrando commented 1 year ago

Hi Kuba, thank you very much, I will try today.

I have a question. I noticed that taking the file that didn't work (A6A6) and saving it with QGIS with UTF-8 encoding was then read correctly by the library. Is it mandatory to use UTF-8 encoding or is it irrelevant?

Thank you bye Francesca

fraferrando commented 1 year ago

Hi Kuba,

I have tried the last version of the library and now with the options var options = new ShapefileReaderOptions() { GeometryBuilderMode = GeometryBuilderMode.FixInvalidShapes };

var currentFeatures = Shapefile.ReadAllFeatures(shpStream, dbfStream, options); //we added the methods that use streams from the start

We can read both a6a6 and 3509 zips!

Thank you so very much!!!

Bye Francesca