csmapcontrol

csmapcontrol Git Source Tree

Root/MapControl/Track.cs

1//
2// csmapcontrol - a C# map control - http://projects.ciarang.com/p/csmapcontrol
3// Copyright (C) 2010-11, Ciaran Gultnieks
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18using System;
19using System.Collections.Generic;
20using System.Xml;
21using System.Drawing;
22using System.Text;
23using System.IO;
24
25namespace csmapcontrol
26{
27
28public class TrackPoint : ICloneable
29{
30public double Lat;
31public double Lon;
32public double Elevation;
33public DateTime Time;
34
35public object Clone()
36{
37TrackPoint copy=new TrackPoint();
38copy.Lat=Lat;
39copy.Lon=Lon;
40copy.Elevation=Elevation;
41copy.Time=Time;
42return copy;
43}
44
45}
46
47public class Track
48{
49
50public List<TrackPoint> Points;
51public string Name;
52
53/// <summary>
54/// Create a new empty Track.
55/// </summary>
56public Track()
57{
58Points=new List<TrackPoint>();
59}
60
61/// <summary>
62/// Create a new Track by loading from a GPX file.
63/// </summary>
64/// <param name="filespec">The filespec of a GPX file.</param>
65public Track(string gpxfile)
66{
67Points=new List<TrackPoint>();
68XmlDocument x=new XmlDocument();
69x.Load(gpxfile);
70if(x.DocumentElement.Name!="gpx")
71throw new ApplicationException("Document element should be 'gpx'");
72string ns="http://www.topografix.com/GPX/1/0";
73string ver=x.DocumentElement.GetAttribute("version");
74if(ver!=null && ver=="1.1")
75ns="http://www.topografix.com/GPX/1/1";
76XmlNamespaceManager nsmgr=new XmlNamespaceManager(x.NameTable);
77nsmgr.AddNamespace("gpx", ns);
78if(x.GetElementsByTagName("name").Count>0)
79Name=x.GetElementsByTagName("name")[0].InnerText;
80else
81Name=Path.GetFileNameWithoutExtension(gpxfile);
82foreach(XmlNode point in x.SelectNodes("//gpx:trkpt",nsmgr))
83{
84TrackPoint p=new TrackPoint();
85p.Lat=double.Parse(point.SelectSingleNode("@lat").Value);
86p.Lon=double.Parse(point.SelectSingleNode("@lon").Value);
87p.Elevation=double.Parse(point.SelectSingleNode("gpx:ele",nsmgr).InnerText);
88p.Time=DateTime.Parse(point.SelectSingleNode("gpx:time",nsmgr).InnerText).ToUniversalTime();
89Points.Add(p);
90}
91}
92
93/// <summary>
94/// Get a GPX representation of the track data.
95/// </summary>
96/// <returns>GPX data.</returns>
97public string ToGPX()
98{
99const string gpx="http://www.topografix.com/GPX/1/1";
100StringBuilder sb=new StringBuilder();
101using(XmlWriter writer=XmlWriter.Create(sb))
102{
103writer.WriteStartElement("gpx",gpx);
104writer.WriteAttributeString("version","1.1");
105writer.WriteAttributeString("creator","CSMapControl");
106
107Bounds b=CalculateBounds();
108writer.WriteStartElement("bounds",gpx);
109writer.WriteAttributeString("minlat",b.MinLat.ToString());
110writer.WriteAttributeString("maxlat",b.MaxLat.ToString());
111writer.WriteAttributeString("minlon",b.MinLon.ToString());
112writer.WriteAttributeString("maxlon",b.MaxLon.ToString());
113
114writer.WriteStartElement("trk",gpx);
115writer.WriteStartElement("name",gpx);
116writer.WriteValue(Name);
117writer.WriteEndElement();
118
119writer.WriteStartElement("trkseg",gpx);
120foreach(TrackPoint p in Points)
121{
122writer.WriteStartElement("trkpt",gpx);
123writer.WriteAttributeString("lat",p.Lat.ToString());
124writer.WriteAttributeString("lon",p.Lon.ToString());
125writer.WriteStartElement("ele",gpx);
126writer.WriteValue(p.Elevation.ToString());
127writer.WriteEndElement();
128writer.WriteStartElement("time",gpx);
129writer.WriteValue(p.Time.ToString("s")+"Z");
130writer.WriteEndElement();
131writer.WriteEndElement();
132}
133
134writer.WriteEndElement();
135}
136return sb.ToString();
137}
138
139/// <summary>
140/// The start time of the track. Returns DateTime.MinValue if the
141/// track has no points.
142/// </summary>
143public DateTime StartTime
144{
145get
146{
147if(Points.Count==0)
148return DateTime.MinValue;
149return Points[0].Time;
150}
151}
152
153/// <summary>
154/// The end time of the track. Returns DateTime.MinValue if the
155/// track has no points.
156/// </summary>
157public DateTime EndTime
158{
159get
160{
161if(Points.Count==0)
162return DateTime.MinValue;
163return Points[Points.Count-1].Time;
164}
165}
166
167/// <summary>
168/// Split this Track at the specified time.
169/// </summary>
170/// <param name="splittime">The time to split at.</param>
171/// <returns>An array containing two new Track objects, the first being everything
172/// from this Track up to and including splittime, and the second being the
173/// remainder.</returns>
174public Track[] Split(DateTime splittime)
175{
176Track[] retval=new Track[1];
177retval[0]=new Track();
178retval[1]=new Track();
179retval[0].Name=Name+" Part 1";
180retval[1].Name=Name+" Part 2";
181foreach(TrackPoint p in Points)
182if(p.Time<=splittime)
183retval[0].Points.Add((TrackPoint)p.Clone());
184else
185retval[1].Points.Add((TrackPoint)p.Clone());
186return retval;
187}
188
189/// <summary>
190/// Remove the trackpoint at the given time.
191/// </summary>
192/// <param name="removetime">The time at which the point will be removed. Any
193/// points at this exact time will be removed.</param>
194public void RemovePoint(DateTime removetime)
195{
196List<TrackPoint> toremove=new List<TrackPoint>();
197foreach(TrackPoint p in Points)
198if(p.Time==removetime)
199toremove.Add(p);
200foreach(TrackPoint p in toremove)
201Points.Remove(p);
202}
203
204public class Bounds
205{
206public double MinLat;
207public double MinLon;
208public double MaxLat;
209public double MaxLon;
210}
211
212/// <summary>
213/// Calculate the bounds of this track.
214/// </summary>
215/// <returns>The bounds of the track, or null if the track contains no
216/// data at all.</returns>
217public Bounds CalculateBounds()
218{
219Bounds bounds=null;
220foreach(TrackPoint p in Points)
221{
222if(bounds==null)
223{
224bounds=new Bounds();
225bounds.MinLat=bounds.MaxLat=p.Lat;
226bounds.MinLon=bounds.MaxLon=p.Lon;
227}
228else
229{
230if(p.Lat<bounds.MinLat)
231bounds.MinLat=p.Lat;
232if(p.Lat>bounds.MaxLat)
233bounds.MaxLat=p.Lat;
234if(p.Lon<bounds.MinLon)
235bounds.MinLon=p.Lon;
236if(p.Lon>bounds.MaxLon)
237bounds.MaxLon=p.Lon;
238}
239}
240return bounds;
241}
242
243}
244}
245

Archive Download this file

Branches