Hand-drawing lines on a Google map

Post Reply
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Hand-drawing lines on a Google map

Post by Enrico Maria Giordano »

Anybody have a sample on how to hand-drawing lines on a Google map and save the result? It can be done, as you can see in

http://quikmaps.com

EMG
alvaro533
Posts: 179
Joined: Sat Apr 19, 2008 10:28 pm
Location: Madrid, España

Re: Hand-drawing lines on a Google map

Post by alvaro533 »

I cannot open the quickmaps web, so I don't know exactly what you mean, but you can draw a Google map in a window of you program and make lines on it. See the example below. If you want to draw lines using the mouse at execution time you can convert mouse coordinates or screen coordinates to geographical coordinates and redraw the control with the new lines. You can also draw “tags” and navigation buttons, which move the focus to specific locations.

I can send you the code of the example below if you are interested.

Regards

Alvaro


Image
norberto
Posts: 566
Joined: Thu Aug 30, 2007 3:40 pm
Location: BR

Re: Hand-drawing lines on a Google map

Post by norberto »

can send to me? please?
norberto@windowslive.com

can you have an sample to mark several points (streets) in the map, only mark, not make routes etc.

very thanks
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Re: Hand-drawing lines on a Google map

Post by Enrico Maria Giordano »

alvaro533 wrote:If you want to draw lines using the mouse at execution time you can convert mouse coordinates or screen coordinates to geographical coordinates and redraw the control with the new lines.
Do you have any samples?

EMG
alvaro533
Posts: 179
Joined: Sat Apr 19, 2008 10:28 pm
Location: Madrid, España

Re: Hand-drawing lines on a Google map

Post by alvaro533 »

I have not done that part (screen coordinates to geographical coordinates).

Zoom in google maps has 19 levels. The scale of the 19 levels can be calculated this way:

Code: Select all

zoom[1]:=31.4283668948
for nFor=2 to 19
zoom[nFor]:= zoom[nFor-1]/2
next nFor
 
The resulting scale for each level is in nautical miles to pixels.

You set the scale this way:

Code: Select all

cHtml += [   map.setCenter(new GLatLng(]+str(latitude)+[,]+str(longitude)+[),]+str(nzoom)+[   ); ]+CRLF
 
The geographical coordinates are in degrees

Code: Select all

latitude:= degrees + minutes/60 + seconds/3600
longitude:= degrees + minutes/60 + seconds/3600
 
The sign is positive for North latitudes and negative for south latitudes.
The sign + for east longitude and (-) for west longitudes.

To convert latitude y longitude to nautical miles

Code: Select all

lat_miles:= latitude*60               
long_miles:= longitude*60*COS(0.017453*latitude)   
 
The 60 is because one minute is one nautical mile and there is 60 minutes in a degree. This is true for latitudes. In longitudes you have to adjust with Cosine of the latitude, because the parallels get smaller as latitude increases. The 0.017453 is to convert degrees to radians.

To covert lat_miles y long_miles to pixels

Code: Select all

x_pix:= long_miles / nZoom
y_pix:= lat_miles / nZoom
 
(nzoom is one of the values of the array zoom above, example zoom[14] for level 14)


To go the other way around:

Code: Select all

Long_miles:= x_pix * nzoom
Lat_miles:= y_pix * nzoom

Latitude:= lat_miles / 60
Longitude:= long_miles /60 / cos(0.017453*latitude)
 
Maybe you have to convert first screen pixel to windows pixels.

To draw a point (marker)

Code: Select all

cHtml += [   var marker = new GMarker(new GLatLng( ]+str(latitude)+","+str(longitude)+ [  ));  ]+CRLF 
cHtml += [   map.addOverlay(marker);  ]+CRLF 
cHtml += [   var html= ']+ cName   + [<br/>' + '] + cLongname  +[';  ]+CRLF 
cHtml += [   marker.bindInfoWindowHtml(html);  ]+CRLF
 
I hope it helps.

Alvaro
alvaro533
Posts: 179
Joined: Sat Apr 19, 2008 10:28 pm
Location: Madrid, España

Re: Hand-drawing lines on a Google map

Post by alvaro533 »

Hi Enrico,

Two more things.

I don't know how to get the coordinates of the mouse click if the activeX control has the focus.

When you draw the control, you know the coordinates of the center of the screen, so you could calculate the coordinates of a click relative to the center. But if the user moves the center of the map then I don’t know where you can obtain the coordinates of the new center. The same if the user changes the zoom level. If I have time I’ll try to look it up in the google maps SDK

Alvaro
Gary Woodley
Posts: 28
Joined: Mon Apr 27, 2009 3:37 pm
Location: Oxford UK

Re: Hand-drawing lines on a Google map

Post by Gary Woodley »

Hi Alvaro,

Could you send me your code for the example to gary@plsoft.co.uk

Many Thanks

Gary
alvaro533
Posts: 179
Joined: Sat Apr 19, 2008 10:28 pm
Location: Madrid, España

Re: Hand-drawing lines on a Google map

Post by alvaro533 »

Gary,

This is the code for the example above. Part of it is adapted from other posts in this forum. My gratitude to the authors.
It draws an activeX control with a map, with specific coordinates and scale, places some "marks" with labels, draws a polyline with several segments, and places various buttons in the map, with different actions as to change the location of the map and the scale (without using the standard ScaleControl)

Regards,
Alvaro

Code: Select all

// -------------------------------------------------------------------------- //
FUNCTION googlemaps(oWndp,como,nnum,nombre)

local oWnd2, oactivex
local icon2,cad
local ancho,alto
LOCAL cHtml
LOCAL nLat, nLon, nZoom , nZoom2
local nsele:=select()
local alineas,i
local latmax:=-90,latmin:=+90,lonmax:=-360,lonmin:=+360
local zoom[19]

zoom[1]:=31.4283668948
for i=2 to 19
zoom[i]:=zoom[i-1]/2
next i

IF !IsGoogleup()
      MsgAlert("No hay Conexión a internet!"+CRLF+"No se puede usar GoogleMap")
      RETURN nil
ENDIF
ancho:=oWndp:nwidth-55
alto:=oWndp:nheight-170

if como="ruta"
sele 0
use datos\flplin new inde datos\flplin alias (alineas:=getnewalias("flplin"))
DBSETRELATION("database", {|| (alineas)->id},"(alineas)->id")
OrdScope(0,nnum*1000)
OrdScope(1,nnum*1000+999)

go top

endif


nombre:=alltrim(nombre)
if empty(nombre)
nombre:="prueba"
endif

lmkdir("google")

                nZoom := 13

DEFINE ICON ICON2 name "google"

cHtml := [   <html> <head> ]+CRLF
cHtml += [   <meta http-equiv="content-type" content="text/html; charset=utf-8"/> ]+CRLF
cHtml += [   <title>Google Maps</title> ]+CRLF
cHtml += [   <script src="http://maps.google.com/maps?file=api&v=2&key=1223" type="text/javascript"></script> ]+CRLF
cHtml += [   <script type="text/javascript"> ]+CRLF
cHtml += "   function load() "+CRLF
cHtml += "   { if (GBrowserIsCompatible()) "+CRLF
cHtml += [   { var map = new GMap2(document.getElementById("map"),G_SATELLITE_MAP); ] + CRLF
       
// cHtml += [   map.addControl(new GLargeMapControl3D());  ]+CRLF
cHtml += [   map.addControl(new GScaleControl());  ]+CRLF
cHtml += [   map.addControl(new GMapTypeControl());  ]+CRLF
// cHtml += [   map.addControl(new GMapTypeControl(),new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10,10)));  ]+CRLF
cHtml += [   map.setCenter(new GLatLng(]+sc(database->LAT)+[,]+sc(database->LON)+[),]+sc(nzoom)+[   ); ]+CRLF
cHtml += [   map.setMapType(G_HYBRID_MAP); ]+CRLF


// -------------------------------------------------------------- POLILINEA
CHTML += "  var polyline = new GPolyline([ "+CRLF
go top
do while !eof()
// CHTML += "  new GLatLng(  " + sc(database->LAT)+","+sc(database->LON)+" ) "
CHTML += "  new GLatLng(parseFloat( " + sc(database->LAT)+"),parseFloat("+sc(database->LON)+") ) "
skip
if !eof()
CHTML += ","
endif
enddo
CHTML += " ], '#00ffff', 8); map.addOverlay(polyline); "+CRLF  // ancho de la linea del poligono



go top
do while !eof()     
cHtml += [   var marker = new GMarker(new GLatLng( ]+sc(database->LAT)+","+sc(database->LON)+ [  ));  ]+CRLF 
cHtml += [   map.addOverlay(marker);  ]+CRLF 
cHtml += [   var html= ']+ sc(database->name)   + [<br/>' + '] + sc(database->longname)  +[';  ]+CRLF 
// cHtml += [   marker.openInfoWindowHtml(html);  ]+CRLF
cHtml += [   marker.bindInfoWindowHtml(html);  ]+CRLF
skip
enddo
// ---------------------------------------------------------------botones ruta     
cHtml += [   function TextualZoomControl() { } ]+CRLF
cHtml += [   TextualZoomControl.prototype = new GControl(); ]+CRLF
cHtml += [   TextualZoomControl.prototype.initialize = function(map) { ]+CRLF
cHtml += [   var container = document.createElement("div"); ]+CRLF


dbeval( { ||   latmax:=max(latmax, database->lat) , ;
            latmin:=min(latmin, database->lat) , ;
            lonmax:=max(lonmax, database->lon) , ;
            lonmin:=min(lonmin, database->lon) })
nlat:=(latmax+latmin)/2         
nlon:=(lonmax+lonmin)/2
latmax:= abs((latmax-latmin)*60)                // millas a lo alto
lonmax:= abs(lonmax-lonmin)*60*COS(0.017453*nlat)   
             // millas a lo ancho
if ancho/alto*latmax > lonmax
nzoom2:=latmax/alto
else
nzoom2:=lonmax/ancho
endif
i:=19
do while .t.
if nzoom2>zoom[i]
i--
else
exit
endif
if i=1
exit
endif
enddo

nzoom2:=i


cHtml += [   var zoomInDiv = document.createElement("div");  this.setButtonStyle_(zoomInDiv); ]+CRLF
cHtml += [   container.appendChild(zoomInDiv);  zoomInDiv.appendChild(document.createTextNode("-TODO-")); ]+CRLF
cHtml += [   GEvent.addDomListener(zoomInDiv, "click", function() {map.setCenter(new GLatLng(]+ sc(nlat) +[,]+ sc(nlon) +[),]+sc(nzoom2)+[   )}); ]+CRLF

go top
do while !eof()
cHtml += [   var zoomInDiv = document.createElement("div");  this.setButtonStyle_(zoomInDiv); ]+CRLF
cHtml += [   container.appendChild(zoomInDiv);  zoomInDiv.appendChild(document.createTextNode("] +sc(subs(database->name,1,6)) +[")); ]+CRLF
cHtml += [   GEvent.addDomListener(zoomInDiv, "click", function() {map.setCenter(new GLatLng(]+sc(database->LAT)+[,]+sc(database->LON)+[),]+sc(nzoom)+[   )}); ]+CRLF
skip
enddo
go top
cHtml += [   map.getContainer().appendChild(container);  return container; } ]+CRLF
cHtml += [   TextualZoomControl.prototype.getDefaultPosition = function() { return new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(7, 7)) ; } ]+CRLF        
        
cHtml += [   TextualZoomControl.prototype.setButtonStyle_ = function(button) {  button.style.color = "#0000cc"; ]+CRLF
cHtml += [   button.style.backgroundColor = "white";   button.style.font = "small Arial";   button.style.border = "1px solid black"; ]+CRLF
cHtml += [   button.style.padding = "2px";   button.style.marginBottom = "3px";   button.style.textAlign = "center"; ]+CRLF
cHtml += [   button.style.width = "6em";  ]+CRLF // ancho
cHtml += [   button.style.cursor = "pointer"; }  ]+CRLF
cHtml += [   map.addControl(new TextualZoomControl());  ]+CRLF 



CHTML += "var customUI = map.getDefaultUI(); customUI.controls.scalecontrol = false; map.setUI(customUI); "+CRLF 
// arriba ponía false en lugar de true

CHTML += "   } } "+ CRLF

CHTML += "    </script> </head> "+CRLF
CHTML += [   <body scroll="no" bgcolor="#CCCCCC" topmargin="0" leftmargin="0" ] +CRLF
CHTML += [   onload="load()" onunload="GUnload()"> ] + CRLF
chtml += [   <div id="map" style="width:]+ sc(ancho) + [px;height:]+ sc(alto) +[px"></div> ] + CRLF
chtml += [   </body> </html> ]

        // cHtml := STRTRAN(cHtml, "<<<ALTO>>>",sc(alto) )

        MemoWrit("google\"+nombre+".htm",chtml)


   DEFINE WINDOW oWnd2 MDICHILD of oWndp icon icon2 TITLE "Plan de Vuelo: "+nombre   



   oActiveX = TActiveX():New( oWnd2, "Shell.Explorer.2" )
// @ 0,0 button "salir" of oWnd2 size 60,20 pixel action oWnd2:end()
oActiveX&#058;nwidth:=ancho
oActiveX&#058;nheight:=alto
oActiveX&#058;ntop:=0
   // oWnd2:oClient = oActiveX // To fill the entire window surface
   if .t.
   oActiveX&#058;Do("Navigate2",(CurDrive() + ":\"+CurDir()+"\google\"+nombre+".htm"))
   else
   oActiveX&#058;Do("Navigate2",(CurDrive() + ":\"+CurDir()+"\MiHtml.htm"))
   endif

oWnd2:nwidth:=ancho+12
oWnd2:nheight:=alto+38  // 38
oWnd2:bKeyDown = { | nKey | teclas(nKey,oWnd2) }

   ACTIVATE WINDOW oWnd2  // on init (oWnd2:move(0,0,1200,1000),oWndp:refresh()) 
 
// ya está cerrada la base de datoa arriba y nsele


if como="ruta"
(alineas)->( DBCLOSEAREA() )
endif
select(nsele)


RETURN NIL

// -------------------------------------------------------------------------- //
Function IsGoogleup()
MsgWait( "Comprobando si hay conexión a internet","Espere",0.3 )
WSAStartup()
return  GetHostByName( "www.google.com" ) != "0.0.0.0" 


// -------------------------------------------------------------------------- //
function sc(cadena,long)

do case
case VALTYPE(cadena) == "C"
cadena:=alltrim(cadena)
case VALTYPE(cadena) == "N"
cadena:=alltrim(str(cadena))
case VALTYPE(cadena) == "L"
cadena:=if(cadena,".t.",".f.")
case VALTYPE(cadena) == "D"
cadena:=dtoc(cadena)
case VALTYPE(cadena) == "A"
cadena:="error, has mandado un array"
case VALTYPE(cadena) == "B"
cadena:="error, has mandado un codeblock"
case VALTYPE(cadena) == "U"
cadena:="** SIN DEFINIR **"
case  cadena == nil
cadena:="**NIL**"
endcase

if long!= NIL
cadena:=subs(cadena+spac(long),1,long)
endif

return cadena

User avatar
Biel EA6DD
Posts: 680
Joined: Tue Feb 14, 2006 9:48 am
Location: Mallorca
Contact:

Re: Hand-drawing lines on a Google map

Post by Biel EA6DD »

Very interesting post.
Here you have a sample how to retrieve the coordinates of the RIGHT mouse click.

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
   <head> 
   <meta http-equiv="content-type" content="text/html; charset=utf-8"/> 
   <title>Google Maps</title> 
   <script src="http://maps.google.com/maps?file=api&v=2&key=1223" type="text/javascript"></script> 
   <script type="text/javascript"> 
   //<![CDATA[ 
   function load(){ 
      if (GBrowserIsCompatible()) 
          // Variables para el mapa
          var lat =        39.52;
          var lon =         3.04;
          var zoom =          10;
          // Crear un nuevo mapa
          var map = new GMap2(document.getElementById("map"));

         map.setCenter(new GLatLng(lat, lon), zoom);
         map.addControl(new GLargeMapControl());
         GEvent.addListener(map, "singlerightclick", function(pixel)
          {
            var clickPoint = map.fromContainerPixelToLatLng(pixel);
            alert(clickPoint.toUrlValue());
          }); 
       }  
   //]]> </script> </head> 
   <body scroll="no" bgcolor="#CCCCCC" topmargin="0" leftmargin="0" 
   onload="load()" onunload="GUnload()"> 
   <div id="map" style="width:       754px;height:       521px"></div> 
   </body> </html> 

 
I don't know how to pass this info to harbour memory. (Maybe writing to a local file, but most browsers do not allow the local disk write, so solution must be via PHP probably)
Saludos desde Mallorca
Biel Maimó
http://bielsys.blogspot.com/
Post Reply