Maps and Picasa
Posted by arcturus
The Google pic service, Picasa, offers us the possibilty to add geoinformation in a easy way.But it’s not so easy to retrieve the pics from a specific location.Endeed we are going to use an undocumented feature from Picasa API.
We asked Google guys to add a new feature, pics search by geoinformation, for GData Picasa API, and the redirected us to a post where explain how to do this:You have to add an extra param to the query pics inside the desired boundingbox:
http://picasaweb.google.com/data/feed/base/all?bbox= west,south,east,north
for example:
http://picasaweb.google.com/data/feed/base/all?bbox=-5.998,37.367,-5.953,37.403
But this query give us all the pics in this area, still we can’t use the bbox param in pic user searchs. What we can do if wanna get only our pics? We have a weird trick, in the name of the pics we have added a mark, and we use gdata query param to search for this mark, so our request looks like:
http://picasaweb.google.com/data/feed/base/all?bbox=west,south,east,north&q=mark_string
for example:
http://picasaweb.google.com/data/feed/base/all?bbox=-5.998,37.367,-5.953,37.403&q=nosvamosdetapas
Add two more params to complete the petition:
- max-results=100 : Limit the number of returned pics to 100.
- alt=json: Get the response in json format.
We encapsulate the call in a php file, and get the results using curl like this:
$curl_handle=curl_init(); $url ="http://picasaweb.google.com/data/feed/base/all?bbox=".$_GET["bounds"]; $url.="&q=nosvamosdetapas.com&maxresults=100&alt=json"; curl_setopt($curl_handle,CURLOPT_URL,$url); curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2); curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1); $buffer = curl_exec($curl_handle);curl_close($curl_handle); print $buffer;
The reason why we use a php script to retrieve the info is cause we can´t make a xhttprequest to an external server, so we make this xhttprequest to a script in the local domain.
We get a list of pics, in this pics we get the geodata information encoded, but most of the pics should have been taken from the same point, so our first task is extract geodata information and see how many different points we have pics for.We do this with tree javascript classes, ussing prototype 1.6:
var PicasaPic = Class.create({
initialize: function(jsonObj)
{
this.author = jsonObj.author.name;
this.title = jsonObj.title.$t;
this.thumb = jsonObj.media$group.media$thumbnail[0].url;
this.url = jsonObj.link[1].href
}
,
getAuthor: function(){ return this.author; }
,
getTitle: function() { return this.title; }
,
getThumb: function() { return this.thumb; }
,
getURL: function() { return this.url; }
});
This class will store all the data we need to know from a picture.
And this one, will represent a point of interest, poi, with an array of pics associated:
var PicPoi = Class.create({
initialize: function(point)
{
this.gpoint = point;
this.pics = $A();
}
,
getPoint: function(){ return this.gpoint; }
,
addPic: function(pic){ this.pics.push(pic); }
,
getPics: function(){ return this.pics; }
});
Our last class, the poi manager, a class that will check all the json entries and add pics to existing points or will create the points:
var PicPoiManager = Class.create({ initialize: function(){
this.picpois = $A();
}
,
analizePic: function(jsonObj, polygon){
var posArray = jsonObj.georss$where.gml$Point.gml$pos.$t.split(" ");
var point = new GLatLng(posArray[0],posArray[1]);
//Check again against the polygon bounding box
if(!polygon.contains(point))
return;
var found = false;
for(j=0;j
if (point.equals(this.picpois[j].getPoint())){
found = true;
this.picpois[j].addPic(new PicasaPic(jsonObj));
}
} if(!found){
var picpoi = new PicPoi(point);
picpoi.addPic(new PicasaPic(jsonObj));
this.picpois.push(picpoi);
}
}
,
getPois: function(){ return this.picpois; }
,
clear: function() { this.picpois = $A(); }
});
You can test the results here or download the source code from this link.
The boundingbox problem
Posted by arcturus
Again with google maps, now we are going to talk about the bounding box problem.
The google api provides the function containsBounds:
| containsPoint(point) | Returns true if the rectangular area (inclusively) contains the pixel coordinates. (Since 2.88) |
The problem is very simple, we wanna check points of interest inside the polygon, not the rectangular area that includes it.

We have solved this problem learning how to extend the GPolygon class with a method Contains that does what we want. You can see more examples of extending this class from this link.
Here is the code we used:
GPolygon.prototype.contains = function(point) { var j=0;
var oddNodes = false;
var x = point.lng();
var y = point.lat();
for (var i=0; i < this.getVertexCount(); i++) {
j++;
if (j == this.getVertexCount()) {j = 0;} if (((this.getVertex(i).lat() < y)
&& (this.getVertex(j).lat() >= y))
|| ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat())
/ (this.getVertex(j).lat()-this.getVertex(i).lat())
* (this.getVertex(j).lng() - this.getVertex(i).lng())>x){>
oddNodes = !oddNodes;
}
}
}
return oddNodes;
}
First test with googlemaps
Posted by arcturus
Hi all,
this is the first example from a serie of tests written to probe the googlemaps capabilities.
This example is quite simple, to draw a circunference in the map, with a center point and a radius:

Well, first of all, the google maps api does not draw circles, so, how is it that we see that circle on the map?
We are using here the solution provided by Esa from Helsinki. He has written a function that draws a polygon simulating a circunference, you can specify the number of polygon edges, better accuracy with more edges. Here is code:
function drawCircle(center, radius, nodes, liColor,
liWidth, liOpa, fillColor, fillOpa){
//http://esa.ilmari.googlepages.com/circle.htm
//calculating km/degree
var latConv = center.distanceFrom(new GLatLng(center.lat()
+0.1, center.lng()))/100;
var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng()
+0.1))/100;
//Loop
var points = [];
var step = parseInt(360/nodes)||10;
for(var i=0; i<=360; i+=step) {
var pint = new GLatLng(center.lat() + (radius/latConv *
Math.cos(i * Math.PI/180)), center.lng() +
(radius/lngConv * Math.sin(i * Math.PI/180)));
points.push(pint);
//bounds.extend(pint); //this is for fit function
}
fillColor = fillColor||liColor||"#2b82bd";
liWidth = liWidth||2;
var poly = new GPolygon(points,liColor,liWidth,liOpa,fillColor,fillOpa);
map.addOverlay(poly);
return poly;
}
Now adding some more functionality to the example from Esa, let´s draw a animation of an circunference growing until it reaches the whole area.
function drawAnimation(distance){
timerStep = 0;
timerId = setTimeout("drawAnimationAux("+distance+")",100);
}
function drawAnimationAux(distance){
if (overlay)
map.removeOverlay(overlay);
var newRadius = distance/10.0 * (timerStep +1);
overlay = drawCircle(actualPoint, newRadius, 30);
timerStep++;
if(timerStep<10)
timerId = setTimeout("drawAnimationAux("+distance+")",100);
}











