Skip to content

Commit 03fc8eb

Browse files
author
Petr Sramek
committed
updated dev version
1 parent 90657af commit 03fc8eb

20 files changed

+369
-177
lines changed

PolylineAlgorithm.sln

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolylineAlgorithm.IO.Pipeli
2020
EndProject
2121
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolylineAlgorithm.Comparison.Benchmarks", "benchmarks\PolylineAlgorithm.Comparison.Benchmarks\PolylineAlgorithm.Comparison.Benchmarks.csproj", "{5E66392A-23C5-41BA-A5E7-E3CA097E3C91}"
2222
EndProject
23+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolylineAlgorithm.Abstraction", "src\PolylineAlgorithm.Abstraction\PolylineAlgorithm.Abstraction.csproj", "{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C}"
24+
EndProject
2325
Global
2426
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2527
Debug|Any CPU = Debug|Any CPU
@@ -46,6 +48,10 @@ Global
4648
{5E66392A-23C5-41BA-A5E7-E3CA097E3C91}.Debug|Any CPU.Build.0 = Debug|Any CPU
4749
{5E66392A-23C5-41BA-A5E7-E3CA097E3C91}.Release|Any CPU.ActiveCfg = Release|Any CPU
4850
{5E66392A-23C5-41BA-A5E7-E3CA097E3C91}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52+
{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
53+
{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
54+
{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C}.Release|Any CPU.Build.0 = Release|Any CPU
4955
EndGlobalSection
5056
GlobalSection(SolutionProperties) = preSolution
5157
HideSolutionNode = FALSE
@@ -56,6 +62,7 @@ Global
5662
{9C7CBAD5-415B-4589-86E1-01C849F9C56C} = {33C03F16-4313-4579-87E6-65892AF21D7D}
5763
{AC2D1BF7-B70C-461A-92FB-2C1E50D6C5FB} = {51C886AF-D610-48A4-9D73-2DEB38742801}
5864
{5E66392A-23C5-41BA-A5E7-E3CA097E3C91} = {33C03F16-4313-4579-87E6-65892AF21D7D}
65+
{2A15894F-3E7D-45E6-983F-FBA7C7B78B3C} = {51C886AF-D610-48A4-9D73-2DEB38742801}
5966
EndGlobalSection
6067
GlobalSection(ExtensibilityGlobals) = postSolution
6168
SolutionGuid = {93A268DC-0947-4FBB-B495-DDAD4B013D82}

benchmarks/PolylineAlgorithm.Benchmarks/PolylineBenchmark.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ public class PolylineBenchmark {
3030
/// <summary>
3131
/// Gets the character array representing the encoded polyline.
3232
/// </summary>
33-
public byte[] ByteArray { get; private set; }
33+
public char[] CharArray { get; private set; }
3434

3535
/// <summary>
3636
/// Gets the read-only memory representing the encoded polyline.
3737
/// </summary>
38-
public ReadOnlyMemory<byte> Memory { get; private set; }
38+
public ReadOnlyMemory<char> Memory { get; private set; }
3939

4040
/// <summary>
4141
/// Gets the read-only memory representing the encoded polyline.
@@ -52,8 +52,8 @@ public class PolylineBenchmark {
5252
public void SetupData() {
5353
Polyline = ValueProvider.GetPolyline(Length);
5454
StringValue = Polyline.ToString();
55-
ByteArray = Encoding.UTF8.GetBytes(StringValue);
56-
Memory = ByteArray.AsMemory();
55+
CharArray = StringValue.ToArray();
56+
Memory = CharArray.AsMemory();
5757
}
5858

5959
/// <summary>
@@ -75,7 +75,7 @@ public Polyline Polyline_FromString() {
7575
[Benchmark]
7676
public Polyline Polyline_FromCharArray() {
7777
var polyline = Polyline
78-
.FromByteArray(ByteArray);
78+
.FromCharArray(CharArray);
7979

8080
return polyline;
8181
}
@@ -123,7 +123,7 @@ public long Polyline_GetCoordinateCount() {
123123
/// <returns>The encoded polyline.</returns>
124124
[Benchmark]
125125
public void Polyline_CopyTo() {
126-
var destination = new byte[Polyline.Length];
126+
var destination = new char[Polyline.Length];
127127

128128
Polyline
129129
.CopyTo(destination);

benchmarks/PolylineAlgorithm.Benchmarks/PolylineDecoderBenchmark.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ public class PolylineDecoderBenchmark {
3131
/// <summary>
3232
/// Gets the character array representing the encoded polyline.
3333
/// </summary>
34-
public byte[] ByteArray { get; private set; }
34+
public char[] CharArray { get; private set; }
3535

3636
/// <summary>
3737
/// Gets the read-only memory representing the encoded polyline.
3838
/// </summary>
39-
public ReadOnlyMemory<byte> Memory { get; private set; }
39+
public ReadOnlyMemory<char> Memory { get; private set; }
4040

4141
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
4242

@@ -51,8 +51,8 @@ public class PolylineDecoderBenchmark {
5151
[GlobalSetup]
5252
public void SetupData() {
5353
StringValue = ValueProvider.GetPolyline(N).ToString();
54-
ByteArray = Encoding.UTF8.GetBytes(StringValue);
55-
Memory = ByteArray.AsMemory();
54+
CharArray = StringValue.ToArray();
55+
Memory = CharArray.AsMemory();
5656
}
5757

5858
/// <summary>
@@ -63,7 +63,7 @@ public void PolylineDecoder_Decode_FromString() {
6363
Polyline polyline = Polyline.FromString(StringValue);
6464

6565
Decoder
66-
.Decode(polyline)
66+
.Decode(StringValue)
6767
.Consume(_consumer);
6868
}
6969

@@ -72,10 +72,10 @@ public void PolylineDecoder_Decode_FromString() {
7272
/// </summary>
7373
[Benchmark]
7474
public void PolylineDecoder_Decode_FromCharArray() {
75-
Polyline polyline = Polyline.FromByteArray(ByteArray);
75+
Polyline polyline = Polyline.FromCharArray(CharArray);
7676

7777
Decoder
78-
.Decode(polyline)
78+
.Decode(StringValue)
7979
.Consume(_consumer);
8080
}
8181

@@ -87,7 +87,7 @@ public void PolylineDecoder_Decode_FromMemory() {
8787
Polyline polyline = Polyline.FromMemory(Memory);
8888

8989
Decoder
90-
.Decode(polyline)
90+
.Decode(StringValue)
9191
.Consume(_consumer);
9292
}
9393

benchmarks/PolylineAlgorithm.Comparison.Benchmarks/PolylineDecoderBenchmark.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ namespace PolylineAlgorithm.Comparison.Benchmarks;
77

88
using BenchmarkDotNet.Attributes;
99
using BenchmarkDotNet.Engines;
10-
using Cloudikka.PolylineAlgorithm.Encoding;
1110
using global::PolylineEncoder.Net.Utility;
1211
using PolylineAlgorithm;
13-
using PolylineAlgorithm.Abstraction;
1412
using PolylineAlgorithm.Comparison.Benchmarks.Internal;
1513
using PolylinerNet;
14+
using PolylineEncoding = Cloudikka.PolylineAlgorithm.Encoding.PolylineEncoding;
1615

1716
/// <summary>
1817
/// Benchmarks for the <see cref="PolylineAlgorithm.PolylineDecoder"/> class.
@@ -63,7 +62,7 @@ public void SetupData() {
6362
[Benchmark(Baseline = true)]
6463
public void PolylineAlgorithm_Decode() {
6564
PolylineAlgorithm
66-
.Decode(PolylineValue)
65+
.Decode(StringValue)
6766
.Consume(_consumer);
6867
}
6968

benchmarks/PolylineAlgorithm.Comparison.Benchmarks/PolylineEncoderBenchmark.cs

+9-12
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
namespace PolylineAlgorithm.Comparison.Benchmarks;
77

88
using BenchmarkDotNet.Attributes;
9-
using Cloudikka.PolylineAlgorithm.Encoding;
9+
using global::PolylineEncoder.Net.Utility;
1010
using PolylineAlgorithm;
1111
using PolylineAlgorithm.Comparison.Benchmarks.Internal;
12-
using global::PolylineEncoder.Net.Utility;
1312
using PolylinerNet;
1413
using System.Collections.Generic;
1514
using System.Threading.Tasks;
16-
using BenchmarkDotNet.Engines;
17-
using Microsoft.Extensions.Primitives;
15+
using PolylineEncoding = Cloudikka.PolylineAlgorithm.Encoding.PolylineEncoding;
1816

1917
/// <summary>
2018
/// Benchmarks for the <see cref="PolylineEncoder"/> class.
@@ -74,17 +72,16 @@ private async IAsyncEnumerable<Coordinate> GetAsyncEnumeration(IEnumerable<Coord
7472
/// Benchmarks the decoding of a polyline from a string.
7573
/// </summary>
7674
[Benchmark(Baseline = true)]
77-
public string PolylineAlgorithm_Decode() {
75+
public Polyline PolylineAlgorithm_Encode() {
7876
return PolylineAlgorithm
79-
.Encode(Enumeration)
80-
.ToString();
77+
.Encode(Enumeration);
8178
}
8279

8380
/// <summary>
8481
/// Benchmarks the decoding of a polyline from a character array.
8582
/// </summary>
8683
[Benchmark]
87-
public string Cloudikka_Decode() {
84+
public string Cloudikka_Encode() {
8885
return Cloudikka
8986
.Encode(Enumeration.Select(c => (c.Latitude, c.Longitude)));
9087
}
@@ -93,16 +90,16 @@ public string Cloudikka_Decode() {
9390
/// Benchmarks the decoding of a polyline from read-only memory.
9491
/// </summary>
9592
[Benchmark]
96-
public void PolylinerNet_Decode() {
93+
public void PolylinerNet_Encode() {
9794
PolylinerNet
98-
.Encode([..Enumeration.Select(c => new PolylinePoint(c.Latitude, c.Longitude))]);
95+
.Encode([.. Enumeration.Select(c => new PolylinePoint(c.Latitude, c.Longitude))]);
9996
}
10097

10198
/// <summary>
10299
/// Benchmarks the decoding of a polyline from read-only memory.
103100
/// </summary>
104101
[Benchmark]
105-
public string Polylines_Decode() {
102+
public string Polylines_Encode() {
106103
return Polylines.Polyline
107104
.EncodePoints(Enumeration.Select(c => new Polylines.PolylineCoordinate { Latitude = c.Latitude, Longitude = c.Longitude }));
108105
}
@@ -111,7 +108,7 @@ public string Polylines_Decode() {
111108
/// Benchmarks the decoding of a polyline from read-only memory.
112109
/// </summary>
113110
[Benchmark]
114-
public string PolylineUtility_Decode() {
111+
public string PolylineUtility_Encode() {
115112
return PolylineUtility
116113
.Encode(Enumeration.Select(c => new Tuple<double, double>(c.Latitude, c.Longitude)));
117114
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//
2+
// Copyright © Pete Sramek. All rights reserved.
3+
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace PolylineAlgorithm.Abstraction;
7+
8+
using System;
9+
using System.Diagnostics.CodeAnalysis;
10+
using System.Linq;
11+
12+
/// <summary>
13+
/// Provides default values used in the Polyline Algorithm.
14+
/// </summary>
15+
[ExcludeFromCodeCoverage]
16+
internal static class Defaults {
17+
/// <summary>
18+
/// Contains default values related to the algorithm.
19+
/// </summary>
20+
public static class Algorithm {
21+
/// <summary>
22+
/// The coordinate rounding precision.
23+
/// </summary>
24+
public const double Precision = 1E5;
25+
26+
/// <summary>
27+
/// The length of the shift used in the algorithm.
28+
/// </summary>
29+
public const byte ShiftLength = 5;
30+
31+
/// <summary>
32+
/// The ASCII value for the question mark character.
33+
/// </summary>
34+
public const byte QuestionMark = 63;
35+
36+
/// <summary>
37+
/// The ASCII value for the space character.
38+
/// </summary>
39+
public const byte Space = 32;
40+
41+
/// <summary>
42+
/// The ASCII value for the unit separator character.
43+
/// </summary>
44+
public const byte UnitSeparator = 31;
45+
}
46+
47+
/// <summary>
48+
/// Contains default values related to polyline.
49+
/// </summary>
50+
public static class Polyline {
51+
public static readonly byte[] Delimiters = [.. Enumerable.Range(0, 32).Select(n => Convert.ToByte(n + Algorithm.QuestionMark))];
52+
53+
/// <summary>
54+
/// The minimum length of an encoded coordinate.
55+
/// </summary>
56+
public const int MinEncodedCoordinateLength = 2;
57+
/// <summary>
58+
/// The maximum length of an encoded coordinate.
59+
/// </summary>
60+
public const int MaxEncodedCoordinateLength = 12;
61+
}
62+
63+
/// <summary>
64+
/// Contains default values related to coordinates.
65+
/// </summary>
66+
public static class Coordinate {
67+
/// <summary>
68+
/// Contains default values related to latitude.
69+
/// </summary>
70+
public static class Latitude {
71+
/// <summary>
72+
/// The minimum value for latitude.
73+
/// </summary>
74+
public const sbyte Min = -Max;
75+
76+
/// <summary>
77+
/// The maximum value for latitude.
78+
/// </summary>
79+
public const byte Max = 90;
80+
}
81+
82+
/// <summary>
83+
/// Contains default values related to longitude.
84+
/// </summary>
85+
public static class Longitude {
86+
/// <summary>
87+
/// The minimum value for longitude.
88+
/// </summary>
89+
public const short Min = -Max;
90+
91+
/// <summary>
92+
/// The maximum value for longitude.
93+
/// </summary>
94+
public const byte Max = 180;
95+
}
96+
97+
///// <summary>
98+
///// Contains default ranges for latitude and longitude.
99+
///// </summary>
100+
//public static class Range {
101+
// /// <summary>
102+
// /// The validation range for latitude.
103+
// /// </summary>
104+
// public static readonly CoordinateRange Latitude = new(Coordinate.Latitude.Min, Coordinate.Latitude.Max);
105+
106+
// /// <summary>
107+
// /// The validation range for longitude.
108+
// /// </summary>
109+
// public static readonly CoordinateRange Longitude = new(Coordinate.Longitude.Min, Coordinate.Longitude.Max);
110+
//}
111+
}
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// Copyright © Pete Sramek. All rights reserved.
3+
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace PolylineAlgorithm.Abstraction;
7+
8+
using System.Runtime.CompilerServices;
9+
10+
public interface IPolylineDecoder {
11+
#region Default method implementations
12+
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
public static bool TryReadValue(ref int value, ref ReadOnlyMemory<char> buffer, ref int position) {
15+
if(position == buffer.Length) {
16+
return false;
17+
}
18+
19+
int chunk = 0;
20+
int sum = 0;
21+
int shifter = 0;
22+
23+
while (position < buffer.Length) {
24+
chunk = buffer.Span[position++] - Defaults.Algorithm.QuestionMark;
25+
sum |= (chunk & Defaults.Algorithm.UnitSeparator) << shifter;
26+
shifter += Defaults.Algorithm.ShiftLength;
27+
28+
if (chunk < Defaults.Algorithm.Space) {
29+
break;
30+
}
31+
}
32+
33+
value += (sum & 1) == 1 ? ~(sum >> 1) : sum >> 1;
34+
35+
return chunk < Defaults.Algorithm.Space;
36+
}
37+
38+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
39+
public static double Denormalize(int value) => value / Defaults.Algorithm.Precision;
40+
41+
#endregion
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//
2+
// Copyright © Pete Sramek. All rights reserved.
3+
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace PolylineAlgorithm.Abstraction;
7+
8+
public interface IPolylineDecoder<TSource, TResult> : IPolylineDecoder {
9+
public TResult Decode(TSource value);
10+
}

0 commit comments

Comments
 (0)