fast-polylines 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +29 -22
- data/ext/fast_polylines/extconf.rb +10 -0
- data/ext/fast_polylines/fast_polylines.c +7 -2
- data/lib/fast_polylines/version.rb +1 -1
- data/spec/fast_polylines_spec.rb +28 -5
- data/spec/spec_helper.rb +3 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b799fba2f53eb5a319d237b5460cfc20185bbe757108420ed4a2c95414ab3b5
|
4
|
+
data.tar.gz: 7853302b6843e13d4ce0161be04c4deb514a4bbd62e3c0f2fd334c00ef3b6d72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5381b5bcaa24e8dc5a6d397dc514fdeed8dc20c894a855385ba78af691e10bab8442b9d93329af658a6a8eba3a26716aff3fb3f9f2a238ca1cc1d5dea4a10243
|
7
|
+
data.tar.gz: '08733692f3f9e7ac461434f57b82b0c689e981eac015f57c92a7be94ae0195f72a283695e876120018f14aa8f8be6095640bf86631eb166701af17f601b624f4'
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Implementation of the [Google polyline algorithm][algorithm].
|
7
7
|
|
8
|
-
**BREAKING CHANGES:** The version 2
|
8
|
+
**BREAKING CHANGES:** The version 2 of FastPolylines includes breaking changes, see [Migrate from V1](#migrate-from-V1)
|
9
9
|
|
10
10
|
|
11
11
|
About **300x faster encoding and decoding** than [Joshua Clayton's gem][polylines].
|
@@ -16,35 +16,35 @@ About **300x faster encoding and decoding** than [Joshua Clayton's gem][polylin
|
|
16
16
|
——————————————————————————————— ENCODING ————————————————————————————————
|
17
17
|
|
18
18
|
Warming up --------------------------------------
|
19
|
-
Polylines
|
20
|
-
FastPolylinesV1 2.
|
21
|
-
FastPolylinesV2
|
19
|
+
Polylines 310.000 i/100ms
|
20
|
+
FastPolylinesV1 2.607k i/100ms
|
21
|
+
FastPolylinesV2 59.833k i/100ms
|
22
22
|
Calculating -------------------------------------
|
23
|
-
Polylines
|
24
|
-
FastPolylinesV1 25.
|
25
|
-
FastPolylinesV2
|
23
|
+
Polylines 2.957k (± 5.9%) i/s - 14.880k in 5.049867s
|
24
|
+
FastPolylinesV1 25.644k (± 5.8%) i/s - 127.743k in 4.999954s
|
25
|
+
FastPolylinesV2 682.981k (± 7.7%) i/s - 3.410M in 5.025952s
|
26
26
|
|
27
27
|
Comparison:
|
28
|
-
FastPolylinesV2:
|
29
|
-
FastPolylinesV1:
|
30
|
-
Polylines:
|
28
|
+
FastPolylinesV2: 682980.7 i/s
|
29
|
+
FastPolylinesV1: 25643.7 i/s - 26.63x slower
|
30
|
+
Polylines: 2957.1 i/s - 230.97x slower
|
31
31
|
|
32
32
|
|
33
33
|
——————————————————————————————— DECODING ————————————————————————————————
|
34
34
|
|
35
35
|
Warming up --------------------------------------
|
36
|
-
Polylines
|
37
|
-
FastPolylinesV1 1.
|
38
|
-
FastPolylinesV2
|
36
|
+
Polylines 127.000 i/100ms
|
37
|
+
FastPolylinesV1 1.225k i/100ms
|
38
|
+
FastPolylinesV2 40.667k i/100ms
|
39
39
|
Calculating -------------------------------------
|
40
|
-
Polylines 1.
|
41
|
-
FastPolylinesV1
|
42
|
-
FastPolylinesV2
|
40
|
+
Polylines 1.289k (± 6.1%) i/s - 6.477k in 5.046552s
|
41
|
+
FastPolylinesV1 15.445k (± 4.4%) i/s - 77.175k in 5.006896s
|
42
|
+
FastPolylinesV2 468.413k (± 7.8%) i/s - 2.359M in 5.068936s
|
43
43
|
|
44
44
|
Comparison:
|
45
|
-
FastPolylinesV2:
|
46
|
-
FastPolylinesV1:
|
47
|
-
Polylines:
|
45
|
+
FastPolylinesV2: 468412.8 i/s
|
46
|
+
FastPolylinesV1: 15445.4 i/s - 30.33x slower
|
47
|
+
Polylines: 1288.8 i/s - 363.46x slower
|
48
48
|
```
|
49
49
|
|
50
50
|
## Install
|
@@ -61,7 +61,7 @@ gem "fast-polylines", "~> 2.0.0"
|
|
61
61
|
## Usage
|
62
62
|
|
63
63
|
```ruby
|
64
|
-
require "
|
64
|
+
require "fast_polylines"
|
65
65
|
|
66
66
|
FastPolylines.encode([[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]])
|
67
67
|
# "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
|
@@ -74,7 +74,7 @@ FastPolylines.decode("_p~iF~ps|U_ulLnnqC_mqNvxq`@")
|
|
74
74
|
|
75
75
|
**Use a different precision**
|
76
76
|
|
77
|
-
Default precision is `5` decimals, to use a precision of `6
|
77
|
+
Default precision is `5` decimals, to use a precision of `6`:
|
78
78
|
```ruby
|
79
79
|
FastPolylines.encode([[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]], 6)
|
80
80
|
# "_izlhA~rlgdF_{geC~ywl@_kwzCn`{nI"
|
@@ -84,17 +84,21 @@ FastPolylines.decode("_izlhA~rlgdF_{geC~ywl@_kwzCn`{nI", 6)
|
|
84
84
|
```
|
85
85
|
The precision max is `13`.
|
86
86
|
|
87
|
-
##
|
87
|
+
## Migrate from V1
|
88
88
|
|
89
89
|
**TL;DR:**
|
90
90
|
|
91
91
|
```ruby
|
92
92
|
# before
|
93
|
+
require "fast-polylines"
|
93
94
|
FastPolylines::Encoder.encode([[1.2, 1.2], [2.4, 2.4]], 1e6)
|
94
95
|
# after
|
96
|
+
require "fast_polylines"
|
95
97
|
FastPolylines.encode([[1.2, 1.2], [2.4, 2.4]], 6)
|
96
98
|
```
|
97
99
|
|
100
|
+
**Detailled:**
|
101
|
+
|
98
102
|
The new version of `FastPolylines` doesn't support precision more than `1e13`,
|
99
103
|
you should not consider using it anyway since [it is way too precise][xkcd].
|
100
104
|
|
@@ -106,6 +110,9 @@ The precision is now an integer representing the number of decimals. It is
|
|
106
110
|
slightly smaller, and mostly this will avoid having any float value as
|
107
111
|
precision.
|
108
112
|
|
113
|
+
The file name to require is now snake_cased, you'll have to require
|
114
|
+
`fast_polylines`. The gem name stays the same however.
|
115
|
+
|
109
116
|
## Run the Benchmark
|
110
117
|
|
111
118
|
You can run the benchmark with `make benchmark`.
|
@@ -72,15 +72,18 @@ rb_FastPolylines__decode(int argc, VALUE *argv, VALUE self) {
|
|
72
72
|
|
73
73
|
static inline uint8_t
|
74
74
|
_polyline_encode_number(char *chunks, int64_t number) {
|
75
|
+
dbg("_polyline_encode_number(\"%s\", %lli)\n", chunks, number);
|
75
76
|
number = number < 0 ? ~(number << 1) : (number << 1);
|
76
77
|
uint8_t i = 0;
|
77
|
-
while (number
|
78
|
+
while (number >= 0x20) {
|
78
79
|
uint8_t chunk = number & 0x1f;
|
79
80
|
chunks[i++] = (0x20 | chunk) + 63;
|
80
81
|
number = number >> 5;
|
81
82
|
}
|
82
|
-
dbg("%u encoded chunks\n", i);
|
83
83
|
chunks[i++] = number + 63;
|
84
|
+
dbg("%u encoded chunks\n", i);
|
85
|
+
dbg("chunks: %s\n", chunks);
|
86
|
+
dbg("/_polyline_encode_number");
|
84
87
|
return i;
|
85
88
|
}
|
86
89
|
|
@@ -108,6 +111,7 @@ rb_FastPolylines__encode(int argc, VALUE *argv, VALUE self) {
|
|
108
111
|
for (i = 0; i < len; i++) {
|
109
112
|
current_pair = RARRAY_AREF(argv[0], i);
|
110
113
|
uint8_t j;
|
114
|
+
Check_Type(current_pair, T_ARRAY);
|
111
115
|
if (RARRAY_LEN(current_pair) != 2) {
|
112
116
|
free(chunks);
|
113
117
|
rb_raise(rb_eArgError, "wrong number of coordinates");
|
@@ -136,6 +140,7 @@ rb_FastPolylines__encode(int argc, VALUE *argv, VALUE self) {
|
|
136
140
|
// We pass a pointer to the current chunk that need to be filled. Doing so
|
137
141
|
// avoid having to copy the string every single iteration.
|
138
142
|
chunks_index += _polyline_encode_number(chunks + chunks_index * sizeof(char), delta);
|
143
|
+
dbg("%s\n", chunks);
|
139
144
|
}
|
140
145
|
}
|
141
146
|
dbg("final chunks_index: %zu\n", chunks_index);
|
data/spec/fast_polylines_spec.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe FastPolylines do
|
4
2
|
describe ".decode" do
|
5
3
|
let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
|
4
|
+
let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
|
6
5
|
context "with default precision" do
|
7
|
-
let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
|
8
6
|
it "should decode a polyline correctly" do
|
9
7
|
expect(described_class.decode(polyline)).to eq points
|
10
8
|
end
|
@@ -47,9 +45,34 @@ describe FastPolylines do
|
|
47
45
|
end
|
48
46
|
|
49
47
|
describe ".encode" do
|
50
|
-
let(:points)
|
48
|
+
let(:points) { [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] }
|
49
|
+
let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
|
50
|
+
it "should raise for invalid input" do
|
51
|
+
expect { described_class.encode(points[0]) }.to raise_error(
|
52
|
+
TypeError,
|
53
|
+
"wrong argument type Float (expected Array)"
|
54
|
+
)
|
55
|
+
expect { described_class.encode([points]) }.to raise_error(
|
56
|
+
ArgumentError,
|
57
|
+
"wrong number of coordinates"
|
58
|
+
)
|
59
|
+
expect { described_class.encode([points[0..1]]) }.to raise_error(
|
60
|
+
TypeError,
|
61
|
+
"no implicit conversion to Float from Array"
|
62
|
+
)
|
63
|
+
end
|
64
|
+
# The method `_polyline_encode_number("", 16)` will check for a chunk
|
65
|
+
# of the size 32, which is the chunk size limit. This was errored due to
|
66
|
+
# a bad sign.
|
67
|
+
# Reported in issue #15, closed in PR #16
|
68
|
+
context "with points close to the chunk size limit" do
|
69
|
+
let(:points) { [[0, 0.00016]] }
|
70
|
+
let(:polyline) { "?_@" }
|
71
|
+
it "should encode points correctly" do
|
72
|
+
expect(described_class.encode(points)).to eq polyline
|
73
|
+
end
|
74
|
+
end
|
51
75
|
context "with default precision" do
|
52
|
-
let(:polyline) { "_p~iF~ps|U_ulLnnqC_mqNvxq`@" }
|
53
76
|
it "should encode points correctly" do
|
54
77
|
expect(described_class.encode(points)).to eq polyline
|
55
78
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast-polylines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyrille Courtière
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: benchmark-ips
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
|
-
rubygems_version: 3.0.
|
91
|
+
rubygems_version: 3.1.0.pre3
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: Fast & easy Google polylines
|