Index: Core/Common/src/Core.Common.Base/Core.Common.Base.csproj
===================================================================
diff -u -r07f3d67fe9512b3c8303ff09398b0a234900d546 -r2fd427d95bfd8c000da089fedcf7b2fe2ca592e2
--- Core/Common/src/Core.Common.Base/Core.Common.Base.csproj (.../Core.Common.Base.csproj) (revision 07f3d67fe9512b3c8303ff09398b0a234900d546)
+++ Core/Common/src/Core.Common.Base/Core.Common.Base.csproj (.../Core.Common.Base.csproj) (revision 2fd427d95bfd8c000da089fedcf7b2fe2ca592e2)
@@ -102,6 +102,7 @@
+
Index: Core/Common/src/Core.Common.Base/Geometry/Segment2DCollectionExtensions.cs
===================================================================
diff -u
--- Core/Common/src/Core.Common.Base/Geometry/Segment2DCollectionExtensions.cs (revision 0)
+++ Core/Common/src/Core.Common.Base/Geometry/Segment2DCollectionExtensions.cs (revision 2fd427d95bfd8c000da089fedcf7b2fe2ca592e2)
@@ -0,0 +1,75 @@
+// Copyright (C) Stichting Deltares 2017. 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 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;
+
+namespace Core.Common.Base.Geometry
+{
+ ///
+ /// Extension methods for collections of .
+ ///
+ public static class Segment2DCollectionExtensions
+ {
+ ///
+ /// Interpolates the segments on .
+ ///
+ /// The segments to interpolate on.
+ /// The x value to use for interpolation.
+ /// The interpolated y value of the segment that is closest to
+ /// or when no interpolation was found.
+ /// Thrown when is null.
+ public static double Interpolate(this IEnumerable segments, double x)
+ {
+ if (segments == null)
+ {
+ throw new ArgumentNullException(nameof(segments));
+ }
+
+ Segment2D segment = segments.LastOrDefault(s => s.FirstPoint.X <= x) ?? segments.First();
+
+ return Interpolate(segment, x);
+ }
+
+ ///
+ /// Interpolates the segment on .
+ ///
+ /// The segment to interpolate on.
+ /// The x value to use for interpolation.
+ /// The interpolated y value of the or
+ /// when no interpolation was found.
+ private static double Interpolate(Segment2D segment, double x)
+ {
+ double differenceInX = segment.SecondPoint.X - segment.FirstPoint.X;
+ if (Math.Abs(differenceInX) < 1e-6)
+ {
+ return double.NaN;
+ }
+
+ double m = (segment.SecondPoint.Y - segment.FirstPoint.Y) / differenceInX;
+
+ double b = segment.FirstPoint.Y - (m * segment.FirstPoint.X);
+
+ return m * x + b;
+ }
+ }
+}
\ No newline at end of file
Index: Core/Common/test/Core.Common.Base.Test/Core.Common.Base.Test.csproj
===================================================================
diff -u -r354316fca628a0f9dcdee5ff156ae4d87e662677 -r2fd427d95bfd8c000da089fedcf7b2fe2ca592e2
--- Core/Common/test/Core.Common.Base.Test/Core.Common.Base.Test.csproj (.../Core.Common.Base.Test.csproj) (revision 354316fca628a0f9dcdee5ff156ae4d87e662677)
+++ Core/Common/test/Core.Common.Base.Test/Core.Common.Base.Test.csproj (.../Core.Common.Base.Test.csproj) (revision 2fd427d95bfd8c000da089fedcf7b2fe2ca592e2)
@@ -93,6 +93,7 @@
+
Index: Core/Common/test/Core.Common.Base.Test/Geometry/Segment2DCollectionExtensionsTest.cs
===================================================================
diff -u
--- Core/Common/test/Core.Common.Base.Test/Geometry/Segment2DCollectionExtensionsTest.cs (revision 0)
+++ Core/Common/test/Core.Common.Base.Test/Geometry/Segment2DCollectionExtensionsTest.cs (revision 2fd427d95bfd8c000da089fedcf7b2fe2ca592e2)
@@ -0,0 +1,147 @@
+// Copyright (C) Stichting Deltares 2017. 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 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 Core.Common.Base.Geometry;
+using NUnit.Framework;
+
+namespace Core.Common.Base.Test.Geometry
+{
+ [TestFixture]
+ public class Segment2DCollectionExtensionsTest
+ {
+ [Test]
+ public void Interpolate_SegmentsNull_ThrowsArgumentNullException()
+ {
+ // Call
+ TestDelegate test = () => ((IEnumerable) null).Interpolate(0);
+
+ // Assert
+ var exception = Assert.Throws(test);
+ Assert.AreEqual("segments", exception.ParamName);
+ }
+
+ [Test]
+ [TestCaseSource(nameof(ValidInterpolation))]
+ public void Interpolate_ValidArguments_ReturnsExpectedResult(IEnumerable segments,
+ double interpolateOnX,
+ double expectedY)
+ {
+ // Call
+ double actualY = segments.Interpolate(interpolateOnX);
+
+ // Assert
+ Assert.AreEqual(expectedY, actualY);
+ }
+
+ [Test]
+ [TestCaseSource(nameof(InvalidInterpolation))]
+ public void Interpolate_InvalidArguments_ReturnsNaN(IEnumerable segments,
+ double interpolateOnX)
+ {
+ // Call
+ double actualY = segments.Interpolate(interpolateOnX);
+
+ // Assert
+ Assert.IsNaN(actualY);
+ }
+
+ private static IEnumerable ValidInterpolation()
+ {
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(-1000, 0), new Point2D(1, 1)),
+ new Segment2D(new Point2D(1, 1), new Point2D(10, 10)),
+ new Segment2D(new Point2D(100, 100), new Point2D(1000, 10))
+ }, 20, 20).SetName("Slope = 1, b = 0 with other segments");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 10), new Point2D(10, 100))
+ }, 0, 10).SetName("Same as first point that passed through origin");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 10), new Point2D(10, 100))
+ }, -10, -80).SetName("Left of first point");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(1, 10), new Point2D(10, 100))
+ }, 1, 10).SetName("Same as first point");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(1, 10), new Point2D(10, 100))
+ }, 10, 100).SetName("Same as second point");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 10), new Point2D(10, 10)),
+ new Segment2D(new Point2D(10, 10), new Point2D(20, 100))
+ }, 30, 190).SetName("Right of last point");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(1, 1), new Point2D(10, 10))
+ }, 5, 5).SetName("Slope = 1, b = 0");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 0), new Point2D(10, 1000))
+ }, 5, 500).SetName("Slope = 100, b = 0");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 0), new Point2D(-5, -9))
+ }, 5, (9.0 / 5.0) * 5).SetName("Slope = 9/5, b = 0");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(5, 2), new Point2D(90, 3))
+ }, 50, ((1 / 85.0) * 50) + (33 / 17.0)).SetName("Slope = 1/85, b = 33/17");
+ }
+
+ private static IEnumerable InvalidInterpolation()
+ {
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 10), new Point2D(0, 10))
+ }, 0).SetName("Vertical line");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 0), new Point2D(double.PositiveInfinity, double.PositiveInfinity))
+ }, 20).SetName("PositiveInfinity");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 0), new Point2D(double.NegativeInfinity, double.NegativeInfinity))
+ }, 20).SetName("NegativeInfinity");
+
+ yield return new TestCaseData(new[]
+ {
+ new Segment2D(new Point2D(0, 0), new Point2D(double.NaN, double.NaN))
+ }, 20).SetName("NaN");
+ }
+ }
+}
\ No newline at end of file