using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Xml.Serialization; using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.Consolidation; using Deltares.Geotechnics.GeotechnicalGeometry; using Deltares.Geotechnics.Mechanisms; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Geotechnics.Validation; using Deltares.Geotechnics.WaternetCreator; using Deltares.Mathematics; using Deltares.Probabilistic; using Deltares.Standard; using Deltares.Standard.Attributes; using Deltares.Standard.Data; using Deltares.Standard.EventPublisher; using Deltares.Standard.Extensions; using Deltares.Standard.Language; using Deltares.Standard.Project; using Deltares.Standard.Units; using Deltares.Standard.Validation; namespace Deltares.Stability { public enum CalculationModel { DSerie, RTO, WBI } public enum SearchAlgorithm { Grid, Genetic, LevenbergMarquardt, GeneticAndLevenbergMarquardt } public enum NailLateralStress { [Translation("NailLateralStressUltimate")] Ultimate, [Translation("NailLateralStressSoil")] Soil } public enum NailShearStress { [Translation("NailShearStressUltimate")] Ultimate, [Translation("NailShearStressBond")] Bond } public enum SlipPlanePosition { Low, High } [Impact(Impact.Computation)] public class StabilityModel : IGeometryModel, IGeometryBuilderListeners, IVisibleEnabled, ISoilPropertyManager, IDescriptive, IDomain, IVisibleEnabledProvider, IDisposable { #region Private variables private readonly List forbiddenLinesList = new List(); private readonly List geotextiles = new List(); private readonly List lineLoads = new List(); private readonly DelegatedList nails = new DelegatedList(); private readonly DelegatedList slipPlaneList = new DelegatedList(); private readonly List stochasts = new List(); private readonly List uniformLoadsData = new List(); private readonly StabilityModelValidator validator; internal RTOCalculationgrid rtoCalculationgrid = null; private Project projectInfo = new Project(); private bool autoGenerateGeneticSpencer; private CalculationModel calculationModel = CalculationModel.DSerie; private UniformLoad consolidationLoad = new UniformLoad(); private DegreeofConsolidationMatrix consolidationMatrix = new DegreeofConsolidationMatrix(); private bool consolidationMatrixDirty = true; private IDisposable createdSurfaceLineToDispose; private long curveDescriptionCounter; private ReliabilityAnalysisOption defaultInputModeAnalysisOption = ReliabilityAnalysisOption.Mean; private Nail defaultNail = new Nail(); private ShearStrengthModel defaultShearStrengthModel = ShearStrengthModel.CPhi; private Earthquake earthquake = new Earthquake(); private long forbiddenLineCounter = 1; private bool generateSlipPlane = false; private GeneticAlgorithmOptions geneticAlgorithmOptions; private GridOrientation gridOrientation; private bool hasGeotextile = false; private bool hasNails = false; private bool hasZonePlot = false; private HorizontalBalance horizontalBalance; private bool isEndSectionFrictionUsed = false; private LevenbergMarquardtOptions levenbergMarquardtOptions = new LevenbergMarquardtOptions(); private long lineLoadDescriptionCounter = 1; private StabilityLocation location = new StabilityLocation(); private double maxAllowedAngleBetweenSlices = 60.0; private double maximumSliceWidth = 1.0; private Measurement measurement = Measurement.Global; private SlidingCurve minimumSafetyCurve = null; private ModelOptions modelOption = ModelOptions.Bishop; private bool moveGrid = true; private List multiplicationFactorsCPhiForUpliftList = new List(); private long nailDescriptionCounter = 1; private NailLateralStress nailLateralStress = NailLateralStress.Ultimate; private NailShearStress nailShearStress = NailShearStress.Ultimate; private int numberOfGridMoves = 50; private bool onlyMinimumSafetyCurve = false; private bool preciseGA = false; private double preconsolidationStressModelFactor = 1; private int previousSoilCount; private ProbabilisticCalculationType probabilisticCalculationType = ProbabilisticCalculationType.Probabilistic; private ProbabilisticDefaults probabilisticDefaults = new ProbabilisticDefaults(); private ReferenceLevelLine referenceLevelLine; private double requiredForcePointsInSlices = 0.8; private SlidingSimpleCurve resultSlidingCurve = new SlidingSimpleCurve(); private SearchAlgorithm searchAlgorithm = SearchAlgorithm.Grid; private SliceData sliceData = new SliceData(); private SlidingModel slidingModel = null; private SlipCircle slipCircle = new SlipCircle(); private int slipInterval = 0; private SlipPlanePosition slipPlanePosition = SlipPlanePosition.High; private SlipPlaneUpliftVan slipPlaneUpliftVan = new SlipPlaneUpliftVan(); private SlipplaneConstraints slipplaneConstraints = new SlipplaneConstraints(); private SoilModel soilModel = new SoilModel(); private SoilProfile2D soilProfile = new SoilProfile2D(); private long soilSurfaceDescriptionCounter = 1; private StabilityTransformer stabilityTransformer = new StabilityTransformer(); private double startValueSafetyFactor = 1; private StressesInGeometry stressesInGeometry = new StressesInGeometry(); private SurfaceLine2 surfaceLine2; private GeometryPointStringAttacher surfaceLineAttacher = new GeometryPointStringAttacher(); private int traversalGridPoints = 2; private TreeOnSlope treeOnSlope; private long uniformLoadDescriptionCounter = 1; private bool updatingWaternet = false; private GeotechnicsModel waterData = new GeotechnicsModel(); private Stochast modelUncertaintyParameterStochast = new Stochast("ModelUncertaintyParameter", DistributionType.Deterministic, 1); private ZoneAreas zoneAreas = new ZoneAreas(); #endregion public StabilityModel() { validator = new StabilityModelValidator(this); IsStressCreated = false; DataEventPublisher.OnChanged += OnPublisherChanged; DataEventPublisher.OnDataListModified += DataEventPublisher_OnDataListModified; DataEventPublisher.OnAfterChange += OnAfterChangePublisher; location.StabilityModel = this; SurfaceLine2 = new SurfaceLine2 { CharacteristicPoints = { GeometryMustContainPoint = false }, Geometry = new LocalizedGeometryPointString() }; createdSurfaceLineToDispose = surfaceLine2; rtoCalculationgrid = new RTOCalculationgrid(this); zoneAreas.StabilityModel = this; slipPlaneUpliftVan.StabilityModel = this; slipCircle.StabilityModel = this; stressesInGeometry.SoilProfile2D = SoilProfile; stressesInGeometry.WaternetModel = waterData.CurrentWaternet; nails.AddMethod = AddNail; slipPlaneList.AddMethod = AddSlipPlane; slipPlaneUpliftVan.StabilityModel = this; modelUncertaintyParameterStochast.Owner = this; consolidationLoad.Name = "Load"; stabilityTransformer.StabilityModel = this; surfaceLineAttacher.SurfaceLineProvider = GeometryData; waterData.Geometry = this.Geometry; geneticAlgorithmOptions = new GeneticAlgorithmOptions { Seed = 1 }; } public bool IsTreeOnSlopeVisible() { bool isVisible = false; if (treeOnSlope != null && ModelOption != ModelOptions.Spencer) { if (treeOnSlope.WindForce == 0.0) { isVisible = false; } else { isVisible = true; } } return isVisible; } /// /// Create Soil Surface /// /// /// public SoilLayer2D CreateSoilSurface(GeometrySurface aNewSurface) { SoilLayer2D LNewSoilSurface = GetExistingSoilSurface(aNewSurface); if (LNewSoilSurface != null) { return LNewSoilSurface; } DataEventPublisher.BeforeChange(this, "SoilSurfaces"); LNewSoilSurface = new SoilLayer2D(); LNewSoilSurface.GeometricObject = aNewSurface; Create(LNewSoilSurface); if (soilModel.DefaultStabilitySoilMaterial != null) { LNewSoilSurface.Soil = soilModel.DefaultStabilitySoilMaterial; } DataEventPublisher.Changed(LNewSoilSurface); DataEventPublisher.AfterChange(this, "SoilSurfaces"); return LNewSoilSurface; } public SoilLayer2D GetExistingSoilSurface(GeometrySurface aNewSurface) { foreach (var soilSurface in soilProfile.Surfaces) { if (soilSurface.GeometrySurface.OuterLoop.CurveList.Count == aNewSurface.OuterLoop.CurveList.Count) { bool isSame = true; foreach (var curve in soilSurface.GeometrySurface.OuterLoop.CurveList) { if (!aNewSurface.OuterLoop.CurveList.Contains(curve)) { isSame = false; break; } } if (isSame) { return soilSurface; } } } return null; } public void SortPointListX(ref List pointList) { int count = pointList.Count; for (int i = (count - 1); i >= 0; i--) { for (int j = 1; j <= i; j++) { if (pointList[j - 1].X >= pointList[j].X) { GeometryPoint temp = pointList[j - 1]; pointList[j - 1] = pointList[j]; pointList[j] = temp; } } } } public bool HandleDelete(List aList) { bool isDeleted = false; foreach (var anObject in aList) { var geometryPoint = anObject as GeometryPoint; if (geometryPoint != null) { int slipPlanelDeletionIndex = -1; foreach (var slipPlane in SlipPlanes) { if (slipPlane.Points.Contains(geometryPoint)) { slipPlanelDeletionIndex = slipPlane.Points.IndexOf(geometryPoint); } } if (slipPlanelDeletionIndex > -1) { for (int i = 0; i < SlipPlanes.Count; i++) { DataEventPublisher.Delete(SlipPlanes[i].Points[slipPlanelDeletionIndex]); SlipPlanes[i].AddOrRemoveListObject(SlipPlanes[i].Points[slipPlanelDeletionIndex], false, 0); if (SlipPlanes[i].Points.Count <= 1) { DataEventPublisher.Delete(SlipPlanes[i].Points[0]); GeometryData.Remove(SlipPlanes[i].Points[0] as GeometryObject, false); Remove(SlipPlanes[i], false); i--; } } } for (int i = 0; i < ForbiddenLinesList.Count; i++) { if (ForbiddenLinesList[i].StartPoint == geometryPoint || ForbiddenLinesList[i].EndPoint == geometryPoint) { ForbiddenLines deleteForbiddenLine = ForbiddenLinesList[i]; Remove(deleteForbiddenLine as GeometryObject, false); i--; } } if (ReferenceLevelLine != null) { int deletionIndex = -1; if (ReferenceLevelLine.Points.Contains(geometryPoint)) { deletionIndex = ReferenceLevelLine.Points.IndexOf(geometryPoint); } if (ReferenceLevelLine.Points.Contains(geometryPoint)) { referenceLevelLine.Points.RemoveAt(deletionIndex); DataEventPublisher.Delete(geometryPoint); } } string reinforcementType = null; if (Geotextiles.Count >= 1) { foreach (var anObject1 in aList) { reinforcementType = anObject1.GetType().Name; for (int i = 0; i < Geotextiles.Count; i++) { if (Geotextiles[i].StartPoint == anObject1 as GeometryPoint || Geotextiles[i].EndPoint == anObject1 as GeometryPoint) { Geotextile deleteGeotextiles = Geotextiles[i]; Remove(deleteGeotextiles as GeometryObject, false); i--; } } } } isDeleted = true; } else if (anObject is SoilLayer2D) { if (GeometryData.Surfaces.Count == 0) { foreach (var slipPlane in slipPlaneList) { Remove(slipPlane as GeometryObject, false); } } Remove(anObject, false); isDeleted = true; } else if (anObject is SlipPlane) { var deleteslipCurve = anObject as SlipPlane; Remove(deleteslipCurve as GeometryObject, false); isDeleted = true; } else if (anObject is ForbiddenLines) { var deleteForbiddenLine = anObject as ForbiddenLines; Remove(deleteForbiddenLine as GeometryObject, false); isDeleted = true; } else if (anObject is HorizontalBalance) { var horizontalBalance = anObject as HorizontalBalance; horizontalBalance.XLeft = 0.0; horizontalBalance.XRight = 0.0; horizontalBalance.ZBottom = 0.0; horizontalBalance.ZTop = 0.0; horizontalBalance.NZInterval = 1; isDeleted = true; } else if (anObject is SlipCircleTangentLine) { var slipCircle = anObject as SlipCircleTangentLine; if (modelOption == ModelOptions.UpliftVan || modelOption == ModelOptions.UpliftSpencer) { SetDefaultValuesForSlipPlaneUpliftVan(); DataEventPublisher.Changed(SlipPlaneUpliftVan); } else if (modelOption == ModelOptions.Bishop || modelOption == ModelOptions.Fellenius || modelOption == ModelOptions.BishopProbabilityRandomField) { slipCircle.TangentLineNumber = 0; slipCircle.TangentLineZBottom = 0; slipCircle.TangentLineZTop = 0; if (SlipCircle != null) { DataEventPublisher.Changed(SlipCircle); } } isDeleted = true; } else if (anObject is SlipCircleFixedPoint) { var slipCircle = anObject as SlipCircleFixedPoint; slipCircle.UseFixedPoint = false; DataEventPublisher.Changed(SlipCircle); isDeleted = true; } else if (anObject is SlipCircleGrid) { if (anObject.Name == "Calculation grid - Left" || anObject.Name == "Calculation grid - Right") { SetDefaultValuesForSlipPlaneUpliftVan(); DataEventPublisher.Changed(SlipPlaneUpliftVan); } else if (anObject.Name == "Calculation Grid") { SlipCircle.SlipCircleGrid.GridXLeft = 0.0; //setting to default values SlipCircle.SlipCircleGrid.GridXNumber = 1; SlipCircle.SlipCircleGrid.GridXRight = 0.0; SlipCircle.SlipCircleGrid.GridZTop = 0.0; SlipCircle.SlipCircleGrid.GridZBottom = 0.0; SlipCircle.SlipCircleGrid.GridZNumber = 1; SlipCircle.SlipCircleGrid.GridZBottom = 0.0; SlipCircle.SlipCircleTangentLine.TangentLineZTop = 0.0; SlipCircle.SlipCircleTangentLine.TangentLineZBottom = 0.0; SlipCircle.SlipCircleTangentLine.TangentLineNumber = 0; SlipCircle.SlipCircleFixedPoint.UseFixedPoint = false; SlipCircle.SlipCircleFixedPoint.XFixed = 0.0; SlipCircle.SlipCircleFixedPoint.ZFixed = 0.0; DataEventPublisher.Changed(SlipCircle); } isDeleted = true; } else if (anObject is Geotextile) { if (anObject.GetType() == typeof(Geotextile)) { var deleteGeotextile = anObject as Geotextile; Remove(deleteGeotextile as GeometryObject, false); } } else if (anObject is ReferenceLevelLine) { Remove(anObject as GeometryObject, false); } if (SlipPlanes.Count > 0) { DataEventPublisher.DataListModified(SlipPlanes); } } if (!isDeleted) { Remove(aList, false); } return true; } public void CreateSlipCircle(Point3D vertex3D) { Point2D vertex2D = GeometryData.GetLocalCoordinate(vertex3D); if (SlipCircle == null) { UndoRedoManager.Instance.BeginAction(); var slipCircle = new SlipCircle(); Create(slipCircle); slipCircle.SlipCircleGrid.GridZNumber = 5; slipCircle.SlipCircleTangentLine.TangentLineNumber = 5; slipCircle.SlipCircleGrid.GridXNumber = 5; slipCircle.SlipCircleGrid.GridXLeft = vertex2D.X - 1; slipCircle.SlipCircleGrid.GridZTop = vertex2D.Y + 1; slipCircle.SlipCircleGrid.GridXRight = vertex2D.X + 1; slipCircle.SlipCircleGrid.GridZBottom = vertex2D.Y - 1; double gridZTop; if (SurfaceLine2 != null && SurfaceLine2.Geometry.Count > 0) { var line = new GeometryPointString(); line.Points.AddRange(SurfaceLine2.Geometry.Points.Where(p => !double.IsNaN(p.X))); gridZTop = line.GetZAtX(vertex2D.X); slipCircle.SlipCircleTangentLine.TangentLineZTop = gridZTop - 1; slipCircle.SlipCircleTangentLine.TangentLineZTop = gridZTop - 4; //slipCircle.SlipCircleTangentLine.TangentLinesBoundaries.XLeft = slipCircle.SlipCircleGrid.GridXLeft - 2; } else { slipCircle.SlipCircleTangentLine.TangentLineZTop = vertex2D.Y - 10; slipCircle.SlipCircleTangentLine.TangentLineZBottom = vertex2D.Y - 12; } SlipCircle = this.slipCircle; DataEventPublisher.Changed(SlipCircle); UndoRedoManager.Instance.EndAction(); } else { UndoRedoManager.Instance.BeginAction(); SlipCircle.SlipCircleGrid.GridZNumber = 5; SlipCircle.SlipCircleTangentLine.TangentLineNumber = 5; SlipCircle.SlipCircleGrid.GridXNumber = 5; SlipCircle.SlipCircleGrid.GridXLeft = vertex2D.X - 1; SlipCircle.SlipCircleGrid.GridZTop = vertex2D.Y + 1; SlipCircle.SlipCircleGrid.GridXRight = vertex2D.X + 1; SlipCircle.SlipCircleGrid.GridZBottom = vertex2D.Y - 1; double gridZTop; if (SurfaceLine2 != null && SurfaceLine2.Geometry.Count > 0) { var line = new GeometryPointString(); line.Points.AddRange(SurfaceLine2.Geometry.Points.Where(p => !double.IsNaN(p.X))); gridZTop = line.GetZAtX(vertex2D.X); slipCircle.SlipCircleTangentLine.TangentLineZTop = gridZTop - 1; slipCircle.SlipCircleTangentLine.TangentLineZTop = gridZTop - 4; } else { SlipCircle.SlipCircleTangentLine.TangentLineZTop = vertex2D.Y - 10; SlipCircle.SlipCircleTangentLine.TangentLineZBottom = vertex2D.Y - 12; } SlipCircle = slipCircle; DataEventPublisher.Changed(SlipCircle); UndoRedoManager.Instance.EndAction(); } } public void CreateUpliftVanSlipPlane(Point3D point) { if (SlipPlaneUpliftVan == null) { var lSlipPlaneUpliftVan = new SlipPlaneUpliftVan(); UndoRedoManager.Instance.BeginAction(); Create(lSlipPlaneUpliftVan); SetDefaultValuesForUpliftVanSlipPlane(point, lSlipPlaneUpliftVan); SlipPlaneUpliftVan = slipPlaneUpliftVan; DataEventPublisher.Changed(SlipPlaneUpliftVan); UndoRedoManager.Instance.EndAction(); } else { UndoRedoManager.Instance.BeginAction(); Create(SlipPlaneUpliftVan); SetDefaultValuesForUpliftVanSlipPlane(point, SlipPlaneUpliftVan); SlipPlaneUpliftVan = slipPlaneUpliftVan; DataEventPublisher.Changed(SlipPlaneUpliftVan); UndoRedoManager.Instance.EndAction(); } } public void GetGammaFromSurface(GeometrySurface aSurface, ref double AGammaDry, ref double AGammaWet) { SoilLayer2D soilsurface = soilProfile.Surfaces.Find(x => x.GeometrySurface == aSurface); AGammaDry = soilsurface.Soil.AbovePhreaticLevel; AGammaWet = soilsurface.Soil.BelowPhreaticLevel; } public void CreateSlipCircleFixedPoint(Point3D vertex3D) { Point2D vertex2D = GeometryData.GetLocalCoordinate(vertex3D); if (SlipCircle != null) { UndoRedoManager.Instance.BeginAction(); SlipCircle.SlipCircleFixedPoint.XFixed = vertex2D.X; SlipCircle.SlipCircleFixedPoint.ZFixed = vertex2D.Y; SlipCircle.SlipCircleFixedPoint.UseFixedPoint = true; DataEventPublisher.Changed(SlipCircle); UndoRedoManager.Instance.EndAction(); } } public void CreateHorizontalBalance(Point3D vertex3D) { Point2D vertex2D = GeometryData.GetLocalCoordinate(vertex3D); if (HorizontalBalance == null) { UndoRedoManager.Instance.BeginAction(); var horizontalBalance = new HorizontalBalance(); Create(horizontalBalance); horizontalBalance.NZInterval = 3; horizontalBalance.XLeft = vertex2D.X - 1; horizontalBalance.XRight = vertex2D.X + 1; horizontalBalance.ZTop = vertex2D.Y + 1; horizontalBalance.ZBottom = vertex2D.Y - 1; HorizontalBalance = horizontalBalance; UndoRedoManager.Instance.EndAction(); } else { UndoRedoManager.Instance.BeginAction(); horizontalBalance.NZInterval = 3; horizontalBalance.XLeft = vertex2D.X - 1; horizontalBalance.XRight = vertex2D.X + 1; horizontalBalance.ZTop = vertex2D.Y + 1; horizontalBalance.ZBottom = vertex2D.Y - 1; HorizontalBalance = horizontalBalance; UndoRedoManager.Instance.EndAction(); } DataEventPublisher.Changed(HorizontalBalance); } public void CreateSlipPlaneUpliftVan() { if (slipPlaneUpliftVan == null) { slipPlaneUpliftVan = new SlipPlaneUpliftVan(); Create(slipPlaneUpliftVan); } } public void CreateStressInGeometry(Point3D point) { if (!IsStressCreated) { Create(StressesInGeometry); StressesInGeometry.X = (GeometryData.Left + GeometryData.Right) / 2; IsStressCreated = true; } else { StressesInGeometry.X = point.X; } } public bool IsSlipCircleDefaultValues() { bool IsDefaultValue = false; if (SlipCircle != null) { if (slipCircle.SlipCircleGrid.GridXLeft == 0.0 && slipCircle.SlipCircleGrid.GridXRight == 0.0 && slipCircle.SlipCircleGrid.GridXNumber == 1.0) { if (slipCircle.SlipCircleGrid.GridZBottom == 0.0 && slipCircle.SlipCircleGrid.GridZTop == 0.0 && slipCircle.SlipCircleGrid.GridZNumber == 1.0) { if (slipCircle.SlipCircleTangentLine.TangentLineNumber == 0.0 && slipCircle.SlipCircleTangentLine.TangentLineZBottom == 0.0 && slipCircle.SlipCircleTangentLine.TangentLineZTop == 0.0) { IsDefaultValue = true; } } } } return IsDefaultValue; } public bool IsUpliftVanSlipPlaneDefaultValues() { bool IsDefaultValue = false; if (SlipPlaneUpliftVan != null) { if (slipPlaneUpliftVan.SlipPlaneLeftGrid.GridXLeft == 0.0 && slipPlaneUpliftVan.SlipPlaneLeftGrid.GridXRight == 0.0 && slipPlaneUpliftVan.SlipPlaneLeftGrid.GridXNumber == 1 && slipPlaneUpliftVan.SlipPlaneLeftGrid.GridZTop == 0.0 && slipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom == 0.0 && slipPlaneUpliftVan.SlipPlaneLeftGrid.GridZNumber == 1 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridXLeft == 0.0 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridXRight == 0.0 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridXNumber == 1 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridZTop == 0.0 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridZBottom == 0.0 && slipPlaneUpliftVan.SlipPlaneRightGrid.GridZNumber == 1 && slipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZTop == 0.0 && slipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZBottom == 0.0 && slipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineNumber <= 1) { IsDefaultValue = true; } } return IsDefaultValue; } public bool IsCalculationAreaDefaultValues() { bool IsDefaultValue = false; if (horizontalBalance != null) { if (horizontalBalance.XLeft == 0.0 && horizontalBalance.XRight == 0.0 && horizontalBalance.ZBottom == 0.0) { if (horizontalBalance.ZTop == 0.0 && horizontalBalance.NZInterval == 1) { IsDefaultValue = true; } } } return IsDefaultValue; } public SlipPlane CreateSlipPlane(List pointList, bool aValidate) { var newCurve = new SlipPlane(); Create(newCurve); int count = 0; foreach (var point in pointList) { newCurve.AddOrRemoveListObject(point, true, count); count++; } return newCurve; } public string SurfaceToSoilName(SoilLayer2D surfaceobject) { return surfaceobject.Soil.Description; } public bool IsSoilMaterialLayerFoundOnClick(double aX, double aY, ref SoilLayer2D aSoilSurface) { if (soilProfile.Surfaces.Count == 0) { return false; } int surfacesFoundCount = 0; SoilLayer2D soilSurfaceFound = null; bool isFoundInOuterLoop = false; bool isFoundInOuterLoopAlone = false; bool isFoundInInnerLoop = false; foreach (var soilSurface in soilProfile.Surfaces) { isFoundInOuterLoop = false; isFoundInInnerLoop = false; PointInPolygon pointInPolygon = Routines2D.CheckIfPointIsInPolygon(soilSurface.GeometrySurface.OuterLoop.GetLocalPoint2DList(), aX, aY); if (pointInPolygon == PointInPolygon.InsidePolygon || pointInPolygon == PointInPolygon.OnPolygonEdge) { if (isFoundInOuterLoopAlone == false) { soilSurfaceFound = soilSurface; } isFoundInOuterLoop = true; surfacesFoundCount++; } // inner-loops if (isFoundInOuterLoop) { for (int i = 0; i < soilSurface.GeometrySurface.InnerLoops.Count; i++) { PointInPolygon pointInPolygon1 = Routines2D.CheckIfPointIsInPolygon(soilSurface.GeometrySurface.InnerLoops[i].GetLocalPoint2DList(), aX, aY); if (pointInPolygon1 == PointInPolygon.InsidePolygon || pointInPolygon1 == PointInPolygon.OnPolygonEdge) { if (isFoundInOuterLoopAlone == false) { soilSurfaceFound = null; } surfacesFoundCount--; isFoundInInnerLoop = true; break; } } } if (isFoundInOuterLoop == true && isFoundInInnerLoop == false) { isFoundInOuterLoopAlone = true; } } if (surfacesFoundCount == 1) { aSoilSurface = soilSurfaceFound; return true; } // case when more than one surface is found at the same point - ex. junction or edge of two surfaces return false; } public void HandleObjectDelete(List aObjectList) { var deleteObjectList = new List(); foreach (var anObject in aObjectList) { deleteObjectList.Add((IGeometryObject)anObject); } Remove(deleteObjectList, false); } public double DetermineZReferenceLevelCu(double aXCoord) { if (ReferenceLevelLine == null) { throw new Exception(" ReferenceLevelLine in DetermineZReferenceLevelCu"); } for (int pointIndex = 0; pointIndex < ReferenceLevelLine.Points.Count - 1; pointIndex++) { double[] beginPoint1 = { ReferenceLevelLine.Points[pointIndex].X, ReferenceLevelLine.Points[pointIndex].Z }; double[] endPoint1 = { ReferenceLevelLine.Points[pointIndex + 1].X, ReferenceLevelLine.Points[pointIndex + 1].Z }; double[] beginpoint2 = { aXCoord, -9999 }; double[] endpoint2 = { aXCoord, 9999 }; double[] intersectPoint = { 0, 0 }; if (GeometryData.CheckIfIntersect(beginPoint1, endPoint1, beginpoint2, endpoint2, ref intersectPoint)) { return intersectPoint[1]; } } return -1; } public void CreateLineLoad(Point3D vertex3D, bool aIsMainInput) { if (aIsMainInput) { UndoRedoManager.Instance.BeginAction(); var newLineLoad = new LineLoad(); Create(newLineLoad); var top = GeometryData.SurfaceLine.GetZAtX(vertex3D.X); if (!double.IsNaN(top)) { newLineLoad.Z = top; } else { newLineLoad.Z = 0.0; } newLineLoad.X = vertex3D.X; newLineLoad.Y = vertex3D.Y; DataEventPublisher.Changed(typeof(GeometryPoint), newLineLoad, true); UndoRedoManager.Instance.EndAction(); } else { UndoRedoManager.Instance.BeginAction(); var newLineLoad = new LineLoad(); Create(newLineLoad); newLineLoad.X = vertex3D.X; newLineLoad.Y = vertex3D.Y; newLineLoad.Z = vertex3D.Z; DataEventPublisher.Changed(typeof(GeometryPoint), newLineLoad, true); UndoRedoManager.Instance.EndAction(); } } public void CreateNail(Point3D vertex3D, bool aIsMainInput) { if (aIsMainInput) { UndoRedoManager.Instance.BeginAction(); var newNail = new Nail(); Create(newNail); var top = GeometryData.SurfaceLine.GetZAtX(vertex3D.X); if (!double.IsNaN(top)) { newNail.Z = top; } else { newNail.Z = 0.0; } newNail.X = vertex3D.X; newNail.Y = vertex3D.Y; DataEventPublisher.Changed(typeof(GeometryPoint), newNail, true); UndoRedoManager.Instance.EndAction(); } else { UndoRedoManager.Instance.BeginAction(); var newNail = new Nail(); Create(newNail); newNail.X = vertex3D.X; newNail.Y = vertex3D.Y; newNail.Z = vertex3D.Z; DataEventPublisher.Changed(typeof(GeometryPoint), newNail, true); UndoRedoManager.Instance.EndAction(); } } public void CreateReferenceLevelLine(List points) { if (ReferenceLevelLine == null) { if (points != null && points.Count > 0) { UndoRedoManager.Instance.BeginAction(); var newReferenceLevelLine = new ReferenceLevelLine(points, Geometry.Left, Geometry.Right); Create(newReferenceLevelLine); referenceLevelLine = newReferenceLevelLine; DataEventPublisher.Changed(typeof(GeometryPoint), referenceLevelLine, true); UndoRedoManager.Instance.EndAction(); } } } public void CreateTreeOnSlope(Point3D vertex3D) { if (TreeOnSlope == null) { if (vertex3D != null) { UndoRedoManager.Instance.BeginAction(); var newTreeOnSlope = new TreeOnSlope(); Create(newTreeOnSlope); newTreeOnSlope.X = vertex3D.X; newTreeOnSlope.Y = vertex3D.Y; newTreeOnSlope.Z = vertex3D.Z; newTreeOnSlope.WindForce = 10.0; TreeOnSlope = newTreeOnSlope; DataEventPublisher.Changed(typeof(GeometryPoint), TreeOnSlope, true); UndoRedoManager.Instance.EndAction(); } } else { UndoRedoManager.Instance.BeginAction(); TreeOnSlope.X = vertex3D.X; TreeOnSlope.Y = vertex3D.Y; TreeOnSlope.Z = vertex3D.Z; TreeOnSlope.WindForce = 10.0; DataEventPublisher.Changed(typeof(GeometryPoint), TreeOnSlope, true); UndoRedoManager.Instance.EndAction(); } } public void DecrementIndex(Type aType) { if (aType == typeof(LineLoad)) { lineLoadDescriptionCounter--; } if (aType == typeof(Nail)) { nailDescriptionCounter--; } } public void CreateUniformLoad(List vertexPointList) { if (vertexPointList.Count >= 2) { UndoRedoManager.Instance.BeginAction(); var newUnfiormLoad = new UniformLoad(); newUnfiormLoad.XStart = vertexPointList[0].X; newUnfiormLoad.XEnd = vertexPointList[1].X; newUnfiormLoad.Magnitude = 10; //default value in graphical input Create(newUnfiormLoad); DataEventPublisher.Changed(typeof(GeometryPoint), newUnfiormLoad, true); UndoRedoManager.Instance.EndAction(); } } //public void PopulateDegreeOfConsolidation() //{ // var sdf = this.soilProfile.Surfaces.Select(surface => surface.Name).ToList(); // DataEventPublisher.Changed(typeof(DegreeofConsolidationMatrix), sdf); //} //public void RefreshDegreeOfConsolidation() //{ // if (this.degreeofConsolidationSoilSurface != null) // { // DataEventPublisher.Changed(this.degreeofConsolidationSoilSurface, null); // } // if (this.degreeofConsolidationEarthquake != null) // { // DataEventPublisher.Changed(this.degreeofConsolidationEarthquake, null); // } // if (this.degreeofConsolidationUniformLoad != null) // { // DataEventPublisher.Changed(this.degreeofConsolidationUniformLoad, null); // } //} [Validate] public IValidationResult[] ValidateProbabilisticDefaults() { return validator.ValidateProbabilisticDefaults(); } [Validate] public IValidationResult[] ValidateHorizontalBalance() { return validator.ValidateHorizontalBalance(); } [Validate] public IValidationResult[] ValidateReferenceLevelLine() { return validator.ValidateReferenceLevelLine(); } [Validate] public IValidationResult[] ValidateEarthquake() { return validator.ValidateEarthquake(); } [Validate] public IValidationResult[] ValidateTreeOnSlope() { return validator.ValidateTreeOnSlope(); } [Validate] public IValidationResult[] ValidateSlipPlaneUpliftVan() { return validator.ValidateSlipPlaneUpliftVan(); } [Validate] public IValidationResult[] ValidateSlipCircle() { return validator.ValidateSlipCircle(); } [Validate] public IValidationResult[] ValidateIntersectionCircleAndSurfaceLine() { return validator.ValidateIntersectionCircleAndSurfaceLine(); } [Validate] public IValidationResult[] ValidateAllSlidingCurvesWithinSurfaceLine() { return validator.ValidateAllSlidingCurvesWithinSurfaceLine(); } public IValidationResult[] ValidateTangentLine() { return validator.ValidateTangentLine(); } [Validate] public IValidationResult[] ValidateForbiddenLines() { return validator.ValidateForbiddenLines(); } [Validate] public IValidationResult[] ValidateGeotextile() { return validator.ValidateGeotextile(); } [Validate] public IValidationResult[] ValidateUniformLoads() { return validator.ValidateUniformLoads(); } [Validate] public IValidationResult[] ValidateNail() { return validator.ValidateNails(); } [Validate] public IValidationResult[] ValidateLineLoad() { return validator.ValidateLineLoad(); } [Validate] public IValidationResult[] ValidateSlipPlane() { return validator.ValidateSlipPlane(); } [Validate] public IValidationResult[] ValidateSpencer() { return validator.ValidateSpencer(); } [Validate] public IValidationResult[] ValidateZoneAreas() { return validator.ValidateZoneAreas(); } [Validate] public IValidationResult[] ValidateSoilSurfaces() { return validator.ValidateSoilSurfaces(); } [Validate] public IValidationResult[] ValidateProperties() { return validator.ValidateProperties(); } [Validate] public IValidationResult[] validateAquifer() { if (RequiresAquifer()) { return validator.ValidateAquifer(); } else { return new IValidationResult[0]; } } /// /// Validates the data in . /// /// The collection of validation messages generated by this method. [Validate] public IValidationResult[] ValidatePreconsolidationStresses() { return validator.ValidatePreconsolidationStresses(); } public IEnumerable GetErrorList(object target) { return validator.GetErrorList(target); } /// /// Generates characteristic points (only dike toe/top at river/polder) if not present. /// Assumes that the profile is flat until the toe except for a given height difference. /// /// The allowed height difference between the start/end of the profile until the dike toe public static void GenerateCharacteristicPoints(SurfaceLine2 surfaceLine) { var points = new List(surfaceLine.Geometry.Points); if (surfaceLine.Geometry.Count == 2) { if (!surfaceLine.HasAnnotation(CharacteristicPointType.SurfaceLevelOutside)) { surfaceLine.AddCharacteristicPoint(points[0].Clone() as GeometryPoint, CharacteristicPointType.SurfaceLevelOutside); points.Remove(points[0]); } if (!surfaceLine.HasAnnotation(CharacteristicPointType.SurfaceLevelInside)) { surfaceLine.AddCharacteristicPoint(points[points.Count - 1].Clone() as GeometryPoint, CharacteristicPointType.SurfaceLevelInside); } } else if (surfaceLine.Geometry.Count > 2) { double initialLevel = surfaceLine.Geometry.Points[0].Z; double finalLevel = surfaceLine.Geometry.Points[surfaceLine.Geometry.Count - 1].Z; double maxLevel = surfaceLine.Geometry.GetMaxZ(); double minLevel = surfaceLine.Geometry.GetMinZ(); double allowedHeightDifference = (maxLevel - minLevel) / 10; int nextIndex = 0; if (!surfaceLine.IsDefined(CharacteristicPointType.SurfaceLevelOutside)) { surfaceLine.AddCharacteristicPoint(points[0].Clone() as GeometryPoint, CharacteristicPointType.SurfaceLevelOutside); points.Remove(points[0]); nextIndex = 1; } if (points.Count == 1) // Bug: always points.Count > 1! { if (!surfaceLine.IsDefined(CharacteristicPointType.SurfaceLevelInside)) { surfaceLine.AddCharacteristicPoint(points[points.Count - 1].Clone() as GeometryPoint, CharacteristicPointType.SurfaceLevelInside); } } if (!surfaceLine.IsDefined(CharacteristicPointType.DikeToeAtRiver)) { for (int i = nextIndex + 1; i < points.Count; i++) // Don't reuse previously used points, bug in surface line { if (points[i].Z - initialLevel > allowedHeightDifference) { if (!surfaceLine.CharacteristicPoints.Select(cp => cp.GeometryPoint).Contains(points[i - 1])) { surfaceLine.AddCharacteristicPoint(points[i - 1].Clone() as GeometryPoint, CharacteristicPointType.DikeToeAtRiver); points.Remove(points[i - 1]); nextIndex = i; break; } } } } if (!surfaceLine.IsDefined(CharacteristicPointType.DikeTopAtRiver)) { for (int i = nextIndex; i < points.Count; i++) { if (Math.Abs(points[i].Z - maxLevel) < allowedHeightDifference) { surfaceLine.AddCharacteristicPoint(points[i].Clone() as GeometryPoint, CharacteristicPointType.DikeTopAtRiver); points.Remove(points[i]); nextIndex = i + 1; break; } } } if (!surfaceLine.IsDefined(CharacteristicPointType.DikeTopAtPolder)) { for (int i = points.Count - 2; i >= nextIndex; i--) { if (Math.Abs(points[i].Z - maxLevel) < allowedHeightDifference) { surfaceLine.AddCharacteristicPoint(points[i].Clone() as GeometryPoint, CharacteristicPointType.DikeTopAtPolder); points.Remove(points[i]); nextIndex = i + 1; break; } } } if (!surfaceLine.IsDefined(CharacteristicPointType.DikeToeAtPolder)) { for (int i = points.Count - 3; i >= nextIndex - 1; i--) // Don't reuse last point { if (points[i].Z - finalLevel > allowedHeightDifference) { surfaceLine.AddCharacteristicPoint(points[i + 1].Clone() as GeometryPoint, CharacteristicPointType.DikeToeAtPolder); points.Remove(points[i + 1]); break; } } } if (!surfaceLine.IsDefined(CharacteristicPointType.SurfaceLevelInside) && points.Count > 0) { surfaceLine.AddCharacteristicPoint(points[points.Count - 1].Clone() as GeometryPoint, CharacteristicPointType.SurfaceLevelInside); } } //to enable modifying the char points in the UI AddMissingCharacteristicPoints(surfaceLine); } /// /// create all characteristic point types that are not present yet and add these to the char points set /// public static void AddMissingCharacteristicPoints(SurfaceLine2 line) { foreach (CharacteristicPointType characteristicPointType in Enum.GetValues(typeof(CharacteristicPointType))) { if (characteristicPointType != CharacteristicPointType.None && MechanismSupport.IsMechanismVisible(characteristicPointType) && !line.HasAnnotation(characteristicPointType)) { var point = new GeometryPoint(Double.NaN, 0, Double.NaN); line.AddCharacteristicPoint(point, characteristicPointType); } } } #region IVisibleEnabled Members public bool IsVisible(string property) { switch (property) { case "CalculationModel": return UserCalculationModel; case "SafetyZoneAreas": return HasZonePlot; case "PreciseGA": return SearchAlgorithm == SearchAlgorithm.Genetic || SearchAlgorithm == SearchAlgorithm.GeneticAndLevenbergMarquardt; case "MoveGrid": return SearchAlgorithm == SearchAlgorithm.Grid; case "GeneticAlgorithmOptions": return SearchAlgorithm == SearchAlgorithm.Genetic || SearchAlgorithm == SearchAlgorithm.GeneticAndLevenbergMarquardt; case "DefaultInputModeAnalysisOption": return IsReliability; case "UseDefaultShearStrengthInput": return IsReliability; case "ProbabilisticCalculationType": return IsReliability; case "Measurement": return DefaultShearStrengthModel == ShearStrengthModel.PseudoValues; case "HasNails": return CalculationModel == CalculationModel.DSerie && (ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Fellenius || ModelOption == ModelOptions.UpliftVan); case "HasGeotextile": return CalculationModel == CalculationModel.DSerie && (ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Fellenius || ModelOption == ModelOptions.UpliftVan); case "HorizontalBalance": return ModelOption == ModelOptions.HorizontalBalance; case "LineLoads": return ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Fellenius || ModelOption == ModelOptions.UpliftVan; case "Nails": return HasNails && (ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Fellenius || ModelOption == ModelOptions.UpliftVan); case "Geotextiles": return HasGeotextile && (ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Fellenius || ModelOption == ModelOptions.UpliftVan); case "UniformLoads": return ModelOption != ModelOptions.BishopProbabilityRandomField; case "StressCurves": return ModelOption != ModelOptions.BishopProbabilityRandomField; case "BondStressCurves": return ModelOption != ModelOptions.BishopProbabilityRandomField; case "TreeOnSlope": return (TreeOnSlope != null && ModelOption != ModelOptions.Spencer) /*this.ModelOption == ModelOptions.Bishop || this.ModelOption == ModelOptions.Fellenius*/; case "SlipPlaneUpliftVan": return ModelOption == ModelOptions.UpliftSpencer || ModelOption == ModelOptions.UpliftVan; case "SlipPlanes": return ModelOption == ModelOptions.Spencer; case "Stochasts": return IsReliability; case "ResultSlidingCurve": return ResultSlidingCurve.Running; case "IsBishop": return true; case "IsSpencer": return true; case "IsFellenius": return CalculationModel == CalculationModel.DSerie; case "IsUpliftSpencer": return CalculationModel == CalculationModel.DSerie; case "IsUpliftVan": return true; case "IsBishopProbabilityRandomField": return CalculationModel == CalculationModel.DSerie; case "IsHorizontalBalance": return CalculationModel == CalculationModel.DSerie; case "UseGenetic": return (CalculationModel == CalculationModel.DSerie && ModelOption != ModelOptions.HorizontalBalance) || ((CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ModelOption == ModelOptions.Spencer); case "UseGaAndLevenbergMarquardt": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ModelOption == ModelOptions.Spencer; case "UseLevenbergMarquardt": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ModelOption == ModelOptions.Spencer; case "SurfaceLine": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "CharacteristicPoints": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "NailShearStress": return HasNails; case "NailLateralStress": return HasNails; case "GridOrientation": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "TraversalGridPoints": case "SlipInterval": case "SlipPlaneMinDepth": case "SlipPlaneMinLength": case "RequestedNumberOfSlices": return CalculationModel == CalculationModel.DSerie; case "IsEndSectionFrictionUsed": return CalculationModel == CalculationModel.DSerie; case "MaximumSliceWidth": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "StartValueSafetyFactor": return ModelOption != ModelOptions.Spencer; case "OnlyMinimumSafetyCurve": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "Location": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "ModelFactor": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "ModelFactorStochast": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "RequiredForcePointsInSlices": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ModelOption == ModelOptions.Spencer; case "MaxAllowedAngleBetweenSlices": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ModelOption == ModelOptions.Spencer; case "AutoGenerateGeneticSpencer": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "IsHighSlipPlanes": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "IsLowSlipPlanes": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "PreConsolidationStressList": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "MultiplicationFactorsCPhiForUpliftList": return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; case "SurfaceLine2": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && (RequiresRightOrder() || RequiresRightShape()); case "ModelUncertaintyParameter": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && !ReliabilityView.IsReliability; case "ModelUncertaintyParameterStochast": return (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) && ReliabilityView.IsReliability; default: return true; } } public bool IsEnabled(string property) { switch (property) { case "HasZonePlot": return !(ModelOption == ModelOptions.BishopProbabilityRandomField || ModelOption == ModelOptions.HorizontalBalance); case "UseGenetic": return CanEnableGeneticAlgorithmGuiOptions(); case "UseGaAndLevenbergMarquardt": return CanEnableGaLevenbergMarquardtGuiOptions(); case "UseLevenbergMarquardt": return CanEnableGeneticAlgorithmGuiOptions(); case "GeneticAlgorithm": return CanEnableGeneticAlgorithmGuiOptions(); case "ExpectedLength": return IsEndSectionFrictionUsed; case "MoveGrid": return ModelOption != ModelOptions.Spencer && SearchAlgorithm == SearchAlgorithm.Grid; case "DefaultShearStrengthModel": return ModelOption != ModelOptions.BishopProbabilityRandomField; case "IsBishop": return true; case "IsSpencer": return true; case "IsFellenius": return true; case "IsUpliftSpencer": return true; case "IsUpliftVan": return true; case "IsBishopProbabilityRandomField": return true; case "IsHorizontalBalance": return true; // Properties bound to SlipPlaneDialog case "IsHighSlipPlanes": return AutoGenerateGeneticSpencer; case "IsLowSlipPlanes": return AutoGenerateGeneticSpencer; case "TraversalGridPoints": case "SlipInterval": case "GeneratedPlanes": return GenerateSlipPlane; default: return true; } } /// /// Determines whether this instance should enable the genetic algorithm GUI options. /// /// /// true if this instance allows to enable the genetic algorithm GUI option, otherwise, false. /// private bool CanEnableGeneticAlgorithmGuiOptions() { return ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.UpliftVan || ModelOption == ModelOptions.Spencer; } /// /// Determines whether this instance should enable the genetic algorithm - Levenberg Marquardt GUI options. /// private bool CanEnableGaLevenbergMarquardtGuiOptions() { return ModelOption == ModelOptions.Spencer; } #endregion #region ISoilPropertyManager Members public Mechanism Mechanism { get { return Mechanism.Stability; } } public object GetValue(string property) { switch (property) { case "UseNails": return HasNails; case "UseNailShearStress": return UseNailShearStress; case "UseLateralShearStress": return UseLateralShearStress; default: return null; } } public ICollection GetDomain(string property) { switch (property) { case "StressTable": return SoilModel.StressCurves; case "BondStressTable": return SoilModel.BondStressCurves; case "Soil": return (VirtualList)SoilModel.ResourceSoils; default: return null; } } #endregion #region IGeometryPresenter Members public GeometryData Geometry { get { return GeometryData; } } // TODO: Comment! /// It is not well documented if this property should be managed as composite /// child of or if it is just aggregating. As such, /// caller is recommended to disposed of the current instance when setting a new /// one. [Validate] [XmlOrder(3)] public SurfaceLine2 SurfaceLine2 // TODO: Determine if aggregation or composition relation { get { if (surfaceLine2 != null) { if (surfaceLine2.Geometry.Count == 0) { surfaceLine2.Geometry.Points.AddRange(GeometryData.SurfaceLine.Points); } if (surfaceLine2.CharacteristicPoints.Count == 0) { DataEventPublisher.InvokeWithoutPublishingEvents(() => { GenerateCharacteristicPoints(surfaceLine2); }); } } return surfaceLine2; } set { if (value != createdSurfaceLineToDispose && createdSurfaceLineToDispose != null) { createdSurfaceLineToDispose.Dispose(); createdSurfaceLineToDispose = null; } if (rtoCalculationgrid != null) { rtoCalculationgrid.SurfaceLine = value; } surfaceLine2 = value; } } [XmlIgnore] public IList CharacteristicPoints { get { return SurfaceLine2.CharacteristicPoints; } } /// /// Gets or sets the safety curve for this zone /// [Label("Safety curve")] [XmlOrder(100)] public SlidingCurve MinimumSafetyCurve { get { return minimumSafetyCurve; } set { minimumSafetyCurve = value; } } [Browsable(false)] public bool OnlyMinimumSafetyCurve { get { return onlyMinimumSafetyCurve; } set { onlyMinimumSafetyCurve = value; } } [Validate] [XmlOrder(90)] public StabilityLocation Location //Composite relationship { get { return location; } set { location = value; location.StabilityModel = this; } } [XmlOrder(50)] public SlipplaneConstraints SlipPlaneConstraints { get { return slipplaneConstraints; } set { slipplaneConstraints = value; } } [XmlOrder(48)] public NailLateralStress NailLateralStress { get { return nailLateralStress; } set { DataEventPublisher.BeforeChange(this, "NailLateralStress"); nailLateralStress = value; DataEventPublisher.AfterChange(this, "NailLateralStress"); } } [XmlOrder(49)] public NailShearStress NailShearStress { get { return nailShearStress; } set { DataEventPublisher.BeforeChange(this, "NailShearStress"); nailShearStress = value; DataEventPublisher.AfterChange(this, "NailShearStress"); } } public bool UseLateralShearStress { get { return NailLateralStress == NailLateralStress.Ultimate; } } [Browsable(false)] [XmlOrder(47)] public Nail DefaultNail { get { return defaultNail; } set { defaultNail = value; } } [XmlOrder(99)] public SlidingModel SlidingModel { get { return slidingModel; } set { slidingModel = value; } } public double PreconsolidationStressModelFactor { get { return preconsolidationStressModelFactor; } set { DataEventPublisher.BeforeChange(this, "PreconsolidationStressModelFactor"); preconsolidationStressModelFactor = value; DataEventPublisher.AfterChange(this, "PreconsolidationStressModelFactor"); } } /// /// Gets or sets the model uncertainty parameter stochast. /// Should be a uncertainty parameter per model (Bishop/UpliftVan/Spencer), but /// there UpliftVan/Spencer has the same values at the moment we still can use one parameter /// /// /// The model uncertainty parameter stochast. /// [Translation("ModelUncertaintyParameter")] [Stochast(AutoAssociatedProperty = true)] public Stochast ModelUncertaintyParameterStochast { get { return modelUncertaintyParameterStochast; } set { this.SetAndNotify2(out modelUncertaintyParameterStochast, value, p => p.ModelUncertaintyParameter); } } /// /// Gets or sets the model uncertainty parameter. /// Should be a uncertainty parameter per model (Bishop/UpliftVan/Spencer), but /// there UpliftVan/Spencer has the same values at the moment we still can use one parameter /// /// /// The model uncertainty parameter. /// [Unit(UnitType.None)] [Format("F3")] [Browsable(false)] public virtual double ModelUncertaintyParameter { get { return TransformerManager.GetTransformedValue(this, s => s.ModelUncertaintyParameter, ModelUncertaintyParameterStochast.Mean); } set { value = TransformerManager.SetTransformedValue(this, s => s.ModelUncertaintyParameter, value); if (value != ModelUncertaintyParameterStochast.Mean) { DataEventPublisher.BeforeChange(this, "ModelUncertaintyParameter"); ModelUncertaintyParameterStochast.Mean = value; DataEventPublisher.AfterChange(this, "ModelUncertaintyParameter"); } } } #endregion #region IDescriptive Members public string GetCategory(string property) { return null; } public string GetDescription(string property) { return null; } public Impact? GetImpact(string property) { return Impact.Computation; } public string GetName(string property) { var demo = string.Format(" ({0})", LocalizationManager.GetTranslatedText(this, "demoCaption")); switch (property) { case "IsBishop": return ModelOptions.Bishop.ToString(); case "IsSpencer": return ModelOptions.Spencer.ToString(); case "IsFellenius": return ModelOptions.Fellenius.ToString(); case "IsUpliftVan": return ModelOptions.UpliftVan.ToString(); case "IsUpliftSpencer": return ModelOptions.UpliftSpencer.ToString(); case "IsBishopProbabilityRandomField": return ModelOptions.BishopProbabilityRandomField.ToString(); case "IsHorizontalBalance": return ModelOptions.HorizontalBalance.ToString(); } return null; } public string GetFormat(string property) { return null; } public UnitType? GetUnit(string property) { return null; } #endregion public virtual void Dispose() { DataEventPublisher.OnChanged -= OnPublisherChanged; DataEventPublisher.OnDataListModified -= DataEventPublisher_OnDataListModified; DataEventPublisher.OnAfterChange -= OnAfterChangePublisher; // Break back-references: ((DelegatedList)soilModel.Soils).DeleteRequestMethod = null; // Undo Hack slipCircle.StabilityModel = null; slipPlaneUpliftVan.StabilityModel = this; zoneAreas.StabilityModel = null; if (soilProfile != null) { soilProfile.Dispose(GeometryType.Stability); } #region Dispose self create BaseSurfaceLine instances if (createdSurfaceLineToDispose != null) { createdSurfaceLineToDispose.Dispose(); createdSurfaceLineToDispose = null; } #endregion slipPlaneUpliftVan.Dispose(); slipCircle.Dispose(); zoneAreas.Dispose(); surfaceLineAttacher.Dispose(); stressesInGeometry.Dispose(); location.Dispose(); if (null != waterData) { waterData.Dispose(); } if (null != soilModel) { soilModel.Dispose(); } } public void UpdateGeometryBounds() { if (ReferenceLevelLine != null) { ReferenceLevelLine.Points[0].X = GeometryData.Left; ReferenceLevelLine.Points[ReferenceLevelLine.Points.Count - 1].X = GeometryData.Right; } } public bool IsVisible(object source, string property) { if (source is Nail) { switch (property) { case "ShearStressCurve": return HasNails && UseNailShearStress; case "LateralStressCurve": return true; default: return true; } } return true; } public bool IsEnabled(object source, string property) { return true; } #region Properties [XmlIgnore] [Impact(Impact.None)] public bool UserCalculationModel { get; set; } [XmlOrder(60)] public CalculationModel CalculationModel { get { return calculationModel; } set { if (calculationModel != value) { DataEventPublisher.BeforeChange(this, "CalculationModel"); calculationModel = value; DataEventPublisher.AfterChange(this, "CalculationModel"); } } } [XmlIgnore] [Label("D-Serie")] public bool IsDSerie { get { return CalculationModel == CalculationModel.DSerie; } set { if (value) { CalculationModel = CalculationModel.DSerie; } } } [XmlIgnore] [Label("RTO")] public bool IsRTO { get { return CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI; } set { if (value) { CalculationModel = CalculationModel.RTO; } } } [Label("Calculation")] [XmlElement("ProbabilisticCalculationType")] public ProbabilisticCalculationType ProbabilisticCalculationType { get { return probabilisticCalculationType; } set { DataEventPublisher.BeforeChange(this, "ProbabilisticCalculationType"); probabilisticCalculationType = value; UpdateProbabilisticTransformer(); DataEventPublisher.AfterChange(this, "ProbabilisticCalculationType"); } } [XmlIgnore] [Impact(Impact.None)] public SlidingSimpleCurve ResultSlidingCurve { get { return resultSlidingCurve; } } //[XmlIgnore] [XmlOrder(1)] public SoilModel SoilModel { get { return soilModel; } set { if (soilModel != null) { ((DelegatedList)soilModel.Soils).DeleteRequestMethod = null; //Hack: You wouldn't do this if Deltares.Geotechnics was a loaded Dll! soilModel.Dispose(); } soilModel = value; soilModel.ModelOption = ModelOption; ((DelegatedList)soilModel.Soils).DeleteRequestMethod = DeleteSoil; //Hack: You wouldn't do this if Deltares.Geotechnics was a loaded Dll! } } [XmlIgnore] public GeometryData GeometryData { get { return SoilProfile != null ? SoilProfile.Geometry : null; } set { if (SoilProfile != null) { SoilProfile.Geometry = value; SoilProfile.Geometry.GeometryBuilderListenersList[GeometryType.Stability] = this; waterData.Geometry = value; } surfaceLineAttacher.SurfaceLineProvider = value; } } [XmlOrder(5)] public GeotechnicsModel GeotechnicsData { get { return waterData; } set { if (null != waterData) { waterData.Dispose(); } waterData = value; waterData.IsExternalWaterLevelVisible = ModelOption == ModelOptions.BishopProbabilityRandomField; stressesInGeometry.WaternetModel = waterData.CurrentWaternet; } } // voorlopig zoalg bindsupport geen paden ondersteunt [XmlIgnore] [Validate] public IList Soils { get { return SoilModel.Soils; } } // voorlopig zoalg bindsupport geen paden ondersteunt [XmlIgnore] public List StressCurves { get { return SoilModel.StressCurves; } } // voorlopig zoalg bindsupport geen paden ondersteunt [XmlIgnore] public List BondStressCurves { get { return SoilModel.BondStressCurves; } } [XmlOrder(70)] public ProbabilisticDefaults ProbabilisticDefaults { get { return probabilisticDefaults; } set { probabilisticDefaults = value; } } [Validate] [NotClear] [XmlOrder(2)] public SoilProfile2D SoilProfile // TODO: Determine if aggregation or composition relation { get { return soilProfile; } set { soilProfile = value; if (soilProfile != null) { DataEventPublisher.BeforeChange(this, "SoilProfile"); soilProfile.AddGeometryListener(GeometryType.Stability, this); stressesInGeometry.SoilProfile2D = soilProfile; rtoCalculationgrid.SetSoilProfile2D(soilProfile); waterData.Geometry = soilProfile.Geometry; consolidationMatrixDirty = true; DataEventPublisher.AfterChange(this, "SoilProfile"); } } } [XmlOrder(35)] public List MultiplicationFactorsCPhiForUpliftList { get { return multiplicationFactorsCPhiForUpliftList; } } public int NonMaterialSurfaceCount { get { int nonMaterialSurfaceCount = 0; foreach (var surface in soilProfile.Surfaces) { if (surface.Soil == null) { nonMaterialSurfaceCount++; } } return nonMaterialSurfaceCount; } } [XmlIgnore] public StabilityModelValidator Validator { get { return validator; } } [XmlIgnore] public long SoilSurfaceNameCounter { get { return soilSurfaceDescriptionCounter; } set { soilSurfaceDescriptionCounter = value; } } [XmlIgnore] public bool IsStressCreated { get; set; } [XmlOrder(20)] public List LineLoads { get { return lineLoads; } } [XmlOrder(19)] public DelegatedList Nails { get { return nails; } } [XmlOrder(28)] public TreeOnSlope TreeOnSlope { get { return treeOnSlope; } set { treeOnSlope = value; if (treeOnSlope != null) { treeOnSlope.StabilityModel = this; } } } /// /// Gets or Sets Uniform Loads. /// [XmlOrder(21)] public List UniformLoads { get { return uniformLoadsData; } } /// /// List of all stochasts also present in underlying data /// [ReadOnly(true)] [XmlOrder(61)] public List Stochasts { get { if (stochasts.Count == 0) { UpdateStochasts(); } return stochasts; } } /// /// Gets or Sets Earthquake. /// [XmlOrder(29)] public Earthquake Earthquake { get { return earthquake; } set { consolidationMatrix.Consolidators.Remove(earthquake); earthquake = value; consolidationMatrix.Consolidators.Add(earthquake); } } /// /// Load which is used as consolidator or all loads /// [Browsable(false)] [XmlOrder(30)] public UniformLoad ConsolidationLoad { get { return consolidationLoad; } set { consolidationMatrix.Consolidators.Remove(consolidationLoad); consolidationLoad = value; consolidationMatrix.Consolidators.Add(consolidationLoad); } } [XmlOrder(24)] public List Geotextiles { get { return geotextiles; } } [XmlElement("ConsolidationValues")] [Browsable(false)] [XmlOrder(35)] public IList XMLConsolidationValues { get { // Use the field instead of the property consolidation matrix, // in order to avoid unnecessary geometry builds (via SoilProfile.Surfaces) when saving to xml return consolidationMatrix.ConsolidationValues; } } [XmlIgnore] public DegreeofConsolidationMatrix ConsolidationMatrix { get { if (consolidationMatrixDirty) { UpdateConsolidationMatrix(); } return consolidationMatrix; } } [XmlIgnore] public List ForbiddenLineErrorList { get { return validator.ForbiddenLineErrorList; } } [XmlIgnore] public List GeoTextileErrorList { get { return validator.GeoTextileErrorList; } } [XmlIgnore] public List SlipPlaneErrorList { get { return validator.SlipPlaneErrorList; } } [XmlIgnore] public List LineLoadErrorList { get { return validator.LineLoadErrorList; } } [XmlIgnore] public List NailErrorList { get { return validator.NailErrorList; } } [XmlIgnore] public List UniformLoadErrorList { get { return validator.UniformLoadErrorList; } } [XmlIgnore] public List ReferenceLevelLineErrorList { get { return validator.ReferenceLevelLineErrorList; } } [XmlIgnore] public StressesInGeometry StressesInGeometry { get { return stressesInGeometry; } } [XmlOrder(66)] public ZoneAreas SafetyZoneAreas { get { if (zoneAreas.StabilityModel == null) { zoneAreas.StabilityModel = this; } return zoneAreas; } set { DataEventPublisher.BeforeChange(this, "SafetyZoneAreas"); zoneAreas = value; zoneAreas.StabilityModel = this; DataEventPublisher.AfterChange(this, "SafetyZoneAreas"); } } [Label("Bishop")] public bool IsBishop { get { return ModelOption == ModelOptions.Bishop; } set { if (value) { ModelOption = ModelOptions.Bishop; } } } [Label("Spencer")] public bool IsSpencer { get { return ModelOption == ModelOptions.Spencer; } set { if (value) { ModelOption = ModelOptions.Spencer; } } } [Label("Fellenius")] public bool IsFellenius { get { return ModelOption == ModelOptions.Fellenius; } set { if (value) { ModelOption = ModelOptions.Fellenius; } } } [Label("UpliftVan")] public bool IsUpliftVan { get { return ModelOption == ModelOptions.UpliftVan; } set { if (value) { ModelOption = ModelOptions.UpliftVan; } } } [Label("UpliftSpencer")] public bool IsUpliftSpencer { get { return ModelOption == ModelOptions.UpliftSpencer; } set { if (value) { ModelOption = ModelOptions.UpliftSpencer; } } } [Label("BishopProbabilityRandomField")] public bool IsBishopProbabilityRandomField { get { return ModelOption == ModelOptions.BishopProbabilityRandomField; } set { if (value) { ModelOption = ModelOptions.BishopProbabilityRandomField; } } } [Label("HorizontalBalance")] public bool IsHorizontalBalance { get { return ModelOption == ModelOptions.HorizontalBalance; } set { if (value) { ModelOption = ModelOptions.HorizontalBalance; } } } [Label("Has zone plot")] public bool HasZonePlot { get { if (modelOption == ModelOptions.BishopProbabilityRandomField || modelOption == ModelOptions.HorizontalBalance) { return false; } else { return hasZonePlot; } } set { if (value != hasZonePlot) { DataEventPublisher.BeforeChange(this, "HasZonePlot"); hasZonePlot = value; DataEventPublisher.AfterChange(this, "HasZonePlot"); } } } [Label("Has geotextiles")] public bool HasGeotextile { get { return hasGeotextile; } set { if (value != hasGeotextile) { DataEventPublisher.BeforeChange(this, "HasGeotextile"); hasGeotextile = value; DataEventPublisher.AfterChange(this, "HasGeotextile"); } } } /// /// Gets or Sets the value for Requested number of slices. /// [Unit(UnitType.Number)] [Minimum(1)] [Maximum(999)] [PropertyOrder(1)] [ValidationIgnore] [XmlIgnore] public int RequestedNumberOfSlices { get { if (sliceData != null) { if (modelOption == ModelOptions.Bishop || modelOption == ModelOptions.Fellenius || modelOption == ModelOptions.BishopProbabilityRandomField) { return sliceData.StriveCircle; } else if (modelOption == ModelOptions.Spencer) { return sliceData.StriveSpencer; } else //for all other models { return sliceData.StriveLift; } } return 0; } set { if (modelOption == ModelOptions.Bishop || modelOption == ModelOptions.Fellenius || modelOption == ModelOptions.BishopProbabilityRandomField) { if (value != sliceData.StriveCircle) { DataEventPublisher.BeforeChange(this, "RequestedNumberOfSlices"); sliceData.StriveCircle = value; DataEventPublisher.AfterChange(this, "RequestedNumberOfSlices"); } } else if (modelOption == ModelOptions.Spencer) { if (value != sliceData.StriveSpencer) { DataEventPublisher.BeforeChange(this, "RequestedNumberOfSlices"); sliceData.StriveSpencer = value; DataEventPublisher.AfterChange(this, "RequestedNumberOfSlices"); } } else { if (value != sliceData.StriveLift) { DataEventPublisher.BeforeChange(this, "RequestedNumberOfSlices"); sliceData.StriveLift = value; DataEventPublisher.AfterChange(this, "RequestedNumberOfSlices"); } } } } /// /// Gets or Sets the value for maximum slice width. /// [Unit(UnitType.Length)] [Minimum(0.01)] [Maximum(100.0)] [PropertyOrder(1)] [Format("F3")] public double MaximumSliceWidth { get { return maximumSliceWidth; } set { DataEventPublisher.BeforeChange(this, "MaximumSliceWidth"); maximumSliceWidth = value; DataEventPublisher.AfterChange(this, "MaximumSliceWidth"); } } public GridOrientation GridOrientation { get { return slipCircle.Orientation; } set { DataEventPublisher.BeforeChange(this, "GridOrientation"); slipCircle.Orientation = value; rtoCalculationgrid.InwardStability = value == GridOrientation.Inwards; DataEventPublisher.AfterChange(this, "GridOrientation"); } } [XmlOrder(101)] public SliceData SliceData { get { return sliceData; } set { sliceData = value; } } [XmlArray("SlipPlanes")] [XmlOrder(70)] public IList SlipPlanes { get { return slipPlaneList; } } [XmlOrder(71)] public SlipPlaneUpliftVan SlipPlaneUpliftVan { get { return slipPlaneUpliftVan; } set { DataEventPublisher.BeforeChange(this, "SlipPlaneUpliftVan"); slipPlaneUpliftVan = value; slipPlaneUpliftVan.ModelOption = ModelOption; slipPlaneUpliftVan.StabilityModel = this; DataEventPublisher.AfterChange(this, "SlipPlaneUpliftVan"); } } [XmlOrder(25)] public List ForbiddenLinesList { get { return forbiddenLinesList; } } /// /// Gets or Sets Horizontal Balance value. /// [XmlOrder(110)] public HorizontalBalance HorizontalBalance { get { return horizontalBalance; } set { DataEventPublisher.BeforeChange(this, "HorizontalBalance"); horizontalBalance = value; DataEventPublisher.AfterChange(this, "HorizontalBalance"); } } [Validate] [XmlOrder(72)] public ReferenceLevelLine ReferenceLevelLine { get { return referenceLevelLine; } set { DataEventPublisher.BeforeChange(this, "ReferenceLevelLine"); referenceLevelLine = value; DataEventPublisher.AfterChange(this, "ReferenceLevelLine"); } } public GeometryObject CurrentSlipCircle { get { if (modelOption == ModelOptions.Bishop || modelOption == ModelOptions.Fellenius) { return SlipCircle; } else if (modelOption == ModelOptions.UpliftVan) { return SlipPlaneUpliftVan; } else if (modelOption == ModelOptions.HorizontalBalance) { return HorizontalBalance; } else if (modelOption == ModelOptions.Spencer) { if (SlipPlanes.Count < 1) { var list = new List() { new GeometryPoint(0, 0, 0) }; var slipplane = CreateSlipPlane(list, false); //SlipPlanes.Add(slipplane); } return SlipPlanes[0]; } else { return null; } } } [XmlOrder(79)] public SlipCircle SlipCircle { get { slipCircle.StabilityModel = this; return slipCircle; } set { DataEventPublisher.BeforeChange(this, "SlipCircle"); if (null != slipCircle) { slipCircle.Dispose(); } slipCircle = value; if (null != slipCircle) { slipCircle.StabilityModel = this; } DataEventPublisher.AfterChange(this, "SlipCircle"); } } [XmlIgnore] public int CurrentDegreeOfConsolidationIndex { get; set; } [XmlIgnore] public bool IsFixedPointVisble { get; set; } [XmlIgnore] public ZoneAreas ZoneAreas { get { return zoneAreas; } set { zoneAreas = value; } } [Label("SlipIntervalCaption")] public int SlipInterval { get { return slipInterval; } set { DataEventPublisher.BeforeChange(this, "SlipInterval"); slipInterval = value; } } [Browsable(false)] public bool GenerateSlipPlane { get { return /*(this.SlipPlanes.Count == 2) && */ generateSlipPlane; } set { DataEventPublisher.BeforeChange(this, "GenerateSlipPlane"); generateSlipPlane = value; DataEventPublisher.AfterChange(this, "GenerateSlipPlane"); } } [Browsable(false)] public bool AutoGenerateGeneticSpencer { get { return autoGenerateGeneticSpencer; } set { DataEventPublisher.BeforeChange(this, "AutoGenerateGeneticSpencer"); autoGenerateGeneticSpencer = value; DataEventPublisher.AfterChange(this, "AutoGenerateGeneticSpencer"); } } public SlipPlanePosition SlipPlanePosition { get { return slipPlanePosition; } set { DataEventPublisher.BeforeChange(this, "SlipPlanePosition"); slipPlanePosition = value; DataEventPublisher.AfterChange(this, "SlipPlanePosition"); } } [XmlIgnore] public bool IsLowSlipPlanes { get { return SlipPlanePosition == SlipPlanePosition.Low; } set { if (value) { SlipPlanePosition = SlipPlanePosition.Low; } } } [XmlIgnore] public bool IsHighSlipPlanes { get { return SlipPlanePosition == SlipPlanePosition.High; } set { if (value) { SlipPlanePosition = SlipPlanePosition.High; } } } [Minimum(2)] [Maximum(100)] [Category("TraversalGridPointCategory")] public int TraversalGridPoints { get { return traversalGridPoints; } set { DataEventPublisher.BeforeChange(this, "TraversalGridPoints"); traversalGridPoints = value; DataEventPublisher.AfterChange(this, "TraversalGridPoints"); } } [Browsable(false)] public int GeneratedPlanes { get { if (SlipPlanes.Count > 0) { return (int)Math.Pow(Convert.ToDouble(traversalGridPoints), Convert.ToDouble(SlipPlanes[0].Points.Count)); } else { return 0; } } } public bool MoveGrid { get { return ModelOption != ModelOptions.Spencer && moveGrid; } set { DataEventPublisher.BeforeChange(this, "MoveGrid"); moveGrid = value; DataEventPublisher.AfterChange(this, "MoveGrid"); } } public bool PreciseGA // Not used { get { return preciseGA; } set { DataEventPublisher.BeforeChange(this, "PreciseGA"); preciseGA = value; DataEventPublisher.AfterChange(this, "PreciseGA"); } } [Label("PreciseGA")] [XmlIgnore] [Obsolete("Use SearchAlgorithm instead")] public bool GeneticAlgorithm { get { return SearchAlgorithm == SearchAlgorithm.Genetic; } set { if (value) { UseGenetic = true; } } } public SearchAlgorithm SearchAlgorithm { get { if (ModelOption == ModelOptions.Bishop || ModelOption == ModelOptions.Spencer || ModelOption == ModelOptions.UpliftVan) { return searchAlgorithm; } else { return SearchAlgorithm.Grid; } } set { DataEventPublisher.BeforeChange(this, "SearchAlgorithm"); searchAlgorithm = value; DataEventPublisher.AfterChange(this, "SearchAlgorithm"); } } public bool UseGrid { get { return SearchAlgorithm == SearchAlgorithm.Grid; } set { if (value) { SearchAlgorithm = SearchAlgorithm.Grid; } } } public bool UseGenetic { get { return SearchAlgorithm == SearchAlgorithm.Genetic; } set { if (value) { SearchAlgorithm = SearchAlgorithm.Genetic; } } } public bool UseLevenbergMarquardt { get { return SearchAlgorithm == SearchAlgorithm.LevenbergMarquardt; } set { if (value) { SearchAlgorithm = SearchAlgorithm.LevenbergMarquardt; } } } public bool UseGaAndLevenbergMarquardt { get { return SearchAlgorithm == SearchAlgorithm.GeneticAndLevenbergMarquardt; } set { if (value) { SearchAlgorithm = SearchAlgorithm.GeneticAndLevenbergMarquardt; } } } /// /// Gets or Sets the value for minumu required percentage of froce-points in slices (used for Spencer acceptance criteria). /// [Unit(UnitType.Fractions)] [Minimum(0)] [Maximum(1)] [PropertyOrder(1)] [Format("F3")] [XmlOldName("MinReqPercForcePointsInSlices")] public double RequiredForcePointsInSlices { get { return requiredForcePointsInSlices; } set { DataEventPublisher.BeforeChange(this, "RequiredForcePointsInSlices"); requiredForcePointsInSlices = value; DataEventPublisher.AfterChange(this, "RequiredForcePointsInSlices"); } } /// /// Gets or Sets the value for maximum angle (in degrees) between slices (used for Spencer acceptance criteria). /// [Unit(UnitType.Angle)] [Minimum(0)] [Maximum(180)] [PropertyOrder(1)] [Format("F3")] public double MaxAllowedAngleBetweenSlices { get { return maxAllowedAngleBetweenSlices; } set { DataEventPublisher.BeforeChange(this, "MaxAllowedAngleBetweenSlices"); maxAllowedAngleBetweenSlices = value; DataEventPublisher.AfterChange(this, "MaxAllowedAngleBetweenSlices"); } } [Validate] [XmlOrder(77)] public GeneticAlgorithmOptions GeneticAlgorithmOptions { get { return geneticAlgorithmOptions; } set { geneticAlgorithmOptions = value; } } [Validate] [XmlOrder(78)] public LevenbergMarquardtOptions LevenbergMarquardtOptions { get { return levenbergMarquardtOptions; } set { levenbergMarquardtOptions = value; } } [Minimum(0)] [Maximum(1000)] public int NumberOfGridMoves { get { return numberOfGridMoves; } set { DataEventPublisher.BeforeChange(this, "NumberOfGridMoves"); numberOfGridMoves = value; } } /// /// Start value saftey factor for Bishop and UpliftVan Models /// [Unit(UnitType.None)] [Minimum(0)] [Maximum(100)] [PropertyOrder(2)] [Format("F3")] public double StartValueSafetyFactor { get { return startValueSafetyFactor; } set { DataEventPublisher.BeforeChange(this, "StartValueSafetyFactor"); startValueSafetyFactor = value; DataEventPublisher.AfterChange(this, "StartValueSafetyFactor"); } } /// /// gets or sets the value indicating whether end section friction is used or not /// public bool IsEndSectionFrictionUsed { get { return isEndSectionFrictionUsed; } set { DataEventPublisher.BeforeChange(this, "IsEndSectionFrictionUsed"); isEndSectionFrictionUsed = value; DataEventPublisher.AfterChange(this, "IsEndSectionFrictionUsed"); } } #region ISoilPropertyManager properties public ModelOptions ModelOption { get { return modelOption; } set { if (value != modelOption) { DataEventPublisher.BeforeChange(this, "ModelOption"); modelOption = value; DataEventPublisher.Changed(this); if (SoilModel != null) { SoilModel.ModelOption = ModelOption; } if (GeotechnicsData != null) { GeotechnicsData.IsExternalWaterLevelVisible = ModelOption == ModelOptions.BishopProbabilityRandomField; } slipCircle.StabilityModel = this; slipPlaneUpliftVan.ModelOption = value; DataEventPublisher.AfterChange(this, "ModelOption"); } } } public ShearStrengthModel DefaultShearStrengthModel { get { return defaultShearStrengthModel; } set { if (value != defaultShearStrengthModel) { DataEventPublisher.BeforeChange(this, "DefaultShearStrengthModel"); defaultShearStrengthModel = value; DataEventPublisher.AfterChange(this, "DefaultShearStrengthModel"); foreach (var soil in SoilModel.Soils) { if (soil.UseDefaultShearStrengthModel) { DataEventPublisher.AfterChange(soil, "ShearStrengthModel"); } } } } } public Measurement Measurement { get { return measurement; } set { if (value != measurement) { DataEventPublisher.BeforeChange(this, "Measurement"); measurement = value; DataEventPublisher.AfterChange(this, "Measurement"); } } } [Label("IsReliabilityCaption")] [Description("IsReliabilityDescription")] public bool IsReliability { get { return ReliabilityView.IsReliability; } set { if (value != ReliabilityView.IsReliability) { DataEventPublisher.BeforeChange(this, "IsReliability"); ReliabilityView.IsReliability = value; UpdateProbabilisticTransformer(); DataEventPublisher.AfterChange(this, "IsReliability"); if (!DataEventPublisher.IsDataEventPublishStopped) { foreach (var soil in Soils) { DataEventPublisher.AfterChange(soil); } foreach (var stress in SoilProfile.PreconsolidationStresses) { DataEventPublisher.AfterChange(stress); } } } } } [Label("Default input model option")] [XmlElement("DefaultInputModeAnalysisOption")] public ReliabilityAnalysisOption DefaultInputModeAnalysisOption { get { return defaultInputModeAnalysisOption; } set { DataEventPublisher.BeforeChange(this, "DefaultInputModeAnalysisOption"); defaultInputModeAnalysisOption = value; UpdateProbabilisticTransformer(); DataEventPublisher.AfterChange(this, "DefaultInputModeAnalysisOption"); } } public bool UseNailShearStress { get { return NailShearStress == NailShearStress.Ultimate; } } #endregion [Label("Has nails")] public bool HasNails { get { return hasNails; } set { DataEventPublisher.BeforeChange(this, "HasNails"); hasNails = value; DataEventPublisher.AfterChange(this, "HasNails"); } } /// /// General project info /// [Browsable(false)] [XmlOrder(0)] public Project ProjectInfo { get { return projectInfo; } set { projectInfo = value; } } private void UpdateProbabilisticTransformer() { if (IsReliability) { if (probabilisticCalculationType == ProbabilisticCalculationType.DeterministicDesign || defaultInputModeAnalysisOption == ReliabilityAnalysisOption.Design) { TransformerManager.Transformer = stabilityTransformer; } else { TransformerManager.Transformer = null; } } else { TransformerManager.Transformer = null; } } /// /// Indicates whether the soil may be deleted /// /// /// private bool DeleteSoil(Soil soil) { // Check whether the soil is used. If this is the case, the soil may not be deleted return SoilProfile.Surfaces.All(p => p.Soil != soil); } private void UpdateStochasts() { stochasts.Clear(); foreach (var soil in Soils) { UpdateStochasts(soil); } if (IsVisible("PreConsolidationStressList") && ReliabilityView.IsReliability) { stochasts.AddRange(SoilProfile.PreconsolidationStresses.Select(p => p.StressStochast)); } if (IsVisible("ModelUncertaintyParameterStochast")) { stochasts.Add(this.ModelUncertaintyParameterStochast); } } private void UpdateStochasts(object stochastOwner) { if (stochastOwner != null) { foreach (var propertyInfo in stochastOwner.GetType().GetProperties()) { if (propertyInfo.PropertyType.Equals(typeof(Stochast))) { var stochast = (Stochast)propertyInfo.GetValue(stochastOwner, null); bool visible = true; if (stochastOwner is IVisibleEnabled) { visible = ((IVisibleEnabled)stochastOwner).IsVisible(propertyInfo.Name); } if (visible) { if (!stochasts.Contains(stochast)) { stochasts.Add(stochast); } } else { stochasts.Remove(stochast); } } } } } private void UpdateConsolidationMatrix() { consolidationMatrixDirty = false; consolidationMatrix.Consolidators.Clear(); consolidationMatrix.Consolidated.Clear(); consolidationMatrix.ConsolidationValues.Clear(); // Fill consolidators consolidationMatrix.Consolidators.Add(ConsolidationLoad); consolidationMatrix.Consolidators.Add(Earthquake); foreach (var layer in SoilProfile.Surfaces) { consolidationMatrix.Consolidators.Add(layer); } // Fill consolidated foreach (var layer in SoilProfile.Surfaces) { consolidationMatrix.Consolidated.Add(layer); } this.UpdateConsolidatorsAndConsolidated(); DataEventPublisher.AfterChange(consolidationMatrix); } private void UpdateConsolidatorsAndConsolidated() { foreach (ConsolidationValue consolidationValue in this.consolidationMatrix.ConsolidationValues) { object consolidator = consolidationValue.Consolidator; object consolidated = consolidationValue.Consolidated; if (consolidator is UniformLoad) { consolidator = this.ConsolidationLoad; } if (consolidator is Earthquake) { consolidator = this.Earthquake; } if (consolidator is SoilLayer2D) { if (!SoilProfile.Surfaces.Contains((SoilLayer2D)consolidator)) { consolidator = FindSoilLayer((SoilLayer2D)consolidator); } } if (consolidated is SoilLayer2D) { if (!SoilProfile.Surfaces.Contains((SoilLayer2D)consolidated)) { consolidated = FindSoilLayer((SoilLayer2D)consolidated); } } ConsolidationMatrix.SetConsolidation(consolidator, consolidated, consolidationValue.Value); } } private SoilLayer2D FindSoilLayer(SoilLayer2D originalLayer) { const double margin = 0.00001; foreach (SoilLayer2D layer in SoilProfile.Surfaces) { if (layer.GeometrySurface == originalLayer.GeometrySurface) { return layer; } } GeometryBounds surfaceBounds = originalLayer.GeometrySurface.GetGeometryBounds(); foreach (SoilLayer2D layer in SoilProfile.Surfaces) { GeometryBounds bounds = layer.GeometrySurface.GetGeometryBounds(); if (Routines2D.AreEqual(bounds.Left, surfaceBounds.Left, margin) && Routines2D.AreEqual(bounds.Right, surfaceBounds.Right, margin) && Routines2D.AreEqual(bounds.Top, surfaceBounds.Top, margin) && Routines2D.AreEqual(bounds.Bottom, surfaceBounds.Bottom, margin)) { return layer; } } return null; } #endregion #region IDataCollection Members /// /// In this method the objects should unsubscribe the events. /// The Class Level objects sholuld be made null here. /// public void DisposeObjects() { Dispose(); referenceLevelLine = null; soilProfile = null; horizontalBalance = null; slipCircle = null; slipPlaneUpliftVan = null; sliceData = null; zoneAreas = null; stressesInGeometry = null; } /// /// Updates the counters. /// public void UpdateCounters() { var descriptionCounter = (long)lineLoads.Count; long maxDescriptionCounter = 1; foreach (var lineLoad in lineLoads) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(lineLoad.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < long.Parse(currentDescriptorCounter)) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { lineLoadDescriptionCounter = maxDescriptionCounter; } else { lineLoadDescriptionCounter = descriptionCounter + 1; } // for Nails. descriptionCounter = (long)Nails.Count; maxDescriptionCounter = 1; foreach (var nail in nails) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(nail.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < long.Parse(currentDescriptorCounter)) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { nailDescriptionCounter = maxDescriptionCounter; } else { nailDescriptionCounter = descriptionCounter + 1; } // for Uniform loads descriptionCounter = (long)uniformLoadsData.Count; maxDescriptionCounter = 1; foreach (var uniformLoad in uniformLoadsData) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(uniformLoad.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < long.Parse(currentDescriptorCounter)) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { uniformLoadDescriptionCounter = maxDescriptionCounter; } else { uniformLoadDescriptionCounter = descriptionCounter + 1; } descriptionCounter = (long)slipPlaneList.Count; maxDescriptionCounter = 0; foreach (var defenitionSlipPlane in slipPlaneList) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(defenitionSlipPlane.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < (long.Parse(currentDescriptorCounter))) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { curveDescriptionCounter = maxDescriptionCounter; } else { curveDescriptionCounter = descriptionCounter; } descriptionCounter = (long)forbiddenLinesList.Count; maxDescriptionCounter = 1; foreach (var forbiddenLine in forbiddenLinesList) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(forbiddenLine.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < (long.Parse(currentDescriptorCounter))) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { forbiddenLineCounter = maxDescriptionCounter; } else { forbiddenLineCounter = descriptionCounter + 1; } descriptionCounter = (long)Geotextiles.Count; maxDescriptionCounter = 1; foreach (var geotextile in Geotextiles) { var currentDescriptorCounter = ""; //using Math Routines For Parsing if (GeneralMathRoutines.GetContainingValue(geotextile.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < long.Parse(currentDescriptorCounter)) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } descriptionCounter = (long)soilProfile.Surfaces.Count; maxDescriptionCounter = 1; foreach (var soilSurface in soilProfile.Surfaces) { var currentDescriptorCounter = ""; if (GeneralMathRoutines.GetContainingValue(soilSurface.Name, ref currentDescriptorCounter)) { if (maxDescriptionCounter < long.Parse(currentDescriptorCounter)) { maxDescriptionCounter = long.Parse(currentDescriptorCounter); } } } if (maxDescriptionCounter > descriptionCounter) { soilSurfaceDescriptionCounter = maxDescriptionCounter; } else { soilSurfaceDescriptionCounter = descriptionCounter + 1; } } #endregion #region Geometry Object Create Logic public IGeometryObject Create(IGeometryObject aData) { if (aData == null) { return null; } DataEventPublisher.BeforeChange(this); // unique reference ID if (aData.GetType() == typeof(SoilLayer2D)) { DataEventPublisher.BeforeChange(soilProfile.Surfaces); if (soilSurfaceDescriptionCounter == (long)soilProfile.Surfaces.Count) { soilSurfaceDescriptionCounter++; } var newSoilSurface = aData as SoilLayer2D; soilProfile.Surfaces.Add(newSoilSurface); newSoilSurface.Name = "Soil surface " + soilSurfaceDescriptionCounter++; DataEventPublisher.DataListModified(soilProfile.Surfaces); } else if (aData.GetType() == typeof(LineLoad)) { var lineLoad = aData as LineLoad; lineLoads.Add(lineLoad); lineLoad.Name = "Line load " + lineLoadDescriptionCounter++; DataEventPublisher.DataListModified(lineLoads); } else if (aData.GetType() == typeof(Nail)) { var nail = aData as Nail; nails.Add(nail); nail.Name = "Nail " + nailDescriptionCounter++; DataEventPublisher.DataListModified(nails); } else if (aData.GetType() == typeof(TreeOnSlope)) { var treeOnSlope = aData as TreeOnSlope; treeOnSlope.Name = "Tree on slope"; TreeOnSlope = treeOnSlope; DataEventPublisher.Create(treeOnSlope); } else if (aData.GetType() == typeof(ReferenceLevelLine)) { var refLevelLine = aData as ReferenceLevelLine; refLevelLine.Name = "Reference level line"; referenceLevelLine = refLevelLine; DataEventPublisher.Create(refLevelLine); } else if (aData.GetType() == typeof(UniformLoad)) { var uniformLoadsData = aData as UniformLoad; this.uniformLoadsData.Add(uniformLoadsData); uniformLoadsData.Name = "Uniform load " + uniformLoadDescriptionCounter++; DataEventPublisher.DataListModified(this.uniformLoadsData); } else if (aData.GetType() == typeof(Earthquake)) { var earthquake = aData as Earthquake; earthquake.Name = "Earthquake"; Earthquake = earthquake; } else if (aData.GetType() == typeof(SlipPlane)) { var slipPlaneCurve = aData as SlipPlane; slipPlaneList.Add(slipPlaneCurve); slipPlaneCurve.Name = "Slip plane " + ++curveDescriptionCounter; DataEventPublisher.DataListModified(slipPlaneList); } else if (aData.GetType() == typeof(HorizontalBalance)) { var horizontalBalance = aData as HorizontalBalance; horizontalBalance.Name = "Calculation Area"; this.horizontalBalance = horizontalBalance; DataEventPublisher.Create(horizontalBalance); } else if (aData.GetType() == typeof(SlipCircle)) { var slipCircle = aData as SlipCircle; slipCircle.SlipCircleGrid.Name = "Calculation Grid"; slipCircle.SlipCircleTangentLine.Name = "Calculation Tangent Lines"; slipCircle.SlipCircleFixedPoint.Name = "Fixed Point"; slipCircle.StabilityModel = this; slipCircle.Name = "Calculation Grid"; DataEventPublisher.Create(slipCircle); // Replace StabilityModel.SlipCircle instance: this.slipCircle.Dispose(); this.slipCircle = slipCircle; } else if (aData.GetType() == typeof(SlipCircleTangentLine)) { } else if (aData.GetType() == typeof(SlipPlaneUpliftVan)) { var slipPlaneUpliftVan = aData as SlipPlaneUpliftVan; slipPlaneUpliftVan.SlipPlaneLeftGrid.Name = "Calculation grid - Left"; slipPlaneUpliftVan.SlipPlaneRightGrid.Name = "Calculation grid - Right"; slipPlaneUpliftVan.SlipPlaneTangentLine.Name = "Calculation Tangent Lines"; slipPlaneUpliftVan.Name = "SlipPlane Uplift Van"; DataEventPublisher.Create(slipPlaneUpliftVan); // Replace StabilityModel.SlipPlaneUpliftVan instance this.slipPlaneUpliftVan.Dispose(); this.slipPlaneUpliftVan = slipPlaneUpliftVan; this.slipPlaneUpliftVan.StabilityModel = this; } return aData; } public object[] GetModelObjects() { return new object[] { horizontalBalance, slipCircle, slipPlaneUpliftVan, treeOnSlope, ReferenceLevelLine }; } public IEnumerable[] GetModelLists() { return new IEnumerable[] { soilProfile.Surfaces, forbiddenLinesList, Geotextiles }; } #endregion #region Geometry Object Remove Logic public bool Remove(IGeometryObject geometryObject, bool aValidate) { if (geometryObject == null) { return false; } if (RemoveSoilSurface(geometryObject)) { return true; } if (RemoveLineLoad(geometryObject)) { return true; } if (RemoveNail(geometryObject)) { return true; } if (RemoveTreeOnSlope(geometryObject)) { return true; } if (RemoveUniformLoad(geometryObject)) { return true; } if (RemoveSlipPlaneCurve(geometryObject, aValidate)) { return true; } var geotextile = geometryObject as Geotextile; if (geotextile != null) { Geotextiles.RemoveAndNotify(geotextile); return true; } var forbiddenLines = geometryObject as ForbiddenLines; if (forbiddenLines != null) { ForbiddenLinesList.RemoveAndNotify(forbiddenLines); return true; } if (RemoveReferenceLevelLine(geometryObject)) { return true; } if (RemoveSlipCircle(geometryObject)) { return true; } if (RemoveHorizontalBalance(geometryObject)) { return true; } if (RemoveSlipPlaneUpliftVan(geometryObject)) { return true; } return false; } public bool Remove(List aList, bool aValidate) { bool result = false; foreach (var anObject in aList) { result = Remove((GeometryObject)anObject, aValidate); } return result; } private void DoRemove(Action action) { if (action == null) { throw new ArgumentNullException("action"); } DataEventPublisher.BeforeChange(this); action(); DataEventPublisher.AfterChange(this); } private void DoRemoveItemFromCollection(object item, IEnumerable collection) { DoRemoveItemFromCollection(item, collection, null); } private void DoRemoveItemFromCollection(object item, IEnumerable collection, Action action) { if (item == null) { throw new ArgumentNullException("item"); } if (collection == null) { throw new ArgumentNullException("collection"); } DataEventPublisher.BeforeChange(collection); DoRemove(() => { if (action != null) { action(); } if (collection is IList) { ((IList)collection).Remove(item); DataEventPublisher.Delete(item); DataEventPublisher.DataListModified(collection); } }); } private static bool CanRemoveItem(object item, IEnumerable collection) { if (collection == null) { throw new ArgumentNullException("collection"); } if (item == null) { return false; } return collection.Contains(item); } private bool RemoveSlipPlaneUpliftVan(IGeometryObject geometryObject) { var upliftVan = geometryObject as SlipPlaneUpliftVan; if (SlipPlaneUpliftVan != null && (geometryObject == SlipPlaneUpliftVan.SlipPlaneLeftGrid || geometryObject == SlipPlaneUpliftVan.SlipPlaneRightGrid)) { upliftVan = SlipPlaneUpliftVan; } if (upliftVan != null) { upliftVan.SlipPlaneLeftGrid = new SlipCircleGrid(); upliftVan.SlipPlaneRightGrid = new SlipCircleGrid(); upliftVan.SlipPlaneTangentLine = new SlipCircleTangentLine(); upliftVan.SlipPlaneTangentLine.StabilityModel = this; return true; } return false; } private bool RemoveHorizontalBalance(IGeometryObject geometryObject) { var balance = geometryObject as HorizontalBalance; if (balance != null) { DoRemove( () => { DataEventPublisher.Delete(horizontalBalance); horizontalBalance = null; }); return true; } return false; } private bool RemoveSlipCircle(IGeometryObject geometryObject) { var circle = geometryObject as SlipCircle; if (circle != null) { DoRemove( () => { DataEventPublisher.Delete(slipCircle.SlipCircleGrid); DataEventPublisher.Delete(slipCircle.SlipCircleTangentLine); DataEventPublisher.Delete(slipCircle.SlipCircleFixedPoint); DataEventPublisher.Delete(slipCircle); slipCircle = null; }); return true; } return false; } private bool RemoveReferenceLevelLine(IGeometryObject geometryObject) { var referenceLine = geometryObject as ReferenceLevelLine; if (referenceLine != null) { DoRemove(() => { for (int i = 0; i < referenceLine.Points.Count; i++) { GeometryData.Remove(referenceLine.Points[i], false); } DataEventPublisher.Delete(referenceLine); referenceLevelLine = null; }); return true; } return false; } private bool RemoveSlipPlaneCurve(IGeometryObject geometryObject, bool aValidate) { var slipPlaneCurve = geometryObject as SlipPlane; if (slipPlaneCurve != null && slipPlaneList.Contains(slipPlaneCurve)) { DoRemove(() => { for (int i = 0; i < slipPlaneCurve.Points.Count; i++) { GeometryData.Remove(slipPlaneCurve.Points[i], aValidate); } curveDescriptionCounter--; slipPlaneList.Remove(slipPlaneCurve); DataEventPublisher.Delete(slipPlaneCurve); DataEventPublisher.DataListModified(slipPlaneList); if (slipPlaneList.Count != 0) { SlipPlanes[0].Name = "Slip Plane " + curveDescriptionCounter; } }); return true; } return false; } private bool RemoveUniformLoad(IGeometryObject geometryObject) { var uniformLoads = geometryObject as UniformLoad; if (uniformLoads != null && uniformLoadsData.Contains(uniformLoads)) { DoRemoveItemFromCollection(uniformLoads, uniformLoadsData); return true; } return false; } private bool RemoveTreeOnSlope(IGeometryObject geometryObject) { if (geometryObject is TreeOnSlope && treeOnSlope != null) { DoRemove( () => { treeOnSlope.WindForce = 0.0; DataEventPublisher.Changed(treeOnSlope); }); return true; } return false; } private bool RemoveLineLoad(IGeometryObject geometryObject) { var lineLoad = geometryObject as LineLoad; if (CanRemoveItem(lineLoad, lineLoads)) { DoRemoveItemFromCollection(lineLoad, lineLoads); return true; } return false; } private bool RemoveNail(IGeometryObject geometryObject) { var nail = geometryObject as Nail; if (CanRemoveItem(nail, nails)) { DoRemoveItemFromCollection(nail, nails); return true; } return false; } private bool RemoveSoilSurface(IGeometryObject geometryObject) { var soilSurface = geometryObject as SoilLayer2D; if (CanRemoveItem(soilSurface, soilProfile.Surfaces)) { DoRemoveItemFromCollection(soilSurface, soilProfile.Surfaces); return true; } return false; } #endregion #region IGeometryBuilderListeners Members public bool CreateGeometryObject(List geometryList, IGeometryObject identifierObject) { bool isCreated = false; for (int objectIndex = 0; objectIndex < geometryList.Count; objectIndex++) { if (geometryList[objectIndex] is GeometrySurface) { CreateSoilSurface((GeometrySurface)geometryList[objectIndex]); isCreated = true; } } return isCreated; } public void DeleteGeometryListenerObjects(List aGeometryList) { if (GeometryData.Surfaces.Count == 0) { var tempSlipPlaneList = new List(); for (int i = 0; i < SlipPlanes.Count; i++) { tempSlipPlaneList.Add(SlipPlanes[i] as IGeometryObject); } HandleDelete(tempSlipPlaneList); } var surfaceToBeDeleted = new List(); foreach (var soilSurfaceToBedeleted in soilProfile.Surfaces) { foreach (var surface in aGeometryList) { if (surface == soilSurfaceToBedeleted.GeometricObject) { surfaceToBeDeleted.Add(soilSurfaceToBedeleted); } } } if (surfaceToBeDeleted.Count > 0) { Remove(surfaceToBeDeleted, false); } } public void UpdateGeometryObject(object aSender) { if (aSender.GetType() == typeof(GeometryPoint)) { foreach (var forbiddenLines in forbiddenLinesList) { var point = aSender as GeometryPoint; if (point == forbiddenLines.StartPoint) { forbiddenLines.StartPoint = point; } else if (point == forbiddenLines.EndPoint) { forbiddenLines.EndPoint = point; } } } } public void ReNumberObjects(Type aObjectType, ref long aStartIndex) { } //public List GetGeometryObjectList(IGeometryObject checkObject, ref bool isAddRowEnabled, ref string parentName) //{ // if (checkObject is GeometryPoint) // { // if (this.SlipPlanes.Count > 0) // { // if (this.SlipPlanes[0].Points.Contains(checkObject as GeometryPoint)) // { // isAddRowEnabled = true; // parentName = this.SlipPlanes[0].Name; // return this.SlipPlanes[0].Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // if (this.SlipPlanes.Count > 1) // { // if (this.SlipPlanes[1].Points.Contains(checkObject as GeometryPoint)) // { // isAddRowEnabled = false; // parentName = this.SlipPlanes[1].Name; // return this.SlipPlanes[1].Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // if (this.referenceLevelLine != null) // { // if (this.referenceLevelLine.Points.Contains(checkObject as GeometryPoint)) // { // isAddRowEnabled = false; // parentName = this.referenceLevelLine.Name; // return this.referenceLevelLine.Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // foreach (ForbiddenLines forbiddenLine in this.forbiddenLinesList) // { // if (forbiddenLine.StartPoint == checkObject as GeometryPoint || forbiddenLine.EndPoint == checkObject as GeometryPoint) // { // var objectList = new List() { forbiddenLine.StartPoint, forbiddenLine.EndPoint }; // isAddRowEnabled = false; // parentName = forbiddenLine.Name; // return objectList; // } // } // foreach (Geotextile geotextile in this.Geotextiles) // { // if (geotextile.StartPoint == checkObject as GeometryPoint || geotextile.EndPoint == checkObject as GeometryPoint) // { // isAddRowEnabled = false; // parentName = geotextile.Name; // return new List() { geotextile.StartPoint, geotextile.EndPoint }; // } // } // } // else if (checkObject is SlipPlane) // { // if (this.SlipPlanes.Count > 0) // { // if (checkObject == this.SlipPlanes[0]) // { // isAddRowEnabled = true; // parentName = this.SlipPlanes[0].Name; // return this.SlipPlanes[0].Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // if (this.SlipPlanes.Count > 1) // { // if (checkObject == this.SlipPlanes[1]) // { // isAddRowEnabled = false; // parentName = this.SlipPlanes[1].Name; // return this.SlipPlanes[1].Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // } // else if (checkObject is SoilLayer2D) // { // var surface = checkObject as SoilLayer2D; // parentName = "Points"; // isAddRowEnabled = false; // if (surface.GeometrySurface != null) // { // return surface.GeometrySurface.OuterLoop.Points.ConvertAll(new Converter(this.GeometryData.GeometryToObject)); // } // } // return null; //} public bool IsGeometryPointValid(GeometryPoint pointToBeValidated, string property) { return validator.IsGeometryPointValid(pointToBeValidated, property); } public void ReassignModelObjects(IGeometryObject aSender, IGeometryObject aReassignmentObject) { SoilLayer2D newSoilSurface = CreateSoilSurface(aReassignmentObject as GeometrySurface); foreach (var soilSurface in soilProfile.Surfaces) { if (soilSurface.GeometrySurface == (GeometrySurface)aSender) { newSoilSurface.Soil = soilSurface.Soil; break; } } } /// /// adds the provided geometry point to the hilighted Object colledtion /// /// geometry point to be added /// object to which the geometry point is added /// True if teh geometry point is added, else false public bool AddPoint(GeometryPoint addedPoint, IGeometryObject hilightedObject) { if (hilightedObject is SlipPlane && addedPoint != null) { var slipPlane = hilightedObject as SlipPlane; IList slipPlanePoints = slipPlane.Points; int insertIndex = GetPointInsertIndex(slipPlanePoints, addedPoint); slipPlane.AddOrRemoveListObject(addedPoint, true, insertIndex); //this.SortPointListX(ref slipPlanePoints); return true; } return false; } #endregion #region IGeometryModel Members public void CreateGeometryObject(List points, object aObjectType) { if (points == null || points.Count == 0) { return; } var stabilityType = (StabilityType)aObjectType; switch (stabilityType) { case StabilityType.SlipPlane: CreateSlipPlane(points); break; case StabilityType.SlipCircle: CreateSlipCircle(points[0]); break; case StabilityType.HorizontalBalance: CreateHorizontalBalance(points[0]); break; case StabilityType.SlipCircleFixedPoint: CreateSlipCircleFixedPoint(points[0]); break; case StabilityType.UpliftVanSlipPlane: CreateUpliftVanSlipPlane(points[0]); break; case StabilityType.LineLoad: CreateLineLoad(points[0], true); break; case StabilityType.Nail: CreateNail(points[0], true); break; case StabilityType.TreeOnSlope: CreateTreeOnSlope(points[0]); break; case StabilityType.UniformLoad: CreateUniformLoad(points); break; case StabilityType.ForbiddenLine: if (points.Count >= 2) { CreateForbiddenLines(points[0], points[1]); } break; case StabilityType.Geotextiles: if (points.Count >= 2) { CreateGeotextile(points[0], points[1]); } break; case StabilityType.StressesInGeometry: CreateStressInGeometry(points[0]); break; case StabilityType.ReferenceLevel: CreateReferenceLevelLine(points); break; } } public void DeleteGeometryObjects(List list) { var geometryObjects = new List(); foreach (var obj in list) { if (obj is IGeometryObject) { var geomObject = (IGeometryObject)obj; geometryObjects.Add(geomObject); } } HandleDelete(geometryObjects); if (Remove(geometryObjects, false)) { //this.geometryData.RegenerateGeometry(); } this.GeometryData.DeleteGeometryObjects(list); this.GeotechnicsData.DeleteGeometryObjects(list); } public void DragDropEnd(object aGeoDataObject) { if (aGeoDataObject is SoilLayer2D) { GeometryData.RegenerateGeometry(); } } public void OnDragging(object aSender) { if (aSender.GetType() == typeof(GeometryPoint)) { foreach (var geotextile in Geotextiles) { var point = aSender as GeometryPoint; if (point == geotextile.StartPoint) { geotextile.StartPoint = point; } else if (point == geotextile.EndPoint) { geotextile.EndPoint = point; } } } else if (aSender.GetType() == typeof(Geotextile)) { ((Geotextile)aSender).StartPoint.X = ((Geotextile)aSender).StartX; ((Geotextile)aSender).StartPoint.Z = ((Geotextile)aSender).StartZ; ((Geotextile)aSender).EndPoint.X = ((Geotextile)aSender).EndX; ((Geotextile)aSender).EndPoint.Z = ((Geotextile)aSender).EndZ; } } public void CreatingGeometryObject(ref object TopPoint, bool aIs2dPoint, bool aIsNearestToppoint) { } public void RenumberGeometryObjects() { curveDescriptionCounter = 1; GeometryData.RenumberGeometryItems(slipPlaneList.ConvertAll(item => (IGeometryObject)item), "Slip plane", ref curveDescriptionCounter, false); forbiddenLineCounter = 1; GeometryData.RenumberGeometryItems(forbiddenLinesList.ConvertAll(item => (IGeometryObject)item), "Forbidden line", ref forbiddenLineCounter, false); GeometryData.RenumberGeometryItems(lineLoads.ConvertAll(item => (IGeometryObject)item), "Line load", ref lineLoadDescriptionCounter, false); GeometryData.RenumberGeometryItems(nails.ConvertAll(item => (IGeometryObject)item), "Nail", ref nailDescriptionCounter, false); GeometryData.RenumberGeometryItems(uniformLoadsData.ConvertAll(item => (IGeometryObject)item), "Uniform load", ref uniformLoadDescriptionCounter, false); } private void StartObserveChange() { UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(this); } private void EndObserveChange() { DataEventPublisher.AfterChange(this); UndoRedoManager.Instance.EndAction(); } private void CreateForbiddenLines(Point3D start, Point3D end) { StartObserveChange(); var forbiddenLine = new ForbiddenLines { StartPoint = new GeometryPoint { X = start.X, Y = start.Y, Z = start.Z }, EndPoint = new GeometryPoint { X = end.X, Y = end.Y, Z = end.Z } }; UniqueNameProvider.ProvideUniqueName(ForbiddenLinesList, forbiddenLine); ForbiddenLinesList.AddAndNotify(forbiddenLine); EndObserveChange(); } private void CreateGeotextile(Point3D start, Point3D end) { StartObserveChange(); var geotextile = new Geotextile { StartPoint = new GeometryPoint { X = start.X, Y = start.Y, Z = start.Z }, EndPoint = new GeometryPoint { X = end.X, Y = end.Y, Z = end.Z } }; UniqueNameProvider.ProvideUniqueName(Geotextiles, geotextile); Geotextiles.AddAndNotify(geotextile); EndObserveChange(); } #endregion #region Data Event Plublisher Handlers public void UpdateAutomaticDefinitions() { if (calculationModel == CalculationModel.DSerie) { return; } bool valid = !(RequiresRightOrder() && !SurfaceLine2Validator.AreAllCharacteristicPointsXCoordinatesAscending(SurfaceLine2)); if (valid && RequiresRightShape() && !SurfaceLine2Validator.AreAllCharacteristicPointsInCorrectShape(SurfaceLine2)) { valid = false; } if (valid && RequiresAquifer() && !SoilProfile.Surfaces.Any(p => p.IsAquifer)) { valid = false; SlipPlanes.Clear(); DataEventPublisher.DataListModified(SlipPlanes); } if (valid && AutoGenerateGeneticSpencer && modelOption == ModelOptions.Spencer) { rtoCalculationgrid.GenerateSpencerSlipPlanes(this); } if (valid && SlipCircle.Auto) { // If there are not surfaces, there is nothing to update: if (!SoilProfile.Surfaces.Any()) { return; } rtoCalculationgrid.CreateGrid(this); } if (valid) { if (SlipPlaneConstraints.CreateZones) { rtoCalculationgrid.CreateZone(this); } } if (location.WaternetCreationMode != WaternetCreationMode.FillInWaternetValues && !updatingWaternet) { IWaternetCreator waternetCreator = GetWaternetCreator(location.PlLineCreationMethod); if (calculationModel != CalculationModel.DSerie && valid && waternetCreator.CanGenerateWaternet(location)) { updatingWaternet = true; try { waternetCreator.UpdateWaternet(GeotechnicsData.CurrentWaternet, location); } finally { updatingWaternet = false; } } else { ClearWaternet(GeotechnicsData.CurrentWaternet); } } } private IWaternetCreator GetWaternetCreator(PlLineCreationMethod plLineCreationMethod) { switch (plLineCreationMethod) { case PlLineCreationMethod.RingtoetsWti2017: return new WaternetCreatorWTI(); default: return new WaternetCreator(); } } /// /// Clears the waternet, to be used when there is no valid input /// private void ClearWaternet(Waternet waternet) { if (waternet.WaternetLineList.Any()) { DataEventPublisher.BeforeChange(waternet.WaternetLineList); waternet.WaternetLineList.Clear(); DataEventPublisher.DataListModified(waternet.WaternetLineList); } if (waternet.HeadLineList.Any()) { DataEventPublisher.BeforeChange(waternet.HeadLineList); waternet.HeadLineList.Clear(); DataEventPublisher.DataListModified(waternet.HeadLineList); } if (waternet.PhreaticLine != null) { if (waternet.PhreaticLine.Points.Any()) { DataEventPublisher.BeforeChange(waternet.PhreaticLine.Points); waternet.PhreaticLine.Points.Clear(); DataEventPublisher.AfterChange(waternet, "PhreaticLine"); DataEventPublisher.DataListModified(waternet.PhreaticLine.Points); } } } private void OnAfterChangePublisher(object sender, PublishEventArgs e) { if (sender is SlipCircle || sender is HorizontalBalance || sender is SlipCircleFixedPoint || sender is SlipCircleTangentLine || sender is SlipPlaneUpliftVan) { if (IsSlipCircleDefaultValues()) { DataEventPublisher.Changed(SlipCircle); } if (IsCalculationAreaDefaultValues()) { DataEventPublisher.Changed(HorizontalBalance); } if (IsUpliftVanSlipPlaneDefaultValues()) { DataEventPublisher.Changed(SlipPlaneUpliftVan); } } else if (sender is StabilityModel && AutoGenerateGeneticSpencer && modelOption == ModelOptions.Spencer) { if (e.Properties.Length > 0 && (e.Properties[0] == "AutoGenerateGeneticSpencer" || e.Properties[0] == "SlipPlanePosition")) { Delayed.Invoke(UpdateAutomaticDefinitions); } } else if (sender is SlipplaneConstraints && e.Properties[0] == "CreateZones") { Delayed.Invoke(UpdateAutomaticDefinitions); } else if (sender is Soil) { if (e.Objects != null) { if (e.Objects.Length > 0) { if (e.Objects[0].ToString() == "Description") { foreach (var surface in soilProfile.Surfaces) { if (surface.Soil == sender) { surface.Name = (sender as Soil).Description + " " + (soilProfile.Surfaces.IndexOf(surface) + 1); DataEventPublisher.Changed(surface.GeometrySurface, null); } } } } } UpdateStochasts(sender); DataEventPublisher.DataListModified(Stochasts); } else if (sender is SoilLayer2D) { var soilLayer = (SoilLayer2D)sender; if (soilLayer.Soil != null && SoilProfile.Surfaces.Contains(soilLayer) && !SoilModel.Soils.Contains(soilLayer.Soil)) { DataEventPublisher.BeforeChange(SoilModel.Soils); SoilModel.Soils.Add(soilLayer.Soil); DataEventPublisher.DataListModified(SoilModel.Soils, soilLayer.Soil); } if (e.Properties.Length > 0 && e.Properties[0] == "IsAquifer") { if (SoilProfile.Surfaces.Contains(soilLayer)) { Delayed.Invoke(UpdateAutomaticDefinitions); } } } else if (sender == location) { if (!updatingWaternet) { Delayed.Invoke(UpdateAutomaticDefinitions); } } if (sender == SlipCircle && e.Properties[0] == "Auto") { if (((SlipCircle)sender).Auto) { // If there are not surfaces, there is nothing to update: if (!SoilProfile.Surfaces.Any()) { return; } if (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) { Delayed.Invoke(UpdateAutomaticDefinitions); } } } else if (sender is CharacteristicPoint) { var characteristicPoint = (CharacteristicPoint)sender; if (SurfaceLine2 != null && characteristicPoint.PointSet == SurfaceLine2.CharacteristicPoints && (e.Property == "Z" || e.Property == "X")) { if (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) { Delayed.Invoke(UpdateAutomaticDefinitions); } } } } private void OnPublisherChanged(object aSender, EventArgs aResult) { if (aSender is Soil) { if (SoilModel.Soils.Count > previousSoilCount) { previousSoilCount = SoilModel.Soils.Count; } } } private void DataEventPublisher_OnDataListModified(object sender, PublishEventArgs e) { if (ReferenceEquals(sender, Soils)) { UpdateStochasts(); DataEventPublisher.DataListModified(Stochasts); } else if (SoilProfile != null && sender is IList && ReferenceEquals(sender, SoilProfile.Surfaces)) { consolidationMatrixDirty = true; DataEventPublisher.AfterChange(this, "ConsolidationMatrix"); } else if (sender is IList && ReferenceEquals(sender, soilProfile.Geometry.Points)) { // update the surface line for geometry change if (surfaceLine2 != null) { surfaceLine2.Geometry.Points.Clear(); surfaceLine2.Geometry.Points.AddRange(GeometryData.SurfaceLine.Points); } } else if (sender is LocalizedGeometryPointString && sender == GeometryData.SurfaceLine) { if (CalculationModel == CalculationModel.RTO || CalculationModel == CalculationModel.WBI) { // Disabled for the moment, because it runs up in too may events Delayed.Invoke(UpdateAutomaticDefinitions); } } } private bool RequiresAquifer() { return SlipCircle.Auto || (AutoGenerateGeneticSpencer && modelOption == ModelOptions.Spencer) || location.WaternetCreationMode != WaternetCreationMode.FillInWaternetValues; } private bool RequiresRightOrder() { return SlipCircle.Auto || (AutoGenerateGeneticSpencer && modelOption == ModelOptions.Spencer) || location.WaternetCreationMode != WaternetCreationMode.FillInWaternetValues; } private bool RequiresRightShape() { return (AutoGenerateGeneticSpencer && modelOption == ModelOptions.Spencer) || location.WaternetCreationMode != WaternetCreationMode.FillInWaternetValues; } #endregion private void AddNail(Nail nail) { nail.VisibleEnabledProvider = this; } private void AddSlipPlane(SlipPlane slipPlane) { slipPlane.StabilityModel = this; surfaceLineAttacher.PointsProviders.Add(slipPlane); } private void CreateSlipPlane(List vertexPointList) { if (SlipPlanes.Count < 2) { UndoRedoManager.Instance.BeginAction(); var slipPlanePointList = new List(); if (SlipPlanes.Count == 1 && SlipPlanes[0].Points.Count == 1) { SlipPlanes.Clear(); } bool pointsTruncate = SlipPlanes.Count == 1; if (vertexPointList.Count < 1) { return; } for (int index1 = 0; index1 < vertexPointList.Count; index1++) { if (pointsTruncate) { if (SlipPlanes[0].Points.Count == index1) { break; } } Point3D vertex3D = vertexPointList[index1]; var geometryPoint = new GeometryPoint(); GeometryData.Create(geometryPoint); GeometryPoint point = geometryPoint; point.X = vertex3D.X; point.Y = vertex3D.Y; point.Z = vertex3D.Z; slipPlanePointList.Add(point); } if (slipPlanePointList[0].X > slipPlanePointList[slipPlanePointList.Count - 1].X) { SortPointListX(ref slipPlanePointList); } AddSlipPlane(CreateSlipPlane(slipPlanePointList, true)); UndoRedoManager.Instance.EndAction(); } } /// /// returns the index to which the point must be inserted /// /// list of points to be evaluated /// point to be inserted /// private int GetPointInsertIndex(IList pointList, GeometryPoint point) { int index = 0; while (index + 1 < pointList.Count) { var point1 = new Point2D(pointList[index].X, pointList[index].Z); var point2 = new Point2D(pointList[index + 1].X, pointList[index + 1].Z); var checkPoint = new Point2D(point.X, point.Z); if (Routines2D.DoesPointExistInLine(point1, point2, checkPoint, GeometryConstants.Accuracy)) { double correctpointX = 0.0; double correctpointY = 0.0; Routines2D.GetPointOnLineClosestTo(checkPoint.X, checkPoint.Y, point1.X, point1.Y, point2.X, point2.Y, out correctpointX, out correctpointY); point.X = correctpointX; point.Z = correctpointY; return index + 1; } index++; } return pointList.Count - 1; } private void SetDefaultValuesForSlipPlaneUpliftVan() { SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXLeft = 0.0; SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXRight = 0.0; SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXNumber = 1; SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZTop = 0.0; SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom = 0.0; SlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZNumber = 1; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridXLeft = 0.0; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridXRight = 0.0; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridXNumber = 1; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridZTop = 0.0; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridZBottom = 0.0; SlipPlaneUpliftVan.SlipPlaneRightGrid.GridZNumber = 1; SlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZTop = 0.0; SlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZBottom = 0.0; SlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineNumber = 1; SlipPlaneUpliftVan.SlipPlaneTangentLine.AutomaticAtBoundaries = false; } private void SetDefaultValuesForUpliftVanSlipPlane(Point3D lVertex3D, SlipPlaneUpliftVan aSlipPlaneUpliftVan) { Point2D lVertex2D = GeometryData.GetLocalCoordinate(lVertex3D); aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridXLeft = lVertex2D.X + 10; aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridXRight = lVertex2D.X + 13; aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridXNumber = 3; aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridZTop = lVertex2D.Y; aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridZBottom = lVertex2D.Y - 5; aSlipPlaneUpliftVan.SlipPlaneRightGrid.GridZNumber = 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXLeft = lVertex2D.X - 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXRight = lVertex2D.X + 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridXNumber = 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZTop = lVertex2D.Y + 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom = lVertex2D.Y - 5; aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZNumber = 10; double gridZTop; if (SurfaceLine2 != null && SurfaceLine2.Geometry.Count > 0) { var line = new GeometryPointString(); line.Points.AddRange(SurfaceLine2.Geometry.Points.Where(p => !double.IsNaN(p.X))); gridZTop = line.GetZAtX(lVertex2D.X); aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZTop = gridZTop - 1; aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZBottom = gridZTop - 4; aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineNumber = 3; } else { gridZTop = aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZTop; aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZTop = ((aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom) + (aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom - gridZTop)); aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineZBottom = ((aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom) + (aSlipPlaneUpliftVan.SlipPlaneLeftGrid.GridZBottom - gridZTop)); aSlipPlaneUpliftVan.SlipPlaneTangentLine.TangentLineNumber = 1; } DataEventPublisher.Changed(aSlipPlaneUpliftVan.SlipPlaneLeftGrid); DataEventPublisher.Changed(aSlipPlaneUpliftVan.SlipPlaneRightGrid); } } }