Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps - FusionTablesLayer to Polygon

I'm using Google Maps API and jquery-ui-maps (this questions has nothing to do with the plugin which is working great).

I've created a FusionTablesLayer with all countries except Mozambique. The user could place a marker and reposition it. I'm trying to find a way to block the drag (or alert the user, it doesn't matter now) if he tries to place the marker outside Mozambique (over the FusionTablesLayer).

After some research I discover this method: containsLocation(point:LatLng, polygon:Polygon), which computes whether the given point lies inside the specified polygon.

It should receive a Polygon and I've got a FusionTablesLayer. Any clue how to solve this?

Here's my code:FIDDLE

Try to place a marker and drag it...

//Initialize the map
var mapa = $('#map_canvas').gmap({'center': '-18.646245,35.815918'});
$('#map_canvas').gmap('option', 'zoom', 7);

//create the layer (all countries except Mozambique)
var world_geometry;
$('#map_canvas').gmap().bind('init', function(event, map) {
    world_geometry = new google.maps.FusionTablesLayer({
        query: {
            select: 'geometry',
            from: '1N2LBk4JHwWpOY4d9fobIn27lfnZ5MDy-NoqqRpk',
            where: "ISO_2DIGIT NOT EQUAL TO 'MZ'"
        },
        styles: [{
                polygonOptions: {
                    fillColor: "#333333",
                    fillOpacity: 0.3
                }
            }],
        map: map,
        suppressInfoWindows: true
    });

});

$('#map_canvas').gmap().bind('init', function(event, map) {
    $(map).click(function(event) {
        $('#map_canvas').gmap('clear', 'markers');
        $('#map_canvas').gmap('addMarker', {
            'position': event.latLng,
            'draggable': true,
            'bounds': false
        }, function(map, marker) {
        }).dragend(function(event) {
            //I need to check if the marker is over the FusionTablesLayer and block the drag.
            //var test = google.maps.geometry.poly.containsLocation(event.latLng, world_geometry);
        }).click(function() {
        })
    });
});
like image 840
Pedro Gil Avatar asked Feb 23 '14 03:02

Pedro Gil


1 Answers

Since there is no containsLocation in FusionTablesLayer, and since no mouseevents but click is supported (that would have made it a lot easier) - there is no other way round than to check if there is being dragged outside the area itself, Mozambique - not into the FusionTablesLayer. The solution is to create an invisible polygon for Mozambique, and use that polygon to check for containsLocation when dragging is finished.

The polygon can be based on the KML from the row you are excluding, MZ. That can be done using google.visualization.Query.

1) include the Google API loader in your project :

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

2) initialize Visualization :

google.load('visualization', '1.0');

3) define a variable for the polygon holding the Mozambique borders :

var mozambique;

The following is a function that loads the geometry data for Mozambique, and then creates an invisible polygon on the map; google.visualization.Query is used instead of the automated FusionTablesLayer so we can extract the <coordinates> from the KML and use them as base for the polygon.

In basic, this is how to convert KML-data from a FusionTable to a polygon :

function initMozambique(map) {
    //init the query string, select mozambique borders
    var sql = encodeURIComponent("SELECT 'geometry' FROM 1N2LBk4JHwWpOY4d9fobIn27lfnZ5MDy-NoqqRpk WHERE ISO_2DIGIT ='MZ'");
    var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + sql);
    query.send(function (response) {
        var data = response.getDataTable().getValue(0, 0);
        //create a XML parser
        if (window.DOMParser) {
            var parser = new DOMParser();
            var kml = parser.parseFromString(data, "text/xml");
        } else { // Internet Explorer 
            var kml = new ActiveXObject("Microsoft.XMLDOM");
            kml.loadXML(data);
        }
        //get the coordinates of Mozambique
        var latLngs = kml.getElementsByTagName("coordinates")[0].childNodes[0].nodeValue.split(' ');
        //create an array of LatLngs
        var mzLatLngs = [];
        for (var i = 0; i < latLngs.length; i++) {
            var latLng = latLngs[i].split(',');
            //<coordinates> for this FusionTable comes in lng,lat format
            mzLatLngs.push(new google.maps.LatLng(latLng[1], latLng[0]));
        }
        //initialize the mozambique polygon
        mozambique = new google.maps.Polygon({
            paths: mzLatLngs,
            fillColor: 'transparent',
            strokeColor : 'transparent',
            map: map
        });
        //make the mozambique polygon "transparent" for clicks (pass clicks to map)
        google.maps.event.addListener(mozambique, 'click', function(event) {
            google.maps.event.trigger(map, 'click', event);
        });
    });
}

Call the above initMozambique function in your second gmap().bind('init'... :

$('#map_canvas').gmap().bind('init', function(event, map) {
   initMozambique(map);
   ...

Now you can check the mozambique-polygon for containsLocation after dragging

...
}).dragend(function(event) {
  if (!google.maps.geometry.poly.containsLocation(event.latLng, mozambique)) {
     alert('You are not allowed to drag the marker outside Mozambique');
  }
  //I need to check if the marker is over the FusionTablesLayer and block the drag.
  //var test = google.maps.geometry.poly.containsLocation(event.latLng, world_geometry);
}).click(function() {
})
...

See forked fiddle, working demo with the code above -> http://jsfiddle.net/yb5t6cw6/

Tested in Chrome, FF and IE, ubuntu and windows.

like image 82
davidkonrad Avatar answered Oct 04 '22 15:10

davidkonrad