Skip to content

Instantly share code, notes, and snippets.

@airbreather
Last active August 26, 2017 14:55
Show Gist options
  • Save airbreather/317c3c8023305ce00cd00b84f921ac07 to your computer and use it in GitHub Desktop.
Save airbreather/317c3c8023305ce00cd00b84f921ac07 to your computer and use it in GitHub Desktop.
using System;
using System.Xml;
using System.Xml.Serialization;
namespace NetTopologySuite.IO
{
public static class GpxSerialization
{
private static readonly XmlSerializer GpxSerializer = new XmlSerializer(typeof(gpxType));
public static gpxType ReadGpx(XmlReader reader) =>
GpxSerializer.Deserialize(reader ?? throw new ArgumentNullException(nameof(reader))) as gpxType;
public static void WriteGpx(XmlWriter writer, gpxType gpx) =>
GpxSerializer.Serialize(writer ?? throw new ArgumentNullException(nameof(writer)),
gpx ?? throw new ArgumentNullException(nameof(gpx)));
/// <summary>
/// Recomputs the bounds of this <see cref="gpxType"/> according to its point data.
/// </summary>
/// <param name="gpx">This <see cref="gpxType"/> instance whose bounds to recompute.</param>
/// <returns><paramref name="gpx"/>, with its <see cref="metadataType.bounds"/> recomputed according to its point data.</returns>
public static gpxType RecomputeBounds(this gpxType gpx)
{
var bounds = new boundsType
{
minlat = Decimal.MaxValue,
minlon = Decimal.MaxValue,
maxlat = Decimal.MinValue,
maxlon = Decimal.MinValue,
};
UpdateBounds(bounds, (gpx ?? throw new ArgumentNullException(nameof(gpx))).wpt);
if (gpx.rte != null)
{
foreach (var rte in gpx.rte)
{
UpdateBounds(bounds, rte.rtept);
}
}
if (gpx.trk != null)
{
foreach (var trk in gpx.trk)
{
if (trk.trkseg != null)
{
foreach (var trkseg in trk.trkseg)
{
UpdateBounds(bounds, trkseg.trkpt);
}
}
}
}
if (gpx.metadata == null)
{
gpx.metadata = new metadataType();
}
if (gpx.metadata.bounds == null)
{
gpx.metadata.bounds = bounds;
}
else
{
gpx.metadata.bounds.minlon = bounds.minlon;
gpx.metadata.bounds.maxlon = bounds.maxlon;
gpx.metadata.bounds.minlat = bounds.minlat;
gpx.metadata.bounds.maxlat = bounds.maxlat;
}
return gpx;
}
// wptType[] instead of IEnumerable<wptType> because it cuts down on
// virtual calls and allocations, the JIT emits faster code, and
// we can get away with it because this is private.
private static void UpdateBounds(boundsType bounds, wptType[] points)
{
if (points == null)
{
return;
}
foreach (var point in points)
{
if (point == null)
{
continue;
}
if (bounds.minlon > point.lon)
{
bounds.minlon = point.lon;
}
if (bounds.minlat > point.lat)
{
bounds.minlat = point.lat;
}
if (bounds.maxlon < point.lon)
{
bounds.maxlon = point.lon;
}
if (bounds.maxlat < point.lat)
{
bounds.maxlat = point.lat;
}
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(ProjectDir)..\..\</SolutionDir>
<TargetFrameworks>net35-client;net40-client;net403-client;net45;netstandard1.3</TargetFrameworks>
<RootNamespace>NetTopologySuite.IO</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SolutionDir)nts.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<Import Project="$(SolutionDir)NetTopologySuite.Common.props" />
<ItemGroup>
<Compile Include="$(SolutionDir)SharedAssemblyVersion.cs" Link="Properties\SharedAssemblyVersion.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
<PackageReference Include="System.Diagnostics.Debug" Version="4.3.0" />
<PackageReference Include="System.Diagnostics.Tools" Version="4.3.0" />
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
</ItemGroup>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment