// Copyright (C) Stichting Deltares 2025. All rights reserved.
//
// This file is part of the Dam Engine.
//
// The Dam Engine is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero 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 Deltares.DamEngine.Calculators.PlLinesCreator;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
using Deltares.DamEngine.Data.General.Sensors;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using NUnit.Framework;
namespace Deltares.DamEngine.Calculators.Tests.Sensors;
[TestFixture]
public class SensorPlLineCreatorTest
{
[Test]
public void CreatePlLine_Pl1NoSensorData_Throws()
{
// setup
var location = new Location("test");
SensorLocation sensorLocation = new SensorFactory().CreateSensorLocation(location);
var creator = SensorPlLineCreator.CreateInstance(sensorLocation, new Dictionary());
// call
Assert.That(() => creator.CreatePlLine(PlLineType.Pl1), Throws.InstanceOf());
}
[Test] // Pl2 is not yet supported
public void CreatePlLine_Pl2_ThrowsNotSupported()
{
// setup
var location = new Location("test");
SensorLocation sensorLocation = new SensorFactory().CreateSensorLocation(location);
var creator = SensorPlLineCreator.CreateInstance(sensorLocation, new Dictionary());
// call
Assert.That(() => creator.CreatePlLine(PlLineType.Pl2), Throws.InstanceOf());
}
[Test]
public void CreatePlLine_Pl3NoSensorData_Throws()
{
// setup
var location = new Location("test");
location.Scenarios.Add(new DesignScenario());
SensorLocation sensorLocation = new SensorFactory().CreateSensorLocation(location);
var creator = SensorPlLineCreator.CreateInstance(sensorLocation, new Dictionary());
// call
Assert.That(() => creator.CreatePlLine(PlLineType.Pl3), Throws.InstanceOf());
}
[Test]
public void CreatePlLine_Pl4NoSensorData_Throws()
{
// setup
var location = new Location("test");
location.Scenarios.Add(new DesignScenario());
SensorLocation sensorLocation = new SensorFactory().CreateSensorLocation(location);
var creator = SensorPlLineCreator.CreateInstance(sensorLocation, new Dictionary());
// call
Assert.That(() => creator.CreatePlLine(PlLineType.Pl4), Throws.InstanceOf());
}
[Test]
public void CreatePlLine_AllPlLinesDummyTest_ResultsAreAsExpected()
{
// setup
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 1, 1);
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.LocationData;
// create dike with ditch
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(85.0, 8.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(95.0, 8.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(108.0, 4.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(116.0, 3.0, CharacteristicPointType.ShoulderTopInside);
surfaceLine.EnsurePointOfType(121.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Test5",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var sensor6 = new Sensor
{
ID = 6,
Name = "Test6",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var sensor7 = new Sensor
{
ID = 7,
Name = "Test7",
Depth = 2,
RelativeLocation = 180,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
repository.Add(sensor5);
repository.Add(sensor6);
repository.Add(sensor7);
IDictionary sensorValues = new Dictionary
{
{
sensor1, 1
},
{
sensor2, 1
},
{
sensor3, 1
},
{
sensor4, 1
},
{
sensor5, 1
},
{
sensor6, 1
},
{
sensor7, 1
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
// call
PlLine actual = creator.CreatePlLine();
// asserts
// Number of expected points in line
int expectedCount = repository.Sensors.Count(s => s.PlLineMappings.Contains(PlLineType.Pl1)) + 2 + 4; // interection + end + 4 configured characteristic points
Assert.That(actual.Points.Count, Is.EqualTo(expectedCount));
// P1
PlLinePoint p1 = actual.Points.First();
Assert.That(p1, Is.Not.Null);
double expectedZValueP1 = sensorValues[sensor1];
Assert.That(p1.Z, Is.EqualTo(expectedZValueP1));
// P2
PlLinePoint p2 = actual.Points.FirstOrDefault(p => p.Name == sensor2.Name);
Assert.That(p2, Is.Not.Null);
Assert.That(p2.X, Is.EqualTo(sensor2.RelativeLocation));
double expectedZValueP2 = sensorValues[sensor2];
Assert.That(p2.Z, Is.EqualTo(expectedZValueP2));
// P3
PlLinePoint p3 = actual.Points.FirstOrDefault(p => p.Name == sensor3.Name);
Assert.That(p3, Is.Not.Null);
Assert.That(p3.X, Is.EqualTo(sensor3.RelativeLocation));
double expectedZValueP3 = sensorValues[sensor3];
Assert.That(p3.Z, Is.EqualTo(expectedZValueP3));
// P4
PlLinePoint p4 = actual.Points.FirstOrDefault(p => p.Name == sensor4.Name);
Assert.That(p4, Is.Not.Null);
Assert.That(p4.X, Is.EqualTo(sensor4.RelativeLocation));
double expectedZValueP4 = sensorValues[sensor4];
Assert.That(p4.Z, Is.EqualTo(expectedZValueP4));
}
[Test]
public void CreatePlLine_NoLocationDataAtPl1DikeToeAtPolderAndNoPolderSensor_HorizontalLineExpectedBetweenLastSensorValueAndSurfaceLevelInside()
{
// setup
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 5, -1);
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(85.0, 8.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(95.0, 8.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(108.0, 4.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(116.0, 3.0, CharacteristicPointType.ShoulderTopInside);
surfaceLine.EnsurePointOfType(121.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
const double sensor1Value = 1.1;
const double sensor2Value = 1.2;
const double sensor3Value = 1.3;
const double sensor4Value = 1.4;
IDictionary sensorValues = new Dictionary
{
{
sensor1, sensor1Value
},
{
sensor2, sensor2Value
},
{
sensor3, sensor3Value
},
{
sensor4, sensor4Value
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
// call
PlLine actual = creator.CreatePlLine();
// asserts
PlLinePoint lastPoint = actual.Points.Last();
Assert.That(actual.Points, Has.Count.EqualTo(9));
Assert.Multiple(() =>
{
Assert.That(actual.Points[0].X, Is.EqualTo(0));
Assert.That(actual.Points[0].Z, Is.EqualTo(5));
Assert.That(actual.Points[1].X, Is.EqualTo(71.875));
Assert.That(actual.Points[1].Z, Is.EqualTo(5));
Assert.That(actual.Points[2].X, Is.EqualTo(85));
Assert.That(actual.Points[2].Z, Is.EqualTo(4.5));
Assert.That(actual.Points[3].X, Is.EqualTo(90));
Assert.That(actual.Points[3].Z, Is.EqualTo(sensor2Value));
Assert.That(actual.Points[4].X, Is.EqualTo(95));
Assert.That(actual.Points[4].Z, Is.EqualTo(3.5));
Assert.That(actual.Points[5].X, Is.EqualTo(104));
Assert.That(actual.Points[5].Z, Is.EqualTo(sensor3Value));
Assert.That(actual.Points[6].X, Is.EqualTo(108));
Assert.That(actual.Points[6].Z, Is.EqualTo(3.9));
Assert.That(actual.Points[7].X, Is.EqualTo(123.3));
Assert.That(actual.Points[7].Z, Is.EqualTo(sensor4Value));
Assert.That(actual.Points[8].X, Is.EqualTo(190));
Assert.That(actual.Points[8].Z, Is.EqualTo(sensor4Value));
});
}
[Test]
public void GetDitchWaterLevelIntersectionAtXDikeSide_PolderLevelIntersectsInDitch_ShouldReturnIntersectionValue()
{
// setup
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
var location = new Location();
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(10, 0.0, CharacteristicPointType.DitchDikeSide);
surfaceLine.EnsurePointOfType(15, -5, CharacteristicPointType.BottomDitchDikeSide);
surfaceLine.EnsurePointOfType(17, -5, CharacteristicPointType.BottomDitchPolderSide);
surfaceLine.EnsurePointOfType(20, 0.0, CharacteristicPointType.DitchPolderSide);
surfaceLine.EnsurePointOfType(25, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.AddSensorLocation();
location.SurfaceLine = surfaceLine;
var creator = new SensorPlLine1Creator(location.SensorLocation, new Dictionary());
double? actual = creator.GetDitchWaterLevelIntersectionAtXDikeSide(-2.5);
const double expected = 12.5;
Assert.That(actual, Is.EqualTo(expected));
}
[Test]
public void CreatePlLine_Pl1IgnorAllSensors_ResultsAreAsExpected()
{
// setup
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 1, 1);
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
// Assert.IsTrue(location.SensorData.IsValid());
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(80.0, 5.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(125, 5.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(140.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(145.0, 0.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Test5",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var sensor6 = new Sensor
{
ID = 6,
Name = "Test6",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var sensor7 = new Sensor
{
ID = 7,
Name = "Test7",
Depth = 2,
RelativeLocation = 180,
PlLineMappings = new[]
{
PlLineType.Pl3,
PlLineType.Pl4
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
repository.Add(sensor5);
repository.Add(sensor6);
repository.Add(sensor7);
IDictionary sensorValues = new Dictionary
{
{
sensor1, 1
},
{
sensor2, 1
},
{
sensor3, 1
},
{
sensor4, 1
},
{
sensor5, 1
},
{
sensor6, 1
},
{
sensor7, 1
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
// call
PlLine actual = creator.CreatePlLine();
// asserts
// Number of expected points in PL 1
const int expectedNumberOfCharacteristicPoints = 1; // Surface line inside
int pl1SensorCount = repository.Sensors.Count(s => s.PlLineMappings.Contains(PlLineType.Pl1)) +
expectedNumberOfCharacteristicPoints + 1; // plus one for the intersection point
Assert.That(actual.Points, Has.Count.EqualTo(pl1SensorCount));
// P2
PlLinePoint p2 = actual.Points.FirstOrDefault(p => p.Name == sensor2.Name);
Assert.That(p2, Is.Not.Null);
Assert.That(p2.X, Is.EqualTo(sensor2.RelativeLocation));
double expectedZValueP2 = sensorValues[sensor2];
Assert.That(p2.Z, Is.EqualTo(expectedZValueP2));
// P3
PlLinePoint p3 = actual.Points.FirstOrDefault(p => p.Name == sensor3.Name);
Assert.That(p3, Is.Not.Null);
Assert.That(p3.X, Is.EqualTo(sensor3.RelativeLocation));
double expectedZValueP3 = sensorValues[sensor3];
Assert.That(p3.Z, Is.EqualTo(expectedZValueP3));
// P4
PlLinePoint p4 = actual.Points.FirstOrDefault(p => p.Name == sensor4.Name);
Assert.That(p4, Is.Not.Null);
Assert.That(p4.X, Is.EqualTo(sensor4.RelativeLocation));
double expectedZValueP4 = sensorValues[sensor4];
Assert.That(p4.Z, Is.EqualTo(expectedZValueP4));
}
[Test]
public void CreatePlLinePl1_DikeHasDitch_ResultsAreAsExpected()
{
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 1, 1);
#region Setup
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
// Assert.IsTrue(location.SensorData.IsValid());
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(80.0, 5.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(125, 5.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(140.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(148.0, 0.5, CharacteristicPointType.DitchDikeSide);
surfaceLine.EnsurePointOfType(150.0, -4.0, CharacteristicPointType.BottomDitchDikeSide);
surfaceLine.EnsurePointOfType(154.0, -4.0, CharacteristicPointType.BottomDitchPolderSide);
surfaceLine.EnsurePointOfType(158.0, 0.0, CharacteristicPointType.DitchPolderSide);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 128,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
IDictionary sensorValues = new Dictionary
{
{
sensor1, 3
},
{
sensor2, 3
},
{
sensor3, 3
},
{
sensor4, 3
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
#endregion
// call
PlLine actual = creator.CreatePlLine();
// asserts
// Number of expected points in line
int pl1SensorCount = repository.Sensors.Count(s => s.PlLineMappings.Contains(PlLineType.Pl1));
Assert.That(actual.Points.Count, Is.EqualTo(pl1SensorCount + 2));
// P2
PlLinePoint p2 = actual.Points.FirstOrDefault(p => p.Name == sensor2.Name);
Assert.That(p2, Is.Not.Null);
Assert.That(p2.X, Is.EqualTo(sensor2.RelativeLocation));
double expectedZValueP2 = sensorValues[sensor2];
Assert.That(p2.Z, Is.EqualTo(expectedZValueP2));
// P3
PlLinePoint p3 = actual.Points.FirstOrDefault(p => p.Name == sensor3.Name);
Assert.That(p3, Is.Not.Null);
Assert.That(p3.X, Is.EqualTo(sensor3.RelativeLocation));
double expectedZValueP3 = sensorValues[sensor3];
Assert.That(p3.Z, Is.EqualTo(expectedZValueP3));
// P4
PlLinePoint p4 = actual.Points.FirstOrDefault(p => p.Name == sensor4.Name);
Assert.That(p4, Is.Not.Null);
Assert.That(p4.X, Is.EqualTo(sensor4.RelativeLocation));
double expectedZValueP4 = sensorValues[sensor4];
Assert.That(p4.Z, Is.EqualTo(expectedZValueP4));
}
[Test]
public void CreatePlLine_DikeHasDitchAndSensor_DichLevelIsHorizontal()
{
const int polderLevel = 0;
const int waterLevel = 1;
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 1, polderLevel);
#region Setup
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.Ignore;
location.SensorLocation.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor;
location.SensorLocation.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.Sensor;
// Assert.IsTrue(location.SensorData.IsValid());
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(80.0, 5.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(125, 5.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(140.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(148.0, 0.5, CharacteristicPointType.DitchDikeSide);
surfaceLine.EnsurePointOfType(150.0, -4.0, CharacteristicPointType.BottomDitchDikeSide);
surfaceLine.EnsurePointOfType(154.0, -4.0, CharacteristicPointType.BottomDitchPolderSide);
surfaceLine.EnsurePointOfType(158.0, 0.0, CharacteristicPointType.DitchPolderSide);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 128,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Test5",
Depth = 2,
RelativeLocation = 152,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.PolderLevel
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
repository.Add(sensor5);
IDictionary sensorValues = new Dictionary
{
{
sensor1, waterLevel
},
{
sensor2, -1
},
{
sensor3, -1
},
{
sensor4, -1
},
{
sensor5, -1.5
}
};
SensorLocation sensorLocation = location.SensorLocation;
#endregion
// call
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
PlLine actual = creator.CreatePlLine();
// checks
double? xDitchDikeSide = creator.GetDitchWaterLevelIntersectionAtXDikeSide(sensorValues[sensor5]);
double? xDitchPolderSide = creator.GetDitchWaterLevelIntersectionAtXPolderSide(sensorValues[sensor5]);
Assert.That(actual.Points.Any(p => p.X == xDitchDikeSide), Is.True);
double zDitchDikeSide = actual.Points.Single(p => p.X == xDitchDikeSide).Z;
double zDitchPolderSide = actual.Points.Single(p => p.X == xDitchPolderSide).Z;
Assert.That(actual.Points.Any(p => p.X == xDitchPolderSide), Is.True);
Assert.That(zDitchPolderSide, Is.EqualTo(zDitchDikeSide));
PlLinePoint endPoint = actual.Points.Last();
// End point should be z of x intersection at dike side in ditch (horizontal)
Assert.That(zDitchDikeSide, Is.EqualTo(endPoint.Z));
}
[Test]
public void CreatePlLine_Pl3and4_FirstSegmentShouldBeHorizontalEqualToLocationData()
{
// setup
const double xDikeToeAtRiver = 50.0;
const double waterLevel = 1.0;
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", waterLevel, waterLevel);
{
location.AddSensorLocation();
location.SensorLocation.SourceTypePl3 = DataSourceTypeSensors.Sensor;
location.SensorLocation.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.LocationData;
location.SensorLocation.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
// Assert.IsTrue(location.SensorData.IsValid());
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(xDikeToeAtRiver, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(80.0, 5.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(125, 5.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(140.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(145.0, 0.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = waterLevel,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Test5",
Depth = -8,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var sensor6 = new Sensor
{
ID = 6,
Name = "Test6",
Depth = -8,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var sensor7 = new Sensor
{
ID = 7,
Name = "Test7",
Depth = -8,
RelativeLocation = 180,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor5);
repository.Add(sensor6);
repository.Add(sensor7);
IDictionary sensorValues = new Dictionary
{
{
sensor1, waterLevel
},
{
sensor5, waterLevel
},
{
sensor6, waterLevel
},
{
sensor7, waterLevel
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine3Creator(sensorLocation, sensorValues);
// call
PlLine actual = creator.CreatePlLine();
//checks
// start first segment
Assert.That(actual.Points[0].X, Is.EqualTo(-0.0));
Assert.That(actual.Points[0].Z, Is.EqualTo(waterLevel));
// end of first segment (ends at DikeToeAtRiver)
Assert.That(actual.Points[1].X, Is.EqualTo(xDikeToeAtRiver));
Assert.That(actual.Points[1].Z, Is.EqualTo(waterLevel));
}
}
[Test]
public void CreatePlLine_Pl3and4_FirstSegmentShouldBeHorizontalEqualToWaterLevelSensor()
{
// setup
const double xDikeToeAtRiver = 50.0;
const double waterLevel = -0.25;
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", 1, 1);
{
location.AddSensorLocation();
location.SensorLocation.SourceTypePl3 = DataSourceTypeSensors.Sensor;
location.SensorLocation.SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor;
location.SensorLocation.SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.Sensor;
// Assert.IsTrue(location.SensorData.IsValid());
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(xDikeToeAtRiver, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(80.0, 5.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(125, 5.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(140.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(145.0, 0.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = -0.25,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor5 = new Sensor
{
ID = 5,
Name = "Test5",
Depth = -8,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var sensor6 = new Sensor
{
ID = 6,
Name = "Test6",
Depth = -8,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var sensor7 = new Sensor
{
ID = 7,
Name = "Test7",
Depth = -8,
RelativeLocation = 180,
PlLineMappings = new[]
{
PlLineType.Pl3
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor5);
repository.Add(sensor6);
repository.Add(sensor7);
IDictionary sensorValues = new Dictionary
{
{
sensor1, waterLevel
},
{
sensor5, 1
},
{
sensor6, 1
},
{
sensor7, 1
}
};
SensorLocation sensorLocation = location.SensorLocation;
var creator = new SensorPlLine3Creator(sensorLocation, sensorValues);
// call
PlLine actual = creator.CreatePlLine();
//checks
// start first segment
Assert.That(actual.Points[0].X, Is.EqualTo(-0.0));
Assert.That(actual.Points[0].Z, Is.EqualTo(waterLevel));
// end of first segment (ends at DikeToeAtRiver)
Assert.That(actual.Points[1].X, Is.EqualTo(xDikeToeAtRiver));
Assert.That(actual.Points[1].Z, Is.EqualTo(waterLevel));
}
}
[TestCase(8.001)]
[TestCase(10.0)]
public void CreatePlLine_Pl1WithRiverLevelHigherThanDikeTopAtRiverSide_Throws(double riverLevel)
{
// setup
SetUpSensorData(riverLevel, out IDictionary sensorValues, out SensorLocation sensorLocation);
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
// call
Assert.That(() => creator.CreatePlLine(), Throws.TypeOf(typeof(SurfaceLineException)).With.Message.Contains("should NOT be higher than dike top at river side"));
}
[TestCase(-0.001)]
[TestCase(-10.0)]
public void CreatePlLine_Pl1WithRiverLevelBelowDikeToeAtRiver_DoesNotThrow(double riverLevel)
{
// setup
SetUpSensorData(riverLevel, out IDictionary sensorValues, out SensorLocation sensorLocation);
var creator = new SensorPlLine1Creator(sensorLocation, sensorValues);
// call
Assert.DoesNotThrow(() => creator.CreatePlLine());
}
private Location CreateConfiguredLocation(string name, double riverLevel, double polderLevel)
{
var location = new Location(name);
var scenario = new DesignScenario
{
PolderLevel = polderLevel,
RiverLevel = riverLevel
};
location.Scenarios.Add(scenario);
location.CurrentScenario = scenario;
return location;
}
private void SetUpSensorData(double riverLevel, out IDictionary sensorValues, out SensorLocation sensorLocation)
{
var surfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = true
},
Geometry = new GeometryPointString()
};
Location location = CreateConfiguredLocation("test", riverLevel, -1);
location.AddSensorLocation();
location.SensorLocation.SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.LocationData;
surfaceLine.EnsurePointOfType(0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(50.0, 0.0, CharacteristicPointType.DikeToeAtRiver);
surfaceLine.EnsurePointOfType(85.0, 8.0, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(95.0, 8.0, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(108.0, 4.0, CharacteristicPointType.ShoulderBaseInside);
surfaceLine.EnsurePointOfType(116.0, 3.0, CharacteristicPointType.ShoulderTopInside);
surfaceLine.EnsurePointOfType(121.0, 0.0, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(190.0, 0.0, CharacteristicPointType.SurfaceLevelInside);
location.SurfaceLine = surfaceLine;
var sensor1 = new Sensor
{
ID = 1,
Name = "Test1",
Depth = 2,
RelativeLocation = 50,
PlLineMappings = new[]
{
PlLineType.Pl1
},
SensorType = SensorType.WaterLevel
};
var sensor2 = new Sensor
{
ID = 2,
Name = "Test2",
Depth = 2,
RelativeLocation = 90,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor3 = new Sensor
{
ID = 3,
Name = "Test3",
Depth = 2,
RelativeLocation = 104,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var sensor4 = new Sensor
{
ID = 4,
Name = "Test4",
Depth = 2,
RelativeLocation = 123.3,
PlLineMappings = new[]
{
PlLineType.Pl1
}
};
var repository = new SensorRepository(location);
repository.Add(sensor1);
repository.Add(sensor2);
repository.Add(sensor3);
repository.Add(sensor4);
sensorValues = new Dictionary
{
{
sensor1, 1
},
{
sensor2, 1
},
{
sensor3, 1
},
{
sensor4, 1
}
};
sensorLocation = location.SensorLocation;
}
#region Setup
[SetUp]
public void FixtureSetup() {}
[TearDown]
public void FixtureTearDown() {}
[SetUp]
public void TestSetup() {}
[TearDown]
public void TestTearDown() {}
#endregion
}