using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using Deltares.Geographic;
using Deltares.Geotechnics;
using Deltares.Geotechnics.Exception;
using Deltares.Mathematics;
using Deltares.Standard;
using Deltares.Standard.Attributes;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Reflection;
using Deltares.Standard.Units;
namespace Deltares.DeltaModel
{
///
/// Enumeration for dike cross section state:
/// UsedCalculated, UsedNotCalculated, NotUsedCalculated, NotUsedNotCalculated
///
public enum DikeCrossSectionState
{
UsedCalculated,
UsedNotCalculated,
NotUsedCalculated,
NotUsedNotCalculated
}
///
/// DikeLocation as a specific point
///
public class DikeCrossSection : DikeLocation, IGeographicPointFromString, IComparable
{
private IGeographicPoint beginPoint;
private IGeographicPoint endPoint;
private DikeLinePoint point;
private bool used;
///
/// Gets or sets the Dike Line Point.
///
///
/// The point.
///
[Browsable(false)]
public DikeLinePoint Point
{
get
{
return point;
}
set
{
var propertyName = this.GetMemberName(dcs => dcs.Point);
DataEventPublisher.BeforeChange(this, propertyName);
point = value;
if (point != null && DikeLine != null)
{
point.DikeLine = DikeLine;
}
DataEventPublisher.AfterChange(this, propertyName);
}
}
///
/// Gets or sets a value indicating whether cross section is used.
///
///
/// true if used; otherwise, false.
///
[Browsable(false)]
[Impact(Impact.Descriptive)]
[XmlIgnore]
public bool Used
{
get
{
return used;
}
set
{
this.SetAndNotify2(out used, value, dcs => dcs.Used);
}
}
///
/// Gets the state of the cross section.
///
///
/// The state of the cross section.
///
[Browsable(false)]
[Data]
public DikeCrossSectionState CrossSectionState
{
get
{
if (Used)
{
return Double.IsNaN(AssessmentLevel)
? DikeCrossSectionState.UsedNotCalculated
: DikeCrossSectionState.UsedCalculated;
}
return Double.IsNaN(AssessmentLevel)
? DikeCrossSectionState.NotUsedNotCalculated
: DikeCrossSectionState.NotUsedCalculated;
}
}
///
/// Gets and Sets the dikeline to which this location belongs
///
public override DikeLine DikeLine
{
get
{
return base.DikeLine;
}
set
{
var dikelineName = this.GetMemberName(dcs => dcs.DikeLine);
DataEventPublisher.BeforeChange(this, dikelineName);
base.DikeLine = value;
if (point != null && value != null)
{
point.DikeLine = value;
}
DataEventPublisher.AfterChange(this, dikelineName);
}
}
///
/// Gets or sets the offset of the cross section along the dikeline
///
[XmlIgnore] // State persisted by DikeLinePointInstance
public override double Offset
{
get
{
return point.Offset;
}
set
{
point.Offset = value;
}
}
///
/// Gets or sets the X-coordinate of geographic location of this cross section.
///
///
/// The X-coordinate of geographic location of this cross section.
///
[Label("X-coordinate")]
[Description("X-coordinate of geographic location of the cross section")]
[Unit(UnitType.Length)]
[PropertyOrder(1, 1)]
[Format("F2")]
[ReadOnly(true)]
[XmlIgnore]
public double X
{
get
{
return point.X;
}
set
{
var xName = this.GetMemberName(dcs => dcs.X);
DataEventPublisher.BeforeChange(this, xName);
point.X = value;
DataEventPublisher.AfterChange(this, xName);
}
}
///
/// Gets or sets the Y-coordinate of geographic location of this cross section.
///
///
/// The Y-coordinate of geographic location of this cross section.
///
[Label("Y-coordinate")]
[Description("Y-coordinate of geographic location of the cross section")]
[Unit(UnitType.Length)]
[PropertyOrder(1, 2)]
[Format("F2")]
[ReadOnly(true)]
[XmlIgnore]
public double Y
{
get
{
return point.Y;
}
set
{
var yName = this.GetMemberName(dcs => dcs.Y);
DataEventPublisher.BeforeChange(this, yName);
point.Y = value;
DataEventPublisher.AfterChange(this, yName);
}
}
///
/// Connects the piezometric heads.
///
/// The piezometric heads.
public void ConnectPiezometricHeads(IEnumerable piezometricHeads)
{
PiezometricHeads = PiezometricHeads.SnapToPoint(Point, piezometricHeads);
}
///
/// Connects the revetment cross sections.
///
/// The revetment cross sections.
public void ConnectRevetmentCrossSections(IEnumerable revetmentCrossSections)
{
foreach (var revetmentCrossSection in revetmentCrossSections)
{
if (revetmentCrossSection.BeginOffset <= Offset && revetmentCrossSection.EndOffset >= Offset)
{
BlockRevetmentCrossSection = revetmentCrossSection;
return;
}
}
BlockRevetmentCrossSection = null;
}
public override IGeographicPoint GetRepresentivePoint()
{
return Point;
}
public override string ToString()
{
return Name;
}
public int CompareTo(DikeCrossSection other)
{
return Point.CompareTo(other.Point);
}
public override bool Equals(object obj)
{
var otherCrossSection = obj as DikeCrossSection;
if (ReferenceEquals(this, obj))
{
return true;
}
if (otherCrossSection != null)
{
return Point.Equals(otherCrossSection.Point);
}
return false;
}
public override int GetHashCode()
{
return Point.GetHashCode();
}
public void SetPointFromString(IList lineString)
{
const double tolerance = 1e-6;
if (lineString.Count < 2)
{
throw new TooFewPointOnLineException();
}
beginPoint = lineString[0];
endPoint = lineString[lineString.Count - 1];
var beginPoint2D = beginPoint.ToPoint2D();
var endPoint2D = endPoint.ToPoint2D();
var found = false;
var expectingPointIntersection = false;
for (var k = 0; k < DikeLine.Points.Count - 1; k++)
{
var currentDikeLinePoint = DikeLine.Points[k].ToPoint2D();
var nextDikeLinePoint = DikeLine.Points[k + 1].ToPoint2D();
Point2D intersectionPoint;
var intersection = Routines2D.DetermineIf2DLinesIntersectStrickly(beginPoint2D, endPoint2D, currentDikeLinePoint, nextDikeLinePoint, out intersectionPoint, tolerance);
if (intersection == LineIntersection.Intersects)
{
if (!expectingPointIntersection)
{
if (found)
{
throw new MultipleIntersectionsWithLineException();
}
found = true;
Point = new DikeLinePoint(intersectionPoint.X, intersectionPoint.Y, DikeLine);
}
expectingPointIntersection = !expectingPointIntersection && Routines2D.DetermineIfPointsCoincide(nextDikeLinePoint, intersectionPoint, tolerance);
}
}
}
}
}