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

PrecisionModel issues #632

Open
oyvindi opened this issue Sep 19, 2022 · 3 comments
Open

PrecisionModel issues #632

oyvindi opened this issue Sep 19, 2022 · 3 comments

Comments

@oyvindi
Copy link

oyvindi commented Sep 19, 2022

I am running into an issue I don't fully understand, using PrecisionModel (NetTopologySuite.Core/1.15.3).

By setting precision to 1000, I expect everything to be rounded off to 3 decimals. When using WktReader, I get expected roundoffs. However, creating the same geometry using factory or constructor, it seems to use 4 decimals.

Is this expected behaviour, or am I missing something here ?

Example code:

var precisionModel = new PrecisionModel(1000);
var geomService = new NtsGeometryServices(CoordinateArraySequenceFactory.Instance, precisionModel, 4230); 
var geometryFactory = geomService.CreateGeometryFactory();

var wktReader = new WKTReader(geometryFactory);
var wktPoly = wktReader.Read(
	"POLYGON ((5.53019009655585414 65.32111738273543722, 5.59648652009346037 65.39004588297750331, 5.6089682537873129 65.26335043965949012, 5.53019009655585414 65.32111738273543722))");
// wktPoly: POLYGON ((5.53 65.321, 5.596 65.39, 5.609 65.263, 5.53 65.321))

// Creating polygon with same coordinates, via factory
var factoryPoly = geometryFactory.CreatePolygon(new Coordinate[]
{
	new(5.53019009655585414, 65.32111738273543722),
	new(5.59648652009346037, 65.39004588297750331),
	new(5.6089682537873129, 65.26335043965949012),
	new(5.53019009655585414, 65.32111738273543722)
});
// factoryPoly: POLYGON ((5.5302 65.3211, 5.5965 65.39, 5.609 65.2634, 5.5302 65.3211))

Console.WriteLine($"wktPoly equals factoryPoly = {wktPoly.EqualsExact(factoryPoly)}"); // false

// Creating polygon by injecting factory via constructor
var constructorPoly = new Polygon(new LinearRing(new Coordinate[]
{
	new(5.53019009655585414, 65.32111738273543722),
	new(5.59648652009346037, 65.39004588297750331),
	new(5.6089682537873129, 65.26335043965949012),
	new(5.53019009655585414, 65.32111738273543722)
}), geometryFactory);
// constructorPoly: POLYGON ((5.5302 65.3211, 5.5965 65.39, 5.609 65.2634, 5.5302 65.3211))

Console.WriteLine($"wktPoly equals constructorPoly = {wktPoly.EqualsExact(constructorPoly)}"); // false
Console.WriteLine($"factoryPoly equals constructorPoly = {factoryPoly.EqualsExact(constructorPoly)}"); // true
@FObermaier
Copy link
Member

The PrecisionModel is only applied during I/O operations and when computing new coordinates during geometry operations. It is not applied at all to the coordinates passed to the `GeometryFactory.Create... methods.

You have to do that yourself.

@oyvindi
Copy link
Author

oyvindi commented Sep 19, 2022

Ok, makes sense.

However, still a bit confused about the output:

  • The WKT produced above via the factory geometry above, yields 4 decimals
  • When using the the default factory, it produces 14-15 decimals in this case

Example:

var factory2 = new GeometryFactory(); 
var ring = factory2.CreateLinearRing(new Coordinate[]
{
	new(5.53019009655585414, 65.32111738273543722),
	new(5.59648652009346037, 65.39004588297750331),
	new(5.6089682537873129, 65.26335043965949012),
	new(5.53019009655585414, 65.32111738273543722)
});
var factoryPoly =  factory2.CreatePolygon(ring);
// POLYGON ((5.530190096555854 65.32111738273544, 5.59648652009346 65.3900458829775, 5.608968253787313 65.26335043965949, 5.530190096555854 65.32111738273544))

So if it uses the custom precision model, it should have been 3 decimals.. and it's not using the default one either ?

@FObermaier
Copy link
Member

FObermaier commented Sep 20, 2022

The coordinates assigned to the geometries are not rounded to the precision model. You can verify that by checking factoryPoly.Coordinate or factoryPoly.Coordinates.
What you see when you call Geometry.ToText() or Geometry.AsText() is that the WKTWriter used internally uses the PrecisionModel of the GeometryFactory that created the geometry to print out the ordinate values.
There might be an issue with computing the PrecisionModel.MaximumSignificantDigits value used to determine the number of digits required to write the rounded value.

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

2 participants