Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializer ignores the IPrecisionModel of geometries #27

Closed
janruo opened this issue Apr 23, 2019 · 5 comments
Closed

Serializer ignores the IPrecisionModel of geometries #27

janruo opened this issue Apr 23, 2019 · 5 comments

Comments

@janruo
Copy link

janruo commented Apr 23, 2019

When serializing a geometry, the serializer seems to ignore the IPrecisionModel of the IGeometry. The coordinates in the JSON are not formatted according to the precision model, but are outputted as is.

Example:

var coords = new []
{
    new Coordinate(0.001, 0.001),
    new Coordinate(10.1, 0.002),
    new Coordinate(10, 10.1),
    new Coordinate(0.05, 9.999),
    new Coordinate(0.001, 0.001)
};

// Creating the polygon with PrecisionModels.Fixed
var polygon = GeometryFactory.Fixed.CreatePolygon(coords);

var serializer = GeoJsonSerializer.CreateDefault();
var writer = new StringWriter();
serializer.Serialize(writer, polygon);

var str = polygon.ToString();
// The precision is one decimal place as expected
// POLYGON ((0 0, 10.1 0, 10 10.1, 0.1 10, 0 0))

var json = writer.ToString();
// The precision is ignored
// {"type":"Polygon","coordinates":[[[0.001,0.001],[10.1,0.002],[10.0,10.1],[0.05,9.999],[0.001,0.001]]]}

Version: 1.15.2

@DGuidi
Copy link
Contributor

DGuidi commented Apr 23, 2019

try with GeoJsonSerializer.Create(GeometryFactory.Fixed); see GeoJsonSerializer.Create(IGeometryFactory)

@janruo
Copy link
Author

janruo commented Apr 23, 2019

That doesn't seem to work. After a quick look at the source code, the serializer seems to only use the factory when reading GeoJSON into geometries, not when writing geometries into GeoJSON.

It could also be possible that someone wants to serialize a FeatureCollection with multiple geometries with different IPrecisionModels. In this case passing the precision when creating the serializer wouldn't work.

@DGuidi
Copy link
Contributor

DGuidi commented Apr 23, 2019

actually this makes sense to me. precision model obviously can't be stored as a defined property inside geojson because of specs violation (but you can maybe add a custom attribute in each feature) and in json geometry looks correct to store info with the maximum precision viable. so, this is a correct behavior to me.

@janruo
Copy link
Author

janruo commented Apr 23, 2019

I'm not sure you understood the issue completely. I'm not saying that the precision model itself should be included in the output GeoJSON. I'm saying that the serializer should probably format the coordinates according to the geometry's defined precision model.

In my example, the geometry was created with a one decimal point precision model, and thus the WKT of the geometry was POLYGON ((0 0, 10.1 0, 10 10.1, 0.1 10, 0 0)) as expected.

However, the serializer doesn't respect the precision, and outputs the coordinates too precisely:
{"type":"Polygon","coordinates":[[[0.001,0.001],[10.1,0.002],[10.0,10.1],[0.05,9.999],[0.001,0.001]]]}

What I would expect is that the serializer respects the precision and outputs this:
{"type":"Polygon","coordinates":[[[0,0],[10.1,0],[10,10.1],[0.1,10],[0,0]]]},
which would match the WKT.


The reason why I noticed this issue is that I'm creating 2D polygons with a lot of coordinates, and applying transformations to them. The transformation causes the coordinates to be very precise and it also adds the Z component, e.g. (2321643.8753857632, 87332567.0012466452, 0.0002155952). Because the polygons are very large and the coordinates are too precise, I would be wasting storage space by storing the serialized GeoJSON in a database.

If the serializer respected the precision model, I could create a custom IPrecisionModel implementation that would format the coordinates to three decimal places and throw away the Z component (2321643.875, 87332567.001), and this would save ~50% storage space.

For now I just created a workaround that manually goes through each geometry and formats the coordinates before serialization. It works, but it's not very elegant.

@FObermaier
Copy link
Member

FObermaier commented Apr 24, 2019

According to the GeoJSON spec your coordinates are out of bounds.

You can use NetTopologySuite.Precision.GeometryPrecisionReducer to reduce the precision used in your geometries.

To handle that on the GeoJsonWriter we could

  • use the PrecisionModel of the geometry (like WKTWriter)
  • use the PrecisionModel of the GeometryFactory of the serializer

Additionally we can add an OutputDimension property with valid values 2 or 3 to ditch z-ordinate if that is not required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants