1- //! # Flexible Polyline encoding
2- //!
3- //! The flexible polyline encoding is a lossy compressed representation of a list of coordinate
4- //! pairs or coordinate triples. It achieves that by:
5- //!
6- //! 1. Reducing the decimal digits of each value.
7- //! 2. Encoding only the offset from the previous point.
8- //! 3. Using variable length for each coordinate delta.
9- //! 4. Using 64 URL-safe characters to display the result.
10- //!
11- //! The encoding is a variant of [Encoded Polyline Algorithm Format]. The advantage of this encoding
12- //! over the original are the following:
13- //!
14- //! * Output string is composed by only URL-safe characters, i.e. may be used without URL encoding
15- //! as query parameters.
16- //! * Floating point precision is configurable: This allows to represent coordinates with precision
17- //! up to microns (5 decimal places allow meter precision only).
18- //! * It allows to encode a 3rd dimension with a given precision, which may be a level, altitude,
19- //! elevation or some other custom value.
20- //!
21- //! ## Specification
22- //!
23- //! See [Specification].
24- //!
25- //! [Encoded Polyline Algorithm Format]: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
26- //! [Specification]: https://github.com/heremaps/flexible-polyline#specifications
27- //!
28- //! ## Example
29- //!
30- //! ```rust
31- //! use flexpolyline::{Polyline, Precision};
32- //!
33- //! // encode
34- //! let coordinates = vec![
35- //! (50.1022829, 8.6982122),
36- //! (50.1020076, 8.6956695),
37- //! (50.1006313, 8.6914960),
38- //! (50.0987800, 8.6875156),
39- //! ];
40- //!
41- //! let polyline = Polyline::Data2d {
42- //! coordinates,
43- //! precision2d: Precision::Digits5,
44- //! };
45- //!
46- //! let encoded = polyline.encode().unwrap();
47- //! assert_eq!(encoded, "BFoz5xJ67i1B1B7PzIhaxL7Y");
48- //!
49- //! // decode
50- //! let decoded = Polyline::decode("BFoz5xJ67i1B1B7PzIhaxL7Y").unwrap();
51- //! assert_eq!(
52- //! decoded,
53- //! Polyline::Data2d {
54- //! coordinates: vec![
55- //! (50.10228, 8.69821),
56- //! (50.10201, 8.69567),
57- //! (50.10063, 8.69150),
58- //! (50.09878, 8.68752)
59- //! ],
60- //! precision2d: Precision::Digits5
61- //! }
62- //! );
63- //! ```
64-
1+ #![ doc = include_str ! ( "../README.md" ) ]
652#![ doc( html_playground_url = "https://play.rust-lang.org/" ) ]
663#![ deny( warnings, missing_docs) ]
674#![ allow( clippy:: unreadable_literal) ]
@@ -185,18 +122,21 @@ pub enum Polyline {
185122
186123impl std:: fmt:: Display for Polyline {
187124 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
188- let prec = f. precision ( ) . unwrap_or ( 6 ) ;
189125 match self {
190126 Polyline :: Data2d {
191127 coordinates,
192128 precision2d,
193129 } => {
130+ let prec_2d = f. precision ( ) . unwrap_or ( precision2d. to_u32 ( ) as usize ) ;
194131 write ! ( f, "{{({}); [" , precision2d. to_u32( ) ) ?;
195132 for coord in coordinates {
196133 write ! (
197134 f,
198135 "({:.*}, {:.*}), " ,
199- prec as usize , coord. 0 , prec as usize , coord. 1
136+ { prec_2d } ,
137+ coord. 0 ,
138+ { prec_2d } ,
139+ coord. 1
200140 ) ?;
201141 }
202142 write ! ( f, "]}}" ) ?;
@@ -207,6 +147,8 @@ impl std::fmt::Display for Polyline {
207147 precision3d,
208148 type3d,
209149 } => {
150+ let prec_2d = f. precision ( ) . unwrap_or ( precision2d. to_u32 ( ) as usize ) ;
151+ let prec_3d = f. precision ( ) . unwrap_or ( precision3d. to_u32 ( ) as usize ) ;
210152 write ! (
211153 f,
212154 "{{({}, {}, {}); [" ,
@@ -218,7 +160,12 @@ impl std::fmt::Display for Polyline {
218160 write ! (
219161 f,
220162 "({:.*}, {:.*}, {:.*}), " ,
221- prec as usize , coord. 0 , prec as usize , coord. 1 , prec as usize , coord. 2
163+ { prec_2d } ,
164+ coord. 0 ,
165+ { prec_2d } ,
166+ coord. 1 ,
167+ { prec_3d } ,
168+ coord. 2
222169 ) ?;
223170 }
224171 write ! ( f, "]}}" ) ?;
@@ -230,15 +177,14 @@ impl std::fmt::Display for Polyline {
230177
231178/// Error reported when encoding or decoding polylines
232179#[ derive( Debug , PartialEq , Eq ) ]
180+ #[ non_exhaustive]
233181pub enum Error {
234182 /// Data is encoded with unsupported version
235183 UnsupportedVersion ,
236184 /// Precision is not supported by encoding
237185 InvalidPrecision ,
238186 /// Encoding is corrupt
239187 InvalidEncoding ,
240- #[ doc( hidden) ]
241- __Nonexhaustive,
242188}
243189
244190impl std:: fmt:: Display for Error {
@@ -247,7 +193,6 @@ impl std::fmt::Display for Error {
247193 Error :: UnsupportedVersion => write ! ( f, "UnsupportedVersion" ) ,
248194 Error :: InvalidPrecision => write ! ( f, "InvalidPrecision" ) ,
249195 Error :: InvalidEncoding => write ! ( f, "InvalidEncoding" ) ,
250- Error :: __Nonexhaustive => panic ! ( ) ,
251196 }
252197 }
253198}
@@ -264,7 +209,7 @@ impl Polyline {
264209 Polyline :: Data2d {
265210 coordinates,
266211 precision2d,
267- } => encode_2d ( & coordinates, precision2d. to_u32 ( ) ) ,
212+ } => encode_2d ( coordinates, precision2d. to_u32 ( ) ) ,
268213 Polyline :: Data3d {
269214 coordinates,
270215 precision2d,
@@ -739,7 +684,7 @@ mod tests {
739684 }
740685 . encode ( ) ?;
741686
742- let polyline = Polyline :: decode ( & encoded) ?;
687+ let polyline = Polyline :: decode ( encoded) ?;
743688 let result = format ! ( "{:.*}" , precision2d as usize + 1 , polyline) ;
744689 assert_eq ! ( expected, result) ;
745690 }
0 commit comments