// Copyright (C) Stichting Deltares 2020. 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.Collections.Generic;
namespace Deltares.LayerOnSlopeTool.Data
{
///
/// Defines the surface line
///
public class SurfaceLine
{
private readonly List surfaceLinePoints = new List();
public string SurfaceLineId { get; set; }
///
/// Gets the surface line points.
///
///
/// The surface line points.
///
public List SurfaceLinePoints
{
get { return surfaceLinePoints; }
}
///
/// Gets the surface line point by location.
///
/// The x.
/// The z.
///
public SurfaceLinePoint GetSurfaceLinePointByLocation(double x, double z)
{
var index = 0;
var searchPoint = new SurfaceLinePoint {XCoordinate = x, ZCoordinate = z};
SurfaceLinePoint surfaceLinePoint = null;
while (surfaceLinePoint == null && index < surfaceLinePoints.Count)
{
if (surfaceLinePoints[index].LocationEquals(searchPoint))
{
surfaceLinePoint = surfaceLinePoints[index];
}
index++;
}
return surfaceLinePoint;
}
///
/// Gets the type of the surface line point by.
///
/// Type of the point.
///
public SurfaceLinePoint GetSurfaceLinePointByType(CharacteristicPointType pointType)
{
var index = 0;
SurfaceLinePoint surfaceLinePoint = null;
while (surfaceLinePoint == null && index < surfaceLinePoints.Count)
{
if (surfaceLinePoints[index].PointType == pointType)
{
surfaceLinePoint = surfaceLinePoints[index];
}
index++;
}
return surfaceLinePoint;
}
///
/// Creates the lowered surface line for given layer thickness.
///
/// The layer thickness.
///
public SurfaceLine CreateLoweredSurfaceLineForGivenLayerThickness(double layerThickness)
{
const double tolerance = 1e-4;
const double horizontalOffset = 0.01;
var loweredSurfaceLine = new SurfaceLine();
var dikeTopPolder = GetSurfaceLinePointByType(CharacteristicPointType.DikeTopAtPolder);
var dikeToePolder = GetSurfaceLinePointByType(CharacteristicPointType.DikeToeAtPolder);
foreach (var point in SurfaceLinePoints)
{
if (point.XCoordinate <= dikeTopPolder.XCoordinate)
{
HandlePointsUpToAndIncludingDikeTopPolder(layerThickness, point, loweredSurfaceLine, dikeTopPolder, tolerance, horizontalOffset);
}
else
{
// Handle all points between dike top polder and dike toe polder (taking into account the horizontal offset).
if (point.XCoordinate > dikeTopPolder.XCoordinate + horizontalOffset && point.XCoordinate < dikeToePolder.XCoordinate - horizontalOffset)
{
var newPointLowered = new SurfaceLinePoint
{
XCoordinate = point.XCoordinate,
ZCoordinate = point.ZCoordinate - layerThickness,
PointType = point.PointType
};
loweredSurfaceLine.SurfaceLinePoints.Add(newPointLowered);
}
else
{
HandlePointsAtDikeToePolderAndBeyond(layerThickness, point, dikeToePolder, tolerance, horizontalOffset, loweredSurfaceLine);
}
}
}
return loweredSurfaceLine;
}
private static void HandlePointsAtDikeToePolderAndBeyond(double layerThickness, SurfaceLinePoint point,
SurfaceLinePoint dikeToePolder, double tolerance, double horizontalOffset, SurfaceLine loweredSurfaceLine)
{
if (Math.Abs(point.XCoordinate - dikeToePolder.XCoordinate) < tolerance)
{
var newPointAtDikeToe = new SurfaceLinePoint
{
XCoordinate = point.XCoordinate - horizontalOffset,
ZCoordinate = point.ZCoordinate - layerThickness,
PointType = CharacteristicPointType.None
};
loweredSurfaceLine.SurfaceLinePoints.Add(newPointAtDikeToe);
}
if (point.XCoordinate >= dikeToePolder.XCoordinate)
{
var newPointBeyondDikeToe = new SurfaceLinePoint
{
XCoordinate = point.XCoordinate,
ZCoordinate = point.ZCoordinate,
PointType = point.PointType
};
loweredSurfaceLine.SurfaceLinePoints.Add(newPointBeyondDikeToe);
}
}
private static void HandlePointsUpToAndIncludingDikeTopPolder(double layerThickness, SurfaceLinePoint point,
SurfaceLine loweredSurfaceLine, SurfaceLinePoint dikeTopPolder, double tolerance, double horizontalOffset)
{
var newPointUpToDikeTop = new SurfaceLinePoint
{
XCoordinate = point.XCoordinate,
ZCoordinate = point.ZCoordinate,
PointType = point.PointType
};
loweredSurfaceLine.SurfaceLinePoints.Add(newPointUpToDikeTop);
if (Math.Abs(point.XCoordinate - dikeTopPolder.XCoordinate) < tolerance)
{
var newPointAtDikeTop = new SurfaceLinePoint
{
XCoordinate = point.XCoordinate + horizontalOffset,
ZCoordinate = point.ZCoordinate - layerThickness,
PointType = CharacteristicPointType.None
};
loweredSurfaceLine.SurfaceLinePoints.Add(newPointAtDikeTop);
}
}
}
}