Drawing polygons with your mouse
Posted by palako
A slight modification to The bounding box problem will let us draw polygons (i.e. circles) centered anywhere on the map with arbitrary radius based on mouse actions. As the circle is drawn, points of interest within its area will be shown.

The dragging functionality is reserved to move the map, so we will start the drawing with a click and will finish it with another click. To let the user know that a drawing is being taken place, we will change the cursor.
For the sake of WYSIWYG, the polygon will be shown in real time as you move your mouse. A tiny line will show the radius conecting the center of the polygon with your mouse pointer.
So, first things first, capture the onclick event:
GEvent.addListener(map, "click", onClick);
When the user clicks the map a new polygon drawing starts or ends. We are storing in a global variable the center of the polygon, so it can also be used to set the state. A null center means the drawing has not started, whereas a not null means you are actually drawing. That means:
If the drawing is starting (center was null):
- Clear any previous polygon or marker.
- Set the center of the polygon.
- Change the cursor to indicate the drawing state.
If the drawing is ending (center was set):
- Unset the center.
- Remove the Tiny line conecting the center with the edge.
function onClick(overlay,point) {
if(myCenter==null) {
myCenter=point;
document.getElementById("map").firstChild.firstChild.style.cursor ="crosshair";
map.clearOverlays();
}
else {
myCenter=null;
map.removeOverlay(lineOverlay);
}
}
After a start drawing click, we want to see the polygon being drawn as we move the mouse, so we have to modify our mousemove callback:
- If a polygon (and its radius line) has been drawn before, remove it.
- Draw the new polygon and its radius tiny line.
- Draw points within the area of the polygon.
if(myCenter!=null) {
if(overlay!=null)
map.removeOverlay(overlay);
if(lineOverlay!=null)
map.removeOverlay(lineOverlay);
var myRadius = myCenter.distanceFrom(point);
overlay = drawCircle(myCenter, myRadius/1000,30);
lineOverlay = new GPolyline(new Array(myCenter,point),"#0000ff",1);
map.addOverlay(lineOverlay);
showSelectedPois();
}
One extra line in showSelectedPois() to hide the markers when they are not contained within the area of the polygon, and we are done.
if (overlay.contains(item))
map.addOverlay(pois[i]);
else
pois[i].hide();
Feel free to test it or download it.
In future posts, we might resize the polygon once created and move the map as you aproach the edges.
Playing with the size of markers
Posted by kan
I don’t like when a map is filled with markers covering all streets there. As there is no way to use vectorial icons for markers, I though I could write a sample which tries to emulate them.
So, we have the same icon in different sizes:
: 8 pixels of width
: 12 pixels of width
: 16 pixels of width
Now, we only need to choose which icon we want depending on the zoom level. So, we’re going to add a callback function for zoom events:
GEvent.addListener(map, "zoomend", zoomCallback);
function zoomCallback() {
document.getElementById("zoom").innerHTML = "Zoom: " + map.getZoom();
initPoIs();
showSelectedPois();
}
The initPoIs() method checks if some markers have been created previously, and then it updates them using the appropiate icon:
function initPoIs() {
var blueIcon = new GIcon(G_DEFAULT_ICON);
if (map.getZoom()>=16) {
blueIcon.image = "http://.../mark16.png";
blueIcon.iconSize = new GSize(16, 16);
blueIcon.shadowSize = new GSize(30, 16);
blueIcon.iconAnchor = new GPoint(3, 16);
blueIcon.infoWindowAnchor = new GPoint(7, 2);
blueIcon.infoShadowAnchor = new GPoint(14, 14);
}
else if (map.getZoom()>=14&&map.getZoom()<=15) {
blueIcon.image = "http://.../mark12.png";
blueIcon.iconSize = new GSize(12, 12);
blueIcon.shadowSize = new GSize(20, 12);
blueIcon.iconAnchor = new GPoint(5, 12);
blueIcon.infoWindowAnchor = new GPoint(5, 2);
blueIcon.infoShadowAnchor = new GPoint(10, 10);
}
else {
blueIcon.image = "http://.../mark8.png";
blueIcon.iconSize = new GSize(8, 8);
blueIcon.shadowSize = new GSize(14, 8);
blueIcon.iconAnchor = new GPoint(3, 8);
blueIcon.infoWindowAnchor = new GPoint(3, 2);
blueIcon.infoShadowAnchor = new GPoint(6, 6);
}
markerOptions = { icon:blueIcon };
for (var i=0; i < pois.length; i++) {
map.removeOverlay(pois[i]);
}
for (var i=0; i < poisinfo.length; i++) {
pois[i]=new GMarker(new GLatLng(poisinfo[i][0],poisinfo[i][1]), markerOptions);
}
}
And, the showSelectedPois() method adds markers to the pois array in the map:
function showSelectedPois() {
for (var i=0; i < pois.length && overlay; i++) {
var item=pois[i].getLatLng();
if (overlay.getBounds().containsLatLng(item)) {
map.addOverlay(pois[i]);
}
}
}
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);
}











