// Copyright (C) Stichting Deltares 2025. All rights reserved. // // This file is part of the application DAM - UI. // // DAM - UI is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Linq; using Deltares.Dam.Data.CsvImporters; using Deltares.Geometry; using Deltares.Geotechnics.Exception; using Deltares.Geotechnics.GeotechnicalGeometry; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Standard.EventPublisher; using Deltares.Standard.Language; using Deltares.Standard.Logging; namespace Deltares.Dam.Data.IO; /// /// Exception class for the class. /// public class CombineImportedDataException : Exception { public CombineImportedDataException(string message) : base(message) {} } /// /// Class for combining imported data from CSV files. /// public class CombineImportedData { /// /// The WaterBoard to which the imported data will be added. /// public WaterBoard WaterBoard { get; set; } /// /// The Location records. /// public IEnumerable LocationRecords { get; set; } /// /// The Segment records. /// public IEnumerable SegmentRecords { get; set; } /// /// The SoilProfile records. /// public IEnumerable SoilProfilerecords { get; set; } /// /// The Aquifer records. /// public IEnumerable AquiferRecords { get; set; } /// /// The SurfaceLine records. /// public IEnumerable SurfaceLineRecords { get; set; } /// /// The Soil records. /// public IEnumerable SoilRecords { get; set; } /// /// The CharacteristicPoints records. /// public IEnumerable CharacteristicPointsRecords { get; set; } /// /// The Scenario records. /// public IEnumerable ScenarioRecords { get; set; } /// /// The SigmaTauCurve records. /// public IEnumerable SigmaTauCurveRecords { get; set; } /// /// The SigmaTauCurve records. /// public IEnumerable SuTableRecords { get; set; } /// /// The error messages. /// public IList ErrorMessages { get; } = new List(); /// /// Adds the imported CSV data to dikes. /// public void AddCsvDataToDikes() { if (WaterBoard == null) { string damProjectDataNotAssignedForImport = LocalizationManager.GetTranslatedText(GetType(), "damProjectDataNotAssignedForImport"); throw new CombineImportedDataException(damProjectDataNotAssignedForImport); } AddDikesFromLocationsToWaterBoard(WaterBoard); foreach (Dike dike in WaterBoard.Dikes) { TransferLocationsData(dike); TransferSoilProfilesData(dike); TransferAquifersData(dike); TransferSegmentData(dike); TransferSigmaTauCurveData(dike); // Should be done before TransferSoilData(), because the SigmaTauCurveData is used there TransferSuTableData(dike); // Should be done before TransferSoilData(), because the SuTableCurveData is used there TransferSoilData(dike); // Use InvokeWithoutPublishingEvents for performance reasons after introducing SurfaceLine2 DataEventPublisher.InvokeWithoutPublishingEvents(() => { TransferSurfaceLines(dike); }); } } public void AddScenarioDataToDikes() { foreach (Dike dike in WaterBoard.Dikes) { if (ScenarioRecords != null) { TransferScenarios(dike); } } } internal bool CheckCharacteristicPointsForCoincidingLocations(SurfaceLine2 surfaceLine2, out CharacteristicPointType type1, out CharacteristicPointType type2) { var doubleFound = false; type1 = CharacteristicPointType.None; type2 = CharacteristicPointType.None; CharacteristicPointSet points = surfaceLine2.CharacteristicPoints; foreach (CharacteristicPoint characteristicPoint in surfaceLine2.CharacteristicPoints) { if (!doubleFound) { // Find the coinciding points IEnumerable doublePoints = points.Where(x => Math.Abs(x.X - characteristicPoint.X) < 1e-4 && Math.Abs(x.Y - characteristicPoint.Y) < 1e-4 && Math.Abs(x.Z - characteristicPoint.Z) < 1e-4); if (doublePoints.Count() > 1) { // if there are coinciding points, see if the types clash. Only valid coinciding points are traffic loads // which may coincide with any other type of point CharacteristicPointType firstType = doublePoints.First().CharacteristicPointType; var skip = 0; foreach (CharacteristicPoint doublePoint in doublePoints) { if (skip > 0 && !doubleFound && firstType != CharacteristicPointType.TrafficLoadInside && firstType != CharacteristicPointType.TrafficLoadOutside) { if (doublePoint.CharacteristicPointType != CharacteristicPointType.TrafficLoadInside && doublePoint.CharacteristicPointType != CharacteristicPointType.TrafficLoadOutside) { doubleFound = doublePoint.CharacteristicPointType != firstType; if (doubleFound) { type1 = firstType; type2 = doublePoint.CharacteristicPointType; } } } firstType = doublePoint.CharacteristicPointType; skip++; } } } } return !doubleFound; } internal bool CheckOnCoincidingPoints(SurfaceLine2 surfaceLine) { bool charCheck; CharacteristicPointType firstType; CharacteristicPointType secondType; charCheck = CheckCharacteristicPointsForCoincidingLocations(surfaceLine, out firstType, out secondType); if (!charCheck) { string coincidingCharPointsFoundForSurfaceError = LocalizationManager.GetTranslatedText(GetType(), "CoincidingCharPointsFoundForSurfaceError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{surfaceLine.Name} : {coincidingCharPointsFoundForSurfaceError} : {firstType.ToString()} : {secondType.ToString()}"); ErrorMessages.Add(logmessage); } return charCheck; } /// /// Adds the dikes from locations to water board. /// /// The water board. private void AddDikesFromLocationsToWaterBoard(WaterBoard targetWaterBoard) { if (LocationRecords == null) { return; } // Create list of unique dikering ids var dikeRingIdList = new List(); foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords) { if (!String.IsNullOrEmpty(locationRecord.DikeRingId)) { if (!dikeRingIdList.Contains(locationRecord.DikeRingId)) { dikeRingIdList.Add(locationRecord.DikeRingId); } } } // if no dikeringIds assigned, then use default dike and assign it to the locations (if there are any) if ((dikeRingIdList.Count <= 0) && LocationRecords.Any()) { var defaultDikeRingId = "Dike from CSV"; if (targetWaterBoard.Dikes.Count > 0) { defaultDikeRingId = targetWaterBoard.Dikes[0].Name; } foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords) { locationRecord.DikeRingId = defaultDikeRingId; } dikeRingIdList.Add(defaultDikeRingId); } // Add dikeringids if not yet in waterboard foreach (string dikeRingId in dikeRingIdList) { Dike dike = targetWaterBoard.Dikes.FirstOrDefault(d => d.Name.Equals(dikeRingId)); if (dike == null) { targetWaterBoard.Dikes.Add(new Dike { Name = dikeRingId }); } } } private bool CheckForValidSegmentId(int segmentRecordId, string segmentId) { if (String.IsNullOrEmpty(segmentId)) { string segmentRecordHasNoId = LocalizationManager.GetTranslatedText(GetType(), "segmentRecordHasNoId"); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {segmentRecordId} : {segmentRecordHasNoId}"); ErrorMessages.Add(logmessage); return false; } return true; } /// /// Check if either a 1D-geometry or a 2D-geometry is specified /// /// /// /// private bool CheckForAnySoilGeometry(string segmentId, string soilProfileId, string soilGeometry2DName) { if ((String.IsNullOrEmpty(soilProfileId)) && (String.IsNullOrEmpty(soilGeometry2DName))) { string segmentHasNoProfileOrGeometry = LocalizationManager.GetTranslatedText(GetType(), "segmentHasNoProfileOrGeometry"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{segmentId} : {segmentHasNoProfileOrGeometry}"); ErrorMessages.Add(logmessage); return false; } return true; } /// /// Check if both a 1D-geometry or a 2D-geometry is specified (which is not allowed) /// /// /// /// private bool CheckForDoubleSoilGeometry(string segmentId, string soilProfileId, string soilGeometry2DName) { if ((!String.IsNullOrEmpty(soilProfileId)) && (!String.IsNullOrEmpty(soilGeometry2DName))) { string segmentHasProfileAndGeometry = LocalizationManager.GetTranslatedText(GetType(), "segmentHasProfileAndGeometry"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{segmentId} : {segmentHasProfileAndGeometry}"); ErrorMessages.Add(logmessage); return false; } return true; } // Before using this, the Locations and (for 1D profiles) SoilProfiles must be known!? private void TransferSegmentData(Dike dike) { if (SegmentRecords == null) { return; } if (WaterBoard.Segments.Count > 0) { foreach (CsvImporterSegments.SegmentRecord segmentRecord in SegmentRecords) { // look for existing segments by Id. If found, remove them from the waterboard as they are to be (re)read here. List oldSegments = WaterBoard.Segments.Where(s => s.Name == segmentRecord.SegmentId).ToList(); foreach (Segment oldSegment in oldSegments) { WaterBoard.Segments.Remove(oldSegment); } } } Dictionary soilProfileLookup = dike.SoilProfiles != null ? dike.SoilProfiles.ToDictionary(sp => sp.Name, sp => sp) : null; foreach (CsvImporterSegments.SegmentRecord segmentRecord in SegmentRecords) { if (CheckForValidSegmentId(segmentRecord.SegmentRecordId, segmentRecord.SegmentId) && (CheckForDoubleSoilGeometry(segmentRecord.SegmentId, segmentRecord.SoilProfileId, segmentRecord.SoilGeometry2DName)) && (CheckForAnySoilGeometry(segmentRecord.SegmentId, segmentRecord.SoilProfileId, segmentRecord.SoilGeometry2DName))) { var newSegment = false; //check if new segment is needed Segment segment = WaterBoard.GetSegmentByName(segmentRecord.SegmentId); if (segment == null) { newSegment = true; segment = new Segment(); } segment.Name = segmentRecord.SegmentId; if (!String.IsNullOrEmpty(segmentRecord.SoilGeometry2DName)) { segment.AddSoilGeometry2DProbability(segmentRecord.SoilGeometry2DName, segmentRecord.Probability, segmentRecord.SegmentFailureMechanismType); } if (!String.IsNullOrEmpty(segmentRecord.SoilProfileId)) { if (soilProfileLookup == null) { string dikeHasNoSoilProfiles = LocalizationManager.GetTranslatedText(GetType(), "dikeHasNoSoilProfiles"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{dike.Name} : {dikeHasNoSoilProfiles}"); ErrorMessages.Add(logmessage); } else { string soilProfileName = segmentRecord.SoilProfileId; SoilProfile1D soilProfile = soilProfileLookup.ContainsKey(soilProfileName) ? soilProfileLookup[soilProfileName] : null; if (soilProfile == null) { //#Bka: do not give message here as it might be that an old project is being loaded which does not have a full // dataset (such as old HHNK projects by Irene), leading to a very large list with non relevant errors as the locations // for which this check is performed are not all used. // var soilProfileForSegmentDoesNotExist = // LocalizationManager.GetTranslatedText(this.GetType(), // "soilProfileForSegmentDoesNotExist"); // LogMessage logmessage = new LogMessage(LogMessageType.Error, null, // String.Format("{0} : {1}:{2}", // segmentRecord.SegmentId, // soilProfileForSegmentDoesNotExist, // segmentRecord.SoilProfileId)); // ErrorMessages.Add(logmessage); } else { segment.AddSoilProfileProbability(soilProfile, segmentRecord.Probability, segmentRecord.SegmentFailureMechanismType); } } } // Note Bka: coupling of segment to location still needs to be done. But can only be achieved when location has info on segment or segment id //segment.Locations.AddRange(dike.Locations.Where(l => l.Segment.Name == segmentRecord.SegmentId)); // var segId = dike.Locations[0].SegmentId; // if (segId == segmentRecord.SegmentId) // dike.Locations[0].Segment = segment; if (newSegment) { WaterBoard.Segments.Add(segment); string segmentId = segmentRecord.SegmentId; IEnumerable locationsWithSegmentId = WaterBoard.Locations.Where(x => x.SegmentId == segmentId); foreach (Location location in locationsWithSegmentId) { location.Segment = segment; } } } } } private void TransferSoilData(Dike dike) { dike.FillImportedCsvSoilsFromCsvFile(SoilRecords); dike.AssignImportedCsvSoilsPropertiesToSoilListSoils(); dike.FillTrafficLoadDegreeOfConsolidationFromCsvFile(SoilRecords); } private void TransferSigmaTauCurveData(Dike dike) { dike.FillImportedSigmaTauCurvesFromCsvFile(SigmaTauCurveRecords); } private void TransferSuTableData(Dike dike) { dike.FillImportedSuTablesFromCsvFile(SuTableRecords); } private void TransferSoilProfilesData(Dike dike) { if (SoilProfilerecords == null) { return; } var newSoilProfile = false; var orgId = ""; SoilProfile1D soilProfile = null; var layerIndex = 0; foreach (CsvImporterSoilProfiles.SoilProfileRecord soilProfileRecord in SoilProfilerecords) { if (string.IsNullOrEmpty(soilProfileRecord.SoilProfileId) || string.IsNullOrEmpty(soilProfileRecord.SoilName)) { string noIdForSoilProfileRecordError = LocalizationManager.GetTranslatedText(GetType(), "noIdOrSoilForSoilProfileRecordError"); var logMessage = new LogMessage(LogMessageType.Error, this, $"Record {soilProfileRecord.SoilProfileRecordId} : {noIdForSoilProfileRecordError}"); ErrorMessages.Add(logMessage); AddErrorMessage("noIdOrSoilForSoilProfileRecordError", soilProfileRecord); } else { // see if a next profile is to be converted from the csv data. If not, layer needs to be added to the current profile if (orgId != soilProfileRecord.SoilProfileId) { // first add current profile (if it exists) to dike. if (soilProfile != null) { if (newSoilProfile) { try { soilProfile.ValidateDirect(); dike.SoilProfiles.Add(soilProfile); } catch (SoilProfileLayersNotSortedDescendingException e) { var logMessage = new LogMessage(LogMessageType.Error, null, e.Message); ErrorMessages.Add(logMessage); } layerIndex = 0; } newSoilProfile = false; } // determine the next profile (existing or new) soilProfile = dike.SoilProfiles.FirstOrDefault(s => s.Name == soilProfileRecord.SoilProfileId); if (soilProfile == null) { soilProfile = new SoilProfile1D(); newSoilProfile = true; } // clear layers of existing profile if (soilProfile.Layers != null) { soilProfile.Layers.Clear(); } else { string existingSoilProfileHasNoLayers = LocalizationManager.GetTranslatedText(GetType(), "existingSoilProfileHasNoLayers"); var logMessage = new LogMessage(LogMessageType.Error, null, $"{soilProfileRecord.SoilProfileId} : {existingSoilProfileHasNoLayers}"); ErrorMessages.Add(logMessage); } soilProfile.Name = soilProfileRecord.SoilProfileId; orgId = soilProfileRecord.SoilProfileId; } // if this is a dummy layer to set the bottom level for the entire profile, then do so if (soilProfileRecord.SoilName == SoilProfile1D.SoilProfileBottomLevelId) { soilProfile.BottomLevel = soilProfileRecord.TopLevel; } else { // else set the layer var layer = new SoilLayer1D { TopLevel = soilProfileRecord.TopLevel, IsAquifer = soilProfileRecord.IsAquifer }; int soilIndex = dike.SoilList.GetSoilIndexByName(soilProfileRecord.SoilName); if (soilIndex == -1) { var soil = new Soil { Name = soilProfileRecord.SoilName }; dike.SoilList.Soils.Add(soil); soilIndex = dike.SoilList.Soils.Count - 1; } layer.Soil = dike.SoilList.Soils[soilIndex]; layer.Name = "Layer" + layerIndex; layerIndex++; soilProfile.Layers.Add(layer); } } } // finally add last current profile to dike. if ((soilProfile != null) && newSoilProfile) { try { if ((soilProfile.Layers == null) || (soilProfile.Layers.Count == 0)) { throw new SoilProfileLayersNotSortedDescendingException($"Soilprofile '{soilProfile.Name}' has no layers"); } soilProfile.ValidateDirect(); dike.SoilProfiles.Add(soilProfile); } catch (SoilProfileLayersNotSortedDescendingException e) { var logmessage = new LogMessage(LogMessageType.Error, null, e.Message); ErrorMessages.Add(logmessage); } } // Make sure all soilprofiles last layer have a height foreach (SoilProfile1D soilProfile1 in dike.SoilProfiles) { try { soilProfile1.EnsureLastLayerHasHeight(); } catch (Exception e) { //var error = new StringBuilder(); var error = $"Error postprocessing soilprofile '{soilProfile1.Name}': {e.Message}"; var logmessage = new LogMessage(LogMessageType.Error, null, error); ErrorMessages.Add(logmessage); } } } private void TransferAquifersData(Dike dike) { dike.FillImportedAquifersFromCsvFile(AquiferRecords); } private void TransferSurfaceLines(Dike dike) { if (SurfaceLineRecords == null) { return; } foreach (CsvImporterSurfaceLines.SurfaceLineRecord surfaceLineRecord in SurfaceLineRecords) { if (String.IsNullOrEmpty(surfaceLineRecord.SurfaceLineId)) { string noIdForSurfaceLineRecordError = LocalizationManager.GetTranslatedText(GetType(), "noIdSurfaceLineRecordError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {surfaceLineRecord.SurfaceLineRecordId} : {noIdForSurfaceLineRecordError}"); ErrorMessages.Add(logmessage); } else { var newSurfaceLine = false; SurfaceLine2 surfaceLine = dike.SurfaceLines2.FirstOrDefault(s => s.Name == surfaceLineRecord.SurfaceLineId); if (surfaceLine == null) { surfaceLine = new SurfaceLine2 { Geometry = new LocalizedGeometryPointString(), CharacteristicPoints = { GeometryMustContainPoint = true } }; newSurfaceLine = true; } surfaceLine.Name = surfaceLineRecord.SurfaceLineId; // first add all points from the surface line csv for (var i = 0; i < surfaceLineRecord.Xcoors.Count; i++) { // empty points will not be added if (surfaceLineRecord.Xcoors[i] != -1 || surfaceLineRecord.Ycoors[i] != -1 || surfaceLineRecord.Zcoors[i] != -1) { surfaceLine.EnsurePointOfType(surfaceLineRecord.Xcoors[i], surfaceLineRecord.Ycoors[i], surfaceLineRecord.Zcoors[i], null); } } // Add the surface line to the dike if (newSurfaceLine) { dike.SurfaceLines2.Add(surfaceLine); } // now see if all characteristic points belonging to this surface line are part of the surface line CsvImporterCharacteristicPoints.CharacteristicPointsRecord characteristicPointsRecord = CharacteristicPointsRecords.FirstOrDefault(s => s.SurfaceLineId == surfaceLine.Name); var charCheck = true; if (characteristicPointsRecord != null) { foreach (CsvImporterCharacteristicPoints.CharPoint point in characteristicPointsRecord.Points) { // ignore unset points if (!((point.X == -1) && (point.Y == -1) && (point.Z == -1))) { GeometryPoint tppoint = surfaceLine.Geometry.GetPointAt(point.X, point.Y, point.Z); if (tppoint != null) { surfaceLine.EnsurePointOfType(point.X, point.Y, point.Z, point.Type); } else { string charPointNotFoundInSurfaceError = LocalizationManager.GetTranslatedText(GetType(), "charPointNotFoundInSurfaceError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{surfaceLine.Name} : {charPointNotFoundInSurfaceError} {point.Type}"); ErrorMessages.Add(logmessage); charCheck = false; } } } } else { string noCharPointsFoundForSurfaceError = LocalizationManager.GetTranslatedText(GetType(), "noCharPointsFoundForSurfaceError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"{surfaceLine.Name} : {noCharPointsFoundForSurfaceError}"); ErrorMessages.Add(logmessage); charCheck = false; } // Check on illegal coinciding characteristic points if (charCheck) { charCheck = CheckOnCoincidingPoints(surfaceLine); } if (!charCheck) { surfaceLine.Dispose(); dike.SurfaceLines2.Remove(surfaceLine); } } } } private void TransferScenarios(Dike dike) { if (ScenarioRecords == null) { return; } Dictionary dikeLocationLookup = dike.Locations.ToDictionary(l => l.Name, l => l); foreach (CsvImporterScenarios.ScenarioRecord scenarioRecord in ScenarioRecords) { var recordError = false; if (string.IsNullOrEmpty(scenarioRecord.LocationId)) { string noLocationIdForScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "noLocationIdForScenarioRecordError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {noLocationIdForScenarioRecordError}"); ErrorMessages.Add(logmessage); recordError = true; } // faassen: location id was of type int with default value -1 if empty. Now it is string and null as the default value if (scenarioRecord.LocationScenarioId == null) { string invalidLocationScenarioIdForScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "invalidLocationScenarioIdForScenarioRecordError"); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {invalidLocationScenarioIdForScenarioRecordError}"); ErrorMessages.Add(logmessage); recordError = true; } Location dikeLocation = dikeLocationLookup.ContainsKey(scenarioRecord.LocationId) ? dikeLocationLookup[scenarioRecord.LocationId] : null; if (dikeLocation == null) { string locationNotFoundForScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "locationNotFoundForScenarioRecordError"); var logmessage = new LogMessage(LogMessageType.Error, this, $"Record {scenarioRecord.ScenarioRecordId} : {locationNotFoundForScenarioRecordError}"); ErrorMessages.Add(logmessage); recordError = true; } if (!recordError) { // Add to location scenario list Scenario dikeScenario = dikeLocation.Scenarios.FirstOrDefault(s => s.Location.Name == scenarioRecord.LocationId && s.LocationScenarioID == scenarioRecord.LocationScenarioId); if (dikeScenario != null) { string duplicateScenarioRecordError = LocalizationManager.GetTranslatedText(GetType(), "duplicateScenarioRecordError"); string errorMessage = string.Format(duplicateScenarioRecordError, dikeLocation.Name, dikeScenario.LocationScenarioID); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {errorMessage}"); ErrorMessages.Add(logmessage); } else { CsvImporterLocations.LocationRecord locationRecord = LocationRecords.FirstOrDefault(l => l.LocationId == scenarioRecord.LocationId); // Check if polder is present in either the location or the scenario record. This // value is mandatory and must be present in either one. if (locationRecord?.PolderLevel == null && scenarioRecord.PolderLevel == null) { string missingPolderLevelError = LocalizationManager.GetTranslatedText(GetType(), "missingPolderLevel"); var logmessage = new LogMessage(LogMessageType.Error, null, $"Record {scenarioRecord.ScenarioRecordId} : {missingPolderLevelError}"); ErrorMessages.Add(logmessage); } else { Scenario scenario = CreateScenario(dikeLocation, scenarioRecord, locationRecord); dikeLocation.Scenarios.Add(scenario); } } } } } /// /// Creates a based on its input arguments. /// /// The that belongs to the . /// The to retrieve the data from. /// The to retrieve the data from. /// A . private static Scenario CreateScenario(Location dikeLocation, CsvImporterScenarios.ScenarioRecord scenarioRecord, CsvImporterLocations.LocationRecord locationRecord) { // set values in scenario (1 from scenariorecord, 2 from locationrecord, 3 default) var modelFactors = new ModelFactors(); modelFactors.RequiredSafetyFactorStabilityInnerSlope = scenarioRecord.RequiredSafetyFactorStabilityInnerSlope ?? (locationRecord.RequiredSafetyFactorStabilityInnerSlope ?? modelFactors.RequiredSafetyFactorStabilityInnerSlope); modelFactors.RequiredSafetyFactorStabilityOuterSlope = scenarioRecord.RequiredSafetyFactorStabilityOuterSlope ?? (locationRecord.RequiredSafetyFactorStabilityOuterSlope ?? modelFactors.RequiredSafetyFactorStabilityOuterSlope); modelFactors.RequiredSafetyFactorPiping = scenarioRecord.RequiredSafetyFactorPiping ?? (locationRecord.RequiredSafetyFactorPiping ?? modelFactors.RequiredSafetyFactorPiping); modelFactors.UpliftCriterionStability = scenarioRecord.UpliftCriterionStability ?? (locationRecord.UpliftCriterionStability ?? modelFactors.UpliftCriterionStability); modelFactors.UpliftCriterionPiping = scenarioRecord.UpliftCriterionPiping ?? (locationRecord.UpliftCriterionPiping ?? modelFactors.UpliftCriterionPiping); var scenario = new Scenario { Location = dikeLocation, LocationScenarioID = scenarioRecord.LocationScenarioId, ModelFactors = modelFactors }; scenario.PlLineOffsetBelowDikeToeAtPolder = scenarioRecord.PlLineOffsetBelowDikeToeAtPolder ?? (locationRecord.PlLineOffsetBelowDikeToeAtPolder ?? scenario.PlLineOffsetBelowDikeToeAtPolder); scenario.PlLineOffsetBelowDikeTopAtPolder = scenarioRecord.PlLineOffsetBelowDikeTopAtPolder ?? (locationRecord.PlLineOffsetBelowDikeTopAtPolder ?? scenario.PlLineOffsetBelowDikeTopAtPolder); scenario.PlLineOffsetBelowDikeTopAtRiver = scenarioRecord.PlLineOffsetBelowDikeTopAtRiver ?? (locationRecord.PlLineOffsetBelowDikeTopAtRiver ?? scenario.PlLineOffsetBelowDikeTopAtRiver); scenario.PlLineOffsetBelowShoulderBaseInside = scenarioRecord.PlLineOffsetBelowShoulderBaseInside ?? (locationRecord.PlLineOffsetBelowShoulderBaseInside ?? scenario.PlLineOffsetBelowShoulderBaseInside); // set values in scenario (1 from scenariorecord, 2 from locationrecord, 3 stays null) scenario.PlLineOffsetBelowDikeCrestMiddle = scenarioRecord.PlLineOffsetBelowDikeCrestMiddle ?? locationRecord.PlLineOffsetBelowDikeCrestMiddle; scenario.PlLineOffsetFactorBelowShoulderCrest = scenarioRecord.PlLineOffsetFactorBelowShoulderCrest ?? locationRecord.PlLineOffsetFactorBelowShoulderCrest; scenario.UsePlLineOffsetBelowDikeCrestMiddle = scenarioRecord.UsePlLineOffsetBelowDikeCrestMiddle ?? locationRecord.UsePlLineOffsetBelowDikeCrestMiddle; scenario.UsePlLineOffsetFactorBelowShoulderCrest = scenarioRecord.UsePlLineOffsetFactorBelowShoulderCrest ?? locationRecord.UsePlLineOffsetFactorBelowShoulderCrest; scenario.HeadPl3 = scenarioRecord.HeadPl3 ?? locationRecord.HeadPl3; scenario.HeadPl4 = scenarioRecord.HeadPl4 ?? locationRecord.HeadPl4; scenario.PolderLevel = scenarioRecord.PolderLevel ?? locationRecord.PolderLevel.Value; scenario.HeadPl2 = scenarioRecord.HeadPl2 ?? locationRecord.HeadPl2; scenario.DikeTableHeight = scenarioRecord.DikeTableHeight ?? locationRecord.DikeTableHeight; scenario.RiverLevel = scenarioRecord.RiverLevel ?? locationRecord.RiverLevel; scenario.RiverLevelLow = scenarioRecord.RiverLevelLow ?? locationRecord.RiverLevelLow; return scenario; } /// /// Transfers the locations data. /// /// The dike. private void TransferLocationsData(Dike dike) { if (LocationRecords == null) { return; } foreach (CsvImporterLocations.LocationRecord locationRecord in LocationRecords) { if (locationRecord.DikeRingId.Equals(dike.Name)) { // Check if id is defined if (String.IsNullOrEmpty(locationRecord.LocationId)) { AddErrorMessage("noIdLocationRecordError", locationRecord); continue; } // See if location already exist; else create one and add it to the dike Location location = dike.Locations.FirstOrDefault(s => s.Name == locationRecord.LocationId); if (location == null) { var errorInrecord = false; location = new Location(); location.Name = locationRecord.LocationId; location.SurfaceLineId = locationRecord.SurfaceLineId; location.SegmentId = locationRecord.SegmentId; if (locationRecord.DikeRingId != null) { location.DikeRingId = locationRecord.DikeRingId; } if (location.DampingFactorPL3 < 0 || location.DampingFactorPL3 > 1) { AddErrorMessage("DampingFactorPl3BeyondLimits", locationRecord); errorInrecord = true; } if (location.DampingFactorPL4 < 0 || location.DampingFactorPL4 > 1) { AddErrorMessage("DampingFactorPl4BeyondLimits", locationRecord); errorInrecord = true; } if (null != locationRecord.DikeEmbankmentMaterial) { location.DikeEmbankmentMaterial = locationRecord.DikeEmbankmentMaterial; } if (null != locationRecord.ShoulderEmbankmentMaterial) { location.ShoulderEmbankmentMaterial = locationRecord.ShoulderEmbankmentMaterial; } location.XRd = locationRecord.GeoX.GetValueOrDefault(location.XRd); location.YRd = locationRecord.GeoY.GetValueOrDefault(location.YRd); location.XSoilGeometry2DOrigin = locationRecord.XSoilGeometry2DOrigin.GetValueOrDefault(location.XSoilGeometry2DOrigin); location.DampingFactorPL3 = locationRecord.DampingFactorPl3.GetValueOrDefault(location.DampingFactorPL3); location.DampingFactorPL4 = locationRecord.DampingFactorPl4.GetValueOrDefault(location.DampingFactorPL4); location.PenetrationLength = locationRecord.PenetrationLength.GetValueOrDefault(location.PenetrationLength); location.TrafficLoad = locationRecord.TrafficLoad.GetValueOrDefault(location.TrafficLoad); location.TL_DegreeOfConsolidation = locationRecord.TL_DegreeOfConsolidation; location.PLLineCreationMethod = locationRecord.PLLineCreationMethod.GetValueOrDefault(location.PLLineCreationMethod); if (locationRecord.IntrusionVerticalWaterPressure.HasValue) { location.IntrusionVerticalWaterPressure = locationRecord.IntrusionVerticalWaterPressure.Value; } location.StabilityShoulderGrowSlope = locationRecord.StabilityShoulderGrowSlope.GetValueOrDefault(location.StabilityShoulderGrowSlope); location.StabilityShoulderGrowDeltaX = locationRecord.StabilityShoulderGrowDeltaX.GetValueOrDefault(location.StabilityShoulderGrowDeltaX); location.StabilitySlopeAdaptionDeltaX = locationRecord.StabilitySlopeAdaptionDeltaX.GetValueOrDefault(location.StabilitySlopeAdaptionDeltaX); location.MinimalCircleDepth = locationRecord.MinimalCircleDepth.GetValueOrDefault(location.MinimalCircleDepth); location.DistanceToEntryPoint = locationRecord.DistanceToEntryPoint.GetValueOrDefault(location.DistanceToEntryPoint); location.SlopeDampingPiezometricHeightPolderSide = locationRecord.SlopeDampingPiezometricHeightPolderSide.GetValueOrDefault(location.SlopeDampingPiezometricHeightPolderSide); location.StabilityDesignMethod = locationRecord.StabilityDesignMethod.GetValueOrDefault(location.StabilityDesignMethod); location.SlopeAdaptionStartCotangent = locationRecord.SlopeAdaptionStartCotangent.GetValueOrDefault(location.SlopeAdaptionStartCotangent); location.SlopeAdaptionEndCotangent = locationRecord.SlopeAdaptionEndCotangent.GetValueOrDefault(location.SlopeAdaptionEndCotangent); location.SlopeAdaptionStepCotangent = locationRecord.SlopeAdaptionStepCotangent.GetValueOrDefault(location.SlopeAdaptionStepCotangent); location.StabilityZoneType = locationRecord.StabilityZoneType.GetValueOrDefault(location.StabilityZoneType); location.ForbiddenZoneFactor = locationRecord.ForbiddenZoneFactor.GetValueOrDefault(location.ForbiddenZoneFactor); location.NewDepthDitch = locationRecord.NewDepthDitch.GetValueOrDefault(location.NewDepthDitch); location.NewDikeSlopeInside = locationRecord.NewDikeSlopeInside.GetValueOrDefault(location.NewDikeSlopeInside); location.NewDikeSlopeOutside = locationRecord.NewDikeSlopeOutside.GetValueOrDefault(location.NewDikeSlopeOutside); location.NewDikeTopWidth = locationRecord.NewDikeTopWidth.GetValueOrDefault(location.NewDikeTopWidth); location.NewMaxHeightShoulderAsFraction = locationRecord.NewMaxHeightShoulderAsFraction.GetValueOrDefault(location.NewMaxHeightShoulderAsFraction); location.NewMinDistanceDikeToeStartDitch = locationRecord.NewMinDistanceDikeToeStartDitch.GetValueOrDefault(location.NewMinDistanceDikeToeStartDitch); location.NewShoulderBaseSlope = locationRecord.NewShoulderBaseSlope.GetValueOrDefault(location.NewShoulderBaseSlope); location.NewShoulderTopSlope = locationRecord.NewShoulderTopSlope.GetValueOrDefault(location.NewShoulderTopSlope); location.NewSlopeAngleDitch = locationRecord.NewSlopeAngleDitch.GetValueOrDefault(location.NewSlopeAngleDitch); location.NewWidthDitchBottom = locationRecord.NewWidthDitchBottom.GetValueOrDefault(location.NewWidthDitchBottom); location.UseNewDikeSlopeInside = locationRecord.UseNewDikeSlopeInside.GetValueOrDefault(location.UseNewDikeSlopeInside); location.UseNewDikeSlopeOutside = locationRecord.UseNewDikeSlopeOutside.GetValueOrDefault(location.UseNewDikeSlopeOutside); location.UseNewDikeTopWidth = locationRecord.UseNewDikeTopWidth.GetValueOrDefault(location.UseNewDikeTopWidth); location.UseNewDitchDefinition = locationRecord.UseNewDitchDefinition.GetValueOrDefault(location.UseNewDitchDefinition); location.UseNewMaxHeightShoulderAsFraction = locationRecord.UseNewMaxHeightShoulderAsFraction.GetValueOrDefault(location.UseNewMaxHeightShoulderAsFraction); location.UseNewMinDistanceDikeToeStartDitch = locationRecord.UseNewMinDistanceDikeToeStartDitch.GetValueOrDefault(location.UseNewMinDistanceDikeToeStartDitch); location.UseNewShoulderBaseSlope = locationRecord.UseNewShoulderBaseSlope.GetValueOrDefault(location.UseNewShoulderBaseSlope); location.UseNewShoulderTopSlope = locationRecord.UseNewShoulderTopSlope.GetValueOrDefault(location.UseNewShoulderTopSlope); if (!errorInrecord) { dike.Locations.Add(location); } else { location.Dispose(); } } } } } private void AddErrorMessage(string errorMessageTranslationId, CsvImporterLocations.LocationRecord locationRecord) { AddErrorMessage(errorMessageTranslationId, locationRecord.LocationRecordId); } private void AddErrorMessage(string errorMessageTranslationId, CsvImporterSoilProfiles.SoilProfileRecord soilProfileRecord) { AddErrorMessage(errorMessageTranslationId, soilProfileRecord.SoilProfileRecordId); } private void AddErrorMessage(string errorMessageTranslationId, int id) { string noIdForSoilProfileRecordError = LocalizationManager.GetTranslatedText(GetType(), errorMessageTranslationId); var logmessage = new LogMessage( LogMessageType.Error, this, $"Record {id} : {noIdForSoilProfileRecordError}" ); ErrorMessages.Add(logmessage); } }