//----------------------------------------------------------------------- // // Copyright (c) 2009 Deltares. All rights reserved. // // R.C. blankenburgh // remko.blankenburgh@deltares.nl // 26-08-2009 // n.a. //----------------------------------------------------------------------- using Deltares.Geotechnics.Converter; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Geotechnics.Validation; using Deltares.Standard.Attributes; using Deltares.Standard.Data; using Deltares.Standard.Language; using Deltares.Standard.Logging; namespace Deltares.Dam.Data { using System; using System.Collections.Generic; using System.IO; using System.Linq; using Soilbase; using Standard; using Geotechnics; using System.ComponentModel; using System.Xml.Serialization; using Standard.Extensions; public class DikeException : Exception { public DikeException(string message) : base(message) { } } public class DikeParameterNames { public const string MapForSoilGeometries2D = "MapForSoilGeometries2D"; } [TrackChanges] public class Dike: IVisibleEnabled, IDisposable { private string description = ""; public virtual string MapForSoilGeometries2D { get; set; } private IList locations; private IList pl1Lines; private bool removeStiFiles; private MStabShearStrength shearmodel; private SoilList soilList; private IList gauges = new List(); private IList gaugePLLines = new List(); private IList nonWaterRetainingObjects; private IList soilProfiles; private string soilDatabaseName = ""; private List databaseSoils = new List(); public Dike() { this.Name = "Dijkring"; this.MapForSoilGeometries2D = ""; this.locations = new List(); this.soilProfiles = new List(); this.surfaceLines = new DelegatedList { AddMethod = ConvertAddedOldSurfaceLineToNewFormat }; SurfaceLines2 = new List(); this.pl1Lines = new List(); this.soilList = new SoilList(); this.nonWaterRetainingObjects = new List(); removeStiFiles = true; } public bool IsRemoveStiFiles { get { return removeStiFiles; } set { removeStiFiles = value; } } public MStabShearStrength ShearStrengthModel { get { return shearmodel; } set { shearmodel = value; } } public virtual string Name { get; set; } public virtual string SoilDatabaseName { get { return this.soilDatabaseName; } set { this.soilDatabaseName = value; UpdateLocationsDatabaseName(); } } /// /// Updates the locations for scenarios. /// public void UpdateLocationsForScenarios() { foreach (Location location in this.Locations) { foreach (Scenario scenario in location.Scenarios) { scenario.Location = location; } } } /// /// Updates the name soil database for all locations. /// public void UpdateLocationsDatabaseName() { foreach (Location location in this.Locations) { location.SoildatabaseName = this.SoilDatabaseName; } } [XmlIgnore] public SoilbaseDB SoilBaseDB { get; set; } /// /// Gets the locations. /// /// /// The locations. /// public virtual IList Locations { get { return this.locations; } private set { this.locations = value; } } /// /// Sorts the locations. /// public void SortLocations() { this.locations = this.Locations.OrderBy(o => o.Name).ToList(); } public IList SurfaceLines2 { get; set; } public virtual IList PL1Lines { get { return this.pl1Lines; } set { this.pl1Lines = value; } } public virtual IList SoilProfiles { get { return this.soilProfiles; } set { this.soilProfiles = value; } } public virtual SoilList SoilList { get { return this.soilList; } set { this.soilList = value; } } [Browsable(false)] public virtual IList Gauges { get { return this.gauges; } set { this.gauges = value; } } [Browsable(false)] public virtual IList GaugePLLines { get { return this.gaugePLLines; } set { this.gaugePLLines = value; } } public virtual IList NonWaterRetainingObjects { get { return this.nonWaterRetainingObjects; } set { this.nonWaterRetainingObjects = value; } } public bool UsesGauges { get { return this.GaugePLLines != null && this.GaugePLLines.Count > 0 && this.Gauges != null; } } public virtual List Scenarios { get { var scenarios = new List(); foreach (Location location in Locations) { scenarios.AddRange(location.Scenarios); } return scenarios; } } public string Description { get { return description; } set { description = value; } } public void Validate() { if (Locations == null || Locations.Count < 1) { throw new DikeException("The dike ring has no locations defined"); } foreach (Location location in Locations) { if (location.LocalXZSurfaceLine2 != null) { var validator = new SurfaceLine2Validator(); var validationResults = validator.ValidateCharacteristicPointsAreOrdered(location.LocalXZSurfaceLine2) .Concat(validator.ValidateGeometryPointsAreOrdered(location.LocalXZSurfaceLine2)).ToArray(); if (validationResults.Length > 0) { throw new SurfaceLineException(validationResults[0].Text); } } } } public void CreateSoilBase() { if (this.SoilDatabaseName == null || !File.Exists(this.SoilDatabaseName)) { throw new DikeException(String.Format("The soil database '{0}' cannot be found", this.SoilDatabaseName)); } this.SoilBaseDB = SoilbaseDB.Create(this.SoilDatabaseName); } /// /// Read all the soils and their parameters from the database /// public void FillDataBaseSoilListFromSoilBase() { using (var geoDatabase = new GeoDatabase(this.SoilDatabaseName)) { geoDatabase.ReUseSoils = true; var newSoilList = geoDatabase.ReadSoils(soilList.Soils); databaseSoils = newSoilList.Soils; } } /// /// Add 1D-soilprofiles from MGeobase database /// public void AddSoilProfilesFromDB() { if (this.SoilDatabaseName == null || !File.Exists(this.SoilDatabaseName)) { throw new DikeException(String.Format("The MGeobase database '{0}' cannot be found", this.SoilDatabaseName)); } if (soilList.Soils.Count == 0) { FillDataBaseSoilListFromSoilBase(); soilList.Soils.AddRange(databaseSoils); } if (soilList.Soils.Count == 0) { throw new DikeException(String.Format("The MGeobase database '{0}' does not contain soils and can not be used.", this.SoilDatabaseName)); } MGeobaseDB mgbDB = new MGeobaseDB(soilList); IList addedSoilProfiles = mgbDB.AddSoilProfiles(this.SoilDatabaseName); foreach (var addedSoilProfile in addedSoilProfiles) { soilProfiles.Add(addedSoilProfile); } } /// /// Adapt data so it is consistent /// public List MakeDataConsistent() { var errorSoils = TryToMakeSoilDataConsistent(); var logMessages = new List(); // Delete all locations without surfaceline logMessages.AddRange(DeleteLocationsWithoutSurfaceLines()); // Delete all locations that have profiles (in their segment) which hold soils // that are not in the soil database and so have no parameters. logMessages.AddRange(DeleteLocationsWithProfilesWithUnknownSoils(errorSoils)); return logMessages; } /// /// Tries to make the soil data as read for 1D profiles consistent with the data in the soil database. /// In the end we have a neat soil list with parameters for every soil as read from the database. /// We might have a list with errors (soils that were not to be found in the database so soils for which /// no parameters could be found). /// /// private List TryToMakeSoilDataConsistent() { var errorSoils = new List(); // Fill the list of errorSoils with soils that are in the current soillist (as result of importing // 1D profiles) but that are not found in the soil database because that are errors foreach (var soil in soilList.Soils) { var fs = databaseSoils.Find(t => String.Equals(t.Name, soil.Name, StringComparison.CurrentCultureIgnoreCase)); if (fs == null) { errorSoils.Add(soil); } } // Remove the error soils form the list foreach (var errorSoil in errorSoils) { soilList.Soils.Remove(errorSoil); } // Get the parameters for every soil in the now proper soil list from the database. Add soils // that are in the database but not yet in the soil list. foreach (Soil soil in databaseSoils) { Soil existingSoil = this.soilList.GetSoilByName(soil.Name); if (existingSoil == null) { this.soilList.Soils.Add(soil); } else { existingSoil.Assign(soil); } } return errorSoils; } /// /// Removes all locations which have profiles that have invalid soils /// private List DeleteLocationsWithProfilesWithUnknownSoils(List invalidSoils) { var logMessages = new List(); var invalidLocations = new List(); string soilProf; string invSoil; foreach (var location in locations) { bool isInValid; string message = ""; if (location.Segment == null) { isInValid = true; message = String.Format(LocalizationManager.GetTranslatedText(this.GetType(), "LocationWitNameHasNoSegment"), location.Name); } else { isInValid = DoesLocationHaveInvalidSoils(invalidSoils, location, out soilProf, out invSoil); if (isInValid) { message = String.Format(LocalizationManager.GetTranslatedText(this.GetType(), "LocationHasProfileWithInvalidSoils"), location.Name, soilProf, invSoil); } } if (isInValid) { invalidLocations.Add(location); logMessages.Add(new LogMessage(LogMessageType.Warning, this, message)); } } foreach (var invalidLocation in invalidLocations) { locations.Remove(invalidLocation); } return logMessages; } /// /// Checks wether a location (or rather the soilprofiles in the segement of the location) contains invalid soils. /// A soil is hereby considered invalid if it is not found in the database. /// /// /// /// /// /// private bool DoesLocationHaveInvalidSoils(List invalidSoils, Location location, out string soilProf, out string invSoil) { soilProf = " "; invSoil = " "; foreach (var spp in location.Segment.SoilProfileProbabilities) { foreach (var invalidSoil in invalidSoils) { var fl = spp.SoilProfile.Layers.Find(l => String.Equals(l.Soil.Name, invalidSoil.Name, StringComparison.CurrentCultureIgnoreCase)); if (fl != null) { soilProf = spp.SoilProfile.Name; invSoil = invalidSoil.Name; return true; } } } return false; } /// /// Delete all locations without surfacelines /// private List DeleteLocationsWithoutSurfaceLines() { var logMessages = new List(); //Add all locations with valid surfaceline var newLocations = new List(); newLocations.AddRange(this.Locations.Where(loc => loc.SurfaceLine2 != null)); // Report which locations are not added because no valid surfaceline is found var deletedLocations = new List(); deletedLocations.AddRange(this.Locations.Where(loc => loc.SurfaceLine2 == null)); foreach (var deletedLocation in deletedLocations) { var locationHasNoSurfaceLine = LocalizationManager.GetTranslatedText(this.GetType(), "LocationHasNoSurfaceLine"); logMessages.Add(new LogMessage(LogMessageType.Warning, this, String.Format(locationHasNoSurfaceLine, deletedLocation.Name))); } this.Locations = newLocations; return logMessages; } public override string ToString() { return this.Name; } public Dictionary GetParametersAsNameValuePairs() { var nameValuePairs = new Dictionary(); nameValuePairs.Add(DikeParameterNames.MapForSoilGeometries2D, MapForSoilGeometries2D); return nameValuePairs; } public void SetParameterFromNameValuePair(string parameterName, string parameterValue) { if (parameterName.Equals(DikeParameterNames.MapForSoilGeometries2D)) this.MapForSoilGeometries2D = parameterValue; } public void UpdateLocation(Location location) { location.SoildatabaseName = this.SoilDatabaseName; location.SoilList = this.SoilList; location.MapForSoilGeometries2D = this.MapForSoilGeometries2D; location.Gauges.Clear(); location.Gauges.AddRange(this.Gauges); location.GaugePLLines.Clear(); location.GaugePLLines.AddRange(this.GaugePLLines); } public bool IsVisible(string property) { return true; } public bool IsEnabled(string property) { switch (property) { case "Name": return false; case "SoilList": return false; default: return true; } } #region Backwards compatibility private IList surfaceLines; /// /// Gets or sets all surface lines instances associated with this dike. /// /// Composite owner of all that are part of the /// application that are associated with this dike. [Obsolete("Do not use this member; Only exists for backwards compatibility.", true)] public virtual IList SurfaceLines { get { return surfaceLines; } set { surfaceLines = value; } } /// /// Performs backwards compatibility conversion from old-style surfaceline to new-style /// surfaceline, and ensures that shared references are set correctly. /// /// Persisted version of the old-style surfaceline. private void ConvertAddedOldSurfaceLineToNewFormat(SurfaceLine argument) { var surfaceLine2 = new OldSurfaceLineToNewConverter().Convert(argument); SurfaceLines2.Add(surfaceLine2); foreach (var location in Locations) { location.SetNewSurfaceLineIfMatchesWithOldPersistedSurfaceLine(surfaceLine2); } // Remove old entry; it is no longer required. surfaceLines.Remove(argument); argument.Dispose(); } #endregion public void Dispose() { foreach (var location in Locations) { location.Dispose(); } foreach (var surfaceLine2 in SurfaceLines2) { surfaceLine2.Dispose(); } } } }