// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of the Dam Engine.
//
// The Dam Engine is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero 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.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStabilityCommon.Assemblers;
using Deltares.DamEngine.Calculators.Stability;
using Deltares.DamEngine.Data.Geotechnics;
namespace Deltares.DamEngine.Calculators.General
{
///
/// Exception class for Geometry2DTo1DConverter
///
public class Geometry2DTo1DConverterException : ApplicationException
{
public Geometry2DTo1DConverterException(string message)
: base(message)
{
}
}
///
/// Object to determine soilprofile below point on surfaceline
///
public class Geometry2DTo1DConverter
{
///
/// Initializes a new instance of the class.
///
/// Name of the soil geometry2 D.
/// The surface line.
/// The dike embankment material.
/// The soil list.
public Geometry2DTo1DConverter(string soilGeometry2DName, SurfaceLine2 surfaceLine, Soil dikeEmbankmentMaterial, SoilList soilList)
{
SoilGeometry2DName = soilGeometry2DName;
SurfaceLine = surfaceLine;
DikeEmbankmentMaterial = dikeEmbankmentMaterial;
this.SoilList = soilList;
XOffsetSoilGeometry2DOrigin = 0;
}
///
/// Initializes a new instance of the class.
///
/// Name of the soil geometry2 D.
/// The surface line.
/// The dike embankment material.
/// The soil list.
/// The x offset soil geometry2 D origin.
public Geometry2DTo1DConverter(string soilGeometry2DName, SurfaceLine2 surfaceLine, Soil dikeEmbankmentMaterial, SoilList soilList, double xOffsetSoilGeometry2DOrigin)
{
SoilGeometry2DName = soilGeometry2DName;
SurfaceLine = surfaceLine;
DikeEmbankmentMaterial = dikeEmbankmentMaterial;
this.SoilList = soilList;
XOffsetSoilGeometry2DOrigin = xOffsetSoilGeometry2DOrigin;
}
public string SoilGeometry2DName { get; set; }
public SurfaceLine2 SurfaceLine { get; set; }
public Soil DikeEmbankmentMaterial { get; set; }
private SoilList SoilList { get; set; }
public double XOffsetSoilGeometry2DOrigin { get; set; }
///
/// Make section on specified x-coordinate.
/// Material above surfacelevel of geometry and below surfaceline will be specified as dikeEmbankmentMaterial
///
/// The x coordinate.
///
public SoilProfile1D Convert(double xCoordinate)
{
//xCoordinate = Math.Min(xCoordinate, this.SurfaceLine[CharacteristicPointType.SurfaceLevelInside].X - 0.1);
//xCoordinate = this.SurfaceLine[CharacteristicPointType.SurfaceLevelInside].X-0.25;
DAMMStabGeometry2DSectionAssembler assembler = new DAMMStabGeometry2DSectionAssembler();
var geometry2DSectionParameters = new Geometry2DSectionParameters();
geometry2DSectionParameters.SoilGeometry2DName = System.IO.Path.GetFullPath(SoilGeometry2DName);
geometry2DSectionParameters.XCoordinateSection = xCoordinate + XOffsetSoilGeometry2DOrigin;
XDocument doc = assembler.CreateDataTransferObject(geometry2DSectionParameters);
String LXMLInput = doc.ToString();
// Following file for debugging
// SaveXMLInputFile(xCoordinate, doc);
StringBuilder LXMLOutput = null;
var stabilityServiceAgent = new StabilityServiceAgent();
stabilityServiceAgent.ConvertGeometry2DTo1D(LXMLInput, ref LXMLOutput);
XDocument docOut = XDocument.Parse(LXMLOutput.ToString());
Geometry2DSectionParameters geometry2DSectionParametersOut = assembler.CreateOutputObject(docOut);
SoilProfile1D soilProfile = geometry2DSectionParametersOut.SoilProfile;
AddDikeMaterialIfSurfaceLineAboveGeometrySurface(ref soilProfile, xCoordinate);
AssignSoilsFromSoilbaseToProfile(soilProfile);
return soilProfile;
}
///
/// Saves the XML input file for debugging.
///
/// The x coordinate.
/// The document.
private void SaveXMLInputFile(double xCoordinate, XDocument doc)
{
string directoryGeometry2DSectionParameters = "Geometry2DSectionParameters";
string filenameGeometry2DSectionParameters = String.Format("Geometry2DSectionParameters_{0}_{1}.xml",
Path.GetFileNameWithoutExtension(SoilGeometry2DName), xCoordinate);
if (!Directory.Exists(directoryGeometry2DSectionParameters))
{
Directory.CreateDirectory(directoryGeometry2DSectionParameters);
}
doc.Save(Path.Combine(directoryGeometry2DSectionParameters, filenameGeometry2DSectionParameters));
}
///
/// Add toplayer made of dikeEmbankmentMaterial when the surfaceline is higher then the defined 2D-geometry
///
/// The soil profile.
/// The x coordinate.
private void AddDikeMaterialIfSurfaceLineAboveGeometrySurface(ref SoilProfile1D soilProfile, double xCoordinate)
{
double surfaceLevel = this.SurfaceLine.Geometry.GetZAtUnsortedX(xCoordinate);
if (surfaceLevel > soilProfile.Layers[0].TopLevel)
{
// Add toplayer
ThrowIfNoDikeMaterialAssigned();
var topLayer = new SoilLayer1D();
topLayer.Name = soilProfile.GetNewUniqueLayerName();
topLayer.SoilName = DikeEmbankmentMaterial.Name;
topLayer.TopLevel = surfaceLevel;
soilProfile.Layers.Insert(0, topLayer);
}
}
///
/// Read soilparameters from soilbase and assign to soil in layers
///
///
private void AssignSoilsFromSoilbaseToProfile(SoilProfile1D soilProfile)
{
foreach (SoilLayer1D layer in soilProfile.Layers)
{
layer.Soil = SoilList.GetSoilByName(layer.SoilName);
if (layer.Soil == null)
{
throw new Geometry2DTo1DConverterException(String.Format("Soil material '{0}' belonging to layer '{1}' not available in soillist", layer.SoilName, layer.Name));
}
if (SoilList.AquiferDictionary.ContainsKey(layer.Soil))
{
layer.IsAquifer = SoilList.AquiferDictionary[layer.Soil];
}
}
var aquifers = soilProfile.GetAquiferLayers();
if (aquifers.Count == 0)
{
soilProfile.Layers.Last().IsAquifer = true;
}
}
///
/// Check if dikeEmbankmentmaterial assigned
///
private void ThrowIfNoDikeMaterialAssigned()
{
if (DikeEmbankmentMaterial == null)
{
throw new Geometry2DTo1DConverterException(String.Format("No dikeEmbankmentmaterial assigned for surfaceline '{0}'", SurfaceLine.Name));
}
}
}
}