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.Reflection; using Deltares.Standard.Units; using Deltares.Standard.Validation; namespace Deltares.DeltaModel { /// /// DikeLocation as a section with begin and end /// public class DikeSection : DikeLocation, IGeographicString { # region Field variables private readonly List dikeCrossSections = new List(); /// /// Start of section /// private DikeLinePoint beginPoint; /// /// End of section /// private DikeLinePoint endPoint; /// /// Dike Cross Section which represents this Dike Section /// private DikeCrossSection representativeDikeCrossSection; # endregion /// /// Initializes a new instance of the class. /// public DikeSection() { DataEventPublisher.OnAfterChange += DataEventPublisher_OnAfterChange; } /// /// Start of section /// /// /// The begin point. /// [Label("")] [Description("")] [XmlIgnore] public DikeLinePoint BeginPoint { get { return beginPoint; } set { DataEventPublisher.BeforeChange(this, ds => ds.BeginPoint); beginPoint = value; if (beginPoint != null) { beginPoint.DikeLine = DikeLine; } DataEventPublisher.AfterChange(this, ds => ds.BeginPoint); } } /// /// End of section /// /// /// The end point. /// [Label("")] [Description("")] [XmlIgnore] public DikeLinePoint EndPoint { get { return endPoint; } set { DataEventPublisher.BeforeChange(this,ds => ds.EndPoint); endPoint = value; if (endPoint != null) { endPoint.DikeLine = DikeLine; } DataEventPublisher.AfterChange(this, ds => ds.EndPoint); } } /// /// Dike Cross Section which represents this Dike Section /// [Domain] [Category("Location")] [XmlIgnore] public DikeCrossSection RepresentativeDikeCrossSection { get { return representativeDikeCrossSection; } set { this.SetAndNotify2(out representativeDikeCrossSection, value, ds => ds.RepresentativeDikeCrossSection); } } /// /// Gets or sets the offset end point. /// /// /// The offset end point. /// [Browsable(false)] [PropertyOrder(1, 14)] [Format("F2")] [Unit(UnitType.Length)] [Category("Location")] [XmlIgnore] public double OffsetEndPoint { get { return EndPoint.Offset; } set { DataEventPublisher.BeforeChange(this, ds => ds.OffsetEndPoint); EndPoint.Offset = value; DataEventPublisher.AfterChange(this, ds => ds.OffsetEndPoint); } } /// /// Gets or sets the offset begin point. /// /// /// The offset begin point. /// [Browsable(false)] [PropertyOrder(1, 13)] [Format("F2")] [Unit(UnitType.Length)] [Category("Location")] [XmlIgnore] public double OffsetBeginPoint { get { return BeginPoint.Offset; } set { DataEventPublisher.BeforeChange(this,ds => ds.OffsetBeginPoint); BeginPoint.Offset = value; DataEventPublisher.AfterChange(this, ds => ds.OffsetBeginPoint); } } /// /// Gets or sets the name. /// /// /// The name. /// [XmlIgnore] public override string Name { get { if (string.IsNullOrWhiteSpace(base.Name)) { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.Name : base.Name; } return base.Name; } } /// /// The dikeline to which this location belongs /// // TODO can be replaced by the Point's implementation... [XmlIgnore] public override DikeLine DikeLine { get { return base.DikeLine; } set { base.DikeLine = value; if (beginPoint != null) { beginPoint.DikeLine = value; } if (endPoint != null) { endPoint.DikeLine = value; } } } /// /// Gets the offset, which is the center point of the section, of the section along the dike line. /// [XmlIgnore] public override double Offset { get { if (EndPoint.Offset >= BeginPoint.Offset) { return (BeginPoint.Offset + EndPoint.Offset)/2; } else { // Cyclic return (BeginPoint.Offset + Length/2)%DikeLine.Length; } } } /// /// Gets or sets the original dike location. /// /// /// The original dike location. /// [Browsable(false)] [XmlIgnore] public override DikeLocation OriginalDikeLocation { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.OriginalDikeLocation : null; } set { if (RepresentativeDikeCrossSection != null) { RepresentativeDikeCrossSection.OriginalDikeLocation = value; } } } [XmlIgnore] public override BlockRevetmentCrossSection BlockRevetmentCrossSection { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.BlockRevetmentCrossSection : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, x => x.BlockRevetmentCrossSection); RepresentativeDikeCrossSection.BlockRevetmentCrossSection = value; DataEventPublisher.AfterChange(this, x => x.BlockRevetmentCrossSection); } } } [XmlIgnore] public override BlockRevetmentRegion BlockRevetmentRegion { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.BlockRevetmentRegion : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.BlockRevetmentRegion); RepresentativeDikeCrossSection.BlockRevetmentRegion = value; DataEventPublisher.AfterChange(this, ds => ds.BlockRevetmentRegion); } } } [XmlIgnore] public override RoughnessCrossSection RoughnessCrossSection { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.RoughnessCrossSection : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.RoughnessCrossSection); RepresentativeDikeCrossSection.RoughnessCrossSection = value; DataEventPublisher.AfterChange(this, ds => ds.RoughnessCrossSection); } } } [XmlIgnore] public override AsphaltCrossSection AsphaltCrossSection { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.AsphaltCrossSection : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.AsphaltCrossSection); RepresentativeDikeCrossSection.AsphaltCrossSection = value; DataEventPublisher.AfterChange(this, ds => ds.AsphaltCrossSection); } } } [XmlIgnore] public override AsphaltRegion AsphaltRegion { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.AsphaltRegion : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.AsphaltRegion); RepresentativeDikeCrossSection.AsphaltRegion = value; DataEventPublisher.AfterChange(this, ds => ds.AsphaltRegion); } } } /// /// Length of the dike location /// [Label("Length")] [Description("Length of the section")] [Unit(UnitType.Length)] [Format("F2")] [ReadOnly(true)] [XmlIgnore] [PropertyOrder(1, 15)] public override double Length { get { return EndPoint.Offset - BeginPoint.Offset; } set {} } /// /// Soil Segments (per failure mechanism) for the location /// [XmlIgnore] public override Dictionary SoilSegments { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.SoilSegments : base.SoilSegments; } } /// /// Gets or sets the break water. /// /// /// The break water. /// [XmlIgnore] public override BreakWater BreakWater { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.BreakWater : null; } set { DataEventPublisher.BeforeChange(this, ds => ds.BreakWater); RepresentativeDikeCrossSection.BreakWater = value; DataEventPublisher.AfterChange(this, ds => ds.BreakWater); } } /// /// Gets or sets the auto setting for break water. /// /// /// The break water. /// [XmlIgnore] public override bool IsAutoLinkedToBreakWater { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.IsAutoLinkedToBreakWater : base.IsAutoLinkedToBreakWater; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.IsAutoLinkedToBreakWater); RepresentativeDikeCrossSection.IsAutoLinkedToBreakWater = value; DataEventPublisher.AfterChange(this, ds => ds.IsAutoLinkedToBreakWater); } } } /// /// Reference to the first station /// Relative share of hydraulic boundary 1 /// [XmlIgnore] public override HydraulicBoundary HydraulicBoundary1 { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.HydraulicBoundary1 : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, x => x.HydraulicBoundary1); RepresentativeDikeCrossSection.HydraulicBoundary1 = value; DataEventPublisher.AfterChange(this, x => x.HydraulicBoundary1); } } } /// /// Reference to the first station /// Relative share of hydraulic boundary 2 /// [XmlIgnore] public override HydraulicBoundary HydraulicBoundary2 { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.HydraulicBoundary2 : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, x => HydraulicBoundary2); RepresentativeDikeCrossSection.HydraulicBoundary2 = value; DataEventPublisher.AfterChange(this, x => HydraulicBoundary2); } } } /// /// Surfaceline that is schematized for a specific mechanism /// /// /// The schematized surface line. /// [XmlIgnore] [Validate] public override SurfaceLine2 SchematizedSurfaceLine { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.SchematizedSurfaceLine : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.SchematizedSurfaceLine); RepresentativeDikeCrossSection.SchematizedSurfaceLine = value; DataEventPublisher.AfterChange(this, ds => ds.SchematizedSurfaceLine); } } } /// /// gets or sets Surfaceline /// /// /// The surface line. /// [XmlIgnore] public override LocalizedGeometryPointString SurfaceLine { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.SurfaceLine : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, ds => ds.SurfaceLine); RepresentativeDikeCrossSection.SurfaceLine = value; DataEventPublisher.AfterChange(this, ds => ds.SurfaceLine); } } } /// /// gets or sets piezometric heads /// [XmlIgnore] public override PiezometricHeads PiezometricHeads { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.PiezometricHeads : null; } set { if (RepresentativeDikeCrossSection != null) { DataEventPublisher.BeforeChange(this, x => x.PiezometricHeads); RepresentativeDikeCrossSection.PiezometricHeads = value; DataEventPublisher.AfterChange(this, x => x.PiezometricHeads); } } } /// /// Get or Set Assessment Level /// public override double AssessmentLevel { get { if (RepresentativeDikeCrossSection != null) { return RepresentativeDikeCrossSection.AssessmentLevel; } return double.NaN; } } /// /// Gets or sets the flow speed. /// /// /// The flow speed. /// [XmlIgnore] public override double FlowSpeed { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.FlowSpeed : 1; } set { if (RepresentativeDikeCrossSection != null) { RepresentativeDikeCrossSection.FlowSpeed = value; } } } /// /// Gets the design values. /// /// /// The design values. /// [XmlIgnore] public override List DesignValues { get { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.DesignValues : base.DesignValues; } } /// /// Gets a representation of this dike section using . This representation starts with the /// and ends with the and all the points on the which are between these two points. /// /// Shallow copy of , points of and . [XmlIgnore] public IList Points { get { if (BeginPoint == null || DikeLine == null) { return null; } var points = new List { BeginPoint }; points.AddRange(DikeLine.GetPointBetweenOffsets(BeginPoint.Offset, EndPoint.Offset)); points.Add(EndPoint); return points; } } /// /// Function to get the ten nearest BreakWaters /// [XmlIgnore] [Browsable(false)] public static Func> GetCrossSections { get; set; } /// /// Creates a dike section based on the dike line end begin point info. /// /// The dike line. /// The begin. /// dike section public static DikeSection Create(DikeLine dikeLine, DikeLinePoint begin) { var dikeSection = Create(dikeLine, begin, new DikeLinePoint(dikeLine.Length, dikeLine)); return dikeSection; } /// /// Creates a dike section based on the dike line, begin and end point info. /// /// The dike line. /// The begin. /// The end. /// dike section public static DikeSection Create(DikeLine dikeLine, DikeLinePoint begin, DikeLinePoint end) { return new DikeSection { DikeLine = dikeLine, BeginPoint = begin, EndPoint = end }; } /// /// Gets the representive point. /// /// /// representative point /// public override IGeographicPoint GetRepresentivePoint() { return RepresentativeDikeCrossSection != null ? RepresentativeDikeCrossSection.GetRepresentivePoint() : BeginPoint; } /// /// Gets the distance to a given location along the same dike line /// /// Location /// Distance public override double GetDistance(double x) { if (OffsetBeginPoint <= OffsetEndPoint) { if (OffsetBeginPoint <= x && OffsetEndPoint >= x) { return 0; } else if (x < OffsetBeginPoint) { return OffsetBeginPoint - x; } else { return x - OffsetEndPoint; } } else { // Cyclic if (x <= OffsetEndPoint || x >= OffsetBeginPoint) { return 0; } else if (x < OffsetBeginPoint) { return OffsetBeginPoint - x; } else { return x - OffsetEndPoint; } } } [Obsolete("Only used for serialization", true)] private SerializedDikeSection State { get { return new SerializedDikeSection(this); } set { DikeLine = value.DikeLine; BeginPoint = value.BeginPoint; EndPoint = value.EndPoint; RepresentativeDikeCrossSection = value.RepresentativeDikeCrossSection; Name = value.Name; } } private void DataEventPublisher_OnAfterChange(object sender, PublishEventArgs e) { var offsetChanged = e.Property == StaticReflection.GetMemberName(ds => ds.Offset); if (ReferenceEquals(sender, BeginPoint) && offsetChanged) { RestrictBeginPointOffsets(); DataEventPublisher.AfterChange(this, ds => ds.BeginPoint); } if (ReferenceEquals(sender, EndPoint) && offsetChanged) { RestrictEndPointOffsets(); } if (ReferenceEquals(sender, RepresentativeDikeCrossSection)) { DataEventPublisher.AfterChange(this, e.Properties); } } private void RestrictEndPointOffsets() { if (endPoint.Offset - beginPoint.Offset <= 0) { endPoint.Offset = beginPoint.Offset + 1; } } private void RestrictBeginPointOffsets() { if (endPoint.Offset - beginPoint.Offset <= 0) { beginPoint.Offset = endPoint.Offset - 1; } } # region Methods /// /// Gets the dike cross sections. /// /// /// The dike cross sections. /// public List DikeCrossSections { get { return dikeCrossSections; } } /// /// Gets the domain. /// /// The property. /// /// domain /// public override ICollection GetDomain(string property) { if (property == StaticReflection.GetMemberName(ds => RepresentativeDikeCrossSection)) { return GetCrossSectionsDomain(); } return base.GetDomain(property); } /// /// Gets the cross sections domain. /// /// Domain private ICollection GetCrossSectionsDomain() { if (GetCrossSections == null) { return null; } return GetCrossSections(this).ToList(); } #region IDisposable public override void Dispose() { DataEventPublisher.OnAfterChange -= DataEventPublisher_OnAfterChange; base.Dispose(); } #endregion #endregion #region class SerializedDikeSection private class SerializedDikeSection { public SerializedDikeSection(DikeSection point) { DikeLine = point.DikeLine; BeginPoint = point.BeginPoint; EndPoint = point.EndPoint; RepresentativeDikeCrossSection = point.RepresentativeDikeCrossSection; Name = point.Name; } private SerializedDikeSection() { } public DikeLine DikeLine { get; private set; } public DikeLinePoint BeginPoint { get; private set; } public DikeLinePoint EndPoint { get; private set; } public DikeCrossSection RepresentativeDikeCrossSection { get; private set; } public String Name { get; private set; } } #endregion } }