using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Serialization;
using Deltares.Geographic;
using Deltares.Geotechnics;
using Deltares.Geotechnics.GeotechnicalGeometry;
using Deltares.Geotechnics.Mechanisms;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Standard;
using Deltares.Standard.Attributes;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Extensions;
using Deltares.Standard.Language;
using Deltares.Standard.Reflection;
using Deltares.Standard.Units;
using Deltares.Standard.Validation;
namespace Deltares.DeltaModel
{
///
/// Enumeration for the types of Hydraulic Boundary Links for dike locations. Values: HydraulicBoundary1, HydraulicBoundary2
///
public enum DikeLocationHydraulicBoundaryLinkType
{
HydraulicBoundary1 = 0,
HydraulicBoundary2 = 1
}
///
/// Specific location on the dikeline
///
public class DikeLocation : IName, IGeographic, IHasSurfaceLine, IHasSchematizedSurfaceLine, IConnectable, IDomain, IVisibleEnabled, IDisposable
{
private const int numberOfClosestHydraulicConditions = 10;
protected Func getErrorMessageForMissingBoundaryLink;
#region field variables
private readonly List designValues = new List();
///
/// Soil Segments (per failure mechanism) for the location
///
private readonly Dictionary soilSegments = new Dictionary();
private AsphaltRegion asphaltRegion;
private BlockRevetmentCrossSection blockRevetmentCrossSection;
private BlockRevetmentRegion blockRevetmentRegion;
// TODO what is imported should be seperated from what is used for schematization, therefore this should be removed in favor of another data object
private GeographicString boundaryProfile = new GeographicString();
private BreakWater breakWater;
///
/// The dikeline to which this section belongs
///
private DikeLine dikeLine;
private double flowSpeed = double.NaN;
private HydraulicBoundary hydraulicBoundary1;
private HydraulicBoundary hydraulicBoundary2;
///
/// Indicates the relative share of boundary 2
///
private double hydraulicBoundaryPartitioning = 0;
private AsphaltCrossSection importedAsphaltCrossSection;
private RoughnessCrossSection importedRoughnessCrossSection;
private bool isAutoLinkedToBreakWater = true;
///
/// Auto link to HydraulicBoundary
///
private bool isAutoLinkedToHydraulicBoundary = true;
///
/// Length of the dike location
///
private double length;
///
/// Name of the dike location
/// All calculations will be based on the dike locations
/// Each assessment mechanism will have its own set of dike locations
///
private string name;
///
/// offset location at dikeline
///
private double offset;
///
/// Dike location from which this instance is a copy / clone
///
private DikeLocation originalDikeLocation;
///
/// Collection of PiezometricHeads; all PiezometricHeadTypes (PL1, PL2, PL3, PL4) can have a value
///
private PiezometricHeads piezometricHeads = new PiezometricHeads();
private double roughnessSegmentsEndPointX;
///
/// Physical (measured) Surfaceline for the location
///
private SurfaceLine2 schematizedSurfaceLine = new SurfaceLine2
{
CharacteristicPoints =
{
GeometryMustContainPoint = false
}
};
///
/// Physical (measured) Surfaceline for the location
///
private LocalizedGeometryPointString surfaceLine = new LocalizedGeometryPointString();
private WaveZone waveZone = new WaveZone();
#endregion field variables
///
/// Initializes a new instance of the class.
///
public DikeLocation()
{
schematizedSurfaceLine.Geometry = surfaceLine;
name = string.Empty;
getErrorMessageForMissingBoundaryLink = () => String.Format(LocalizationManager.GetTranslatedText(this, "DikeLocationNotLinkedMessage"), Name);
// Disabled this event handler because it is very slow!! need to
// optimize or re-design:
//DataEventPublisher.OnDataListModified += RevetmentZoneListModified; // TODO: If re-enabled, add counterpart to Dispose method!
DataEventPublisher.OnAfterChange += DataEventPublisher_OnAfterChange;
importedAsphaltCrossSection = new AsphaltCrossSection(this);
importedRoughnessCrossSection = new RoughnessCrossSection(this);
}
///
/// Gets or sets the domain provider.
///
///
/// The domain provider.
///
[XmlIgnore]
[Browsable(false)]
public static IDomain DomainProvider { get; set; }
///
/// Gets or sets the visible enabled provider.
///
///
/// The visible enabled provider.
///
[XmlIgnore]
[Browsable(false)]
public static IVisibleEnabledProvider VisibleEnabledProvider { get; set; }
///
/// Gets or sets the revetment zones end point x.
///
///
/// The revetment zones end point x.
///
[Browsable(false)]
[ReadOnly(true)]
public double RoughnessSegmentsEndPointX
{
get
{
return roughnessSegmentsEndPointX;
}
set
{
this.SetAndNotify2(out roughnessSegmentsEndPointX, value, x => x.RoughnessSegmentsEndPointX);
}
}
///
/// Gets or sets the original dike location.
///
///
/// The original dike location.
///
[Browsable(false)]
[XmlOmit(null)]
public virtual DikeLocation OriginalDikeLocation
{
get
{
return originalDikeLocation;
}
set
{
this.SetAndNotify2(out originalDikeLocation, value, x => x.OriginalDikeLocation);
}
}
///
/// Gets or sets the wave zone.
///
///
/// The wave zone.
///
[Mechanism(Mechanism.BlockRevetment, Mechanism.AsphaltRevetment)]
[Browsable(false)]
public virtual WaveZone WaveZone
{
get
{
return waveZone;
}
set
{
this.SetAndNotify2(out waveZone, value, x => x.WaveZone);
}
}
///
/// Gets or sets the revetment cross section.
///
///
/// The revetment cross section.
///
[Mechanism(Mechanism.BlockRevetment)]
[NotClear]
[Browsable(false)]
public virtual BlockRevetmentCrossSection BlockRevetmentCrossSection
{
get
{
return blockRevetmentCrossSection;
}
set
{
this.SetAndNotify2(out blockRevetmentCrossSection, value, x => x.BlockRevetmentCrossSection);
}
}
///
/// The block revetment region.
///
[Mechanism(Mechanism.BlockRevetment)]
[NotClear]
[Validate]
[Browsable(false)]
public virtual BlockRevetmentRegion BlockRevetmentRegion
{
get
{
return blockRevetmentRegion;
}
set
{
this.SetAndNotify2(out blockRevetmentRegion, value, x => x.BlockRevetmentRegion);
}
}
[Mechanism(Mechanism.Overtopping)]
[Validate]
[Browsable(false)]
public virtual RoughnessCrossSection RoughnessCrossSection
{
get
{
return importedRoughnessCrossSection;
}
set
{
this.SetAndNotify2(out importedRoughnessCrossSection, value, x => x.RoughnessCrossSection);
}
}
[Mechanism(Mechanism.AsphaltRevetment)]
[NotClear]
[Validate]
[Browsable(false)]
public virtual AsphaltCrossSection AsphaltCrossSection
{
get
{
return importedAsphaltCrossSection;
}
set
{
this.SetAndNotify2(out importedAsphaltCrossSection, value, x => x.AsphaltCrossSection);
}
}
///
/// The asphalt revetment region.
///
[Mechanism(Mechanism.AsphaltRevetment)]
[NotClear]
[Validate]
[Browsable(false)]
public virtual AsphaltRegion AsphaltRegion
{
get
{
return asphaltRegion;
}
set
{
this.SetAndNotify2(out asphaltRegion, value, x => x.AsphaltRegion);
}
}
///
/// Gets or sets the flow speed.
///
///
/// The flow speed.
///
[Unit(UnitType.Velocity)]
[Mechanism(Mechanism.BlockRevetment)]
[NotClear]
[Format("F2")]
public virtual double FlowSpeed
{
get
{
return flowSpeed;
}
set
{
this.SetAndNotify2(out flowSpeed, value, x => x.FlowSpeed);
}
}
///
/// Gets or sets the boundary profile / grensvlak.
///
///
/// The boundary profile.
///
[Mechanism(Mechanism.Dunes)] // grensvlak
[Browsable(false)]
public GeographicString BoundaryProfile
{
get
{
return boundaryProfile;
}
set
{
this.SetAndNotify2(out boundaryProfile, value, x => x.BoundaryProfile);
}
}
///
/// Parameterization value for water pressure damping in aquifer
/// on riverside at PL3.
///
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
[Mechanism(Mechanism.Stability)]
[Clearable]
public double LeakageLengthOutwardsPl3
{
get
{
return PiezometricHeads.LeakageLengthOutwardsPl3;
}
set
{
if (PiezometricHeads.LeakageLengthOutwardsPl3 != value)
{
DataEventPublisher.BeforeChange(this, x => x.LeakageLengthOutwardsPl3);
PiezometricHeads.LeakageLengthOutwardsPl3 = value;
DataEventPublisher.AfterChange(this, x => x.LeakageLengthOutwardsPl3);
}
}
}
///
/// Parameterization value for water pressure damping in aquifer
/// on riverside at PL4.
///
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
[Mechanism(Mechanism.Stability)]
[Clearable]
public double LeakageLengthOutwardsPl4
{
get
{
return PiezometricHeads.LeakageLengthOutwardsPl4;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.LeakageLengthOutwardsPl4);
PiezometricHeads.LeakageLengthOutwardsPl4 = value;
DataEventPublisher.AfterChange(this, x => x.LeakageLengthOutwardsPl4);
}
}
///
/// Parameterization value for waterpressure damping in aquifer
/// on polderside at PL3.
///
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
[Mechanism(Mechanism.Stability)]
[Clearable]
public double LeakageLengthInwardsPl3
{
get
{
return PiezometricHeads.LeakageLengthInwardsPl3;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.LeakageLengthInwardsPl3);
PiezometricHeads.LeakageLengthInwardsPl3 = value;
DataEventPublisher.AfterChange(this, x => x.LeakageLengthInwardsPl3);
}
}
///
/// Parameterization value for waterpressure damping in aquifer
/// on polderside at PL4.
///
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
[Mechanism(Mechanism.Stability)]
[Clearable]
public double LeakageLengthInwardsPl4
{
get
{
return PiezometricHeads.LeakageLengthInwardsPl4;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.LeakageLengthInwardsPl4);
PiezometricHeads.LeakageLengthInwardsPl4 = value;
DataEventPublisher.AfterChange(this, x => x.LeakageLengthInwardsPl4);
}
}
///
/// PiezometricHead Type 2 at polder side.
///
[Unit(UnitType.Length)]
[Format("F2")]
[XmlIgnore]
[Mechanism(Mechanism.Stability)]
[Clearable]
public double HeadInPlLine2Inwards
{
get
{
return PiezometricHeads.HeadInPlLine2Inwards;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.HeadInPlLine2Inwards);
PiezometricHeads.HeadInPlLine2Inwards = value;
DataEventPublisher.AfterChange(this, x => x.HeadInPlLine2Inwards);
}
}
///
/// Physical (measured) Surfaceline for the location
///
public virtual SurfaceLine2 SchematizedSurfaceLine
{
get
{
return schematizedSurfaceLine;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.SchematizedSurfaceLine);
if (null != schematizedSurfaceLine)
{
schematizedSurfaceLine.Dispose();
}
schematizedSurfaceLine = value;
DataEventPublisher.AfterChange(this, x => x.SchematizedSurfaceLine);
}
}
///
/// Physically measured Surfaceline
///
///
/// The surface line.
///
public virtual LocalizedGeometryPointString SurfaceLine
{
get
{
return surfaceLine;
}
set
{
DataEventPublisher.BeforeChange(this, x => x.SurfaceLine);
surfaceLine = value;
schematizedSurfaceLine.Geometry = surfaceLine;
DataEventPublisher.AfterChange(this, x => x.SurfaceLine);
}
}
///
/// Gets the representive point.
///
/// null
public virtual IGeographicPoint GetRepresentivePoint()
{
return null;
}
#region administrative properties
///
/// The dikeline to which this location belongs
///
[PropertyOrder(1, 0)]
[ReadOnly(true)]
[Label("Dikeline")]
[Description("Dikeline")]
public virtual DikeLine DikeLine
{
get
{
return dikeLine;
}
set
{
DataEventPublisher.BeforeChange(this, "DikeLine");
dikeLine = value;
DataEventPublisher.AfterChange(this, "DikeLine");
}
}
///
/// Gets or sets the offset of the cross section along the dikeline
///
[Label("Offset")]
[Description("Offset of the dike location along the dikeline")]
[Unit(UnitType.Length)]
[PropertyOrder(1, 10)]
[Format("F2")]
[Category("Location")]
public virtual double Offset
{
get
{
return offset;
}
set
{
DataEventPublisher.BeforeChange(this, "Offset");
offset = value;
DataEventPublisher.AfterChange(this, "Offset");
}
}
///
/// Gets the angle.
///
///
/// The angle in degrees relative to the north.
///
[Label("Angle")]
[Unit(UnitType.Angle)]
[PropertyOrder(1, 11)]
[Format("F2")]
[Category("Location")]
public double Angle
{
get
{
return SurfaceLine.LongitudeAngle;
}
}
///
/// Length of the dike location
///
///
/// The length.
///
[Label("Length")]
[Description("Length of the section")]
[Unit(UnitType.Length)]
[PropertyOrder(1, 12)]
[Format("F2")]
[Browsable(false)]
[Category("Location")]
public virtual double Length
{
get
{
return length;
}
set
{
this.SetAndNotify2(out length, value, dl => dl.Length);
}
}
///
/// Gets or sets the name.
///
///
/// The name.
///
[Label("Name")]
[Description("Name of the dike location")]
[PropertyOrder(0, 0)]
[Data]
[Category("Identification")]
public virtual string Name
{
get
{
return name;
}
set
{
DataEventPublisher.BeforeChange(this, "Name");
name = value;
DataEventPublisher.AfterChange(this, "Name");
}
}
///
/// Gets the distance to a given location along the same dike line
///
/// Location
/// Distance
public virtual double GetDistance(double x)
{
return Math.Abs(Offset - x);
}
#endregion administrative properties
#region geotechnical properties
///
/// Level of water at riverside
///
[Label("Water level")]
[Description("Water level")]
[Unit(UnitType.Depth)]
[Format("F2")]
[PropertyOrder(5, 1)]
[XmlIgnore]
[ReadOnly(true)]
[Mechanism(Mechanism.AssessmentLevel, Mechanism.PipingUpliftGradient, Mechanism.Piping, Mechanism.Stability, Mechanism.Structures, Mechanism.BlockRevetment, Mechanism.AsphaltRevetment, Mechanism.Dunes, Mechanism.Overtopping)]
public virtual double AssessmentLevel
{
get
{
double assessmentLevel = GetDesignValue(GetProbability()).WaterLevel;
return TransformerManager.GetTransformedValue(this, p => p.AssessmentLevel, assessmentLevel);
}
set
{
DataEventPublisher.BeforeChange(this, "AssessmentLevel");
GetDesignValue(GetProbability()).WaterLevel = value;
DataEventPublisher.AfterChange(this, "AssessmentLevel");
}
}
///
/// Level of water at riverside
///
[Label("Crest level")]
[Description("Crest level")]
[Unit(UnitType.Length)]
[Format("F2")]
[PropertyOrder(5, 2)]
public virtual double CrestLevel
{
get
{
return GetDesignValue(0.0001).CrestLevel;
}
}
///
/// Level of water at riverside
///
[Label("Overtopping volume")]
[Description("Overtopping volume")]
[Unit(UnitType.VolumePerLength)]
[Format("F2")]
[PropertyOrder(5, 3)]
public virtual double OvertoppingVolume
{
get
{
return GetDesignValue(0.0001).OvertoppingVolume;
}
}
///
/// PiezometricHead Type 1
///
[Label("PiezometricHead Type 1")]
[Description("PiezometricHead Type 1")]
[Unit(UnitType.Depth)]
[Format("F2")]
[PropertyOrder(3, 2)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
public virtual double PiezometricHead1
{
get
{
return PiezometricHeads.HeadPl1;
}
set
{
if (PiezometricHeads.HeadPl1 != value)
{
DataEventPublisher.BeforeChange(this, x => x.PiezometricHead1);
PiezometricHeads.HeadPl1 = value;
DataEventPublisher.AfterChange(this, x => x.PiezometricHead1);
}
}
}
///
/// PiezometricHead Type 2 at river side
///
[Label("PiezometricHead Type 2")]
[Description("PiezometricHead Type 2")]
[Unit(UnitType.Depth)]
[Format("F2")]
[PropertyOrder(3, 3)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
public virtual double PiezometricHead2
{
get
{
return PiezometricHeads.HeadPl2;
}
set
{
if (PiezometricHeads.HeadPl2 != value)
{
DataEventPublisher.BeforeChange(this, x => x.PiezometricHead2);
PiezometricHeads.HeadPl2 = value;
DataEventPublisher.AfterChange(this, x => x.PiezometricHead2);
}
}
}
///
/// PiezometricHead Type 3
///
[Label("PiezometricHead Type 3")]
[Description("PiezometricHead Type 3")]
[Unit(UnitType.Depth)]
[Format("F2")]
[PropertyOrder(3, 4)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
[NotClear]
public virtual double PiezometricHead3
{
get
{
return PiezometricHeads.HeadPl3;
}
set
{
if (PiezometricHeads.HeadPl3 != value)
{
DataEventPublisher.BeforeChange(this, x => x.PiezometricHead3);
PiezometricHeads.HeadPl3 = value;
DataEventPublisher.AfterChange(this, x => x.PiezometricHead3);
}
}
}
///
/// PiezometricHead Type 4
///
[Label("PiezometricHead Type 4")]
[Description("PiezometricHead Type 4")]
[Unit(UnitType.Depth)]
[Format("F2")]
[PropertyOrder(3, 5)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
public virtual double PiezometricHead4
{
get
{
return PiezometricHeads.HeadPl4;
}
set
{
if (PiezometricHeads.HeadPl4 != value)
{
DataEventPublisher.BeforeChange(this, x => x.PiezometricHead4);
PiezometricHeads.HeadPl4 = value;
DataEventPublisher.AfterChange(this, x => x.PiezometricHead4);
}
}
}
///
/// Damping Factor PL3 (only 1 aquifier layer)
///
[Label("Damping Factor PL3")]
[Description("Damping Factor PL3")]
[Unit(UnitType.None)]
[Format("F2")]
[PropertyOrder(3, 6)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
public virtual double DampingFactorPl3
{
get
{
return PiezometricHeads.DampingFactorPl3;
}
set
{
if (PiezometricHeads.DampingFactorPl3 != value)
{
DataEventPublisher.BeforeChange(this, x => x.DampingFactorPl3);
PiezometricHeads.DampingFactorPl3 = value;
DataEventPublisher.AfterChange(this, x => x.DampingFactorPl3);
}
}
}
///
/// Damping Factor PL4 (only 2 aquifier layers)
///
[Label("Damping Factor PL4")]
[Description("Damping Factor PL4")]
[Unit(UnitType.None)]
[Format("F2")]
[PropertyOrder(3, 7)]
[XmlIgnore]
[Mechanism(Mechanism.None)]
[Clearable]
public virtual double DampingFactorPl4
{
get
{
return PiezometricHeads.DampingFactorPl4;
}
set
{
if (PiezometricHeads.DampingFactorPl4 != value)
{
DataEventPublisher.BeforeChange(this, x => x.DampingFactorPl4);
PiezometricHeads.DampingFactorPl4 = value;
DataEventPublisher.AfterChange(this, x => x.DampingFactorPl4);
}
}
}
///
/// Soil Segments (per failure mechanism) for the location
///
public virtual Dictionary SoilSegments
{
get
{
return soilSegments;
}
}
///
/// Set of this.PiezometricHeads (Pl1 - Pl4 plus damping factors)
///
[Browsable(false)]
[Mechanism(Mechanism.None)]
[Validate]
public virtual PiezometricHeads PiezometricHeads
{
get
{
return piezometricHeads;
}
set
{
if (value != null)
{
this.SetAndNotify2(out piezometricHeads, value, dl => dl.PiezometricHeads);
}
}
}
///
/// Gets or sets the break water.
///
///
/// The break water.
///
[PropertyOrder(24, 6)]
[Mechanism(Mechanism.Overtopping)]
[Domain]
public virtual BreakWater BreakWater
{
get
{
return breakWater;
}
set
{
if (value != null && value == breakWater)
{
return;
}
this.SetAndNotify2(out breakWater, value, dl => dl.BreakWater);
}
}
///
/// Reference to the first station
/// Relative share of hydraulic boundary 1
///
[Label("Relative share of hydraulic boundary 1")]
[Description("Relative share of hydraulic boundary 1")]
[PropertyOrder(24, 2)]
[Mechanism(Mechanism.AssessmentLevel, Mechanism.BlockRevetment, Mechanism.AsphaltRevetment, Mechanism.Overtopping)]
[Domain]
public virtual HydraulicBoundary HydraulicBoundary1
{
get
{
return hydraulicBoundary1;
}
set
{
if (value == hydraulicBoundary1 || (value != null && value == hydraulicBoundary2))
{
return;
}
this.SetAndNotify2(out hydraulicBoundary1, value, dl => dl.HydraulicBoundary1);
}
}
///
/// Reference to the second station
/// Relative share of hydraulic boundary 2"
///
[Label("Relative share of hydraulic boundary 2")]
[Description("Relative share of hydraulic boundary 2")]
[PropertyOrder(24, 3)]
[Mechanism(Mechanism.AssessmentLevel, Mechanism.BlockRevetment, Mechanism.AsphaltRevetment, Mechanism.Overtopping)]
[Domain]
public virtual HydraulicBoundary HydraulicBoundary2
{
get
{
return hydraulicBoundary2;
}
set
{
if (value == hydraulicBoundary2 || (value != null && value == hydraulicBoundary1))
{
return;
}
this.SetAndNotify2(out hydraulicBoundary2, value, dl => dl.HydraulicBoundary2);
}
}
///
/// Indicates the relative share of boundary 2
///
[Minimum(0)]
[Maximum(1)]
[Label("Hydraulic boundary partitioning")]
[Description("Hydraulic boundary partitioning")]
[PropertyOrder(24, 4)]
//[ReadOnly(true)]
[Format("F2")]
[Unit(UnitType.Fractions)]
[Mechanism(Mechanism.AssessmentLevel, Mechanism.BlockRevetment, Mechanism.AsphaltRevetment, Mechanism.Overtopping)]
public double HydraulicBoundaryPartitioning
{
get
{
if (hydraulicBoundary1 != null && hydraulicBoundary2 != null)
{
return hydraulicBoundaryPartitioning;
}
if (hydraulicBoundary1 == null)
{
return 1;
}
if (hydraulicBoundary2 == null)
{
return 0;
}
return 0;
}
set
{
DataEventPublisher.BeforeChange(this, "HydraulicBoundaryPartitioning");
hydraulicBoundaryPartitioning = value;
DataEventPublisher.AfterChange(this, "HydraulicBoundaryPartitioning");
}
}
///
/// Gets a value indicating whether location has hydraulic boundary 1.
///
///
/// true if has hydraulic boundary 1; otherwise, false.
///
[Browsable(false)]
public bool HasHydraulicBoundary1
{
get
{
return HydraulicBoundary1 != null;
}
}
///
/// Gets a value indicating whether location has hydraulic boundary 2.
///
///
/// true if has hydraulic boundary 2; otherwise, false.
///
[Browsable(false)]
public bool HasHydraulicBoundary2
{
get
{
return HydraulicBoundary2 != null;
}
}
///
/// Auto linked to a to hydraulic boundary
///
[Label("IsAutoLinkedToHydraulicBoundary")]
[Description("IsAutoLinkedToHydraulicBoundary")]
[PropertyOrder(24, 1)]
[Mechanism(Mechanism.AssessmentLevel, Mechanism.BlockRevetment, Mechanism.AsphaltRevetment, Mechanism.Overtopping)]
public bool IsAutoLinkedToHydraulicBoundary
{
get
{
return isAutoLinkedToHydraulicBoundary;
}
set
{
DataEventPublisher.BeforeChange(this, "IsAutoLinkedToHydraulicBoundary");
isAutoLinkedToHydraulicBoundary = value;
DataEventPublisher.AfterChange(this, "IsAutoLinkedToHydraulicBoundary");
}
}
///
/// Auto linked to a to hydraulic boundary
///
[Label("IsAutoLinkedToBreakWater")]
[Description("IsAutoLinkedToBreakWater")]
[PropertyOrder(24, 5)]
[Mechanism(Mechanism.Overtopping)]
public virtual bool IsAutoLinkedToBreakWater
{
get
{
return isAutoLinkedToBreakWater;
}
set
{
DataEventPublisher.BeforeChange(this, "IsAutoLinkedToBreakWater");
isAutoLinkedToBreakWater = value;
DataEventPublisher.AfterChange(this, "IsAutoLinkedToBreakWater");
}
}
///
/// Gets the design values.
///
///
/// The design values.
///
[Label("DesignValues")]
[Description("DesignValues")]
[ReadOnly(true)]
[Browsable(false)]
public virtual List DesignValues
{
get
{
return OriginalDikeLocation != null ? OriginalDikeLocation.DesignValues : designValues;
}
}
///
/// Determines whether the probability has a design value.
///
/// The probability.
///
/// true if design value for probability can be found; otherwise, false.
///
public bool HasDesignValue(double probability)
{
foreach (var designValue in DesignValues)
{
if (Math.Abs(designValue.Probability - probability) < 1E-12)
{
return true;
}
}
return false;
}
///
/// Gets or creates the design value for given probability.
///
/// The probability.
/// design value
public DesignValue GetDesignValue(double probability)
{
foreach (var designValue in DesignValues)
{
if (Math.Abs(designValue.Probability - probability) < 1E-12)
{
return designValue;
}
}
var newDesignValue = new DesignValue();
newDesignValue.Probability = probability;
DesignValues.Add(newDesignValue);
return newDesignValue;
}
///
/// Gets the most important boundary.
///
/// most important hydraulic boundary
public HydraulicBoundary GetMostImportantBoundary()
{
if (HydraulicBoundary2 == null)
{
return HydraulicBoundary1;
}
else if (HydraulicBoundary1 == null)
{
return HydraulicBoundary2;
}
else if (HydraulicBoundaryPartitioning >= 0.5)
{
return HydraulicBoundary1;
}
else
{
return HydraulicBoundary2;
}
}
private double GetProbability()
{
double probability = 0.001;
if (DikeLine != null && DikeLine.AllowedFailureProbability != null)
{
probability = DikeLine.AllowedFailureProbability.Probability;
}
return probability;
}
#endregion geotechnical properties
#region IDomain Members
///
/// Function to get the ten nearest HydraulicBoundaries
///
[XmlIgnore]
[Browsable(false)]
public static Func, int, IList> GetNNearestHydraulicBoundaries { get; set; }
///
/// Function to get the ten nearest BreakWaters
///
[XmlIgnore]
[Browsable(false)]
public static Func, List> Get10NearestBreakWaters { get; set; }
///
/// Gets the domain.
///
/// The property.
/// domain
public virtual ICollection GetDomain(string property)
{
switch (property)
{
case "SurfaceLine":
return DomainProvider.GetDomain("SurfaceLine");
case "HydraulicBoundary1":
return GetHydraulicBoundaryDomain(HydraulicBoundary1, HydraulicBoundary2);
case "HydraulicBoundary2":
return GetHydraulicBoundaryDomain(HydraulicBoundary2, HydraulicBoundary1);
case "BreakWater":
return GetBreakWaterDomain();
default:
return DomainProvider.GetDomain(property);
}
}
private ICollection GetHydraulicBoundaryDomain(HydraulicBoundary includedHydraulicBoundary, HydraulicBoundary excludedHydraulicBoundary)
{
if (GetNNearestHydraulicBoundaries == null)
{
return null;
}
IList boundaries = new List();
boundaries.AddRange(GetNNearestHydraulicBoundaries(GetRepresentivePoint(),
(List)
DomainProvider.GetDomain("HydraulicBoundaries"),
numberOfClosestHydraulicConditions));
if (includedHydraulicBoundary != null && !boundaries.Contains(includedHydraulicBoundary))
{
boundaries.Insert(0, includedHydraulicBoundary);
}
if (excludedHydraulicBoundary != null && boundaries.Contains(excludedHydraulicBoundary))
{
boundaries.Remove(excludedHydraulicBoundary);
}
return boundaries.ToArray();
}
private ICollection GetBreakWaterDomain()
{
if (Get10NearestBreakWaters == null)
{
return BreakWater != null ? new[]
{
BreakWater
} : null;
}
return Get10NearestBreakWaters(GetRepresentivePoint(), (List)DomainProvider.GetDomain("BreakWaters"));
}
#endregion
#region Validation methods
///
/// Checks whether hydraulic boundaries have been attached
///
/// Validation results
[Validate]
public ValidationResult[] ValidateHydraulicBoundaries()
{
if (HydraulicBoundary1 == null && HydraulicBoundary2 == null)
{
return new[]
{
new ValidationResult(ValidationResultType.Error, getErrorMessageForMissingBoundaryLink(), "HydraulicBoundary", this)
};
}
else
{
return new ValidationResult[0];
}
}
///
/// Checks whether attached hydraulic boundaries have same regionId
///
/// Validation results
[Validate]
public ValidationResult[] ValidateRegionHydraulicBoundaries()
{
if (HydraulicBoundary1 != null && HydraulicBoundary2 != null && HydraulicBoundary1.Region.Id != HydraulicBoundary2.Region.Id)
{
return new[]
{
new ValidationResult(ValidationResultType.Error, String.Format(LocalizationManager.GetTranslatedText(this, "DikeLocationHydraulicBoundariesNotFromTheSameRegionMessage"), Name), this)
};
}
else
{
return new ValidationResult[0];
}
}
#endregion
///
/// Returns a that represents this instance.
///
///
/// A that represents this instance.
///
public override string ToString()
{
return Name;
}
#region IDisposable
public virtual void Dispose()
{
if (schematizedSurfaceLine != null)
{
schematizedSurfaceLine.Dispose();
}
if (blockRevetmentCrossSection != null)
{
blockRevetmentCrossSection.Dispose();
}
if (importedAsphaltCrossSection != null)
{
importedAsphaltCrossSection.Dispose();
}
if (importedRoughnessCrossSection != null)
{
importedRoughnessCrossSection.Dispose();
}
//DataEventPublisher.OnDataListModified -= RevetmentZoneListModified; // TODO: If re-enabled, add counterpart to Dispose method!
DataEventPublisher.OnAfterChange -= DataEventPublisher_OnAfterChange;
}
#endregion
#region IConnect Members
///
/// Trying to connect to the target Object,
/// X and Y are real world Coordinates
///
///
/// true if successful, otherwise false
public bool TryToConnectToObject(object targetObject)
{
var targetAsHydraulicBoundary = targetObject as HydraulicBoundary;
if (targetAsHydraulicBoundary != null)
{
if (HydraulicBoundary1 == null)
{
IsAutoLinkedToHydraulicBoundary = false;
HydraulicBoundary1 = targetAsHydraulicBoundary;
return true;
}
else
{
IsAutoLinkedToHydraulicBoundary = false;
HydraulicBoundary2 = targetAsHydraulicBoundary;
return true;
}
}
var targetAsBreakWater = targetObject as BreakWater;
if (targetAsBreakWater != null)
{
IsAutoLinkedToBreakWater = false;
BreakWater = targetAsBreakWater;
return true;
}
return false;
}
#endregion
#region IVisibleEnabled Members
///
/// Visibility injection to overrule the IsVisible (Stability.Calculation and Stability.Calculation2 (new) needs different inputs, but the mechanism.stability doesn't determine ..
/// bool? => if the injector doesn't want to control the visibility it returns null
///
[XmlIgnore]
[Browsable(false)]
public static Func IsVisibleInjection { private get; set; }
///
/// Determines whether the specified property is enabled.
///
/// The property.
/// true if property is enabled; otherwise, false.
public virtual bool IsEnabled(string property)
{
if (property == this.GetMemberName(x => x.Name))
{
return Context.IsEnabled(this, this.GetMemberName(x => x.Name)) ?? true;
}
if (property == this.GetMemberName(x => x.HydraulicBoundary1))
{
return !IsAutoLinkedToHydraulicBoundary;
}
if (property == this.GetMemberName(x => x.HydraulicBoundary2))
{
return !IsAutoLinkedToHydraulicBoundary && HydraulicBoundary1 != null;
}
if (property == this.GetMemberName(x => x.HydraulicBoundaryPartitioning))
{
return !IsAutoLinkedToHydraulicBoundary && HydraulicBoundary1 != null && HydraulicBoundary2 != null;
}
if (property == this.GetMemberName(x => x.BreakWater))
{
return !IsAutoLinkedToBreakWater;
}
return true;
}
///
/// Determines whether the specified property is visible.
///
/// The property.
/// true if property is visible; otherwise, false.
public virtual bool IsVisible(string property)
{
if (IsVisibleInjection != null)
{
var result = IsVisibleInjection.Invoke(this, property);
if (result != null)
{
return result == true;
}
}
if (!MechanismSupport.IsMechanismVisible(typeof(DikeLocation), property))
{
return false;
}
if (VisibleEnabledProvider != null && !VisibleEnabledProvider.IsVisible(this, property))
{
return false;
}
const double tolerance = 1e-4;
switch (property)
{
case "Angle":
return SurfaceLine != null;
case "HasHydraulicBoundary1":
return HasHydraulicBoundary1;
case "HasHydraulicBoundary2":
return HasHydraulicBoundary2;
case "HydraulicBoundaryPartitioning":
return HydraulicBoundary1 != null && HydraulicBoundary2 != null;
//case "AssessmentLevel":
// return HasDesignValue(tolerance) && !Double.IsNaN(GetDesignValue(tolerance).WaterLevel);
case "CrestLevel":
return HasDesignValue(tolerance) && !Double.IsNaN(GetDesignValue(tolerance).CrestLevel);
case "OvertoppingVolume":
return HasDesignValue(tolerance) && !Double.IsNaN(GetDesignValue(tolerance).OvertoppingVolume);
case "RevertSurfaceLine":
return OriginalDikeLocation != null;
default:
return true;
}
}
#endregion
private void DataEventPublisher_OnAfterChange(object sender, PublishEventArgs e)
{
if (sender == SchematizedSurfaceLine)
{
DataEventPublisher.AfterChange(this, x => x.SchematizedSurfaceLine);
}
else if (sender == OriginalDikeLocation)
{
DataEventPublisher.AfterChange(this, e.Properties);
}
}
}
}