using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Xml.Serialization;
using Deltares.Geographic;
using Deltares.Geometry;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Standard;
using Deltares.Standard.Attributes;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.EventPublisher.Enum;
using Deltares.Standard.Extensions;
using Deltares.Standard.Language;
using Deltares.Standard.Units;
using Deltares.Standard.Validation;
namespace Deltares.Geotechnics.WaternetCreator
{
///
/// Different options for generating the waternet - either letting it be generated or filling in values self
///
public enum WaternetCreationMode
{
[XmlOldName("True")]
CreateWaternet,
CreatePhreaticAndHeadLinesOnly,
[XmlOldName("False")]
FillInWaternetValues
}
public enum DikeSoilScenario
{
ClayDikeOnClay,
SandDikeOnClay,
ClayDikeOnSand,
SandDikeOnSand
}
[XmlOldName("Deltares.Stability.RingtoetsLocation")]
public class Location : IGeographicPoint, IVisibleEnabled, IDisposable, IDomain
{
private bool adjustPl3And4ForUplift = true;
private DikeSoilScenario dikeSoilScenario = DikeSoilScenario.ClayDikeOnClay;
private bool drainageConstructionPresent = false;
private double headInPLLine3 = double.NaN;
private double headInPLLine4 = double.NaN;
private bool inwards = true;
private double minimumLevelPhreaticLineAtDikeTopPolder = double.NaN;
private double minimumLevelPhreaticLineAtDikeTopRiver = double.NaN;
private PhreaticAdaptionType nwoPhreaticAdaption = PhreaticAdaptionType.None;
private double penetrationLength = double.NaN;
private PiezometricHeads piezometricHeads = new PiezometricHeads();
private PlLineCreationMethod plLineCreationMethod = PlLineCreationMethod.RingtoetsWti2017;
private double plLineOffsetBelowDikeToeAtPolder = 0.1;
private double plLineOffsetBelowDikeTopAtPolder = 1.5;
private double plLineOffsetBelowDikeTopAtRiver = 0.5;
private double plLineOffsetBelowPointBRingtoetsWti2017 = 0.5;
private double plLineOffsetBelowShoulderBaseInside = 0.1;
private double slopeDampingPiezometricHeightPolderSide = double.NaN;
private SurfaceLine2 surfaceline;
private bool useDefaultOffsets = true;
private double waterLevelRiver = double.NaN;
private double waterLevelRiverAverage = double.NaN;
private double waterLevelRiverLow = double.NaN;
private WaternetCreationMode waternetCreationMode = WaternetCreationMode.FillInWaternetValues;
private double xCoordMiddleDrainageConstruction = double.NaN;
private double zCoordMiddleDrainageConstruction = double.NaN;
public Location()
{
DataEventPublisher.OnAfterChange += DataEventPublisher_OnAfterChange;
DataEventPublisher.AddListenerForSenders(EventType.AfterChange, this, piezometricHeads);
}
[Browsable(false)]
[Validate]
public virtual SoilProfile2D SoilProfile2D { get; set; }
[Browsable(false)]
[Validate]
public virtual SoilProfile1D SoilProfile1D { get; set; }
[Browsable(false)]
[Validate]
public virtual SurfaceLine2 Surfaceline
{
get
{
return surfaceline;
}
set
{
DataEventPublisher.BeforeChange(this, "Surfaceline");
surfaceline = value;
DataEventPublisher.AfterChange(this, "Surfaceline");
}
}
[Label("NWO phreatic adaption")]
[Browsable(false)]
public PhreaticAdaptionType NWOPhreaticAdaption
{
get
{
return nwoPhreaticAdaption;
}
set
{
DataEventPublisher.BeforeChange(this, "NWOPhreaticAdaption");
nwoPhreaticAdaption = value;
DataEventPublisher.AfterChange(this, "NWOPhreaticAdaption");
}
}
[Browsable(false)]
public virtual PhreaticLine LocalXzpl1Line { get; set; }
///
/// Gets or sets the general setting - autogenerate or self filling in.
/// Sets the Auto and the UserDefinedPl3AndPl4 parameters of Location.
///
[PropertyOrder(10, 1)]
[XmlOldName("Auto")]
public WaternetCreationMode WaternetCreationMode
{
get
{
return waternetCreationMode;
}
set
{
DataEventPublisher.BeforeChange(this, "WaternetCreationMode");
waternetCreationMode = value;
DataEventPublisher.AfterChange(this, "WaternetCreationMode");
}
}
[PropertyOrder(10, 2)]
[Format("F2")]
public DikeSoilScenario DikeSoilScenario
{
get
{
return dikeSoilScenario;
}
set
{
DataEventPublisher.BeforeChange(this, "DikeSoilScenario");
dikeSoilScenario = value;
if (dikeSoilScenario == DikeSoilScenario.ClayDikeOnClay || dikeSoilScenario == DikeSoilScenario.ClayDikeOnSand)
{
DrainageConstructionPresent = false;
}
DataEventPublisher.AfterChange(this, "DikeSoilScenario");
}
}
[PropertyOrder(10, 3)]
[Format("F2")]
public PlLineCreationMethod PlLineCreationMethod
{
get
{
return plLineCreationMethod;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineCreationMethod");
plLineCreationMethod = value;
DataEventPublisher.AfterChange(this, "PlLineCreationMethod");
if (waternetCreationMode == WaternetCreationMode.CreatePhreaticAndHeadLinesOnly && plLineCreationMethod != PlLineCreationMethod.RingtoetsWti2017)
{
waternetCreationMode = WaternetCreationMode.CreateWaternet;
}
}
}
[PropertyOrder(20, 10)]
[Unit(UnitType.Depth)]
[Format("F2")]
[Clearable]
public double WaterLevelRiver
{
get
{
return waterLevelRiver;
}
set
{
DataEventPublisher.BeforeChange(this, l => l.WaterLevelRiver);
headInPLLine4 = value;
headInPLLine3 = value;
waterLevelRiver = value;
DataEventPublisher.AfterChange(this, l => l.WaterLevelRiver);
}
}
[PropertyOrder(20, 11)]
[Unit(UnitType.Depth)]
[Format("F2")]
[Clearable]
public double WaterLevelRiverAverage
{
get
{
return waterLevelRiverAverage;
}
set
{
DataEventPublisher.BeforeChange(this, "WaterLevelRiverAverage");
waterLevelRiverAverage = value;
DataEventPublisher.AfterChange(this, "WaterLevelRiverAverage");
}
}
[PropertyOrder(20, 12)]
[Unit(UnitType.Depth)]
[Format("F2")]
[Clearable]
public double WaterLevelRiverLow
{
get
{
return waterLevelRiverLow;
}
set
{
DataEventPublisher.BeforeChange(this, "WaterLevelRiverLow");
waterLevelRiverLow = value;
DataEventPublisher.AfterChange(this, "WaterLevelRiverLow");
}
}
[PropertyOrder(20, 13)]
[Unit(UnitType.Depth)]
[Format("F2")]
[Clearable]
[NotClear]
[XmlIgnore]
public double WaterLevelPolder
{
get
{
return piezometricHeads.HeadPl1;
}
set
{
DataEventPublisher.BeforeChange(this, "WaterLevelPolder");
piezometricHeads.HeadPl1 = value;
DataEventPublisher.AfterChange(this, "WaterLevelPolder");
}
}
[PropertyOrder(20, 14)]
public bool DrainageConstructionPresent
{
get
{
return drainageConstructionPresent;
}
set
{
var newValue = dikeSoilScenario == DikeSoilScenario.ClayDikeOnClay || dikeSoilScenario == DikeSoilScenario.ClayDikeOnSand ? false : value;
this.SetAndNotify2(out drainageConstructionPresent, newValue, l => l.DrainageConstructionPresent);
}
}
[PropertyOrder(20, 15)]
[Unit(UnitType.Length)]
[Format("F3")]
public double XCoordMiddleDrainageConstruction
{
get
{
return xCoordMiddleDrainageConstruction;
}
set
{
DataEventPublisher.BeforeChange(this, "XCoordMiddleDrainageConstruction");
xCoordMiddleDrainageConstruction = value;
DataEventPublisher.AfterChange(this, "XCoordMiddleDrainageConstruction");
}
}
[PropertyOrder(20, 16)]
[Unit(UnitType.Depth)]
[Format("F3")]
public double ZCoordMiddleDrainageConstruction
{
get
{
return zCoordMiddleDrainageConstruction;
}
set
{
DataEventPublisher.BeforeChange(this, "ZCoordMiddleDrainageConstruction");
zCoordMiddleDrainageConstruction = value;
DataEventPublisher.AfterChange(this, "ZCoordMiddleDrainageConstruction");
}
}
[PropertyOrder(20, 17)]
[Unit(UnitType.Depth)]
[Format("F3")]
[Clearable]
public double MinimumLevelPhreaticLineAtDikeTopRiver
{
get
{
return minimumLevelPhreaticLineAtDikeTopRiver;
}
set
{
DataEventPublisher.BeforeChange(this, "MinimumLevelPhreaticLineAtDikeTopRiver");
minimumLevelPhreaticLineAtDikeTopRiver = value;
DataEventPublisher.AfterChange(this, "MinimumLevelPhreaticLineAtDikeTopRiver");
}
}
[PropertyOrder(20, 18)]
[Unit(UnitType.Depth)]
[Format("F3")]
[Clearable]
public double MinimumLevelPhreaticLineAtDikeTopPolder
{
get
{
return minimumLevelPhreaticLineAtDikeTopPolder;
}
set
{
DataEventPublisher.BeforeChange(this, "MinimumLevelPhreaticLineAtDikeTopPolder");
minimumLevelPhreaticLineAtDikeTopPolder = value;
DataEventPublisher.AfterChange(this, "MinimumLevelPhreaticLineAtDikeTopPolder");
}
}
[PropertyOrder(20, 19)]
public bool UseDefaultOffsets
{
get
{
return useDefaultOffsets;
}
set
{
DataEventPublisher.BeforeChange(this, "UseDefaultOffsets");
useDefaultOffsets = value;
DataEventPublisher.AfterChange(this, "UseDefaultOffsets");
}
}
[PropertyOrder(20, 30)]
[Unit(UnitType.Length)]
[Format("F2")]
public double PlLineOffsetBelowDikeTopAtRiver
{
get
{
return plLineOffsetBelowDikeTopAtRiver;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineOffsetBelowDikeTopAtRiver");
plLineOffsetBelowDikeTopAtRiver = value;
DataEventPublisher.AfterChange(this, "PlLineOffsetBelowDikeTopAtRiver");
}
}
///
/// The offset of PL-line 1 (= phreatic line) below point B, according to Ringtoets WTI 2017 mehtod:
/// - for clay dikes: point B is situated 1 meter at the right side of point A (intersection dike with phreatic line at river side)
/// - for sand dike on clay: point B is situated 1 cm at the right side of point A
/// - for sand dike on sand: point B is dike top at river side
///
[PropertyOrder(20, 31)]
[Unit(UnitType.Length)]
[Format("F2")]
public double PlLineOffsetBelowPointBRingtoetsWti2017
{
get
{
return plLineOffsetBelowPointBRingtoetsWti2017;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineOffsetBelowPointBRingtoetsWti2017");
plLineOffsetBelowPointBRingtoetsWti2017 = value;
DataEventPublisher.AfterChange(this, "PlLineOffsetBelowPointBRingtoetsWti2017");
}
}
[PropertyOrder(20, 32)]
[Unit(UnitType.Length)]
[Format("F2")]
public double PlLineOffsetBelowDikeTopAtPolder
{
get
{
return plLineOffsetBelowDikeTopAtPolder;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineOffsetBelowDikeTopAtPolder");
plLineOffsetBelowDikeTopAtPolder = value;
DataEventPublisher.AfterChange(this, "PlLineOffsetBelowDikeTopAtPolder");
}
}
[PropertyOrder(20, 33)]
[Unit(UnitType.Length)]
[Format("F2")]
public double PlLineOffsetBelowShoulderBaseInside
{
get
{
return plLineOffsetBelowShoulderBaseInside;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineOffsetBelowShoulderBaseInside");
plLineOffsetBelowShoulderBaseInside = value;
DataEventPublisher.AfterChange(this, "PlLineOffsetBelowShoulderBaseInside");
}
}
[PropertyOrder(20, 34)]
[Unit(UnitType.Length)]
[Format("F2")]
public double PlLineOffsetBelowDikeToeAtPolder
{
get
{
return plLineOffsetBelowDikeToeAtPolder;
}
set
{
DataEventPublisher.BeforeChange(this, "PlLineOffsetBelowDikeToeAtPolder");
plLineOffsetBelowDikeToeAtPolder = value;
DataEventPublisher.AfterChange(this, "PlLineOffsetBelowDikeToeAtPolder");
}
}
[Clearable]
[ReadOnly(true)]
[PropertyOrder(30, 1)]
[Unit(UnitType.Depth)]
[Format("F2")]
public double HeadInPLLine3
{
get
{
return headInPLLine3;
}
set
{
DataEventPublisher.BeforeChange(this, "HeadInPLLine3");
headInPLLine3 = value;
DataEventPublisher.AfterChange(this, "HeadInPLLine3");
}
}
[ReadOnly(true)]
[PropertyOrder(30, 2)]
[Unit(UnitType.Depth)]
[Format("F2")]
public double HeadInPLLine4
{
get
{
return headInPLLine4;
}
set
{
DataEventPublisher.BeforeChange(this, "HeadInPLLine4");
headInPLLine4 = value;
DataEventPublisher.AfterChange(this, "HeadInPLLine4");
}
}
[PropertyOrder(30, 10)]
[Format("F2")]
public bool AdjustPl3And4ForUplift
{
get
{
return adjustPl3And4ForUplift;
}
set
{
DataEventPublisher.BeforeChange(this, "AdjustPl3And4ForUplift");
adjustPl3And4ForUplift = value;
DataEventPublisher.AfterChange(this, "AdjustPl3And4ForUplift");
}
}
[Clearable]
[PropertyOrder(40, 50)]
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
public double LeakageLengthOutwardsPl3
{
get
{
return piezometricHeads.LeakageLengthOutwardsPl3;
}
set
{
DataEventPublisher.BeforeChange(this, "LeakageLengthOutwardsPl3");
piezometricHeads.LeakageLengthOutwardsPl3 = value;
DataEventPublisher.AfterChange(this, "LeakageLengthOutwardsPl3");
}
}
[Clearable]
[PropertyOrder(40, 51)]
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
public double LeakageLengthInwardsPl3
{
get
{
return piezometricHeads.LeakageLengthInwardsPl3;
}
set
{
DataEventPublisher.BeforeChange(this, "LeakageLengthInwardsPl3");
piezometricHeads.LeakageLengthInwardsPl3 = value;
DataEventPublisher.AfterChange(this, "LeakageLengthInwardsPl3");
}
}
[Clearable]
[PropertyOrder(40, 52)]
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
public double LeakageLengthOutwardsPl4
{
get
{
return piezometricHeads.LeakageLengthOutwardsPl4;
}
set
{
DataEventPublisher.BeforeChange(this, "LeakageLengthOutwardsPl4");
piezometricHeads.LeakageLengthOutwardsPl4 = value;
DataEventPublisher.AfterChange(this, "LeakageLengthOutwardsPl4");
}
}
[Clearable]
[PropertyOrder(40, 53)]
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
public double LeakageLengthInwardsPl4
{
get
{
return piezometricHeads.LeakageLengthInwardsPl4;
}
set
{
DataEventPublisher.BeforeChange(this, "LeakageLengthInwardsPl4");
piezometricHeads.LeakageLengthInwardsPl4 = value;
DataEventPublisher.AfterChange(this, "LeakageLengthInwardsPl4");
}
}
[PropertyOrder(40, 70)]
[Unit(UnitType.Angle)]
[Format("F2")]
[Browsable(false)]
public double SlopeDampingPiezometricHeightPolderSide
{
get
{
return slopeDampingPiezometricHeightPolderSide;
}
set
{
DataEventPublisher.BeforeChange(this, "SlopeDampingPiezometricHeightPolderSide");
slopeDampingPiezometricHeightPolderSide = value;
DataEventPublisher.AfterChange(this, "SlopeDampingPiezometricHeightPolderSide");
}
}
[Clearable]
[Validate]
[PropertyOrder(50, 1)]
[Unit(UnitType.Depth)]
[Format("F2")]
[XmlIgnore]
public double HeadInPLLine2Outwards
{
get
{
return piezometricHeads.HeadPl2;
}
set
{
DataEventPublisher.BeforeChange(this, "HeadInPLLine2Outwards");
piezometricHeads.HeadPl2 = value;
DataEventPublisher.AfterChange(this, "HeadInPLLine2Outwards");
}
}
[Browsable(false)]
[Unit(UnitType.Depth)]
[Format("F2")]
[XmlIgnore]
public double CorrectedHeadInPLLine2Outwards
{
get
{
if (!double.IsNaN(waterLevelRiverAverage))
{
return Math.Min(waterLevelRiverAverage, HeadInPLLine2Outwards);
}
else if (!double.IsNaN(waterLevelRiver))
{
return Math.Min(waterLevelRiver, HeadInPLLine2Outwards);
}
else
{
return HeadInPLLine2Outwards;
}
}
}
[Clearable]
[Validate]
[PropertyOrder(50, 2)]
[Unit(UnitType.Depth)]
[Format("F2")]
[XmlIgnore]
public double HeadInPLLine2Inwards
{
get
{
return piezometricHeads.HeadInPlLine2Inwards;
}
set
{
DataEventPublisher.BeforeChange(this, "HeadInPLLine2Inwards");
piezometricHeads.HeadInPlLine2Inwards = value;
DataEventPublisher.AfterChange(this, "HeadInPLLine2Inwards");
}
}
[Browsable(false)]
[Unit(UnitType.Depth)]
[Format("F2")]
[XmlIgnore]
public double CorrectedHeadInPLLine2Inwards
{
get
{
if (!double.IsNaN(waterLevelRiverAverage))
{
return Math.Min(waterLevelRiverAverage, HeadInPLLine2Inwards);
}
else if (!double.IsNaN(waterLevelRiver))
{
return Math.Min(waterLevelRiver, HeadInPLLine2Inwards);
}
else
{
return HeadInPLLine2Inwards;
}
}
}
[Validate]
[Unit(UnitType.Length)]
[Format("F3")]
[Minimum(0)]
[PropertyOrder(50, 10)]
public double PenetrationLength
{
get
{
return penetrationLength;
}
set
{
DataEventPublisher.BeforeChange(this, "PenetrationLength");
penetrationLength = value;
DataEventPublisher.AfterChange(this, "PenetrationLength");
}
}
[Browsable(false)]
public PiezometricHeads PiezometricHeads
{
get
{
return piezometricHeads;
}
set
{
if (piezometricHeads != value)
{
DataEventPublisher.RemoveListenerForSenders(EventType.AfterChange, this, piezometricHeads);
DataEventPublisher.BeforeChange(this, "PiezometricHeads");
piezometricHeads = value;
DataEventPublisher.AfterChange(this, "PiezometricHeads");
DataEventPublisher.AddListenerForSenders(EventType.AfterChange, this, piezometricHeads);
}
}
}
[Browsable(false)]
public virtual bool Inwards
{
get
{
return inwards;
}
set
{
inwards = value;
}
}
#region IVisibleEnabled
public virtual bool IsEnabled(string property)
{
switch (property)
{
case "DrainageConstructionPresent":
return (dikeSoilScenario != DikeSoilScenario.ClayDikeOnClay && dikeSoilScenario != DikeSoilScenario.ClayDikeOnSand);
// PL 4 is created only for Clay/Sand dike on clay (1A and 2A) and only if an in-between aquifer is present
case "LeakageLengthOutwardsPl4":
case "LeakageLengthInwardsPl4":
case "HeadInPLLine4":
if (dikeSoilScenario == DikeSoilScenario.SandDikeOnSand || dikeSoilScenario == DikeSoilScenario.ClayDikeOnSand)
{
return false;
}
else
{
GeometryPoint xDikeTopAtPolder = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder);
if (SoilProfile2D != null && Surfaceline != null && xDikeTopAtPolder != null)
{
// The check of the presence of an in-between aquifer is done at Dike Top At River
// If not present, the input parameters for the creation of PL 4 are not needed
return (SoilProfile2D.GetSoilProfile1D(xDikeTopAtPolder.X).InBetweenAquiferLayer != null);
}
else
{
return true;
}
}
case "LeakageLengthInwardsPl3":
case "LeakageLengthOutwardsPl3":
return (dikeSoilScenario != DikeSoilScenario.SandDikeOnSand);
default:
return true;
}
}
public virtual bool IsVisible(string property)
{
if (WaternetCreationMode == WaternetCreationMode.FillInWaternetValues)
{
return property == "WaternetCreationMode";
}
else
{
switch (property)
{
case "WaterLevelRiverLow":
return (!Inwards);
case "XCoordMiddleDrainageConstruction":
case "ZCoordMiddleDrainageConstruction":
return drainageConstructionPresent;
case "MinimumLevelPhreaticLineAtDikeTopRiver":
case "MinimumLevelPhreaticLineAtDikeTopPolder":
return plLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017;
case "PlLineOffsetBelowDikeTopAtRiver":
return plLineCreationMethod != PlLineCreationMethod.RingtoetsWti2017;
case "PlLineOffsetBelowPointBRingtoetsWti2017":
return plLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017 && !useDefaultOffsets;
case "PlLineOffsetBelowDikeTopAtPolder":
case "PlLineOffsetBelowDikeToeAtPolder":
case "PlLineOffsetBelowShoulderBaseInside":
if (plLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017 && useDefaultOffsets)
{
return false;
}
else
{
return true;
}
case "HeadInPLLine3":
case "HeadInPLLine4":
return (PlLineCreationMethod != PlLineCreationMethod.RingtoetsWti2017);
default:
return true;
}
}
}
#endregion
#region Validation
[Validate]
public ValidationResult[] Validate()
{
var results = new List();
if (waternetCreationMode == WaternetCreationMode.CreateWaternet)
{
if (Surfaceline == null || Surfaceline.Geometry.Count < 2)
{
results.Add(BuildErrorValidationResultForThis("SurfaceLineNotPresent"));
return results.ToArray();
}
if (!Surfaceline.IsDefined(CharacteristicPointType.SurfaceLevelOutside))
{
results.Add(BuildErrorValidationResultForThis("SurfaceLevelOutsideNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.SurfaceLevelInside))
{
results.Add(BuildErrorValidationResultForThis("SurfaceLevelInsideNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.DikeToeAtPolder))
{
results.Add(BuildErrorValidationResultForThis("DikeToeAtPolderNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.DikeToeAtRiver))
{
results.Add(BuildErrorValidationResultForThis("DikeToeAtRiverNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.DikeTopAtPolder))
{
results.Add(BuildErrorValidationResultForThis("DikeTopAtPolderNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.DikeTopAtRiver))
{
results.Add(BuildErrorValidationResultForThis("DikeTopAtRiverNotPresent"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.DitchDikeSide) ||
!Surfaceline.IsDefined(CharacteristicPointType.DitchPolderSide))
{
results.Add(BuildWarningValidationResultForThis("DitchPointsNotComplete"));
}
if (!Surfaceline.IsDefined(CharacteristicPointType.TrafficLoadInside) ||
!Surfaceline.IsDefined(CharacteristicPointType.TrafficLoadOutside))
{
results.Add(BuildWarningValidationResultForThis("TrafficLoadNotPresent"));
}
if (Surfaceline.IsDefined(CharacteristicPointType.DikeTopAtPolder))
{
if (WaterLevelPolder > Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z)
{
results.Add(BuildErrorValidationResultForThis("WaterLevelPolderGreaterThanDikeTopAtPolder"));
}
}
if (Surfaceline.IsDefined(CharacteristicPointType.SurfaceLevelInside))
{
if (PlLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017 &&
(WaterLevelPolder > Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).Z))
{
results.Add(BuildErrorValidationResultForThis("WaterLevelPolderGreaterThanSurfaceLevelInside"));
}
}
if (Surfaceline.IsDefined(CharacteristicPointType.DikeTopAtRiver))
{
if (WaterLevelRiver > Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).Z)
{
results.Add(BuildErrorValidationResultForThis("WaterLevelRiverGreaterThanDikeTopAtRiver"));
}
}
if (double.IsNaN(LeakageLengthInwardsPl3) || double.IsNaN(LeakageLengthOutwardsPl3))
{
results.Add(BuildErrorValidationResultForThis("LeakageLengthValuesNotPresent"));
}
if (double.IsNaN(HeadInPLLine2Outwards) || double.IsNaN(HeadInPLLine2Inwards))
{
results.Add(BuildErrorValidationResultForThis("HeadPLLine2ValuesNotPresent"));
}
if (double.IsNaN(WaterLevelPolder))
{
results.Add(BuildErrorValidationResultForThis("WaterLevelPolderNotPresent"));
}
if (!Inwards && plLineCreationMethod != PlLineCreationMethod.RingtoetsWti2017 && double.IsNaN(WaterLevelRiverLow))
{
results.Add(BuildErrorValidationResultForThis("WaterLevelRiverLowNotPresent"));
}
if (PlLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017 &&
(double.IsNaN(minimumLevelPhreaticLineAtDikeTopPolder) ||
double.IsNaN(minimumLevelPhreaticLineAtDikeTopRiver)))
{
results.Add(BuildErrorValidationResultForThis("MinimumLevelsPhreaticLineNotPresent"));
}
if (results.Count > 0)
{
return results.ToArray();
}
// Validation of the drainage construction
double zTopDike = Surfaceline.Geometry.GetZAtX(XCoordMiddleDrainageConstruction);
double xDikeToeAtPolder = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X;
double xDikeTopAtPolder = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X;
bool isDrainageConstruction = (PlLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017
&& (DikeSoilScenario == DikeSoilScenario.SandDikeOnClay || DikeSoilScenario == DikeSoilScenario.SandDikeOnSand)
&& DrainageConstructionPresent);
if (isDrainageConstruction && (double.IsNaN(XCoordMiddleDrainageConstruction) || double.IsNaN(ZCoordMiddleDrainageConstruction)))
{
results.Add(BuildErrorValidationResultForThis("CoordinatesDrainageConstructionNotPresent"));
}
if (isDrainageConstruction && (XCoordMiddleDrainageConstruction > xDikeToeAtPolder || XCoordMiddleDrainageConstruction < xDikeTopAtPolder))
{
results.Add(BuildErrorValidationResultForThis("DrainageConstructionMustBeSituatedBetweenDikeTopAndDikeToe"));
}
if (isDrainageConstruction && ZCoordMiddleDrainageConstruction > zTopDike)
{
results.Add(BuildErrorValidationResultForThis("DrainageConstructionOutsideTheDike"));
}
if (isDrainageConstruction && ZCoordMiddleDrainageConstruction < WaterLevelPolder)
{
results.Add(BuildErrorValidationResultForThis("DrainageConstructionBelowWaterLevelPolder"));
}
//if (HeadInPLLine2Inwards > waterLevelRiverAverage)
//{
// results.Add(BuildErrorValidationResultForThis("HeadPL2InwardsMoreThanAverageHighWaterLevel"));
//}
//if (HeadInPLLine2Outwards > waterLevelRiverAverage)
//{
// results.Add(BuildErrorValidationResultForThis("HeadPL2OutwardsMoreThanAverageHighWaterLevel"));
//}
if (waterLevelRiverAverage > waterLevelRiver)
{
results.Add(BuildErrorValidationResultForThis("AverageHighWaterLevelMoreThanWaterLevelRiver"));
}
//if (double.IsNaN(waterLevelRiverAverage) &&
// (HeadInPLLine2Outwards > waterLevelRiver || HeadInPLLine2Inwards > waterLevelRiver))
//{
// results.Add(BuildErrorValidationResultForThis("HeadPL2MoreThanWaterLevelRiver"));
//}
double firstX = Surfaceline.Geometry.Points.First(p => !double.IsNaN(p.X)).X;
double lastX = Surfaceline.Geometry.Points.Last(p => !double.IsNaN(p.X)).X;
double slopeHead2 = Math.Abs((firstX - lastX) / (HeadInPLLine2Inwards - HeadInPLLine2Outwards));
if (slopeHead2 < 100.0)
{
results.Add(BuildErrorValidationResultForThis("SlopeOfHead2TooSteep"));
}
results.AddRange(ValidateAquifers());
}
return results.ToArray();
}
///
/// Validates whether aquifer definitions are all right
///
///
/// Don't decorate with Validate attribute, since it is called by the Validate method
///
///
/// Validation results
///
public ValidationResult[] ValidateAquifers()
{
List results = new List();
const double margin = 0.0001;
bool hasAquifer = false;
foreach (var soilLayer in SoilProfile2D.Surfaces)
{
if (soilLayer.IsAquifer)
{
hasAquifer = true;
if (soilLayer.GeometrySurface.OuterLoop.GetMinX() > SoilProfile2D.Geometry.Left + margin ||
soilLayer.GeometrySurface.OuterLoop.GetMaxX() < SoilProfile2D.Geometry.Right - margin)
{
results.Add(new ValidationResult(ValidationResultType.Error, LocalizationManager.GetTranslatedText(typeof(Location), "NoAquiferCompleteWidth"), soilLayer));
}
}
}
if (!hasAquifer)
{
results.Add(new ValidationResult(ValidationResultType.Error, LocalizationManager.GetTranslatedText(typeof(Location), "NoAquifer"), SoilProfile2D));
}
if (dikeSoilScenario == DikeSoilScenario.ClayDikeOnClay)
{
double xNoDike;
if (Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder) != null)
{
xNoDike = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X + 0.001;
}
else
{
xNoDike = Surfaceline.Geometry.GetMaxX();
}
SoilProfile1D profile1DWithoutDike = SoilProfile2D.GetSoilProfile1D(xNoDike);
profile1DWithoutDike.Layers.Sort();
if (profile1DWithoutDike.Layers[0].IsAquifer)
{
results.Add(new ValidationResult(ValidationResultType.Error, LocalizationManager.GetTranslatedText(typeof(Location), "FirstLayerBelowDikeIsAquifer"), SoilProfile2D));
}
}
if (dikeSoilScenario == DikeSoilScenario.ClayDikeOnSand)
{
double xTopDike;
if (Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder) != null)
{
xTopDike = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X;
}
else
{
xTopDike = Surfaceline.Geometry.GetMaxX();
}
SoilProfile1D profile1DWithoutDike = SoilProfile2D.GetSoilProfile1D(xTopDike);
profile1DWithoutDike.Layers.Sort();
if (profile1DWithoutDike.Layers[0].IsAquifer)
{
results.Add(new ValidationResult(ValidationResultType.Error, LocalizationManager.GetTranslatedText(typeof(Location), "DikeIsAquifer"), SoilProfile2D));
}
}
return results.ToArray();
}
///
/// Validatates case when Toetspeil was not calculated yet and therefor there is no value for WaterLevelRiver
///
/// The collection with all detected validation problems
[Validate]
public ValidationResult[] ValidateWaterLevelRiver()
{
var results = new List();
if ((Inwards || plLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017) && double.IsNaN(WaterLevelRiver) && waternetCreationMode == WaternetCreationMode.CreateWaternet)
{
results.Add(BuildErrorValidationResultForThis("WaterLevelRiverNotPresent"));
}
return results.ToArray();
}
///
/// Validates if it has the expected number of aquifer layers.
///
/// The collection with all detected validation problems.
/// This method has sideseffects: setting .
[Validate]
public ValidationResult[] ValidateSoilProfile()
{
var results = new List();
if (waternetCreationMode == WaternetCreationMode.CreateWaternet && Surfaceline != null)
{
// TODO: This path creates side-effects: refactor to make this method Pure.
if (SoilProfile2D != null &&
Surfaceline.IsDefined(CharacteristicPointType.DikeToeAtRiver))
{
var xStart = Surfaceline.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X;
SoilProfile1D = SoilProfile2D.GetSoilProfile1D(xStart);
}
else
{
SoilProfile1D = SoilProfile1D;
}
// Early exit in a similar fashion if surface line is missing:
if (SoilProfile1D == null)
{
return results.ToArray();
}
var toppestLayerOfDeepestClusterOfAquifers = SoilProfile1D.BottomAquiferLayer;
if (toppestLayerOfDeepestClusterOfAquifers == null)
{
return results.ToArray();
}
IList sortedLayers = SoilProfile1D.Layers.OrderBy(l => l.TopLevel).ToList();
int numberOfInBetweenClustersOfAquifers = 0;
for (int i = 1; i < sortedLayers.Count; i++)
{
if (sortedLayers[i].TopLevel > toppestLayerOfDeepestClusterOfAquifers.TopLevel && sortedLayers[i].IsAquifer)
{
if (sortedLayers[i].IsAquifer && !sortedLayers[i - 1].IsAquifer)
{
++numberOfInBetweenClustersOfAquifers;
}
}
}
if (numberOfInBetweenClustersOfAquifers > 1)
{
results.Add(BuildErrorValidationResultForThis("MoreThanOneInBetweenAquiferPresent"));
}
}
return results.ToArray();
}
private ValidationResult BuildWarningValidationResultForThis(string message)
{
var correctlyTranslatedMessage = LocalizationManager.GetTranslatedText(typeof(Location), message);
return new ValidationResult(ValidationResultType.Warning, correctlyTranslatedMessage, this);
}
private ValidationResult BuildErrorValidationResultForThis(string message)
{
var correctlyTranslatedMessage = LocalizationManager.GetTranslatedText(typeof(Location), message);
return new ValidationResult(ValidationResultType.Error, correctlyTranslatedMessage, this);
}
#endregion
[Browsable(false)]
public double X { get; set; }
[Browsable(false)]
public double Y { get; set; }
public void Dispose()
{
DataEventPublisher.RemoveListenerForSenders(EventType.AfterChange, this, piezometricHeads);
DataEventPublisher.OnAfterChange -= DataEventPublisher_OnAfterChange;
}
private void DataEventPublisher_OnAfterChange(object sender, PublishEventArgs e)
{
if (sender == piezometricHeads)
{
DataEventPublisher.AfterChange(this);
}
}
public ICollection GetDomain(string property)
{
switch (property)
{
case "WaternetCreationMode":
if (PlLineCreationMethod == PlLineCreationMethod.RingtoetsWti2017)
{
return new[] { WaternetCreationMode.CreateWaternet, WaternetCreationMode.CreatePhreaticAndHeadLinesOnly, WaternetCreationMode.FillInWaternetValues };
}
else
{
return new[] { WaternetCreationMode.CreateWaternet, WaternetCreationMode.FillInWaternetValues };
}
default:
return null;
}
}
}
}