How to get addresses (geocoding informations) from polygon in maps? - maps

I was looking for a way to retrive all the addresses inside a polygon in a map (google map?). I saw in this post that someone said that is not possible..
I ask this: if is possible to retrive the address from a point on the map, why is not possible to do the same in a polygon? Can't you just: - set an hypoteticl grid in the area of the polygon - for every intersection point of the grid retrive the location address - store the address (if is already stored delete it).
Wouln't this method be workable? thanks Francesco

Looking around I'm almost find a way to do that, merging up various methods.. I'm new in js, so my code is probably full of dumb stuff..
Anyway, I reached a point where I managed to retrive my unique addresses into an array, but can't complete the job beacuse I always get the error of OVER_QUERY_LIMIT, beacuse I send too many requests as explainedin this page
So I think there is no way to do this, unless you want to spend a lot in buying the billing to unlock higher quotas, and this will be a very hard hit beacuse a method like this will require thousands of request each call.
Anyway, this is the code, inserted into the one found here , wich I got from Polygon Drawing and Getting Coordinates with Google Map API v3
Sorry again for the various newbie stuff you will find in it.
var arrAddress=[]; //global
var arrCoord=[]; //global
function selPoly(shape) { //after create polygon do the job
var latlngStr=[];
var lat,lng;
var polCoords = [];
posstr = "" + selectedShape.position;
if (typeof selectedShape.position == 'object') {
posstr = selectedShape.position.toUrlValue();
}
if (typeof selectedShape.getPath == 'function') {
var mycoord="";
var partlng, partlng;
for (var i = 0; i < selectedShape.getPath().getLength(); i++) {
// .toUrlValue(5) limits number of decimals, default is 6 but can do more
mycoord=selectedShape.getPath().getAt(i).toUrlValue();
latlngStr = mycoord.split(',');
//create array with polygon path
polCoords.push(new google.maps.LatLng(latlngStr[0] , latlngStr[1]));
//add 0s to lat
lat=latlngStr[0];
partlat = latlngStr[0].substring(latlngStr[0].indexOf(".") + 1);
switch(partlat.length) {
case 4:
lat =lat +"00";
break;
case 5:
lat =lat +"0";
break;
}
//add 0s to lng
lng=latlngStr[1];
partlng = latlngStr[1].substring(latlngStr[1].indexOf(".") + 1);
switch(partlng.length) {
case 4:
lng =lng +"00";
break;
case 5:
lng =lng +"0";
break;
}
arrCoord.push(lat+","+lng);
}
};
//find higher and lower lat and lng in the polygon, converting lan e lng to number
var maxlat=0, maxlng=0;minlat=99999999,minlng=9999999;
var latlngStr=[];
for(var i=0;i<arrCoord.length;i++) {
latlngStr = arrCoord[i].split(',');
console.log(latlngStr);
lat = parseInt(latlngStr[0].replace(".", ""));
console.log(lat);
lng = parseInt(latlngStr[1].replace(".", ""));
if (lat>maxlat){
maxlat=lat;
};
if (lng>maxlng){
maxlng=lng;
};
if (lat<minlat){
minlat=lat;
};
if (lng<maxlng){
minlng=lng;
};
};
//create new polygon with that path
var polygon = new google.maps.Polygon({
paths: polCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
//move from (minlan,minlng) every 100 horizontal until reach maxlan, then add 200 to lng and star again.
var coordinate;
var newlat="",newlng="";
for (var i=minlat;i<maxlat;i+=100){
for (var j=minlng;j<maxlng;j+=200){
//reconvert lat e lng from number to string
newlat=i.toString();
newlng=j.toString();
newlat=newlat.substring(0,newlat.length-6) + "." +newlat.substring(newlat.length-6,6);
newlng=newlng.substring(0,newlng.length-6) + "." +newlng.substring(newlng.length-6,6);
coordinate=newlat +"," + newlng;
//for every point find out if is inside the polygon
var isWithinPolygon = polygon.containsLatLng(parseFloat(newlat),parseFloat(newlng));
if(isWithinPolygon){
newgeocodeLatLng(function(addr){
if (arrAddress.length==0){arrAddress.push(addr);} else{
for (var i =0; i<arrAddress.length;i++){
var ok=0;
///if address (retrive only the street name) found from point is already in the array, don't put in it. i'm sure there is a better ay to do it....
if (arrAddress[i].split(',')[0]==addr.split(',')[0]){
ok=1;};
};
if(ok==0){arrAddress.push(addr);
};
};
},coordinate); //end newgeocodelatlng
}; //end if iswithpolygon
};//end for j
};//end for i
};
function newgeocodeLatLng(callback,mycoord) {
var address;
var latlngStr = mycoord.split(',');
getReverseGeocodingData(function(addr){
address=addr;
callback(address);
// console.log("address4=" + address);
},latlngStr[0], latlngStr[1]);
};
function getReverseGeocodingData(callback,lat, lng) {
var address="";
var latlng = new google.maps.LatLng(lat, lng);
// This is making the Geocode request
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status !== google.maps.GeocoderStatus.OK) {
alert(status);
}
// This is checking to see if the Geoeode Status is OK before proceeding
if (status == google.maps.GeocoderStatus.OK) {
callback(results[0].formatted_address);
}
});
}

Related

How to compare current user Latitude and Longitude with other user Latitude and Longitude

I am a bit of loss on how to compare current user's lat and lng with other user lat and lng. I have tried the following. I want all user key who's lat and lng who is nearby the current user lat and lng. I have tried the following.
Here's my code:
openMapPage()
{
// GETTING THE CURRENT USER ADDRESS FOR LATITUDE AND LONGTITUDE
var uid = firebase.auth().currentUser.uid;
var ref = firebase.database().ref("request/" + uid);
ref.once("value").then((snapshot) => { // <------ Here!
var a = snapshot.exists(); // true
var c = snapshot.hasChild("reqdetails"); // true
var d = snapshot.child('reqdetails').exists();
var requestsKey = snapshot.key;
var requestsValue = snapshot.val();
ref.once('value', (request) => {
var currentUserAddress = request.val().regdetails.address;
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': currentUserAddress}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var latlng = new LatLng(latitude, longitude);
//var userAddress = new LatLng(currentUserAddress);
console.log("SURESH IS COOL");
console.log(latlng);
}
});
});
// GETTING THE ALL USER ADDRESS FOR LATITUDE AND LONGTITUDE
var ref1 = firebase.database().ref("request");
ref1.once("value").then((snapshot1) => { // <------ Here!
var a = snapshot1.exists(); // true
var c = snapshot1.hasChild("reqdetails"); // true
var d = snapshot1.child('reqdetails').exists();
var requestsKey = snapshot1.key;
var requestsValue = snapshot1.val();
snapshot1.forEach((childSnapshot) => { // <------ And here!
var requestKey = childSnapshot.key;
var requestValue = childSnapshot.val();
var reqdetails = requestValue.reqdetails;
var AllUserAddress = requestValue.regdetails.address;
//console.log("ALL USER ADDRESS");
//console.log(AllUserAddress);
var geocoder1 = new google.maps.Geocoder();
geocoder1.geocode( { 'address': AllUserAddress}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var latlng1 = new LatLng(latitude, longitude);
//var userAddress = new LatLng(currentUserAddress);
//console.log("SURESH IS COOL");
//console.log(latlng1);
var distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween (this.latlng, this.latlng1);
if(distanceInMeters)
{
console.log("NEARBY ADDRESS that is near current user address");
console.log(latlng1);
}
}
});
});
});
//END OF CURRENT USER
});
}
As you specifically see at this part i tried to compare the current user lat and lng with other user lat and lng. Using the if statement but nothing shows up in the console.
var distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween (this.latlng, this.latlng1);
if(distanceInMeters)
{
console.log("NEARBY ADDRESS that is near current user address");
console.log(latlng1);
}
Since you are using google maps, use the following:
var distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween (latlng, latlng1);
if( distanceInMeters < meterLimit ) //decide some threshold value for 'nearby' places.
{
console.log("NEARBY ADDRESS that is near current user address");
console.log( distanceInMeters );
}
For using the above, you need to append '&libraries=geometry' to your google map script tag's src value.
You can specify multiple libraries as a comma-separated list.
Edit:
If your priority is to show the nearest address, rather than nearby addresses, you should calculate all distances (in a loop), store them in an array, sort these into another array. Now compare the two to find out which element/address corresponds to lowest distance.

Ionic google map shows only first time a view is loaded

My ionic app gets some places from the database and generates a map from this data.
$scope.$on('$ionicView.beforeEnter', function(){
// get event data
Events.getEvent($stateParams.eventId).then(function(data){
$scope.eventInfo = data[0];
$ionicLoading.hide();
// get location data
if(data[0].location){
Locations.getLocation(data[0].location).then(function(data){
$scope.location = data[0];
// call the map
$scope.initialize($scope.location.locstreet, $scope.location.zip, $scope.location.ort);
});
}
});
After retrieving the data, the script calls the initialize function:
function initialize(strasse, plz, ort) {
var map = new google.maps.Map(document.getElementById('map'),{
zoom: 14
});
img = new google.maps.MarkerImage("img/icon.png", null, null, null, new google.maps.Size(30,30));
var geocoder = new google.maps.Geocoder();
var address = strasse + ", " + plz + " " + ort;
geocoder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
icon: img
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
This works great the first time I´m navigating to this view. If I leave the view and come back to the same view with other data, the map just shows grey with the google logo right bottom.
I think that this could happen because of the multiple intializing var map. But if I declare var map outside of the funktion it doesn´t work either.
Add this : cache: false to your state provider (when you defined your map).
This worked for me.

GeoFire geoQuery returning data

I'm newbie with Firebase + GeoFire and I'm having trouble with geoFire query function.
I want to add in an array the results from geoQuery function and return it in a function. But the data I have manipulating inside geoQuery.on method seems out of scope or not available or due to promises, I dont know... the fact is outside the geoquery.on method the variable sellers is empty.
How can I return results from geoQuery and save it into a return variable
//Set seller position in firebase db
var setPosition = function() {
navigator.geolocation.getCurrentPosition(setPositionSuccess, error, options);
//navigator.geolocation.watchPosition(setPositionSuccess, positionError, { enableHighAccuracy:true })
};
//Get sellers near buyer position
var getSellersForCurrentPosition = function() {
navigator.geolocation.getCurrentPosition(getPositionSuccess, error, options);
//navigator.geolocation.watchPosition(positionSuccess, positionError, { enableHighAccuracy:true })
};
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var sellers = [];
var oneSeller = {};
var onKeyEnteredRegistration = geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
sellers.push(oneSeller);
});
var onReadyRegistration = geoQuery.on("ready", function() {
geoQuery.cancel();
});
return sellers;
}
By the way, how accurate is html5 geolocation? Is it different between desktop browser and mobile browser?
Geofire monitors the sellers in the range you indicate. Any time a seller enters/exits the range, it fires a key_entered or key_exited event. These events can happen at any time after you start the query. In JavaScript terms this is often described as: the callbacks happen asynchronously.
A simple event flow, might explain what happens best:
you call getPositionSuccess()
you start a Geoquery to monitor the sellers that are in range: geoFire.query()
no sellers are immediately in range, so your callback doesn't fire
the getPositionSuccess() function is done and exits
a seller comes in range
GeoFire fires the key_entered event and your callback runs
but getPositionSuccess() has already exited, so how can it return a value?
Even if you were to wait for the first seller to come into range before returning (not possible in a browser, but it is possible in other languages/environments), how will you return the value when a second seller comes in range?
For this reason, you have to deal with asynchronous data differently. Typically you do this by moving the code that would call the getPositionSuccess() function into the function.
Say you are now trying to do this:
var sellers = getPositionSuccess(pos);
sellers.forEach(function(seller) {
addSellerToMap(seller);
});
To handle the asynchronous nature of the events, you'd move this code into getPositionSuccess:
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var oneSeller = {};
geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
addSellerToMap(oneSeller);
});
}
I understand that in your use-case your sellers won't move, so it may be more intuitive to think of them as a static list. But even in this case, the results are loaded from a remote database and it will take some time before that data is loaded. The modern web loads data asynchronously and all your code will have to deal with it in a way similar to what I outlined above.

AngularJS & Google Map API V3 remove marker from map

I'm rattling my brains here and cannot figure out why this is not working
var lat = Math.round(top_location.geometry.location.lat() * 1000000)/1000000;
var lng = Math.round(top_location.geometry.location.lng() * 1000000)/1000000;
geocode_results[i]['lat'] = lat;
geocode_results[i]['lng'] = lng;
geocode_results[i]['l_type'] = top_location.geometry.location_type;
marker = new google.maps.Marker({
icon: mapIcon,
position: new google.maps.LatLng(lat,lng),
map: map
});
markersArray.push(top_location.address_components[0].long_name);
Using the above created my marker(s) and plots them on my map.
Using the following code to remove the markers from the map
$scope.removemarkers = function() {
console.log($scope);
console.log(markersArray);
if (markersArray && markersArray.length) {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
markersArray = [];
}
};
I get the following error in console.log()
TypeError: Object AB42 2DL has no method 'setMap'at
Object.$scope.removemarkers
AB42 2DL being a random postcode used when plotting a marker
markersArray doesn't contain markers, it contains strings.
Try this:
markersArray.push(marker);

Openlayers: markers disappear when zoomming

I'm new with Openlayers, so not sure what is wrong. I can add markers when I change a select drop down and when I click the map. The issue comes when I zoom the map, the markers disappear.
I realised that markers don't disappear, they just move to another place, to the point 0,0.
This is the code
(function($) {
$().ready(function() {
var ZOOM_LEVEL_PROVINCE = 12;
var projection = new OpenLayers.Projection("EPSG:4326");
var map;
var markerLayer;
var initMap = function() {
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.ScaleLine({geodesic: true}),
new OpenLayers.Control.Permalink('permalink'),
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.Attribution()],
//maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0339,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:4326"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
layer = new OpenLayers.Layer.OSM("Simple OSM Map");
map.addLayer(layer);
var point = getLonLatProvince('san-jose');
map.setCenter(point.transform(projection, map.getProjectionObject()), ZOOM_LEVEL_PROVINCE);
}
var initMakerLayer = function(){
markerLayer = new OpenLayers.Layer.Markers( "MarkerLayer" );
markerLayer.id = "MarkerLayer";
map.addLayer(markerLayer);
}
var showMarker = function( province ){
var point = getLonLatProvince(province);
var location = point.transform(projection, map.getProjectionObject());
showMarkerPosition(location);
}
var showMarkerPosition = function( location ){
markerLayer.clearMarkers();
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png',size,offset);
markerLayer.addMarker(new OpenLayers.Marker(location,icon.clone()));
var newPoint = location.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
$("#edit-plonlat").val( newPoint );
}
var getLonLatProvince = function( province ){
...
}
initMap();
initMakerLayer();
showMarker('san-jose');
map.events.register("click", map, function(e) {
var location = map.getLonLatFromPixel(e.xy);
showMarkerPosition(location);
});
$('#edit-pprovinces').change(function() {
var selectedPronvince = $(this).val();
var point = getLonLatProvince(selectedPronvince);
showMarker(selectedPronvince);
map.setCenter(point.transform(projection, map.getProjectionObject()), ZOOM_LEVEL_PROVINCE);
});
});
})(jQuery);
I think your call to map.getLonLatFromPixel(e.xh) is getting a location in WGS84 (EPSG:4326) since that is the projection of the map. Then you call showMarkerPosition in your "click" handler. In showMarkerPosition you transform that location from the Google to WGS84 projection, which would change a large lat/lon in meters to a much smaller lat/lon in degrees.
If you've started out with degrees for that meters-to-degrees transform, then I think you'll end up with a lat/lon that's very close to 0,0 off the West coast of Africa.
A projection transform issue is where I always start looking when I see 0,0 lat/lon's.

Resources