I'm using the Google maps API to allow users to set a location by clicking on a map. Wherever the user clicks, the marker is placed and it works quite well. My problem is, my users are adding duplicate locations to my application despite the fact that they can visually see there's already a marker at that location (I'm loading markers for existing locations from my database).
Is there a way, within the Google Maps API, to fire an event if a marker is placed within X distance of a marker already on the map? I know I could probably use the haversine algorithm in javascript in some way, but I'd like to avoid that kind of complexity on the client side if I can.
Another approach, which doesn't require any further calculating of distances or similar:
For every marker placed on the map also create a circle at the same position.
Hide the circle by setting fillOpacity and strokeOpacity to 0 and apply a radius that fit's your needs.
Result: the circle is not visible, but still exists. The map will not respond to click-events when the user clicks on the hidden circle.
Please try this method.. this may be require some modification based on your need, this will be client side but the logic can be implemented server side also.
function CheckIFMarkersAreNearBy(preExistingMarkersArray, milesToCheck, lat, lon){
var range = milesToCheck/70;
var minLat = lat - range;
var maxLat = lat + range;
var minLon = lon - range;
var maxLon = lon + range;
var markersNearBy = 0;
for( var i = 0; i < preExistingMarkersArray.length; i++){
if(preExistingMarkersArray[i].lat > minLat && preExistingMarkersArray[i].lat < maxLat && preExistingMarkersArray[i].lon > minLon && preExistingMarkersArray[i].lon < maxLon){
markersNearBy++;
}
}
alert('you have ' + markersNearBy + 'markers near by you current selection');
}
I don't think there is specific function for that. The closest thing you will find is going to be google.maps.geometry.spherical which includes a function to computeDistanceBetween(from:LatLng, to:LatLng, radius?:number)
So before you drop a new marker on your map just get the distance between your current markers and the newly requested one. Keep in mind, that even if Google Maps API provided way to do it, it would still be on the client side, so you would not be avoiding the "complexity on the client side" anyways.
Related
In Bing Maps v7 I was able to add pushpins to an entityCollection and then loop through that collection later in the code to set options or whatever. Now, I am having trouble getting pins from the v8 layers.
Here is what I used to do in v7 after I had already added the pin to the entityCollection:
for (var i = 0; i < entityCollection.getLength() ; i++) {
var pin = entityCollection.get(i);
pin.setOptions({ visible: true });
}
I have changed the object entityCollection to a layer for v8 and I am also looping through the layer while i < entityCollection.data.length
Now, in Bing Maps v8, I'm having trouble getting the pin object from the layer that I have already added it to. The code above throws an error on the setOptions line and I have also tried getting the pin with:
entityCollection.data[i]
instead of
entityCollection.get(i)
But that doesn't work either. I'm afraid my question is too generic, because I can't find anything that actually answers my question. I have a work around, but that causes failures later when I want to hide all the pins with certain attributes. Thanks in advance!
Bing Maps v8 has done away with the entityCollection - though they say it's still sort of supported, you obviously don't want to be using deprecated things any more.
Anywhere you have an entityCollection, replace it with a Layer (Microsoft.Maps.Layer). Layers expose the getPrimitives() method which will provide you with an array of the contents.
var map = new Microsoft.Maps.Map(..., ...);
var layer = new Microsoft.Maps.Layer();
// Add layer data...
layer.add(new Microsoft.Maps.Pushpin(...));
// Add layer to map
map.layers.insert(layer);
// Then you can iterate
var layerItems = layer.getPrimitives();
var len = layerItems.length;
for(var i = 0; i < len; i++){
var pin = layerItems[i];
// Do something with your pin
pin.setOptions({visible: false});
}
Note that if you're doing mass updates to the entire contents of the layer, such as showing or hiding every pin in the layer, you can do that directly on the layer. This will save you (the browser) a chunk of work setting each pin individually.
layer.setVisible(true);
Yes, in V8 layers have a getPrimitives function which returns an array containing all the shapes. You can then loop through these shapes like you would any other array.
I'm building a NativeScript app using the nativescript-google-maps-sdk.
I have added an eventlistener for the coordinateTapped event and now that it is working I want to plot a marker on the map at the position at which I tap.
I cannot find an example of this online or in the sdk documentation.
I feel I am very close and just have a few minor corrections to make.
var mapsModule = require("nativescript-google-maps-sdk");
function onCoordinateTapped(args) {
console.log("coordinate tapped!");
var mapView = args.object;
var marker = new mapsModule.Marker();
marker.position = mapsModule.Position.positionFromLatLng(args.latitude,args.longitude);
mapView.addMarker(marker);
}
Note: I've labelled this question with the google-maps tag as there is no nativescript-google-maps tag.
Never it's too late to answer this kind of questions.
The problem was that the args object doesn't have a latitude nor a longitude attribute, so you are trying to add a marker with latitude and longitude as undefined.
Inside your function onCoordinateTapped(args) you can access to two different positions.
First, args.object.latitude and args.object.longitude.
var lat = args.object.latitude;
var lng = args.object.longitude;
Those attributes stand for the current position of the map (you know, the center of it).
Second, args.position.latitude and args.position.longitude.
var lat = args.position.latitude;
var lng = args.position.longitude;
In this case, those attributes represents the actual position of your tap on the map.
Also, this works on coordinateLongPress.
Hey #Danoram you code looks'n'feels right and although there is no XML file I guess you have used the coordinateEvent to pass the fallback function onCoordinateTapped like here
<maps:mapView coordinateTapped="onCoordinateTapped" />
Is that working out for you or are you experiencing some kind of error/unexpected behaviour? It is not entirely clear from your post where the issue is...
Geofencing - I am beginner in OS MAPS.We are planning to develop user defined fence,when user click on points of his own choice on map then it should join with a line and finally coming to last point loop should be closed.
To achieve that we have used Vector layer to draw the polygon.Now after finishing the polygon.
a)How could we get the co-ordinates(lat,long) values of the drawn polygon.
b)Also how can I load from the database and draw the same fence with the saved co-ordinates.
Could anyone suggest some solutions for the above.
A partial answer, actually, I think you should split the b) part to another question since it raises many questions out of Openlayers scope, like: PHP, Database. So a) part:
draw.on('drawend', function(evt){
var feature = evt.feature;
var geom = feature.getGeometry();
var coords = geom.getCoordinates();
console.info(coords);
if(geom instanceof ol.geom.Polygon){
coords[0].forEach(function(each){
var formated = ol.coordinate.toStringXY(each, 2);
//just to visualize
element_coords.innerHTML += formated + '<br>';
});
}
});
Your Fiddle updated.
NO, THE ABOVE ANSWERS DON'T ANSWER MY QUESTION. PLEASE READ MY UPDATE BELOW TO SEE THE CLARIFICATION WHY THIS IS A DIFFERENT CASE!!!
I'm using Google maps API V3. When I write this code:
map.fitBounds(map.getBounds());
the map zooms out!
I understand that it's according to the documentation since fitBounds ensures to show the given bounds on the map so that all the edges are shown inside the map. Therefore, the answer I'm looking for lies into the following:
How to modify the result of getBounds to be used for fitBounds without zoom effect afterwards?
Basically, I'm quite sure this can be calculated because that's what the map does, but in the opposite direction, when adding margins, to show the given bounds completely. In these terms, tell me how to calculate the margins (and therefore, how to calculate the correct input for fitBounds having output from getBounds) and your answer will be accepted.
Thanks in advance!
Update:
Zoom and Center retrieval and setting does not work for me! here's the reason why:
I am going to hold the map's viewport information in the database. Later on, I want to re-create the map and show the exact same location again. However, the mapping platform can differ from user to user. Therefore, zoom and center is not standard between different mapping platforms/frameworks and cannot be used in all them with the same results. Therefore, the only standard way is to hold the bounds in the database. So the question needs an answer exactly in the direction it is asking for.
Store instead of the bounds the zoom and center of the map and restore these values later.
I had the exact same problem and decided to shrink the bounding box resulting from getBounds() with 15%. That does the job nicely for me:
var neLat = map.getBounds().getNorthEast().k;
var neLong = map.getBounds().getNorthEast().B;
var swLat = map.getBounds().getSouthWest().k;
var swLong = map.getBounds().getSouthWest().B;
var boundingBoxPerc = 0.15;
var mapWidth = neLong - swLong;
var mapHeight = neLat - swLat;
var ne = new google.maps.LatLng(neLat - mapHeight * boundingBoxPerc, neLong - mapWidth * boundingBoxPerc);
var sw = new google.maps.LatLng(swLat + mapHeight * boundingBoxPerc, swLong + mapWidth * boundingBoxPerc);
map.fitBounds(new google.maps.LatLngBounds(sw, ne));
I have markers dotted around a map, and a radius (circle overlay) on a marker marking your location (which changes every time you move).
Is there any way I can check to see if the other markers come inside the circle?
UPDATE
I got around this by looping through each other marker, and using the geometry library calculating the distance between your marker and the other marker and then a simple if statement to see if it's less than 100 meters.
function checkAllChests() {
var Current = 0;
$.each(treasureArray, function() {
//var thisLocation = treasureArray[Current].getPosition();
var distanceBetween = Math.ceil(google.maps.geometry.spherical.computeDistanceBetween(treasureArray[Current].getPosition(), marker_me.getPosition()));
if(distanceBetween < 100) {
alert('CAN OPEN THIS CHEST');
}
Current++;
});
}
I'd like to note that the above code uses jQuery, so if you aren't using jQuery it won't work.
Here's a way to add a contains method to the google.maps.Circle class. It first uses the bounding box to exclude a point if it's not even in the bounding box. If it is in the bounding box, then it compares the distance from the point to the center with the radius, and returns true only if the distance is shorter than the radius.
Once you add the javascript below, you can call the contains() method on your circle object.
google.maps.Circle.prototype.contains = function(latLng) {
return this.getBounds().contains(latLng) && google.maps.geometry.spherical.computeDistanceBetween(this.getCenter(), latLng) <= this.getRadius();
}