using System; using System.Collections.Generic; using System.Linq; using Deltares.Dam.Data.Sensors.Specifications; using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.SurfaceLines; using Deltares.Standard.Application; using Deltares.Standard.Specifications.Extensions; namespace Deltares.Dam.Data.Sensors { internal abstract class SensorPLLineCreatorBase : IPLLineCreator { internal readonly static LogHelper Logger = LogHelper.Create(); protected SensorLocation SensorLocation; protected readonly IDictionary SensorValues; /// /// Initializes a new instance of the class. /// /// The sensor location. /// The type. /// The sensor values. protected SensorPLLineCreatorBase(SensorLocation sensorLocation, PLLineType type, IDictionary sensorValues) { SensorLocation = sensorLocation; SensorValues = sensorValues; PLLineType = type; } /// /// Gets the water level sensor. /// public Sensor WaterLevelSensor { get { try { return SensorLocation.Sensors .GetBySpecification(new WaterLevelSensorSpecification()) .Single(); } catch (Exception e) { throw new PLLinesCreatorException("There was an error getting the water level sensor. Maybe because there was no water level sensor defined", e); } } } /// /// Gets the water level sensor. /// public Sensor PolderLevelSensor { get { var sensors = SensorLocation.Sensors.GetBySpecification(new PolderLevelSensorSpecification()).ToList(); if (sensors.Count() == 1) { return sensors.First(); } if (!sensors.Any()) { return null; } throw new PLLinesCreatorException("There are multiple polder level sensors defined."); } } /// /// Gets the PiezometricHead type sensors sorted along profile. /// /// /// Water level and polder level sensors should not be in this collection /// protected IEnumerable SensorsSortedAlongProfile { get { return SensorLocation.GetSensorsSortedByRelativeLocationAlongProfile(PLLineType).Select(s => s.Value); } } /// /// Gets the X begin boundary. /// protected double XBeginBoundary { get { return SensorLocation.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X; } } /// /// Gets the X end boundary. /// protected double XEndBoundary { get { return SensorLocation.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X; } } protected bool DikeHasDitch { get { return SensorLocation.SurfaceLine.HasDitch(); } } protected bool DikeHasShoulder { get { return SensorLocation.SurfaceLine.HasShoulderInside(); } } /// /// Gets the Y value at the end boundary. /// protected double YEndBoundary { get { return SensorLocation.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).Y; } } protected double XDikeToeAtRiver { get { return SensorLocation.SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X; } } /// /// Intersection of line at river with a given Z value. /// /// protected double IntersectionXAtRiverWaterLevel(double waterLevel) { GeometryPoint point = SensorLocation.SurfaceLine.DetermineIntersectionBetweenTaludRiverSideAndWaterLevel(waterLevel); if (point == null) { throw new PLLinesCreatorException("No intersection point found with water level at dike river side"); } return point.X; } /// /// Intersection of line at polder with a given Z value. /// /// protected double IntersectionXAtPolderZ(double z) { var intersectionsXatZ = SensorLocation.SurfaceLine.Geometry.IntersectionsXAtZ(z).ToList(); var hasIntersections = intersectionsXatZ.Count() == 2; return hasIntersections ? intersectionsXatZ.Last() : double.NaN; } /// /// Gets the sensor X value. /// /// The sensor. /// protected double GetSensorXValue(Sensor sensor) { return sensor.RelativeLocation; } /// /// Gets the sensor Z value. /// /// The sensor. /// protected double GetSensorZValue(Sensor sensor) { return SensorValues[sensor]; } /// /// Gets the water level at polder. /// protected double WaterLevelAtPolder { get { var sensor = SensorLocation.GetSensorsSortedByRelativeLocationAlongProfile(PLLineType).Last().Value; var value = SensorLocation.GetValue(x => x.PL1WaterLevelAtPolder, SensorValues, sensor); if (value.HasValue) return value.Value; var message = string.Format("Water level at polder for the location '{0}' was not set or initialized", SensorLocation.LocationName); throw new InvalidOperationException(message); } } /// /// Gets the type of the PL line. /// /// /// The type of the PL line. /// public PLLineType PLLineType { get; private set; } /// /// Creates the PL line. /// /// public abstract PLLine CreatePLLine(); } }