Google Maps Marker Lasso Search Tool

Output

0 m²
0 km²

Options

[Map Height : Small - Medium - Large]

Description

This tool will show how google maps can be used to lasso an area on a map and then return markers that only exist within that area. This is only intended to be a proof of concept and not a tool as such.

How To Use

  1. Click multiple time around the map to define an area
  2. The markers in that area will then display
  3. You can drag and drop markers after they have been put on the map

Options

Click Clear Map to start again.

Click Show All Markers to see al the markers on the map.

Click Delete Last Point to remove the last point that you clicked.

Click Find Markers to re-scan the map to find the lassoed markers again

Requirements

Javascript enabled

How it Works

There are 100 random markers placed around the map when the page is first loaded, but not displayed. As you select an area using a polygon, markers that are found inside this area are then made visible.

Code Used

A copy of the code used on this page. Unfortunately we can not guarantee any support or explanation of this code!

var map;
var points=[];
var pointsrand=[];
var areaDiv=document.getElementById('area');
var areaDivkm=document.getElementById('areakm');
var randomMarkers=new Array(0);
var routeMarkers=new Array(0);
var lines=[];
var lineColor='#ff0000';
var fillColor='#00FF00';
var lineWidth=4;
var polygon;
var routePath;
var routePath2;
var ShowHideONOFF=0;
var radiansPerDegree=Math.PI/180.0;
var degreesPerRadian=180.0/Math.PI;
var earthRadiusMeters=6367460.0;
var metersPerDegree=2.0*Math.PI*earthRadiusMeters/360.0;
var metersPerKm=1000.0;
var meters2PerHectare=10000.0;
var feetPerMeter=3.2808399;
var feetPerMile=5280.0;
var acresPerMile2=640;

function initialize() 
{
	var latlng = new google.maps.LatLng(34.12016327332972,-118.0456525824976);
	var myOptions = {zoom:16,center:latlng,mapTypeId:google.maps.MapTypeId.HYBRID,draggableCursor:'crosshair',mapTypeControlOptions:{style:google.maps.MapTypeControlStyle.DROPDOWN_MENU}};
	map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
	google.maps.event.addListener(map, 'click', mapclick);
	
	areaDiv.innerHTML='0 m²';
	areaDivkm.innerHTML='0 km²';
	
	Display();
	
	//delay by 200ms!
	setTimeout('Regen()', 200);
}

function Regen()
{
	var bounds = map.getBounds();
	var southWest = bounds.getSouthWest();
	var northEast = bounds.getNorthEast();
	var lngSpan = northEast.lng() - southWest.lng();
	var latSpan = northEast.lat() - southWest.lat();
	pointsrand=[];
	for (var i = 0; i < 100; i++) 
	{
		var point = new google.maps.LatLng(southWest.lat() + latSpan * Math.random(),southWest.lng() + lngSpan * Math.random());
		pointsrand.push(point);
	}
}

function mapclick(event)
{										  
	points.push(event.latLng);
	ShowHideONOFF=0;
	Display();
}

function SearchPointsAdd()
{
	if (!(polygon==undefined))
	{
		if (randomMarkers) 
		{	
			for (i in randomMarkers) 
			{
				randomMarkers[i].setMap(null);
			}
		}
		
		for(var i=0;i2)
	{
		var points2 = [points[0],points[points.length-1]];
	
		routePath2 = new google.maps.Polyline({
			path: points2,
			strokeColor: lineColor,
			strokeOpacity: 1.0,
			strokeWeight: lineWidth,
			geodesic: true
		});
		routePath2.setMap(map);
		
		polygon = new google.maps.Polygon({
			paths: points,
			strokeColor: "#FF0000",
			strokeOpacity: 1,
			strokeWeight: 1,
			fillColor: fillColor,
			fillOpacity: 0.5
		  });
		
		  polygon.setMap(map);
		  
		areaDiv.innerHTML=' ';
		areaDivkm.innerHTML=' ';
		var areaMeters2=SphericalPolygonAreaMeters2(points);
		if(areaMeters2<1000000.0)
		areaMeters2=PlanarPolygonAreaMeters2(points);
		//update display for area
		areaDiv.innerHTML=Areas(areaMeters2);
		areaDivkm.innerHTML=Areaskm(areaMeters2);
	}
		

	lines=[];
	routeMarkers=new Array(0);

	for(var i=0;i0)
	points.length--;
	Display();
}

function placeMarker(location,number) 
{
	var image = new google.maps.MarkerImage('//www.daftlogic.com/images/gmmarkersv3/stripes.png',
	// This marker is 20 pixels wide by 32 pixels tall.
	new google.maps.Size(20, 34),
	// The origin for this image is 0,0.
	new google.maps.Point(0,0),
	// The anchor for this image is the base of the flagpole at 0,32.
	new google.maps.Point(9, 33));

	var marker = new google.maps.Marker({position:location,map:map,icon:image,draggable:true});

	google.maps.event.addListener(marker, 'dragend', function(event)
	{
		points[number]=event.latLng;
		Display();
	});
	
	return marker;
}

function placeMarkerred(location,number) 
{
	var image = new google.maps.MarkerImage('images/gmmarkersv3/marker.png',
	// This marker is 20 pixels wide by 32 pixels tall.
	new google.maps.Size(20, 34),
	// The origin for this image is 0,0.
	new google.maps.Point(0,0),
	// The anchor for this image is the base of the flagpole at 0,32.
	new google.maps.Point(9, 33));

	var marker = new google.maps.Marker({position:location,map:map,icon:image,draggable:true});

	google.maps.event.addListener(marker, 'dragend', function(event)
	{
		points[number]=event.latLng;
		Display();
	});
	
	return marker;
}


function GreatCirclePoints(p1,p2)
{
	var maxDistanceMeters=200000.0;
	var ps=[];
	if(p1.distanceFrom(p2)<=maxDistanceMeters)
{
	ps.push(p1);
	ps.push(p2);
}
else
{
	var theta1=p1.lng()*radiansPerDegree;
	var phi1=(90.0-p1.lat())*radiansPerDegree;
	var x1=earthRadiusMeters*Math.cos(theta1)*Math.sin(phi1);
	var y1=earthRadiusMeters*Math.sin(theta1)*Math.sin(phi1);
	var z1=earthRadiusMeters*Math.cos(phi1);
	var theta2=p2.lng()*radiansPerDegree;
	var phi2=(90.0-p2.lat())*radiansPerDegree;
	var x2=earthRadiusMeters*Math.cos(theta2)*Math.sin(phi2);
	var y2=earthRadiusMeters*Math.sin(theta2)*Math.sin(phi2);
	var z2=earthRadiusMeters*Math.cos(phi2);
	var x3=(x1+x2)/2.0;
	var y3=(y1+y2)/2.0;
	var z3=(z1+z2)/2.0;
	var r3=Math.sqrt(x3*x3+y3*y3+z3*z3);
	var theta3=Math.atan2(y3,x3);
	var phi3=Math.acos(z3/r3);
	var p3=new GLatLng(90.0-phi3*degreesPerRadian,theta3*degreesPerRadian);
	var s1=GreatCirclePoints(p1,p3);
	var s2=GreatCirclePoints(p3,p2);
	for(var i=0;i420.0)
	{
		totalAngle=points.length*360.0-totalAngle;
		sphericalExcess=totalAngle-planarTotalAngle;
	}
	else if(sphericalExcess>300.0&&sphericalExcess<420.0)
	{
		sphericalExcess=Math.abs(360.0-sphericalExcess);
	}
	return sphericalExcess*radiansPerDegree*earthRadiusMeters*earthRadiusMeters;
}

function PlanarPolygonAreaMeters2(points)
{var a=0.0;
for(var i=0;i= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng()) {
        if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) {
          inPoly = !inPoly;
        }
      }

      j = i;
    }
  }

  return inPoly;
};

google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
   // setup our variables
   var lat1 = this.lat();
   var radianLat1 = lat1 * ( Math.PI  / 180 );
   var lng1 = this.lng();
   var radianLng1 = lng1 * ( Math.PI  / 180 );
   var lat2 = newLatLng.lat();
   var radianLat2 = lat2 * ( Math.PI  / 180 );
   var lng2 = newLatLng.lng();
   var radianLng2 = lng2 * ( Math.PI  / 180 );
   // sort out the radius, MILES or KM?
   var earth_radius = 3959; // (km = 6378.1) OR (miles = 3959) - radius of the earth
 
   // sort our the differences
   var diffLat =  ( radianLat1 - radianLat2 );
   var diffLng =  ( radianLng1 - radianLng2 );
   // put on a wave (hey the earth is round after all)
   var sinLat = Math.sin( diffLat / 2  );
   var sinLng = Math.sin( diffLng / 2  ); 
 
   // maths - borrowed from http://www.opensourceconnections.com/wp-content/uploads/2009/02/clientsidehaversinecalculation.html
   var a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0);
 
   // work out the distance
   var distance = earth_radius * 2 * Math.asin(Math.min(1, Math.sqrt(a)));
 
   // return the distance
   return distance;
};

Relevant Links

http://www.google.com/apis/maps/

Further Uses and Ideas

  • This type of system could be used for example for estate agents to allow house finders to define an area within which they wish to search for property.

Version History

  • Version 1 (03/05/2007)
  • Version 2 (22/02/2008)
    Added Draggable Markers
    Update search results on every event
  • Version 3 (06/10/2009)
    Fixed issue where clicking back inside polyline broke the polyline
    Changed appearance of custom markers
  • Version 4 (20/11/2010)
    Implemented Google Maps API V3
  • Version 5 (21/08/2012) - You are here
    Added code output

Comments For This Page

On 22nd June 2017 - can you give a bit more detail please?
By Daft Logic on 23rd June 2017
please test the code,its showing wrong output
On 22nd June 2017
this is awesome. thanks. would be great if you could add support for the perimeter length.
On 5th June 2015
It would be great if you could 'pick up' the lasso'ed area, in order to superimpose it on another part of the map to compare areas, e.g. to see how much of central london Richmond Park would cover...
By Tim on 7th August 2014
Where can i get code for the above functionality.
By Alena on 10th May 2014
Is this code shared anywhere?
On 18th August 2012
This is what I need, how do I get the code?
By og846 on 15th September 2011
For a good solution, take a look at: https://github.com/tparkin/Google-Maps-Point-in-Polygon

On 11th November 2010
Where can i get code for the above functionality.
By Bhavesh on 15th October 2010
Hi there, id like to get all the areas within a certain radius of a marker.

if i place a marker, id like to know all the areas that falls within 15 km of that marker.

Any ideas?

Thanks, pretoriuskevin@hotmail.com
By Kevin on 16th February 2010
REALLY great work. Reminds me a bit of the short lived and infinitely useful Ask.Com Search-Enabled Drawing Tools, which were really fantastic, and I'm not sure why they disappeared.

What would really make this useful is if the points were defined by a Google Maps business search.. and then spit out all the results within the defined area.

Magazines/Newspapers could use it to pull contact information for every potential advertising client from a given industry within their range of circulation.
By Will on 22nd July 2008
How about a box/rectangle draw selection instead of a zoom?

See this:
http://earthcode.com/blog/2006/07/gzoom.html

he's zooming with his javascript, but what I need is to _select_ with a box. like selecting multiple files in windows for deletion! cept i wanna select multiple locations on a map and use them in a web form.
On 4th March 2008
Is there a place to look at your code? I am trying to find a way to ask the map for all the markers within a certain radius or a GLatLng.
By Rob on 29th January 2008

Add your own comment below and let others know what you think: