using System;
using System.IO;
using System.Text;
using Core.Gis.GeoApi.Geometries;
using Core.GIS.NetTopologySuite.Algorithm;
using Core.GIS.NetTopologySuite.Utilities;
namespace Core.GIS.NetTopologySuite.GeometriesGraph
{
///
/// Models the end of an edge incident on a node.
/// EdgeEnds have a direction
/// determined by the direction of the ray from the initial
/// point to the next point.
/// EdgeEnds are IComparable under the ordering
/// "a has a greater angle with the x-axis than b".
/// This ordering is used to sort EdgeEnds around a node.
///
public class EdgeEnd : IComparable
{
///
/// The parent edge of this edge end.
///
protected Edge edge = null;
///
///
///
protected Label label = null;
///
///
///
///
///
///
public EdgeEnd(Edge edge, ICoordinate p0, ICoordinate p1) :
this(edge, p0, p1, null) {}
///
///
///
///
///
///
///
public EdgeEnd(Edge edge, ICoordinate p0, ICoordinate p1, Label label)
: this(edge)
{
Init(p0, p1);
this.label = label;
}
///
///
///
///
protected EdgeEnd(Edge edge)
{
this.edge = edge;
}
///
///
///
public Edge Edge
{
get
{
return edge;
}
}
///
///
///
public Label Label
{
get
{
return label;
}
}
///
///
///
public ICoordinate Coordinate { get; private set; }
///
///
///
public ICoordinate DirectedCoordinate { get; private set; }
///
///
///
public int Quadrant { get; private set; }
///
///
///
public double Dx { get; private set; }
///
///
///
public double Dy { get; private set; }
///
///
///
public Node Node { get; set; }
///
/// Implements the total order relation:
/// a has a greater angle with the positive x-axis than b.
/// Using the obvious algorithm of simply computing the angle is not robust,
/// since the angle calculation is obviously susceptible to roundoff.
/// A robust algorithm is:
/// - first compare the quadrant. If the quadrants
/// are different, it it trivial to determine which vector is "greater".
/// - if the vectors lie in the same quadrant, the computeOrientation function
/// can be used to decide the relative orientation of the vectors.
///
///
public int CompareDirection(EdgeEnd e)
{
if (Dx == e.Dx && Dy == e.Dy)
{
return 0;
}
// if the rays are in different quadrants, determining the ordering is trivial
if (Quadrant > e.Quadrant)
{
return 1;
}
if (Quadrant < e.Quadrant)
{
return -1;
}
// vectors are in the same quadrant - check relative orientation of direction vectors
// this is > e if it is CCW of e
return CGAlgorithms.ComputeOrientation(e.Coordinate, e.DirectedCoordinate, DirectedCoordinate);
}
///
/// Subclasses should override this if they are using labels
///
public virtual void ComputeLabel() {}
///
///
///
///
public virtual void Write(StreamWriter outstream)
{
double angle = Math.Atan2(Dy, Dx);
string fullname = GetType().FullName;
int lastDotPos = fullname.LastIndexOf('.');
string name = fullname.Substring(lastDotPos + 1);
outstream.Write(" " + name + ": " + Coordinate + " - " + DirectedCoordinate + " " + Quadrant + ":" + angle + " " + label);
}
///
///
///
///
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(('['));
sb.Append(Coordinate.X);
sb.Append((' '));
sb.Append(DirectedCoordinate.Y);
sb.Append((']'));
return sb.ToString();
}
///
///
///
///
///
public int CompareTo(object obj)
{
EdgeEnd e = (EdgeEnd) obj;
return CompareDirection(e);
}
///
///
///
///
///
protected void Init(ICoordinate p0, ICoordinate p1)
{
Coordinate = p0;
DirectedCoordinate = p1;
Dx = p1.X - p0.X;
Dy = p1.Y - p0.Y;
Quadrant = QuadrantOp.Quadrant(Dx, Dy);
Assert.IsTrue(!(Dx == 0 && Dy == 0), "EdgeEnd with identical endpoints found");
}
}
}