This is my first post in this blog using Google Maps. Also to highlight in China, to be more precise in Beijing, there is a offset of 265 meters between the map and satellite views.
To see the actual difference, click on the Map view and the Satellite view.
On info technology, gadgets, travel and thinking written from a learner's perspective.
Showing posts with label Google Maps. Show all posts
Showing posts with label Google Maps. Show all posts
JavaFX and Google Maps
Recently, I have taken a very keen interest in JavaFX. The declarative nature of the language and its powerful data binding capabilities, coupled with the fact that there are so many existing Java programs will accelerate its adoption very quickly.
My exploration with JavaFX has been very fruitful. It is really easy to pick up and to be productive with it in a matter of hours. When I started to learn how Google Maps can be used with JavaFX, I found very little useful information in the Web. Googling the keywords "JavaFX Google Maps" was less than satisfactory. Then, I stumbled upon Google Maps can be used statically without Javascript. For example, the following map on Eiffel Tower is displayed using a static html link. Notice the latitude and longitude are specified in the URL.
It then dawned upon me how easy it is to incorporate Google Maps into JavaFX, all we need are the JavaFX Image and ImageView objects. For instance, the following codes will display the above map in a JavaFX application.
Hence, using static Google Maps and GeoCoding web service, I ventured to develop this demonstration application using the latest JavaFX 1.2. A screen shot of the application is given here.
This simple application allows the user to enter an address. If Google recognises it, the map of the address will be shown. The user can also pan the map by dragging the mouse or zoom in and out of the map using the slider. The application comprises three files Main.fx, GMapUtils.fx and GmapGeoCoding.fx.
Click on the Launch button to try the application.
The full source codes of these three files are given as follows.
My exploration with JavaFX has been very fruitful. It is really easy to pick up and to be productive with it in a matter of hours. When I started to learn how Google Maps can be used with JavaFX, I found very little useful information in the Web. Googling the keywords "JavaFX Google Maps" was less than satisfactory. Then, I stumbled upon Google Maps can be used statically without Javascript. For example, the following map on Eiffel Tower is displayed using a static html link. Notice the latitude and longitude are specified in the URL.
http://maps.google.com/staticmap?center=48.8531,2.3691&markers=48.8531,2.3691,rede&zoom=14&size=320x240

def stage = Stage { title : "JavaFX Google Maps Demonstration" scene: Scene { width: 500 height: 400 content: [ ImageView { image: Image { url: "http://maps.google.com/staticmap?center=48.8531,2.3691&markers=48.8531,2.3691,rede&zoom=12&size=320x240" } } ] } }Next, I discovered the use of Google Geocoding web service. Given an address, you can get the latitude and longitude of that address. For example, to find the latitude and longitude of New York USA, enter the following url.
http://maps.google.com/maps/geo?q=NEW+YORK+USA&output=xmlThe Google Geocoding web service will return the following XML. Notice the latitude and longitude of New York, USA are returned in the coordinates element in line 25.
NEW YORK USA 200
geocode New York, NY, USA US USA NY New York -73.9869510,40.7560540,0
Hence, using static Google Maps and GeoCoding web service, I ventured to develop this demonstration application using the latest JavaFX 1.2. A screen shot of the application is given here.
This simple application allows the user to enter an address. If Google recognises it, the map of the address will be shown. The user can also pan the map by dragging the mouse or zoom in and out of the map using the slider. The application comprises three files Main.fx, GMapUtils.fx and GmapGeoCoding.fx.
Click on the Launch button to try the application.
The full source codes of these three files are given as follows.
// Main.fx package jfxgm; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.Cursor; import javafx.scene.image.ImageView; import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.control.TextBox; import javafx.scene.control.Label; import javafx.scene.control.Button; import javafx.scene.control.Slider; var lng:Number = 103.8476410; var lat:Number = 1.3717300; var zoom:Integer = bind javafx.util.Math.round(sZoom.value); bound function getMapImage(lt, lg, zm):Image { var mapurl:String = "http://maps.google.com/staticmap?center={lt},{lg}&markers={lt},{lg},reda&zoom={zm}&size=480x320"; var map:Image = Image { url: mapurl; } return map; } function setLatLng(lt:Number, lg:Number):Void { lat = lt; lng = lg; } var mapview:ImageView = ImageView { layoutX:10 layoutY:75; image: bind getMapImage(lat, lng, zoom); cursor : Cursor.MOVE; var anchorx:Number; var anchory:Number; onMousePressed: function( e: MouseEvent ):Void { anchorx = e.x; anchory = e.y; } onMouseReleased: function( e: MouseEvent ):Void { var diffx = anchorx - e.x; var diffy = anchory - e.y; lat = GMapUtils.adjustLatByPixels(lat, diffy, zoom); lng = GMapUtils.adjustLngByPixels(lng, diffx, zoom); } } def lblAddress = Label { layoutX:10 layoutY:15; text: "Address :" } def txtAddress = TextBox { layoutX:70 layoutY:10; text: "" columns: 28 selectOnFocus: true } def lblLat = Label { layoutX:39 layoutY:45; text: "Lat :" } def txtLatitude = TextBox { layoutX:70 layoutY:40; text: bind (lat.toString()); columns: 8 editable: false; } def lblLng = Label { layoutX:175 layoutY:45; text: "Lng :" } def txtLongitude = TextBox { layoutX:210 layoutY:40; text: bind (lng.toString()); columns: 8 editable: false; } def btnUpdateMap = Button { layoutX:320 layoutY:10; text: "Get Latitude and Longitude" action: function() { var addr:String = txtAddress.text; GMapGeoCoding.getLatLng(addr, setLatLng); } } def lblLevel = Label { layoutX:310 layoutY:45; text: "Level :" } def sZoom:Slider = Slider { layoutX:355 layoutY:45; min: 1 max: 20 value:15 vertical: false } def stage = Stage { title : "JavaFX Google Maps Demonstration" scene: Scene { width: 500 height: 400 content: [ lblAddress, txtAddress, lblLat, txtLatitude, lblLng, txtLongitude, btnUpdateMap, lblLevel,sZoom, mapview, ] } }
// GMapUtils.fx package jfxgm; import javafx.util.Math.*; def GMAPOFFSET = 268435456; def RADIUS = GMAPOFFSET / PI; def GMAPMAXZOOM = 21; function lng2x(lng):Integer { return round(GMAPOFFSET + RADIUS * lng * PI / 180); } function lat2y(lat) { return round(GMAPOFFSET - RADIUS * log((1 + sin(lat * PI / 180)) / (1 - sin(lat * PI / 180))) / 2); } function x2Lng(x:Number):Number { return ((round(x) - GMAPOFFSET) / RADIUS) * 180/ PI; } function y2Lat(y:Number) { return (PI / 2 - 2 * atan(exp((round(y) - GMAPOFFSET) / RADIUS))) * 180 / PI; } public function adjustLngByPixels(lng:Number, delta:Number, zoom:Number):Number { return x2Lng(lng2x(lng) + (delta * pow(2, (GMAPMAXZOOM - zoom)))); } public function adjustLatByPixels(lat:Number, delta:Number, zoom:Number):Number { return y2Lat(lat2y(lat) + (delta * pow(2, (GMAPMAXZOOM - zoom)))); }
// GMapGeoCoding.fx package jfxgm; import javafx.io.http.*; import javafx.data.pull.PullParser; import javafx.data.pull.Event; import javafx.io.http.URLConverter; public function getLatLng(address:String, setLatLng:function(lat:Number, lng:Number)):Void { def getRequest: HttpRequest = HttpRequest { var addr = URLConverter{}.encodeString(address); location: "http://maps.google.com/maps/geo?q={addr}&output=xml"; onInput: function(is: java.io.InputStream) { def parser = PullParser { documentType: PullParser.XML; input: is; onEvent: function(event: Event) { if (event.type == PullParser.END_ELEMENT) { if (event.qname.name == "code" and event.text == "602") { setLatLng(0.0, 0.0); } else if (event.qname.name == "coordinates") { var pts = event.text.split(","); setLatLng(java.lang.Float.parseFloat(pts[1]), java.lang.Float.parseFloat(pts[0])); } } } } parser.parse(); parser.input.close(); } } getRequest.start(); }
Subscribe to:
Posts (Atom)