// 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}'");
}
}
}