// -----------------------------------------------------------------------
//
// TODO: Update copyright text.
//
// -----------------------------------------------------------------------
namespace OsmReader.OsmData.Elements
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Xml.Serialization;
///
/// TODO: Update summary.
///
public class OsmNode : AbstractTaggedOsmElement
{
private const double EARTH_RADIUS = 6371000.0;
private const double HALFCIRCLE = 180.0;
[XmlAttribute(AttributeName = "id")]
public long id { get; set; }
[XmlAttribute(AttributeName = "lat")]
public double lat { get; set; }
[XmlAttribute(AttributeName = "lon")]
public double lon { get; set; }
[XmlAttribute(AttributeName = "user")]
public string user { get; set; }
[XmlAttribute(AttributeName = "uid")]
public int uid { get; set; }
[XmlAttribute(AttributeName = "visible")]
public bool visible { get; set; }
[XmlAttribute(AttributeName = "version")]
public int version { get; set; }
[XmlAttribute(AttributeName = "changeset")]
public long changeset { get; set; }
[XmlAttribute(AttributeName = "timestamp")]
public string timestamp { get; set; }
[XmlIgnore]
public int links { get; set; }
[XmlIgnore]
public int inLinks { get; set; }
[XmlIgnore]
public int outLinks { get; set; }
[XmlIgnore]
public string NodeType
{
get
{
return getTagValue("highway");
}
}
[XmlIgnore]
public string Ref
{
get
{
return getTagValue("ref");
}
}
///
/// Get the distance in meters between two nodes.
///
/// Node 1
/// Node 2
/// Distance in meters.
public static double calcDistance(OsmNode node1, OsmNode node2)
{
double d = 0;
if (node1 != null && node2 != null)
{
double dLat = (node2.lat - node1.lat) / HALFCIRCLE * Math.PI;
double dLon = (node2.lon - node1.lon) / HALFCIRCLE * Math.PI;
double lat1 = node1.lat / HALFCIRCLE * Math.PI;
double lat2 = node2.lat / HALFCIRCLE * Math.PI;
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
d = EARTH_RADIUS * c;
}
return d;
}
public override string ToString()
{
return id.ToString() + " [" + this.lat.ToString(CultureInfo.InvariantCulture) + "," + this.lon.ToString(CultureInfo.InvariantCulture) + "]";
}
public override int GetHashCode()
{
uint hash = (uint)this.lat.GetHashCode() ^ (((uint)this.lon.GetHashCode() & 0xffff) << 16 | ((uint)this.lon.GetHashCode() & 0xffff0000) >> 16);
return (int)hash;
}
public override bool Equals(object obj)
{
bool match = false;
if (obj is OsmNode)
{
OsmNode node1 = (OsmNode)obj;
match = (this.lat == node1.lat) && (this.lon == node1.lon);
}
return match;
}
///
/// Check if the position is close to the given position.
///
/// Object to compare with.
/// Distance to cover from position.
///
public bool CloseTo(OsmNode obj, double radius)
{
bool match = calcDistance(this, obj) <= radius;
return match;
}
}
}