// Copyright (C) Stichting Deltares 2016. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU 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.Common.Base.Data;
using Core.Common.Base.Geometry;
using Core.Common.Base.Storage;
using Core.Common.TestUtil;
using NUnit.Framework;
using Ringtoets.Piping.Data.Properties;
using Ringtoets.Piping.Primitives;
using Ringtoets.Piping.Primitives.Exceptions;
using PipingPrimitivesResources = Ringtoets.Piping.Primitives.Properties.Resources;
namespace Ringtoets.Piping.Data.Test
{
[TestFixture]
public class RingtoetsPipingSurfaceLineTest
{
[Test]
public void DefaultConstructor_ExpectedValues()
{
// Call
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Assert
Assert.IsInstanceOf(surfaceLine);
Assert.AreEqual(String.Empty, surfaceLine.Name);
CollectionAssert.IsEmpty(surfaceLine.Points);
Assert.IsNull(surfaceLine.StartingWorldPoint);
Assert.IsNull(surfaceLine.EndingWorldPoint);
Assert.IsNull(surfaceLine.ReferenceLineIntersectionWorldPoint);
Assert.AreEqual(0, surfaceLine.StorageId);
}
[Test]
public void ReferenceLineIntersectionWorldPoint_SetNewValue_GetNewlySetValue()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
var point = new Point2D(1.2, 3.4);
// Call
surfaceLine.ReferenceLineIntersectionWorldPoint = point;
// Assert
Assert.AreEqual(point, surfaceLine.ReferenceLineIntersectionWorldPoint);
}
[Test]
public void SetGeometry_EmptyCollection_PointsSetEmptyAndNullStartAndEndWorldPoints()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
var sourceData = Enumerable.Empty();
// Call
surfaceLine.SetGeometry(sourceData);
// Assert
CollectionAssert.IsEmpty(surfaceLine.Points);
Assert.IsNull(surfaceLine.StartingWorldPoint);
Assert.IsNull(surfaceLine.EndingWorldPoint);
}
[Test]
public void SetGeometry_CollectionOfOnePoint_InitializeStartAndEndWorldPointsToSameInstanceAndInitializePoints()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
var sourceData = new[]
{
new Point3D(1.1, 2.2, 3.3)
};
// Call
surfaceLine.SetGeometry(sourceData);
// Assert
Assert.AreNotSame(sourceData, surfaceLine.Points);
CollectionAssert.AreEqual(sourceData, surfaceLine.Points);
Assert.AreSame(sourceData[0], surfaceLine.StartingWorldPoint);
Assert.AreSame(sourceData[0], surfaceLine.EndingWorldPoint);
}
[Test]
public void SetGeometry_CollectionOfMultiplePoints_InitializeStartAndEndWorldPointsInitializePoints()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
var sourceData = new[]
{
new Point3D(1.1, 2.2, 3.3),
new Point3D(4.4, 5.5, 6.6),
new Point3D(7.7, 8.8, 9.9),
new Point3D(10.10, 11.11, 12.12),
};
// Call
surfaceLine.SetGeometry(sourceData);
// Assert
Assert.AreNotSame(sourceData, surfaceLine.Points);
CollectionAssert.AreEqual(sourceData, surfaceLine.Points);
Assert.AreSame(sourceData[0], surfaceLine.StartingWorldPoint);
Assert.AreSame(sourceData[3], surfaceLine.EndingWorldPoint);
}
[Test]
public void ProjectGeometryToLZ_EmptyCollection_ReturnEmptyCollection()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
RoundedPoint2DCollection lzCoordinates = surfaceLine.ProjectGeometryToLZ();
// Assert
CollectionAssert.IsEmpty(lzCoordinates);
Assert.AreEqual(2, lzCoordinates.NumberOfDecimalPlaces);
}
[Test]
public void ProjectGeometryToLZ_GeometryWithOnePoint_ReturnSinglePointAtZeroXAndOriginalZ()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
const double originalZ = 3.3;
surfaceLine.SetGeometry(new[]
{
new Point3D(1.1, 2.2, originalZ)
});
// Call
RoundedPoint2DCollection lzCoordinates = surfaceLine.ProjectGeometryToLZ();
// Assert
CollectionAssert.AreEqual(new[]
{
new Point2D(0.0, originalZ)
}, lzCoordinates);
Assert.AreEqual(2, lzCoordinates.NumberOfDecimalPlaces);
}
[Test]
public void ProjectGeometryToLZ_GeometryWithMultiplePoints_ProjectPointsOntoLzPlaneKeepingOriginalZ()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
surfaceLine.SetGeometry(new[]
{
new Point3D(1.0, 1.0, 2.2),
new Point3D(2.0, 3.0, 4.4), // Outlier from line specified by extrema
new Point3D(3.0, 4.0, 7.7)
});
// Call
RoundedPoint2DCollection actual = surfaceLine.ProjectGeometryToLZ();
// Assert
var length = Math.Sqrt(2*2 + 3*3);
const double secondCoordinateFactor = (2.0*1.0 + 3.0*2.0)/(2.0*2.0 + 3.0*3.0);
var expectedCoordinatesX = new[]
{
0.0,
secondCoordinateFactor*length,
length
};
CollectionAssert.AreEqual(expectedCoordinatesX, actual.Select(p => p.X).ToArray(), new DoubleWithToleranceComparer(Math.Pow(10.0, -actual.NumberOfDecimalPlaces)));
CollectionAssert.AreEqual(surfaceLine.Points.Select(p => p.Z).ToArray(), actual.Select(p => p.Y).ToArray());
Assert.AreEqual(2, actual.NumberOfDecimalPlaces);
}
[Test]
public void SetGeometry_GeometryIsNull_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetGeometry(null);
// Assert
var exception = Assert.Throws(test);
StringAssert.StartsWith(PipingPrimitivesResources.RingtoetsPipingSurfaceLine_Collection_of_points_for_geometry_is_null, exception.Message);
}
[Test]
public void SetGeometry_GeometryContainsNullPoint_ThrowsArgumentException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetGeometry(new Point3D[]
{
null
});
// Assert
var exception = Assert.Throws(test);
StringAssert.StartsWith(PipingPrimitivesResources.RingtoetsPipingSurfaceLine_A_point_in_the_collection_was_null, exception.Message);
}
[Test]
public void GetZAtL_GeometryIsEmpty_ThrowInvalidOperationException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
var l = new Random(21).NextDouble();
// Call
TestDelegate test = () => surfaceLine.GetZAtL(l);
// Assert
var exceptionMessage = Assert.Throws(test).Message;
Assert.AreEqual(PipingPrimitivesResources.RingtoetsPipingSurfaceLine_SurfaceLine_has_no_Geometry, exceptionMessage);
}
[Test]
public void GetZAtL_SurfaceLineContainsPointAtL_ReturnsZOfPoint()
{
// Setup
var testZ = new Random(22).NextDouble();
var surfaceLine = new RingtoetsPipingSurfaceLine();
var l = 2.0;
surfaceLine.SetGeometry(new[]
{
new Point3D(0.0, 0.0, 2.2),
new Point3D(l, 0.0, testZ),
new Point3D(3.0, 0.0, 7.7)
});
// Call
var result = surfaceLine.GetZAtL(l);
// Assert
Assert.AreEqual(testZ, result, 1e-2);
}
[Test]
[TestCase(-1)]
[TestCase(-1e-6)]
[TestCase(3.1 + 1e-6)]
[TestCase(4.0)]
public void GetZAtL_SurfaceLineDoesNotContainsPointAtL_ThrowsArgumentOutOfRange(double l)
{
// Setup
var testZ = new Random(22).NextDouble();
var surfaceLine = new RingtoetsPipingSurfaceLine();
surfaceLine.SetGeometry(new[]
{
new Point3D(1.0, 0.0, 2.2),
new Point3D(2.0, 0.0, testZ),
new Point3D(4.1, 0.0, 7.7)
});
// Call
TestDelegate test = () => surfaceLine.GetZAtL(l);
// Assert
var expectedMessage = string.Format("Kan geen hoogte bepalen. De lokale coördinaat moet in het bereik [{0}, {1}] liggen.",
0, 3.1);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, expectedMessage);
}
[Test]
public void GetZAtL_SurfaceLineVerticalAtL_ThrowsRingtoetsPipingSurfaceLineException()
{
// Setup
var testZ = new Random(22).NextDouble();
var surfaceLine = new RingtoetsPipingSurfaceLine();
var l = 2.0;
surfaceLine.SetGeometry(new[]
{
new Point3D(0.0, 0.0, 2.2),
new Point3D(l, 0.0, testZ),
new Point3D(l, 0.0, testZ + 1),
new Point3D(3.0, 0.0, 7.7)
});
// Call
TestDelegate test = () => surfaceLine.GetZAtL(l);
// Assert
var exception = Assert.Throws(test);
var message = string.Format(PipingPrimitivesResources.RingtoetsPipingSurfaceLine_Cannot_determine_reliable_z_when_surface_line_is_vertical_in_l, l);
Assert.AreEqual(message, exception.Message);
}
[Test]
public void ToString_ReturnName()
{
// Setup
const string niceName = "Nice name";
var surfaceLine = new RingtoetsPipingSurfaceLine
{
Name = niceName
};
// Call
var text = surfaceLine.ToString();
// Assert
Assert.AreEqual(niceName, text);
}
[Test]
public void SetDitchPolderSideAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetDitchPolderSideAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.DitchPolderSide);
Assert.AreNotSame(testPoint, surfaceLine.DitchPolderSide);
}
[Test]
public void SetDitchPolderSideAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDitchPolderSideAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_DitchPolderSide);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetDitchPolderSideAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDitchPolderSideAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void SetBottomDitchPolderSideAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetBottomDitchPolderSideAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.BottomDitchPolderSide);
Assert.AreNotSame(testPoint, surfaceLine.BottomDitchPolderSide);
}
[Test]
public void SetBottomDitchPolderSideAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetBottomDitchPolderSideAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_BottomDitchPolderSide);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetBottomDitchPolderSideAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetBottomDitchPolderSideAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void SetBottomDitchDikeSideAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetBottomDitchDikeSideAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.BottomDitchDikeSide);
Assert.AreNotSame(testPoint, surfaceLine.BottomDitchDikeSide);
}
[Test]
public void SetBottomDitchDikeSideAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetBottomDitchDikeSideAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_BottomDitchDikeSide);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetBottomDitchDikeSideAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetBottomDitchDikeSideAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void SetDitchDikeSideAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetDitchDikeSideAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.DitchDikeSide);
Assert.AreNotSame(testPoint, surfaceLine.DitchDikeSide);
}
[Test]
public void SetDitchDikeSideAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDitchDikeSideAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_DitchDikeSide);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetDitchDikeSideAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDitchDikeSideAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void SetDikeToeAtRiverAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetDikeToeAtRiverAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.DikeToeAtRiver);
Assert.AreNotSame(testPoint, surfaceLine.DikeToeAtRiver);
}
[Test]
public void SetDikeToeAtRiverAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDikeToeAtRiverAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_DikeToeAtRiver);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetDikeToeAtRiverAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDikeToeAtRiverAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void SetDikeToeAtPolderAt_PointInGeometry_PointSetFromGeometry()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
surfaceLine.SetDikeToeAtPolderAt(testPoint);
// Assert
Assert.AreEqual(testPoint, surfaceLine.DikeToeAtPolder);
Assert.AreNotSame(testPoint, surfaceLine.DikeToeAtPolder);
}
[Test]
public void SetDikeToeAtPolderAt_GeometryEmpty_ThrowsInvalidOperationException()
{
// Setup
var random = new Random(21);
Point3D testPoint = new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDikeToeAtPolderAt(testPoint);
// Assert
var message = string.Format(Resources.RingtoetsPipingSurfaceLine_SetCharacteristicPointAt_Geometry_does_not_contain_point_at_0_to_assign_as_characteristic_point_1_,
testPoint, Resources.CharacteristicPoint_DikeToeAtPolder);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message);
}
[Test]
public void SetDikeToeAtPolderAt_Null_ThrowsArgumentNullException()
{
// Setup
var surfaceLine = new RingtoetsPipingSurfaceLine();
// Call
TestDelegate test = () => surfaceLine.SetDikeToeAtPolderAt(null);
// Assert
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, "Cannot find a point in geometry using a null point.");
}
[Test]
public void ValidateInRange_PointNotInRange_ThrowsArgumentOutOfRangeException()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
TestDelegate call = () => surfaceLine.ValidateInRange(5.0, surfaceLine.ProjectGeometryToLZ().ToArray());
// Assert
var expectedMessage = string.Format("Kan geen hoogte bepalen. De lokale coördinaat moet in het bereik [{0}, {1}] liggen.", 0, 1.37);
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, expectedMessage);
}
[Test]
public void ValidateInRange_PointInRange_DoesNotThrow()
{
// Setup
var testX = 1.0;
var testY = 2.2;
var testZ = 4.4;
Point3D testPoint = new Point3D(testX, testY, testZ);
var surfaceLine = new RingtoetsPipingSurfaceLine();
CreateTestGeometry(testPoint, surfaceLine);
// Call
TestDelegate call = () => surfaceLine.ValidateInRange(1.12, surfaceLine.ProjectGeometryToLZ().ToArray());
// Assert
Assert.DoesNotThrow(call);
}
private static void CreateTestGeometry(Point3D testPoint, RingtoetsPipingSurfaceLine surfaceLine)
{
var random = new Random(21);
var points = new[]
{
new Point3D(random.NextDouble(), random.NextDouble(), random.NextDouble()),
new Point3D(testPoint.X, testPoint.Y, testPoint.Z),
new Point3D(2 + random.NextDouble(), random.NextDouble(), random.NextDouble())
};
surfaceLine.SetGeometry(points);
}
}
}