Skip to content

Commit 1443c70

Browse files
committed
feat: bytey blog
1 parent 126dc29 commit 1443c70

File tree

1 file changed

+73
-0
lines changed
  • blog/2025/2025-01-21-introducing-bytey

1 file changed

+73
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
slug: 2025/introducing-bytey
3+
title: Introducing Bytey - A Google Polyline Encoding library
4+
authors: [connort]
5+
tags: [php, google, polyline, encoding]
6+
---
7+
8+
One day we saw an interesting crash that one of our applications was generating a URL so long that Google's static map generation refused to generate it. With a bit of research we discovered lodged in the official [documentation](https://developers.google.com/maps/documentation/maps-static/start#url-size-restriction) that there was a known limit.
9+
10+
:::note
11+
12+
_Maps Static API URLs are restricted to 16384 characters in size. In practice, you will probably not have need for URLs longer than this, unless you produce complicated maps with a high number of markers and paths._
13+
14+
:::
15+
16+
This led us to discovering that Google had the [Encoded Polyline Algorithm Format](https://developers.google.com/maps/documentation/utilities/polylinealgorithm) designed to help pack information in the URL into a dense binary format in plain ASCII text in order to reduce characters. This blog is our journey to writing a little package to accomplish this in PHP.
17+
18+
{/* truncate */}
19+
20+
We did start with a bit of research if any library existed for this, but nothing we found existed in a modern PHP format with a software license we could leverage. Thankfully this was a 10-step algorithm that we could implement in a fresh new library. The algorithm works roughly in this way:
21+
22+
1. Starts with the signed coordinate pairs (`(38.5, -120.2)`)
23+
2. Converts the values into integers that were rounded. (`3850000`, `-12020000`)
24+
3. Converts the values into binary, supporting negatives by using two's complement.
25+
4. Left shifting the binary one bit to optionally invert if negative.
26+
5. Break the binary value into 5-bit chunks reversed.
27+
6. Optionally OR each value with `0x20` if another chunk applies.
28+
7. Convert each value to decimal and add `63` to each one.
29+
8. Convert the value to ASCII (`_p~iF~ps|U`)
30+
31+
You can see how `38.5` became `_p~iF` and `-120.2` became `~ps|U`. The first coordinate doesn't have much of a cost savings, but as the coordinate pairs continue and each pair has the offset from the previous you can tell how the data savings begin to take place.
32+
33+
We wrote a quick PHPUnit test to confirm our implementation of the algorithm, and it matched Google's documentation.
34+
35+
```php
36+
#[DataProvider('googleDataProvider')]
37+
public function test_google_polyline_encode(array $coordinates, string $expected): void {
38+
$this->assertEquals($expected, Bytey::googlePolylineEncode($coordinates));
39+
}
40+
41+
public static function googleDataProvider(): array {
42+
return [
43+
'simple example' => [
44+
'coordinates' => [
45+
[-179.9832104],
46+
],
47+
'expected' => '`~oia@',
48+
],
49+
'rounding example' => [
50+
'coordinates' => [
51+
[48.000006, 2.000004],
52+
[48.00001, 2.00000],
53+
],
54+
'expected' => 'a_~cH_seK??',
55+
],
56+
'google example' => [
57+
'coordinates' => [
58+
[38.5, -120.2],
59+
[40.7, -120.95],
60+
[43.252, -126.453],
61+
],
62+
'expected' => '_p~iF~ps|U_ulLnnqC_mqNvxq`@',
63+
],
64+
];
65+
}
66+
```
67+
68+
So we took our affected entity that was generating a 19.5k character URL and ran it through the algorithm. The new URL was 3.3k characters, which suggested an 83% reduction in character length. A few more real life tests, and we had a fix out the door and a new package built.
69+
70+
Thus, [Bytey](https://github.com/sourcetoad/Bytey) was born.
71+
72+
* [GitHub Repo](https://github.com/sourcetoad/Bytey)
73+
* [Google's Polyline Docs](https://developers.google.com/maps/documentation/utilities/polylinealgorithm)

0 commit comments

Comments
 (0)