Co-ordinate to image position

spot133

Member
Licensed User
Longtime User
Hello,

I want to create a program with a image covering the whole screen and another smaller image over it showing where i am so if i walk north i want the dot to move upwards on the image. I also want the dot to remain on the right place if i pinch to zoom the bigger image covering the screen.

Currently i have managed to use a webview to show a picture that i can pinch to zoom on and i have the gps latitude and longitude. The problem now for me is to figure out how i can put a dot on the image that is on the correct place depending on my latitude and longitude.

Sorry for my crappy English and i would really appreciate if someone guided me in the right direction :)
 

warwound

Expert
Licensed User
Longtime User
How good are you at coding javascript?

If you can code javascript then you could use the Google Maps API to acheive what you want.

Google Maps Javascript API V3 Map Types - Google Maps JavaScript API V3 - Google Code

You could make a custom tile layer from your main image and use the smaller image as an icon to show your location.
A custom tile layer may be overkill though - and it's quite an advanced process.

Instead you could use the Google Maps GroundOverlay object.

Google Maps Javascript API V3 Overlays - Google Maps JavaScript API V3 - Google Code

You create a Google Map, tell it the URL of your main image and the geographical bounds that it covers and the Google Maps API does all the rest for you.

Martin.
 
Upvote 0

spot133

Member
Licensed User
Longtime User
How good are you at coding javascript?

If you can code javascript then you could use the Google Maps API to acheive what you want.

Google Maps Javascript API V3 Map Types - Google Maps JavaScript API V3 - Google Code

You could make a custom tile layer from your main image and use the smaller image as an icon to show your location.
A custom tile layer may be overkill though - and it's quite an advanced process.

Instead you could use the Google Maps GroundOverlay object.

Google Maps Javascript API V3 Overlays - Google Maps JavaScript API V3 - Google Code

You create a Google Map, tell it the URL of your main image and the geographical bounds that it covers and the Google Maps API does all the rest for you.

Martin.

I downloaded the GroundOverlay-simple.html but the problem with that is that it shows the world map under the other map and i don't want the user to be able to see anything else then my map and i'm not able to pinch-to-zoom with the javascript.

I tried to use this code:
B4X:
Sub GPS_LocationChanged (Location1 As Location)
   lblLat.Text = "Lat = " & Location1.ConvertToMinutes(Location1.Latitude)
   lblLon.Text = "Lon = " & Location1.ConvertToMinutes(Location1.Longitude)
   lblSpeed.Text = "Speed = " & Location1.Speed
   webview1.LoadHtml("<html><head><meta name='viewport' content='initial-scale=1.0, user-scalable=no' /><meta http-equiv='content-type' content='text/html; charset=UTF-8'/><link href='http://code.google.com/apis/maps/documentation/javascript/examples/default.css' rel='stylesheet' type='text/css' /><script Type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=false'></script><script Type='text/javascript'>function initialize() {var newark = new google.maps.LatLng("&Location1.ConvertToMinutes(Location1.Latitude)&", "&Location1.ConvertToMinutes(Location1.Longitude)&");var imageBounds = new google.maps.LatLngBounds(new google.maps.LatLng("&Location1.ConvertToMinutes(Location1.Latitude)&", "&Location1.ConvertToMinutes(Location1.Longitude)&"),new google.maps.LatLng("&Location1.ConvertToMinutes(Location1.Latitude)&", "&Location1.ConvertToMinutes(Location1.Longitude)&"));var myOptions = {zoom: 13,center: newark,mapTypeId: google.maps.MapTypeId.ROADMAP}var Map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);var oldmap = new google.maps.GroundOverlay('http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',imageBounds);oldmap.setMap(Map);}</script></head><body onload='initialize()'><div id='map_canvas'></div></body></html>")
End Sub
but it just shows a white page but it works fine when i load it from my website http://skidf.webuda.com/
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Hi again.

First thing i'd suggest is to simply get your device location to display on a map - once that's working progress to adding the GroundOverlay.

Here's a couple of useful links you might want to bookmark, first the official documentation page for the Google Maps API:

Google Maps Javascript API V3 Reference - Google Maps JavaScript API V3 - Google Code

And secondly the Google Maps API Group:

https://groups.google.com/group/google-maps-js-api-v3

Now to check out the documentation for the google.maps.LatLng class:

Google Maps Javascript API V3 Reference - Google Maps JavaScript API V3 - Google Code

See how a LatLng constructor requires coordinates in decimal degrees?
So you need to update the HTML that you're passing to the WebView, here's an updated version of the HTML that should simply load the ROADMAP type at zoom level 13 centered on your device location:

B4X:
<html>
<head>
<meta name='viewport' content='initial-scale=1.0, user-scalable=no' />
<meta http-equiv='content-type' content='text/html; charset=UTF-8'/>
<link href='http://code.google.com/apis/maps/documentation/javascript/examples/default.css' rel='stylesheet' type='text/css' />
<script type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=false'></script>
<script type='text/javascript'>
function initialize() {
   var myLocation = new google.maps.LatLng("&Location1.Latitude&", "&Location1.Longitude&");
   var myOptions = {
      zoom: 13,
      center: myLocation,
      mapTypeId: google.maps.MapTypeId.ROADMAP
   };
   var Map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);
}
</script>
</head>
<body onload='initialize()'>
<div id='map_canvas'></div>
</body>
</html>

Removing the formatting so the HTML is a single line string would give you:

B4X:
webview1.LoadHtml("<html><head><meta name='viewport' content='initial-scale=1.0, user-scalable=no' /><meta http-equiv='content-type' content='text/html; charset=UTF-8'/><link href='http://code.google.com/apis/maps/documentation/javascript/examples/default.css' rel='stylesheet' type='text/css' /><script type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=false'></script><script type='text/javascript'>function initialize() {var myLocation = new google.maps.LatLng("&Location1.Latitude&", "&Location1.Longitude&");var myOptions = {zoom: 13,center: myLocation,mapTypeId: google.maps.MapTypeId.ROADMAP};var Map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);}</script></head><body onload='initialize()'><div id='map_canvas'></div></body></html>")

When you display a Google Map in a WebView you should be able to double tap your device screen to center and zoom in on it BUT you'll not get any pinch to zoom unfortunately.

So let's say your Sub GPS_LocationChanged is now working - you'll notice that it's very inefficient.
It'll reload the entire page everytime your GPS fires a LocationChanged event.
It'll look awful and waste lots of CPU time, battery power and network bandwidth!

You could re-structure it all:

1) Create a simple web page that displays the map.
Add the web page to your project files.
Load the WebPage in Sub Activity_Create using the WebView LoadUrl method:

B4X:
webview1.LoadUrl("file:///android_asset/web_page_name_here.html")

2) When Sub GPS_LocationChanged is called you want to pass the new user location to the map.
How to pass B4A data to the javascript in your web page?
My JSInterface library will work perfectly: http://www.b4x.com/forum/additional-libraries-official-updates/9893-jsinterface.html

3) Now you need a function in your web page javascript that can be called by B4A using my JSInterface, the function needs to accept the new user location and center the map on that location.

4) Get that working and you can look at plotting the user location using a google.maps.Marker and then progress to using a custom icon for your marker.

5) Finally you can look at adding your GroundOverlay and removing the built in map tiles (ROADMAP, TERRAIN etc).
Removing all the built in map types is possible once you create your own custom base map type.

I've done the basic code for you and attached it to this post.
Steps 1, 2, 3 and 5 working.
Don't forget you'll need my JSInterface library in your Additional Libraries folder.

My groundOverlayBounds are approx bounds of the UK and don't reflect the true bounds covered by the image i've used for the GroundOverlay.

Replace the URL to the image used for the GroundOverlay with the URL to your image and be as exact as possible when defining the bounds covered by your image and it should all work as you want.
If you add your image to the project files then you should be able to use a URL such as file:///android_asset/my_overlay_image.jpg in the javascript.

Have a play with my code and post again if you need more help.

Martin.
 

Attachments

  • GPSLocationMap.zip
    13.2 KB · Views: 402
Upvote 0

bluedude

Well-Known Member
Licensed User
Longtime User
Pretty interesting, however need to extract a more cleaner sample from this. All the groundoverlay stuff Uk etc. is a little too much :)
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Pretty interesting, however need to extract a more cleaner sample from this. All the groundoverlay stuff Uk etc. is a little too much :)

Look at the attached update.

I've removed all the GroundOverlay stuff and left behind just a basic Google Map.
The map initialises it's default view as center lat,lng (0,0) and zoom level 0.

Double tap the map to zoom in a level and as soon as you get a GPS fix the map will center on your location.

Martin.
 

Attachments

  • GPSLocationMap.zip
    12.9 KB · Views: 395
Upvote 0

neavilag

Member
Licensed User
Longtime User
nice example, have some questions

1. Why the parameters should be sent as json ? cant just be send as strings?

2. why cannot be used the geolocation from the webpage instead of from the application ?

regards
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Hi.

There's no reason why you can't send data to the webpage as a plain string and no reason why you can't use the HTML5 geolocation API for GPS features.

I think though that anyone that's familiar with programming in B4A but has little experience of HTML5 would find it quicker to use the B4A GPS library rather than learn HTML5.

Passing a JSON string to the webpage enables the WebView to use it's native JSON support - you can use JSON.parse(myString) and you get the values you want in the format you want.

Passing values as strings would require the use of parseInt() or parseFloat() for example to get numeric values from the string - with JSON you don't have to bother about data types.

Martin.
 
Upvote 0
Top