-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add memory efficient polyline decoder
- Loading branch information
Showing
4 changed files
with
119 additions
and
35 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
services-geojson/src/main/java/com/mapbox/geojson/utils/PolylineDecoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package com.mapbox.geojson.utils; | ||
|
||
import com.mapbox.geojson.Point; | ||
|
||
import java.io.Closeable; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.Iterator; | ||
|
||
/** | ||
* Decodes an encoded path string as an iterator of {@link Point}. | ||
* This is a memory efficient version of {@link PolylineUtils#decode}. | ||
* | ||
* @see <a href="https://github.com/mapbox/polyline/blob/master/src/polyline.js">Part of algorithm came from this source</a> | ||
* @see <a href="https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java">Part of algorithm came from this source.</a> | ||
* @since 6.10.0 | ||
*/ | ||
public class PolylineDecoder implements Iterator<Point>, Closeable { | ||
|
||
private final InputStream inputStream; | ||
|
||
// OSRM uses precision=6, the default Polyline spec divides by 1E5, capping at precision=5 | ||
private final double factor; | ||
|
||
// For speed we preallocate to an upper bound on the final length, then | ||
// truncate the array before returning. | ||
private int lat = 0; | ||
private int lng = 0; | ||
private int data = -1; | ||
|
||
/** | ||
* Decodes an encoded input stream into a sequence of {@link Point}. | ||
* | ||
* @param inputStream InputStream that reads a String as bytes | ||
* @param precision OSRMv4 uses 6, OSRMv5 and Google uses 5 | ||
*/ | ||
public PolylineDecoder(InputStream inputStream, int precision) { | ||
this.inputStream = inputStream; | ||
this.factor = Math.pow(10, precision); | ||
loadNext(); | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
return data != -1; | ||
} | ||
|
||
@Override | ||
public Point next() { | ||
int result = 1; | ||
int shift = 0; | ||
int temp; | ||
do { | ||
temp = data - 63 - 1; | ||
loadNext(); | ||
result += temp << shift; | ||
shift += 5; | ||
} | ||
while (temp >= 0x1f); | ||
lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1); | ||
|
||
result = 1; | ||
shift = 0; | ||
do { | ||
temp = data - 63 - 1; | ||
loadNext(); | ||
result += temp << shift; | ||
shift += 5; | ||
} | ||
while (temp >= 0x1f); | ||
lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1); | ||
|
||
return Point.fromLngLat(lng / factor, lat / factor); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
try { | ||
inputStream.close(); | ||
} catch (IOException exception) { | ||
// Safe close | ||
} | ||
} | ||
|
||
private void loadNext() throws RuntimeException { | ||
try { | ||
this.data = inputStream.read(); | ||
} catch (IOException exception) { | ||
this.data = -1; | ||
throw new RuntimeException("Failed to read the encoded path", exception); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.