// Copyright (C) Stichting Deltares 2019. 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.Data.General; using Deltares.DamEngine.Data.General.PlLines; using Deltares.DamEngine.Data.General.Sensors; using Deltares.DamEngine.Data.General.Sensors.Specifications; using Deltares.DamEngine.Data.General.Specifications.Extensions; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; namespace Deltares.DamEngine.Calculators.PlLinesCreator { 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) { GeometryPointString surfaceLineGeometry = SensorLocation.SurfaceLine.Geometry; double shift = surfaceLineGeometry.GetMaxX() - surfaceLineGeometry.GetMinX(); return GetSensorXLocation(sensor, shift); } /// /// 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 { throw new NotImplementedException(); // 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(); /// /// Gets the X coordinate of the sensor location. /// /// The to retrieve the X coordinate for. /// The offset for the X Coordinate /// The X location of the sensor. private static double GetSensorXLocation(Sensor sensor, double offset) { double sensorXCoordinate = sensor.RelativeLocation; if (sensorXCoordinate < 0) { return sensorXCoordinate + offset; } return sensorXCoordinate; } } }