// Copyright (C) Stichting Deltares 2019. All rights reserved. // // This file is part of Riskeer. // // Riskeer is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Linq; using Core.Components.DotSpatial.Projections; using DotSpatial.Data; using DotSpatial.Projections; using GeoAPI.Geometries; using NetTopologySuite.Geometries; using NUnit.Framework; namespace Core.Components.DotSpatial.Test.Projections { [TestFixture] public class ReprojectExtensionsTest { [Test] public void Reproject_LinearRingNull_ThrowArgumentNullException() { // Setup ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; ILinearRing linearRing = null; // Call TestDelegate call = () => linearRing.Reproject(projection, projection); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("ring", paramName); } [Test] public void Reproject_ForLinearRingWithSourceProjectionNull_ThrowArgumentNullException() { // Setup var p1 = new Coordinate(0.0, 0.0); var p2 = new Coordinate(1.1, 1.1); var linearRing = new LinearRing(new[] { p1, p2, p2, p1 }); ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call TestDelegate call = () => linearRing.Reproject(null, projection); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("source", paramName); } [Test] public void Reproject_ForLinearRingWithTargetProjectionNull_ThrowArgumentNullException() { // Setup var p1 = new Coordinate(0.0, 0.0); var p2 = new Coordinate(1.1, 1.1); var linearRing = new LinearRing(new[] { p1, p2, p2, p1 }); ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call TestDelegate call = () => linearRing.Reproject(projection, null); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("target", paramName); } [Test] public void Reproject_ForLinearRingWithTargetAndSourceTheSameCoordinateSystem_DensifiedLinearRing() { // Setup var p1 = new Coordinate(0.0, 0.0); var p2 = new Coordinate(1.1, 1.1); var p3 = new Coordinate(2.2, 0.0); Coordinate[] triangleCoordinates = { p1, p2, p3, p1 }; var ring = new LinearRing(triangleCoordinates); ProjectionInfo sourceProjection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call ILinearRing reprojectedRing = ring.Reproject(sourceProjection, sourceProjection); // Assert const int numberOfEdges = 3; const int expectedNumberOfExtraPoints = 35; Assert.AreEqual(numberOfEdges * expectedNumberOfExtraPoints + numberOfEdges + 1, reprojectedRing.Coordinates.Length); const double allowedError = 1e-6; // Allow small drift in reprojecting to same coordinate system. const int expectedP1Index = 0; const int expectedP2Index = expectedNumberOfExtraPoints + 1; const int expectedP3Index = 2 * (expectedNumberOfExtraPoints + 1); const int expectedP1RepeatIndex = 3 * (expectedNumberOfExtraPoints + 1); AssertCoordinatesAreEqual(p1, reprojectedRing.Coordinates[expectedP1Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p1, p2, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP1Index + 1, expectedP2Index - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p2, reprojectedRing.Coordinates[expectedP2Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p2, p3, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP2Index + 1, expectedP3Index - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p3, reprojectedRing.Coordinates[expectedP3Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p3, p1, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP3Index + 1, expectedP1RepeatIndex - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p1, reprojectedRing.Coordinates[expectedP1RepeatIndex], allowedError); } [Test] public void Reproject_ForLinearRingWithDifferentCoordinateSystem_DensifiedAndReprojectedLinearRing() { // Setup var p1 = new Coordinate(0.0, 0.0); var p2 = new Coordinate(1.1, 1.1); var p3 = new Coordinate(2.2, 0.0); Coordinate[] triangleCoordinates = { p1, p2, p3, p1 }; var ring = new LinearRing(triangleCoordinates); ProjectionInfo sourceProjection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; ProjectionInfo targetProjection = KnownCoordinateSystems.Projected.World.WebMercator; // Call ILinearRing reprojectedRing = ring.Reproject(sourceProjection, targetProjection); // Assert const int numberOfEdges = 3; const int expectedNumberOfExtraPoints = 35; Assert.AreEqual(numberOfEdges * expectedNumberOfExtraPoints + numberOfEdges + 1, reprojectedRing.Coordinates.Length); const double allowedError = 1e-6; const int expectedP1Index = 0; const int expectedP2Index = expectedNumberOfExtraPoints + 1; const int expectedP3Index = 2 * (expectedNumberOfExtraPoints + 1); const int expectedP1RepeatIndex = 3 * (expectedNumberOfExtraPoints + 1); // Note: Very rough estimates can be gotten from https://epsg.io/transform#s_srs=28992&t_srs=900913 // Use them as sanity checks for the values below. AssertCoordinatesAreEqual(new Coordinate(368882.53051896818, 6102740.2091378355), reprojectedRing.Coordinates[expectedP1Index], allowedError); AssertCoordinatesAreEqual(new Coordinate(368884.12244735827, 6102741.8971153079), reprojectedRing.Coordinates[expectedP2Index], allowedError); AssertCoordinatesAreEqual(new Coordinate(368885.80535674578, 6102740.3003927628), reprojectedRing.Coordinates[expectedP3Index], allowedError); AssertCoordinatesAreEqual(reprojectedRing.Coordinates[expectedP1Index], reprojectedRing.Coordinates[expectedP1RepeatIndex], allowedError); } [Test] public void Reproject_ForLinearRingWithTargetCoordinateSystemWithoutTransform_ReturnDesifiedLinearRing() { // Setup var p1 = new Coordinate(0.0, 0.0); var p2 = new Coordinate(1.1, 1.1); var p3 = new Coordinate(2.2, 0.0); Coordinate[] triangleCoordinates = { p1, p2, p3, p1 }; var ring = new LinearRing(triangleCoordinates); ProjectionInfo sourceProjection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; var targetProjection = new ProjectionInfo(); targetProjection.CopyProperties(sourceProjection); targetProjection.Transform = null; // Call ILinearRing reprojectedRing = ring.Reproject(sourceProjection, sourceProjection); // Assert const int numberOfEdges = 3; const int expectedNumberOfExtraPoints = 35; Assert.AreEqual(numberOfEdges * expectedNumberOfExtraPoints + numberOfEdges + 1, reprojectedRing.Coordinates.Length); const double allowedError = 1e-6; // Allow small drift in reprojecting to same coordinate system. const int expectedP1Index = 0; const int expectedP2Index = expectedNumberOfExtraPoints + 1; const int expectedP3Index = 2 * (expectedNumberOfExtraPoints + 1); const int expectedP1RepeatIndex = 3 * (expectedNumberOfExtraPoints + 1); AssertCoordinatesAreEqual(p1, reprojectedRing.Coordinates[expectedP1Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p1, p2, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP1Index + 1, expectedP2Index - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p2, reprojectedRing.Coordinates[expectedP2Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p2, p3, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP2Index + 1, expectedP3Index - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p3, reprojectedRing.Coordinates[expectedP3Index], allowedError); AssertCoordinatesAreEqual(GetExpectedExtraDesificationCoordinates(p3, p1, expectedNumberOfExtraPoints).ToArray(), TakeElementsFromTo(reprojectedRing.Coordinates, expectedP3Index + 1, expectedP1RepeatIndex - 1).ToArray(), allowedError); AssertCoordinatesAreEqual(p1, reprojectedRing.Coordinates[expectedP1RepeatIndex], allowedError); } [Test] public void Reproject_ForNullExtent_ThrowArgumentNullException() { // Setup Extent extent = null; ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call TestDelegate call = () => extent.Reproject(projection, projection); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("extent", paramName); } [Test] public void Reproject_ForExtentWithSourceProjectionNull_ThrowArgumentNullException() { // Setup var extent = new Extent(); ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call TestDelegate call = () => extent.Reproject(null, projection); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("source", paramName); } [Test] public void Reproject_ForExtentWithTargetProjectionNull_ThrowArgumentNullException() { // Setup var extent = new Extent(); ProjectionInfo projection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call TestDelegate call = () => extent.Reproject(projection, null); // Assert string paramName = Assert.Throws(call).ParamName; Assert.AreEqual("target", paramName); } [Test] public void Reproject_ForExtentWithTargetAndSourceTheSameCoordinateSystem_ReturnEqualExtent() { // Setup var extent = new Extent(1.1, 2.2, 3.3, 4.4); ProjectionInfo sourceProjection = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; // Call Extent result = extent.Reproject(sourceProjection, sourceProjection); // Assert AssertExtentAreEqual(extent, result, 1e-6); } [Test] public void Reproject_ForExtentWithDifferentCoordinateSystems_ReturnReprojectedExtent() { // Setup var extent = new Extent(1.1, 2.2, 3.3, 4.4); ProjectionInfo source = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; ProjectionInfo targetProjection = KnownCoordinateSystems.Projected.World.WebMercator; // Call Extent result = extent.Reproject(source, targetProjection); // Assert var expectedExtent = new Extent(368883.9859757676, 6102743.5394654693, 368887.35179595748, 6102746.9154212056); AssertExtentAreEqual(expectedExtent, result, 1e-6); } [Test] public void Reproject_ForExtentWithTargetProjectionWithoutTransform_ReturnEqualExtent() { // Setup var extent = new Extent(1.1, 2.2, 3.3, 4.4); ProjectionInfo source = KnownCoordinateSystems.Projected.NationalGrids.Rijksdriehoekstelsel; var targetProjection = new ProjectionInfo(); targetProjection.CopyProperties(KnownCoordinateSystems.Projected.World.WebMercator); targetProjection.Transform = null; // Call Extent result = extent.Reproject(source, targetProjection); // Assert AssertExtentAreEqual(extent, result, 1e-6); } private void AssertExtentAreEqual(Extent expected, Extent actual, double delta) { Assert.AreEqual(expected.MinX, actual.MinX, delta); Assert.AreEqual(expected.MinY, actual.MinY, delta); Assert.AreEqual(expected.MaxX, actual.MaxX, delta); Assert.AreEqual(expected.MaxY, actual.MaxY, delta); } private static IEnumerable TakeElementsFromTo(IEnumerable coordinates, int fromIndex, int toIndex) { return coordinates.Skip(fromIndex).Take(toIndex - fromIndex + 1); } private void AssertCoordinatesAreEqual(Coordinate expected, Coordinate actual, double delta) { Assert.AreEqual(expected.X, actual.X, delta); Assert.AreEqual(expected.Y, actual.Y, delta); } private void AssertCoordinatesAreEqual(IList expectedCoordinates, IList actualCoordinates, double delta) { Assert.AreEqual(expectedCoordinates.Count, actualCoordinates.Count); for (var i = 0; i < expectedCoordinates.Count; i++) { AssertCoordinatesAreEqual(expectedCoordinates[i], actualCoordinates[i], delta); } } private IEnumerable GetExpectedExtraDesificationCoordinates(Coordinate start, Coordinate end, int expectedNumberOfAdditionalPoints) { double dx = (end.X - start.X) / (expectedNumberOfAdditionalPoints + 1); double dy = (end.Y - start.Y) / (expectedNumberOfAdditionalPoints + 1); for (var i = 1; i <= expectedNumberOfAdditionalPoints; i++) { yield return new Coordinate(start.X + i * dx, start.Y + i * dy); } } } }