// 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. //#define INCLUDE_ALL_LINE_TYPES using System; using System.Collections.Generic; using System.IO; using System.Linq; using Deltares.Geometry; using Deltares.Geotechnics.SurfaceLines; using Deltares.Maps; namespace Deltares.Dam.Data.Importers; public class LocationCharacteristicPointImporter { // define file names private const string CharacteristicLinesFile = "Kruin_dijkring10.shp"; public const string CharacteristicLineAttributeName = "TEMP_ID"; private const string LocationsFile = "Locations.shp"; public const string LocationIDAttributeName = "LOCATION"; const string DikeTopPolderLineID = "kruin-binnen"; #if INCLUDE_ALL_LINE_TYPES private IEnumerable supportedLineTypes = new[] { DikeTopPolderLineID, DikeTopAtPolderLineID }; #else private readonly IEnumerable supportedLineTypes = new[] { DikeTopPolderLineID }; #endif private string dataFolder; private readonly IEnumerable locations; public LocationCharacteristicPointImporter(IEnumerable locations) { if (locations == null) { throw new ArgumentNullException("locations"); } this.locations = locations; } public LocationCharacteristicPointImporter(string dataFolder, IEnumerable locations) : this(locations) { LoadRepositories(dataFolder); } private void LoadRepositories(string dataFolder) { if (dataFolder == null) { throw new ArgumentNullException("dataFolder"); } this.dataFolder = dataFolder; ValidateDataFolder(); var profileLocationsShapeFile = new ShapeFileLocation(this.dataFolder, LocationsFile); // Get all the locations from the profile data shape file using a repository ProfileLocationsRepository = FeatureRepository.CreateFromShapeFile(profileLocationsShapeFile); var shapeFile = new ShapeFileLocation(this.dataFolder, CharacteristicLinesFile); CharacteristicLineRepository = FeatureRepository.CreateFromShapeFile(shapeFile); // Load and validate the attributes required to import the locations ThrowWhenDataFileNotValid(ProfileLocationsRepository, LocationIDAttributeName, LocationsFile); ThrowWhenDataFileNotValid(CharacteristicLineRepository, CharacteristicLineAttributeName, CharacteristicLinesFile); } public IFeatureRepository CharacteristicLineRepository { get; set; } public IFeatureRepository ProfileLocationsRepository { get; set; } /// /// /// /// Preconditions: /// - A valid data folder needs to given /// - A set of "locations" with their characteristic points table and initialized id's available from the dike /// - The required files need to be in the data folder (one for the characteristics points, /// - A set of (characteristic) lines wich have to be retrieved from the files /// /// Postconditions: /// - Some locations (the result of a join from the Location shape file and the existing location list from the dike) have new characteristic point values /// /// /// /// /// /// public void Import() { ThrowWhenRepositoryIsInvalid(CharacteristicLineRepository, CharacteristicLineAttributeName); ThrowWhenRepositoryIsInvalid(ProfileLocationsRepository, LocationIDAttributeName); // TODO Test both repositories on geometry type (must be linestring) // Find the intersection points between the geometries IEnumerable> results = ProfileLocationsRepository.GetIntersectionPoints(CharacteristicLineRepository); IEnumerable work = results.GetResultsHavingCount(1); foreach (IntersectionResult intersectionResult in work) { IFeature profile, characteristicLine; if (intersectionResult.Source.Attributes.Exists(CharacteristicLineAttributeName)) { profile = intersectionResult.Target; characteristicLine = intersectionResult.Source; } else { profile = intersectionResult.Source; characteristicLine = intersectionResult.Target; } var lineTypeID = characteristicLine.Attributes[CharacteristicLineAttributeName].ToString(); if (!supportedLineTypes.Contains(lineTypeID)) { LogMessage(); continue; } List locationList = locations.ToList(); var locname = profile.Attributes[LocationIDAttributeName].ToString(); // Get the surface line for the location having the location ID SurfaceLine2 surfaceLine = locationList.First(loc => loc.Name == locname).SurfaceLine2; GeometryPoint dikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); dikeTopAtPolder.X = intersectionResult.IntersectionPoints.ElementAt(0).X; dikeTopAtPolder.Y = intersectionResult.IntersectionPoints.ElementAt(0).Y; } } private static void LogMessage() {} private static IEnumerable GetAllFiles(string path) { if (!Directory.Exists(path)) { throw new DirectoryNotFoundException($"Data folder '{path}' not found"); } return Directory.GetFiles(path); } private static bool IsRepositoryValid(IFeatureRepository repository, string attributeName) { if (repository == null) { return false; } bool keyAndValueExist = !repository.Features.Any(geom => !geom.Attributes.Exists(attributeName) || geom.Attributes[attributeName] == null); return keyAndValueExist; } private static void ThrowWhenRepositoryIsInvalid(IFeatureRepository repository, string attributeName) { if (!IsRepositoryValid(repository, attributeName)) { throw new InvalidOperationException( $"The geometry repository doesn't contain the required attribute '{attributeName}'"); } } private static void ThrowWhenDataFileNotValid(IFeatureRepository repository, string attributeName, string fileName) { if (!IsRepositoryValid(repository, attributeName)) { throw new ArgumentException( $"The ShapeFile '{fileName}' doesn't contain the required attribute '{attributeName}'"); } } private void ValidateDataFolder() { // Get all the shape files from the data folder IEnumerable files = GetAllFiles(dataFolder); // Validate the existence of the required files if (!files.Any(file => file.EndsWith(CharacteristicLinesFile))) { throw new FileNotFoundException($"The folder '{dataFolder}' doesn't contain the required file '{CharacteristicLinesFile}'"); } if (!files.Any(file => file.EndsWith(LocationsFile))) { throw new FileNotFoundException( $"The folder '{dataFolder}' doesn't contain the required file '{LocationsFile}'"); } } }