Tell me more ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I would like to use this java code inside Mathematica using JLink. It converts Google Maps API Encoded Polylines to a list of points. I tried the Mathematica tutorial but get lost.

There is the Java code:

private List<GeoPoint> decodePoly(String encoded) {

List<GeoPoint> poly = new ArrayList<GeoPoint>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;

while (index < len) {
    int b, shift = 0, result = 0;
    do {
        b = encoded.charAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
    } while (b >= 0x20);
    int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
    lat += dlat;

    shift = 0;
    result = 0;
    do {
        b = encoded.charAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
    } while (b >= 0x20);
    int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
    lng += dlng;

    GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6),
         (int) (((double) lng / 1E5) * 1E6));


      poly.add(p);
    }

    return poly;
}

As example:

wjiGtdpcNrAlBJZ

should return

43.64175, -79.38651
43.64133, -79.38706
43.64127, -79.3872

I have no experience in JAVA. The code came from here.

share|improve this question
4  
This answer by Leonid is exactly what you want. – rm -rf Oct 3 '12 at 22:01
I sow the post, tks. But it do not worked (the original post test code worked). I just replaced the code above in the argument jlcsCode and tried to compile it. I should have done something more? – Murta Oct 4 '12 at 2:39
Leonid's code tests for the presence of a class, and this is only a function. Also, if it were a class, we would still need access to the GeoPoint class, and I have no idea where to get it. Lastly, Mark McClure has Mathematica code to do perform the decoding, so you could use his – rcollyer Oct 4 '12 at 4:15
1  
@rcollyer Actually, my Mathematica code only encodes polylines, rather than decoding them. The decoding scheme is bitwise operation based and would likely be a pain to translate. I responded with instructions on accessing a Java class, though. – Mark McClure Oct 4 '12 at 8:06
Also, I believe the GeoPoint class is part of Google's Android map development kit, which seems a bit heavyweight if you just want to decode a polyline. – Mark McClure Oct 4 '12 at 8:08
show 1 more comment

1 Answer

up vote 5 down vote accepted

Comment

I've placed a Notebook version of this post on my webspace here: http://facstaff.unca.edu/mcmcclur/polylineDecoder.zip

The Notebook is actually contained in a ZIP file that also contains all the Java class files necessary to get this code to work. The Notebook sets the Java class relative to it's own directory using AddToClassPath[NotebookDirectory[]], so everything should just run without difficulty.

Answer

Here's my preferred java polyline decoder: https://github.com/scoutant/polyline-decoder

The advantage of this version is that it is self-contained, while Jeffery's depends on a GeoPoint class defined in a rather large SDK.

After compiling the files in src/main/java/org/scoutant/polyline, you can use the decoder like so:

Needs["JLink`"];
InstallJava[];
AddToClassPath["scoutant-polyline-decoder-76406ba/src/main/java/"];
polylineDecoder = JavaNew["org.scoutant.polyline.PolylineDecoder"];
decoded = polylineDecoder@decode["wjiGtdpcNrAlBJZ"];
length = decoded@size[];
Table[
 point = decoded@get[k];
 {point@getLat[], point@getLng[]},
 {k, 0, length - 1}]

(* Out:
   {{1.3638, -79.3865}, {1.36338, -79.3871}, {1.36332, -79.3872}}
*)

While the latitudes all disagree with your expected result, it agrees with my javascript decoder: http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/decode.html

It also agrees with Google's own polyline decoder utility: https://developers.google.com/maps/documentation/utilities/polylineutility

An example using imported directions

As a fun example, we could download some driving directions from Google Maps, extract the encoded polyline string, and display it on a CountryData map.

Needs["JLink`"];
InstallJava[];
AddToClassPath[NotebookDirectory[]];
polylineDecoder = JavaNew[
 "org.scoutant.polyline.PolylineDecoder"
];
jsonString = StringDrop[Import[
  "https://maps.google.com/maps?saddr=NY,+NY&daddr=LA,+CA&output=json"
], 9];
json = ImportString[jsonString, "JSON"];
polylines = "polylines" /. 
  Cases[json, HoldPattern["polylines" -> _], Infinity];
pointStrings = Table["points" /. polyline, {polyline, polylines}];
pointString = First[pointStrings];
pointString = StringReplace[pointString, "\\\\" -> "\\"];
decoded = polylineDecoder@decode[pointString];
length = decoded@size[];
pts = {#@getLng[], #@getLat[]} & /@ decoded@toArray[];
Show[{
  CountryData["UnitedStates", {"Shape", "Equirectangular"}],
  Graphics[{{Blue, Line[pts]},
   {PointSize[Large], Green, Point[First[pts]], Red, 
    Point[Last[pts]]}}]
}]

enter image description here

share|improve this answer
Tks Mark!. Very good post, exact what I need. Just one more question: I download the file "scoutant-polyline-decoder-76406ba" from github as you pointed, but how I compile it to use in Mathematica? It's using "ReinstallJava[ClassPath -> "~/MyJavaDir/MyPackage.jar:~/MyJavaDir"]" ? Some clue? I use Mac OS. – Murta Oct 4 '12 at 11:32
@Murta Awesome! If you use Mac OS, open the terminal application (Go menu -> Applications, then terminal is in Utilities). You should get a command line interface. Use the cd command to get to the polyline directory and then type "javac *". If you have a java compiler, which you might, then this should generate java class files. If not, you can get one by installing XCode. If that's all a bit too much, I'd be happy to compile and post the executables with a working notebook in a ZIP file. – Mark McClure Oct 4 '12 at 11:40
HI @Mark. I compiled it, and 3 .class files where created together with pre existent .java. Sorry, but I don't know how to connect it with your first code. The notebook is welcome. Tks in advance! – Murta Oct 4 '12 at 12:13
@Murta If you've got the .class files, then you should be ready to go! The only issue I can imagine is at the AddToClassPath step. The easiest thing to do would be to save your working notebook right into the scoutant-polyline-decoder-76406ba directory. (I wonder if the "76506ba" is randomly generated?). Then the AddToClassPath call should be AddToClassPath["src/main/java/"]. I'll probably create the notebook anyway, but not until later. – Mark McClure Oct 4 '12 at 12:22
Also, note that I've made some edits to the code in the post to fix a couple of errors. – Mark McClure Oct 4 '12 at 12:23
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.