-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide positioned log entries as GeoJSON #189
- Loading branch information
Showing
13 changed files
with
268 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using DotSpatial.Projections; | ||
using ILICheck.Web.XtfLog; | ||
using NetTopologySuite.Features; | ||
using NetTopologySuite.Geometries; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace ILICheck.Web | ||
{ | ||
/// <summary> | ||
/// Provides helper methods for the GeoJSON (RFC 7946) format. | ||
/// </summary> | ||
public static class GeoJsonHelper | ||
{ | ||
private static readonly ProjectionInfo lv95 = ProjectionInfo.FromEpsgCode(2056); | ||
|
||
/// <summary> | ||
/// Converts XTF log entries to a GeoJSON feature collection. | ||
/// </summary> | ||
/// <param name="logResult">The XTF log entries.</param> | ||
/// <returns>A feature collection containing the log entries or <c>null</c> if the log entries contain either no coordinates or coordinates outside of the LV95 bounds.</returns> | ||
public static FeatureCollection CreateFeatureCollection(IEnumerable<LogError> logResult) | ||
{ | ||
if (!AllCoordinatesAreLv95(logResult)) | ||
{ | ||
return null; | ||
} | ||
|
||
var features = logResult | ||
.Where(log => log.Geometry?.Coord != null) | ||
.Select(log => new Feature(ProjectLv95ToWgs84(log.Geometry.Coord), new AttributesTable(new KeyValuePair<string, object>[] | ||
{ | ||
new ("type", log.Type), | ||
new ("message", log.Message), | ||
new ("objTag", log.ObjTag), | ||
new ("dataSource", log.DataSource), | ||
new ("line", log.Line), | ||
new ("techDetails", log.TechDetails), | ||
}))); | ||
|
||
var featureCollection = new FeatureCollection(); | ||
foreach (var feature in features) | ||
{ | ||
featureCollection.Add(feature); | ||
} | ||
|
||
return featureCollection; | ||
} | ||
|
||
/// <summary> | ||
/// Checks that the log entries contain coordinates and all are in the LV95 bounds. | ||
/// </summary> | ||
/// <param name="logResult">The XTF log entries.</param> | ||
/// <returns><c>true</c> if the log entries contain coordinates and all are in the LV95 bounds; otherwise, <c>false</c>.</returns> | ||
private static bool AllCoordinatesAreLv95(IEnumerable<LogError> logResult) | ||
{ | ||
var hasLv95Coordinates = false; | ||
foreach (var logEntry in logResult) | ||
{ | ||
if (logEntry.Geometry?.Coord != null) | ||
{ | ||
hasLv95Coordinates = true; | ||
if (!IsLv95Coordinate(logEntry.Geometry.Coord)) | ||
{ | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
return hasLv95Coordinates; | ||
} | ||
|
||
/// <summary> | ||
/// Checks if the coordinate is within the LV95 bounds. | ||
/// </summary> | ||
/// <param name="coord">The coordinate to check.</param> | ||
/// <returns><c>true</c> if the coordinate is in the LV95 bounds; otherwise, <c>false</c>.</returns> | ||
private static bool IsLv95Coordinate(Coord coord) | ||
{ | ||
// Values are based on https://models.geo.admin.ch/CH/CHBase_Part1_GEOMETRY_V2.ili | ||
return coord.C1 >= 2_460_000 && coord.C1 <= 2_870_000 | ||
&& coord.C2 >= 1_045_000 && coord.C2 <= 1_310_000; | ||
} | ||
|
||
/// <summary> | ||
/// Projects the LV95 coordinate to WGS84. | ||
/// </summary> | ||
/// <param name="coord">The coordinate using LV95 CRS.</param> | ||
/// <returns>The coordinate projected to WGS84.</returns> | ||
private static Point ProjectLv95ToWgs84(Coord coord) | ||
{ | ||
var source = lv95; | ||
var target = KnownCoordinateSystems.Geographic.World.WGS1984; | ||
double[] xy = { (double)coord.C1, (double)coord.C2 }; | ||
double[] z = { 0 }; | ||
Reproject.ReprojectPoints(xy, z, source, target, 0, 1); | ||
return new Point(xy[0], xy[1]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using ILICheck.Web.XtfLog; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using NetTopologySuite.IO.Converters; | ||
using System.Text.Json; | ||
|
||
namespace ILICheck.Web | ||
{ | ||
[TestClass] | ||
public class GeoJsonHelperTest | ||
{ | ||
private JsonSerializerOptions serializerOptions; | ||
|
||
[TestInitialize] | ||
public void Initialize() | ||
{ | ||
serializerOptions = new JsonSerializerOptions(); | ||
serializerOptions.Converters.Add(new GeoJsonConverterFactory()); | ||
} | ||
|
||
[TestMethod] | ||
public void CreateFeatureCollectionForGeoJson() | ||
{ | ||
var logResult = new[] | ||
{ | ||
new LogError | ||
{ | ||
Message = "Error message without coordinate", | ||
Type = "Error", | ||
}, | ||
new LogError | ||
{ | ||
Message = "Error message 1", | ||
Type = "Error", | ||
ObjTag = "Model.Topic.Class", | ||
Line = 11, | ||
Geometry = new Geometry | ||
{ | ||
Coord = new Coord | ||
{ | ||
C1 = 2671295m, | ||
C2 = 1208106m, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
var featureCollection = GeoJsonHelper.CreateFeatureCollection(logResult); | ||
Assert.AreEqual(1, featureCollection.Count); | ||
|
||
var geoJson = JsonSerializer.Serialize(featureCollection, serializerOptions); | ||
Assert.AreEqual("{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[8.376399953106437,47.02016965999489]},\"properties\":{\"type\":\"Error\",\"message\":\"Error message 1\",\"objTag\":\"Model.Topic.Class\",\"dataSource\":null,\"line\":11,\"techDetails\":null}}]}", geoJson); | ||
} | ||
} | ||
} |
Oops, something went wrong.