using System; using System.ComponentModel; using System.Drawing; using System.Xml.Serialization; using Deltares.Geometry; using Deltares.Geotechnics.Soils; using Deltares.Standard; using Deltares.Standard.EventPublisher; namespace Deltares.Stability { public enum GridOrientation { Inwards, Outwards } public interface ITangentLinesBoundaries { double XLeft { get; } double XRight { get; } } public interface ISlipCircleGridOwner { SlipCircleTangentLine SlipCircleTangentLine { get; } StabilityModel StabilityModel { get; } } public class SlipCircle : GeometryObject, IVisibleEnabled, ITangentLinesBoundaries, ISlipCircleGridOwner, IDisposable { private bool auto = false; private SlipCircleGrid movedSlipCircleGrid = new SlipCircleGrid { Color = Color.LightCoral, IsReadOnly = true }; private GridOrientation orientation = GridOrientation.Inwards; private SlipCircleFixedPoint slipCircleFixedPoint = new SlipCircleFixedPoint(); private SlipCircleGrid slipCircleGrid = new SlipCircleGrid(); private SlipCircleTangentLine slipCircleTangenTLine = new SlipCircleTangentLine(); private StabilityModel stabilityModel; public SlipCircle() { DataEventPublisher.InvokeWithoutPublishingEvents(() => { SlipCircleGrid.Name = "Calculation Grid"; SlipCircleTangentLine.Name = "Calculation Tangent Lines"; SlipCircleFixedPoint.Name = "Fixed Point"; SlipCircleTangentLine.TangentLinesBoundaries = this; slipCircleGrid.Owner = this; movedSlipCircleGrid.Owner = this; slipCircleFixedPoint.Owner = this; }); } [Browsable(false)] [XmlElement("FixedPoint")] public SlipCircleFixedPoint SlipCircleFixedPoint { get { return slipCircleFixedPoint; } set { DataEventPublisher.BeforeChange(this, "SlipCircleFixedPoint"); slipCircleFixedPoint = value; DataEventPublisher.AfterChange(this, "SlipCircleFixedPoint"); } } [Browsable(false)] [XmlElement("CalculationGrid")] public SlipCircleGrid SlipCircleGrid { get { return slipCircleGrid; } set { DataEventPublisher.BeforeChange(this, "SlipCircleGrid"); slipCircleGrid = value; slipCircleGrid.Owner = this; DataEventPublisher.AfterChange(this, "SlipCircleGrid"); } } [Browsable(false)] public SlipCircleGrid MovedSlipCircleGrid { get { return movedSlipCircleGrid; } set { var tmp = value; if (tmp != null) { tmp.IsReadOnly = true; } DataEventPublisher.BeforeChange(this, "MovedSlipCircleGrid"); movedSlipCircleGrid = value; movedSlipCircleGrid.Owner = this; DataEventPublisher.AfterChange(this, "MovedSlipCircleGrid"); } } public virtual bool Auto { get { if (stabilityModel != null && stabilityModel.CalculationModel == CalculationModel.RTO) { return auto; } else { return false; } } set { this.SetAndNotify2(out auto, value, s => s.Auto); } } public GridOrientation Orientation { get { return orientation; } set { DataEventPublisher.BeforeChange(this, "Orientation"); orientation = value; DataEventPublisher.AfterChange(this, "Orientation"); } } #region IVisibleEnabled Members public bool IsEnabled(string property) { switch (property) { case "Orientation": return Auto; case "SlipCircleFixedPoint": return slipCircleFixedPoint.UseFixedPoint; default: return true; } } public bool IsVisible(string property) { // Note: This clause is required because binding can keep an instance of SlipCircle // alive while the composite owner of SlipCircle is disposed (setting StabilityModel // to null). if (stabilityModel == null) { return false; } switch (property) { case "Auto": return stabilityModel.CalculationModel == CalculationModel.RTO; case "SlipCircleFixedPoint": return slipCircleFixedPoint.UseFixedPoint; default: return stabilityModel.ModelOption == ModelOptions.Bishop || stabilityModel.ModelOption == ModelOptions.BishopProbabilityRandomField || stabilityModel.ModelOption == ModelOptions.Fellenius; } } #endregion [Browsable(false)] [XmlElement("TangentLines")] public SlipCircleTangentLine SlipCircleTangentLine { get { return slipCircleTangenTLine; } set { DataEventPublisher.BeforeChange(this, "SlipCircleTangentLine"); if (null != slipCircleTangenTLine) { slipCircleTangenTLine.Dispose(); // Dispose the old object } slipCircleTangenTLine = value; slipCircleTangenTLine.TangentLinesBoundaries = this; slipCircleTangenTLine.StabilityModel = StabilityModel; DataEventPublisher.AfterChange(this, "SlipCircleTangentLine"); } } [XmlIgnore] [Browsable(false)] public StabilityModel StabilityModel { get { return stabilityModel; } set { stabilityModel = value; if (slipCircleTangenTLine != null) { slipCircleTangenTLine.StabilityModel = value; } } } [Browsable(false)] public double XLeft { get { if (SlipCircleFixedPoint.UseFixedPoint) { return Math.Max(stabilityModel.GeometryData.Left, SlipCircleFixedPoint.XFixed - SlipCircleTangentLine.TangentLineOffset); } else { return Math.Max(stabilityModel.GeometryData.Left, SlipCircleGrid.GridXLeft - SlipCircleTangentLine.TangentLineOffset); } } } [Browsable(false)] public double XRight { get { if (SlipCircleFixedPoint.UseFixedPoint) { return Math.Min(stabilityModel.GeometryData.Right, SlipCircleFixedPoint.XFixed + SlipCircleTangentLine.TangentLineOffset); } else { return Math.Min(stabilityModel.GeometryData.Right, SlipCircleGrid.GridXRight + SlipCircleTangentLine.TangentLineOffset); } } } public virtual void Dispose() { // Break back-reference: slipCircleGrid.Owner = null; movedSlipCircleGrid.Owner = null; slipCircleFixedPoint.Owner = null; slipCircleTangenTLine.Dispose(); } } }