Polyline Encoding
The rapidgeo.polyline module provides Google Polyline Algorithm encoding and decoding with optional simplification support.
The Google Polyline Algorithm is a lossy compression format for storing sequences of coordinates as ASCII strings. It’s commonly used in mapping applications like Google Maps.
Core Functions
Google Polyline Algorithm encoding/decoding with simplification support
- rapidgeo.polyline.encode(coordinates, precision=5)
Encode a sequence of coordinates into a Google Polyline Algorithm string.
Compresses coordinate sequences using variable-length encoding and delta compression. Commonly used for GPS tracks, routes, and mapping applications.
- Parameters:
- Returns:
Encoded polyline string
- Return type:
- Raises:
ValueError – If precision is invalid or coordinates cause overflow
Examples
>>> from rapidgeo import LngLat >>> from rapidgeo.polyline import encode >>> coords = [LngLat(-120.2, 38.5), LngLat(-120.95, 40.7)] >>> polyline = encode(coords, 5) >>> print(polyline) '_p~iF~ps|U_ulLnnqC_mqNvxq`@'
- rapidgeo.polyline.decode(polyline, precision=5)
Decode a Google Polyline Algorithm string back into coordinates.
Reverses the polyline encoding process to reconstruct the original coordinate sequence. The precision must match what was used during encoding.
- Parameters:
- Returns:
Decoded coordinate sequence
- Return type:
List[LngLat]
- Raises:
ValueError – If polyline is malformed or precision is invalid
Examples
>>> from rapidgeo.polyline import decode >>> polyline = '_p~iF~ps|U_ulLnnqC_mqNvxq`@' >>> coords = decode(polyline, 5) >>> print(f"First coord: {coords[0].lng}, {coords[0].lat}") First coord: -120.2, 38.5
- rapidgeo.polyline.encode_simplified(coordinates, tolerance_m, method='great_circle', precision=5)
Encode coordinates with line simplification into a Google Polyline string.
Combines Douglas-Peucker line simplification with polyline encoding in one step. This reduces coordinate count while maintaining essential shape, then compresses the result using Google’s polyline algorithm.
- Parameters:
coordinates (List[LngLat]) – Sequence of coordinates to simplify and encode
tolerance_m (float) – Simplification tolerance in meters. Higher values = more simplification.
method (str, optional) – Distance calculation method. Defaults to “great_circle”. - “great_circle”: Accurate geographic distance (recommended) - “planar”: Fast approximation for small areas - “euclidean”: Fastest, treat coordinates as flat plane
precision (int, optional) – Decimal places of precision (1-11). Defaults to 5.
- Returns:
Simplified and encoded polyline string
- Return type:
- Raises:
ValueError – If tolerance is negative, method is unknown, or precision is invalid
Examples
>>> from rapidgeo import LngLat >>> from rapidgeo.polyline import encode_simplified >>> # GPS track with noise - simplify to 10 meter tolerance >>> track = [LngLat(-120.2, 38.5), LngLat(-120.201, 38.501), LngLat(-120.95, 40.7)] >>> simplified = encode_simplified(track, tolerance_m=10.0) >>> # Result has fewer points than original track
- rapidgeo.polyline.simplify_polyline(polyline, tolerance_m, method='great_circle', precision=5)
Simplify an already-encoded Google Polyline string.
Decodes a polyline string, applies Douglas-Peucker simplification, then re-encodes it. Useful when you have polyline data from external sources that needs simplification without converting back to coordinate arrays.
- Parameters:
polyline (str) – Encoded polyline string to simplify
tolerance_m (float) – Simplification tolerance in meters. Higher values = more simplification.
method (str, optional) – Distance calculation method. Defaults to “great_circle”. - “great_circle”: Accurate geographic distance (recommended) - “planar”: Fast approximation for small areas - “euclidean”: Fastest, treat coordinates as flat plane
precision (int, optional) – Decimal places of precision (1-11). Defaults to 5.
- Returns:
Simplified polyline string with same precision as input
- Return type:
- Raises:
ValueError – If polyline is malformed, tolerance is negative, method is unknown, or precision is invalid
Examples
>>> from rapidgeo.polyline import simplify_polyline >>> # Simplify detailed polyline from mapping API to reduce size >>> detailed = '_p~iF~ps|U_ulLnnqC_c~vLvxq`@' >>> simplified = simplify_polyline(detailed, tolerance_m=50.0) >>> # Result string is shorter with fewer encoded points
- rapidgeo.polyline.encode_batch(coordinates_list, precision=5)
Encode multiple sequences of coordinates into Google Polyline Algorithm strings.
Batch processing version of encode() that efficiently handles multiple coordinate sequences in parallel. Useful for encoding many routes, tracks, or boundaries at once.
- Parameters:
- Returns:
List of encoded polyline strings, one for each input sequence
- Return type:
List[str]
- Raises:
ValueError – If precision is invalid or any coordinates cause overflow
Examples
>>> from rapidgeo import LngLat >>> from rapidgeo.polyline import encode_batch >>> routes = [ ... [LngLat(-120.2, 38.5), LngLat(-120.95, 40.7)], ... [LngLat(-121.0, 39.0), LngLat(-122.0, 40.0)] ... ] >>> polylines = encode_batch(routes, 5) >>> len(polylines) 2
- rapidgeo.polyline.decode_batch(polylines, precision=5)
Decode multiple Google Polyline Algorithm strings back into coordinate sequences.
Batch processing version of decode() that efficiently handles multiple polyline strings in parallel. Useful for decoding many encoded routes, tracks, or boundaries at once.
- Parameters:
- Returns:
List of decoded coordinate sequences, one for each input polyline
- Return type:
List[List[LngLat]]
- Raises:
ValueError – If any polyline is malformed or precision is invalid
Examples
>>> from rapidgeo.polyline import decode_batch >>> polylines = [ ... '_p~iF~ps|U_ulLnnqC_mqNvxq`@', ... 'u{~vFvyys@fS]' ... ] >>> routes = decode_batch(polylines, 5) >>> len(routes) 2 >>> len(routes[0]) # Number of points in first route 3
- rapidgeo.polyline.encode_simplified_batch(coordinates_list, tolerance_m, method='great_circle', precision=5)
Encode multiple coordinate sequences with line simplification into Google Polyline strings.
Batch processing version of encode_simplified() that efficiently handles multiple coordinate sequences in parallel. Combines Douglas-Peucker line simplification with polyline encoding for each sequence. Useful for processing many GPS tracks, routes, or boundaries with noise reduction.
- Parameters:
coordinates_list (List[List[LngLat]]) – List of coordinate sequences to simplify and encode
tolerance_m (float) – Simplification tolerance in meters. Higher values = more simplification. Applied uniformly to all sequences in the batch.
method (str, optional) – Distance calculation method. Defaults to “great_circle”. - “great_circle”: Accurate geographic distance (recommended) - “planar”: Fast approximation for small areas - “euclidean”: Fastest, treat coordinates as flat plane
precision (int, optional) – Decimal places of precision (1-11). Defaults to 5.
- Returns:
List of simplified and encoded polyline strings, one for each input sequence
- Return type:
List[str]
- Raises:
ValueError – If tolerance is negative, method is unknown, or precision is invalid
Examples
>>> from rapidgeo import LngLat >>> from rapidgeo.polyline import encode_simplified_batch >>> # Multiple GPS tracks with noise - simplify all to 10 meter tolerance >>> tracks = [ ... [LngLat(-120.2, 38.5), LngLat(-120.201, 38.501), LngLat(-120.95, 40.7)], ... [LngLat(-121.0, 39.0), LngLat(-121.001, 39.001), LngLat(-122.0, 40.0)] ... ] >>> simplified = encode_simplified_batch(tracks, tolerance_m=10.0) >>> len(simplified) 2 >>> # Each result has fewer points than original tracks
- rapidgeo.polyline.encode_column(coordinates_column, precision=5)
Encode an entire pandas column/Series of coordinates to polylines
This is the fastest way to convert coordinate data to polylines. Takes a pandas Series or any iterable of coordinate arrays and returns all polylines in one shot. Uses Rayon parallelization internally for maximum performance.
- Parameters:
coordinates_column – pandas Series, list, or iterable of coordinate arrays
precision (int, optional) – Decimal places of precision (1-11). Defaults to 5.
- Returns:
List of encoded polyline strings, one per input coordinate array
- Return type:
List[str]
Examples
>>> df['polylines'] = rapidgeo.polyline.encode_column(df['coordinates']) >>> # processes entire column at once with parallel encoding
Basic Usage
Encoding:
from rapidgeo.distance import LngLat
from rapidgeo.polyline import encode, decode
# Define a simple path
path = [
LngLat.new_deg(-122.4194, 37.7749), # San Francisco
LngLat.new_deg(-87.6298, 41.8781), # Chicago
LngLat.new_deg(-74.0060, 40.7128), # New York City
]
# Encode to polyline string
polyline_str = encode(path, precision=5)
print(f"Encoded: {polyline_str}")
# Decode back to coordinates
decoded_path = decode(polyline_str, precision=5)
print(f"Decoded {len(decoded_path)} points")
Precision Levels:
precision=5: Standard precision (~1 meter accuracy)
precision=6: High precision (~0.1 meter accuracy)
precision=7: Very high precision (~0.01 meter accuracy)
Higher precision results in longer encoded strings but better coordinate accuracy.
Simplification
Polylines can be simplified during encoding to reduce size while maintaining shape:
from rapidgeo.polyline import encode_simplified
# Create a detailed path with many points
detailed_path = [
LngLat.new_deg(-122.4194, 37.7749),
LngLat.new_deg(-122.4180, 37.7755), # Close intermediate point
LngLat.new_deg(-122.4160, 37.7765), # Another close point
LngLat.new_deg(-87.6298, 41.8781), # Far point - will be kept
]
# Encode with simplification (1km tolerance)
simplified = encode_simplified(detailed_path, tolerance_m=1000.0, precision=5)
print(f"Simplified polyline: {simplified}")
# You can also simplify an existing polyline
from rapidgeo.polyline import simplify_polyline
original = encode(detailed_path, precision=5)
simplified = simplify_polyline(original, tolerance_m=1000.0, precision=5)
Batch Operations
Process multiple polylines efficiently:
from rapidgeo.polyline import encode_batch, decode_batch, encode_simplified_batch
# Multiple paths to process
paths = [
[LngLat.new_deg(-122.4, 37.7), LngLat.new_deg(-122.3, 37.8)],
[LngLat.new_deg(-74.0, 40.7), LngLat.new_deg(-74.1, 40.8)],
]
# Batch encode
encoded_polylines = encode_batch(paths, precision=5)
print(f"Encoded {len(encoded_polylines)} polylines")
# Batch decode
decoded_paths = decode_batch(encoded_polylines, precision=5)
print(f"Decoded {len(decoded_paths)} paths")
# Batch encode with simplification
simplified_polylines = encode_simplified_batch(
paths, tolerance_m=100.0, precision=5
)
Real-World Example
Here’s a complete example showing how you might use polylines in a web mapping application:
from rapidgeo.distance import LngLat
from rapidgeo.polyline import encode_simplified, decode
from rapidgeo.distance.batch import path_length_haversine
# GPS track data (e.g., from a mobile app)
gps_track = [
LngLat.new_deg(-122.4194, 37.7749),
LngLat.new_deg(-122.4180, 37.7755),
LngLat.new_deg(-122.4160, 37.7765),
LngLat.new_deg(-122.4140, 37.7775),
# ... many more points
LngLat.new_deg(-122.4000, 37.7900),
]
# Calculate original track length
original_length = path_length_haversine(gps_track)
print(f"Original track: {len(gps_track)} points, {original_length/1000:.2f} km")
# Encode with simplification for web transmission
# 10m tolerance reduces data size while preserving route shape
polyline_str = encode_simplified(gps_track, tolerance_m=10.0, precision=5)
print(f"Encoded polyline: {len(polyline_str)} characters")
# On the client side, decode the polyline
simplified_track = decode(polyline_str, precision=5)
simplified_length = path_length_haversine(simplified_track)
print(f"Simplified track: {len(simplified_track)} points, {simplified_length/1000:.2f} km")
print(f"Size reduction: {(1 - len(simplified_track)/len(gps_track))*100:.1f}%")
Algorithm Details
Encoding Process:
Convert coordinates to integers by multiplying by 10^precision
Calculate deltas between consecutive points
Apply zigzag encoding to handle negative numbers
Convert to base32 representation using specific character set
Precision vs. Size:
Higher precision = more accurate coordinates but longer strings
Lower precision = smaller strings but coordinate quantization
Choose precision based on your accuracy requirements
Simplification:
Uses Douglas-Peucker algorithm during encoding
Tolerance specified in meters (real-world distance)
Points are retained if they deviate more than tolerance from the simplified line
Implementation Notes
Processing:
Batch operations handle multiple polylines efficiently
Simplification uses Douglas-Peucker algorithm
Memory usage scales with input size
Precision Trade-offs:
Higher precision = more accurate coordinates, longer strings
Lower precision = shorter strings, some coordinate rounding
Choose based on your accuracy requirements