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); } } } }