Panoramio Data API Returns blank JSON response - panoramio

Panoramio Data API:
I'm trying to access the photos from New Zealand through the following request of
http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=10&minx=-33.541395&miny=167.380829&maxx=-46.498392&maxy=179.817352
The above URL always returns an empty content as mentioned below:
{"count":271,"has_more":false,"photos":[]}
But, the request with a different co-ordinates works fine as mentioned below.
http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=10&minx=-124.29382324218749&miny=36.089060460282006&maxx=-119.8773193359375&maxy=38.724090458956965
Can any one let me know, what is the problem and how this can be rectified, is the API restricted to any specific country?
Thanks in advance!

The url in your example is right but the coordinates are in the middle of pacific ocean where there is no images by panoramio.
You can test it here
http://www.panoramio.com/map/#lt=-33.541395&ln=167.380829&z=8&k=2&a=1&tab=1&pl=all
One can also use this fiddle to test your panoramio requests
http://jsfiddle.net/qb0tyyjk/2/
new Request.JSONP({
url: 'http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=10&minx=-124.29382324218749&miny=36.089060460282006&maxx=-119.8773193359375&maxy=38.724090458956965',
data: {},
onSuccess: function(response) {
show_response(response, $('post'));
}
}).send();
show_response = function(obj, result) {
$H(obj).each(function(v, k) {
new Element('li', {
text: k + ': ' + JSON.stringify(v, null, 4)
}).inject(result);
});
result.highlight();
};

Natural feel says that minx, maxx are latitude and miny, maxy are longitude but the api seems to expect minx, maxx as longitude and miny, maxy as latitude. So, try swapping those values; meaning try to hit the below url
http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=10&minx=167.380829&miny=-46.498392&maxx=179.817352&maxy=-33.541395

Related

Esri-Leaflet - Search within a distance

I need to design an application using a feature layer stored in ArcGIS online. Using a geocoder/search, I need to be able to enter an address and select a distance (1 block, 2 blocks, etc). The result will show the new point, a distance radius, and all points within the radius. I would also like to have a table of the results.
What I need is exactly like this app created by Derek Eder from DataMade: https://carto-template.netlify.app/, except mine needs the data stored in a secured ArcGIS layer. Can anyone point me to an example, tutorial, etc with an esri-leaflet implementation similar to this application? I have spent the past five days trying to convert the code, and I feel like I am getting no where.
Here is a link to guthub: https://github.com/datamade/searchable-map-template-carto
-------UPDATE-------
Seth - I can get the layer to display; however, the query to join the searched point with the layer does not work. I imagine I’m leaving something out, because the console error reads “token required”. See below:
const radius = 1610;
/**************************************************************************************************/
// ArcGIS Authoization
/**************************************************************************************************/
$("#loginModal").modal({ backdrop: 'static', keyboard: false });
// submit element of form
var submitBtn = document.getElementById('btnArcGISOnline');
// add event listener to form
submitBtn.addEventListener('click', addServicesFromServer);
// create map and set zoom level and center coordinates
var map = L.map('mapCanvas', {
}).setView([30.46258, -91.13171], 12);
// set basemap to Esri Streets
L.esri.basemapLayer('Streets').addTo(map);
var layerurl = 'secure/layer/URL';
var tokenUrl = 'https://www.arcgis.com/sharing/generateToken';
// function to make request to server
function serverAuth(server, username, password, callback) {
L.esri.post(server, {
username: username,
password: password,
f: 'json',
expiration: 86400,
client: 'referer',
referer: window.location.origin
}, callback);
}
// function to run when form submitted
function addServicesFromServer(e) {
// prevent page from refreshing
e.preventDefault();
// get values from form
var username = document.getElementById('username').value;
var password = document.getElementById('password').value;
// generate token from server and add service from callback function
serverAuth(tokenUrl, username, password, function (error, response) {
if (error) {
return;
}
// add layer to map
var featureLayer = L.esri.featureLayer({
url: layerurl,
opacity: 1,
token: response.token
});
featureLayer.addTo(map);
$("#loginModal").modal("hide");
}); // end serverAuth call
} // end addServicesFromServer call
// HARNESS GEOCODER RESULTS
let circle;
// GeoSearch
const search = L.esri.Geocoding.geosearch({
useMapBounds: false,
expanded: true,
collapseAfterResult: false
});
search.addTo(map);
search.on("results", (results) => {
if (results && results.latlng) {
if (circle) {
circle.remove();
}
circle = L.circle(results.latlng, { radius });
circle.addTo(map);
queryLayer(results.latlng);
}
});
// SET UP QUERY FUNCTION
function queryLayer(point) {
const query = L.esri.query({ url: layerurl }).nearby(point, radius);
query.run(function (error, featureCollection, response) {
if (error) {
console.log(error);
return;
}
console.log(featureCollection.features);
populateList(featureCollection.features);
});
}
// WRITE RESULTS INTO A LIST
function populateList(features) {
const list = document.getElementById("results-list");
let listItems = "";
features.forEach((feature) => {
listItems =
listItems +
`
<li>
Place: ${feature.properties?.Location} <br>
Lat: ${feature.properties?.Latitude} <br>
Lng: ${feature.properties?.Longitude} <br>
</li>
`;
list.innerHTML = listItems;
});
}
I attempted to pass the token to the query as pasted below, but then I get an invalid token error.
var layerUrl_token = layerurl + "?token=" + response.token;
I also tried using turf.js, but I haven’t been successful. I know turf.js uses long/lat, but I haven’t even been able to get the correct syntax to pull the lat and long from the feature layer.
What you're trying to do is not too hard. While there are a handful of tutorials on different parts of what you want to do, let's piece things together. I'm going to use esri-leaflet-geocoder for my search functionality, as its consistent with esri-leaflet, and IMO its one of the best geocoders available for leaflet.
Setting up the geocoder
After setting up a basic leaflet map, let's import esri-leaflet and esri-leaflet-geocoder, and create a geocoder:
import L from "leaflet";
import * as EL from "esri-leaflet";
import * as ELG from "esri-leaflet-geocoder";
const search = ELG.geosearch({
useMapBounds: false,
expanded: true,
collapseAfterResult: false
});
search.addTo(map);
Don't forget to add the geocoder css to your html, as shown in the documentation example.
Add your layer:
const layerurl = "YOUR_LAYER_URL";
const featureLayer = EL.featureLayer({ url: layerurl });
featureLayer.addTo(map);
If you are using an authenication-required layer, you will need to get a token and use it as one of the options in featurelayer, (featureLayer({ url: layerurl, token: token })). If you're not sure how to get a token, make a comment and I can add some code for that, but there are some nice tutorials already available for that.
Harness the results of the search
The ELG.geosearch comes with a results event that you can harness. It is called when the user selects one of the results in the autocomplete dropdown of the geosearch. In that event, we can get the location data of location the user selected. We center the map there (which is a default of the geosearch actually), draw a circle with a given radius, and perform a query (more on that layer):
let circle;
search.on("results", (results) => {
if (results && results.latlng) {
if (circle) {
circle.remove();
}
circle = L.circle(results.latlng, { radius });
circle.addTo(map);
queryLayer(results.latlng);
}
});
Query the layer
Now we know the latlng of the location the user selected from the search. We can create an esri-leaflet query, which can query your feature layer in various ways. We'll see up a nearby query, which will query the layer for any features within a given radius of a point:
function queryLayer(point) {
const query = EL.query({ url: layerurl }).nearby(point, radius);
query.run(function (error, featureCollection, response) {
if (error) {
console.log(error);
return;
}
populateList(featureCollection.features);
});
}
If you are querying an authenticated layer, you'll need to add a token to the request. I'm fairly certain the way to do this is like so:
function queryLayer(point) {
const query = EL.query({ url: layerurl })
.token(<your_token_here>)
.nearby(point, radius);
// ... same as above
}
You may also be able to run a query directly off of your layer:
featureLayer.query().nearby(point, radius)
I'm not as familiar with this second way, but you can read more about it here: Query a feature layer.
Render to the page
Once we .run the query, we will have access to the results in the form of a featureCollection. We can loop through the features of that featureCollection and render some HTML:
function populateList(features) {
const list = document.getElementById("results-list");
let listItems = "";
features.forEach((feature) => {
listItems =
listItems +
`
<li>
Place: ${feature.properties?.Location} <br>
Lat: ${feature.properties?.Latitude} <br>
Lng: ${feature.properties?.Longitude} <br>
</li>
`;
list.innerHTML = listItems;
});
}
In this particular example, I am using a point layer I made that is being served through arcgis online. This point layer does not have address data, so feature.properties doesn't contain any address info. For your featurelayer, the attributes of your layer will be available in a feature.properties. So depending on what's there, you might want to use feature.properties?.address or whatever. This last bit is just an example, you will probably customize that a lot differently for your own purposes.
Working Codesandbox
Try searching heavily populated areas in this example. Note that in this featurelayer there are many overlapping locations, so there are more results in the list than it looks like there are markers on the map.
Also note, this example I'm posting using esri-leaflet and esri-leaflet-geocoder versions 2^. These were just updated to versions 3 about 1-2 months ago, and the new versions require use of an API key in the geocoder and in the layer declaration, so if you want to use the latest versions (recommended), you will need to add those in. I used version 2 so as not to expose an API key in a sandbox (and I sort of hate the new API key requirement . The new arcgis developers documentation for esri-leaflet has some examples of that, but the official documentation has not yet been updated to match those examples.

Leaflet - custom tile layer - get lat long coordinates

My requirement is be able to call an api which returns me GeoJson - this api requires the bounding box in lat/long coordinates. I would like to be able to have this api called for each tile but am stuck trying to convert the L.Coords x,y,z values to bounds.
I would have thought this would be a common use case - is there another way I should be approaching this problem?
Code demonstrates my approach.
L.TileLayer.Custom = L.TileLayer.extend({
getTileUrl: (coords: L.Coords) => {
const bounds = coords?.getBounds();
const geometry = {
ymin: bounds?.getSouth(),
xmin: bounds?.getWest(),
ymax: bounds?.getNorth(),
xmax: bounds?.getEast()
};
// call api Api.call(geometry).then(...)
},
});
L.tileLayer.custom = function () {
return new L.TileLayer.Custom();
};
L.tileLayer.custom().addTo(map);

Fetching elevation of one point from MapQuest API in Leaflet

I am trying to get elevation of clicked location via fetching elevation values from MapQuest elevation profile API
https://developer.mapquest.com/documentation/open/elevation-api/elevation-profile/get/
But I can't find the parameter of getting elevation of only one point not for a route; I mean latLng not latLngCollection.
Here is my code:
var myLocation = e.latlng;
console.log(myLocation);
fetch('http://open.mapquestapi.com/elevation/v1/profile?key=tHXSNAGXRx6LAoBNdgjjLycOhGqJalg7&shapeFormat=raw&latLngCollection='+myLocation)
.then(r => r.json())
.then(data => {
var elevation = data;
console.log(data);
})
Is there is any way to get elevation for only one point?
A one location collection seems to be working as expected.
http://open.mapquestapi.com/elevation/v1/profile?shapeFormat=raw&key=KEY&latLngCollection=51.50631,%20-0.12714

Huge GIS data need to show on map using leaflet

I have a huge GIS data in db. I am fetching this data and converting it into geoJson file before viewing the map. I am fetching all of the data to meet the requirements, which is taking a lot of time. Is there any way to load data for a particular map window which user is viewing, and only loading respective GIS data for the same window using the leaflet library?
In my case, I am using Google Maps to show parking slots (GIS data) of a country on a map.
Yes, you need to write some piece of code to get only the specific data from server. See if below lines can help you
//whenever a drag or zoom finish, trigger the function to get new data
map.on('dragend', getData);//leaflet event
map.on('zoomend', getData);//leaflet event
function getData(){
//get the extent of your window
var minx = map.getBounds().getEast();
var miny = map.getBounds().getSouth();
var maxx = map.getBounds().getWest();
var maxy = map.getBounds().getNorth();
//trigger an ajax call to get data as per your extent
$.ajax({
url: 'url_like_a_php_service',
type: "get",
dataType: 'json',
async: false,
//send your extent to service to get specific data, like below
data: 'minx=' + minx + '&miny='+miny+ '&maxx='+maxx+ '&maxy='+maxy,
beforeSend: function () {
//you may write code here like showing a gif on map
},
complete: function (response) {
//pass data to another function to render on map
renderDataonMap();
}
});
}

Google Maps API v3 marker setPosition not working in Safari (sencha touch)

I am using Sencha Touch to develop a mobile version of a Bus Tracker for Boston University. The problem I a running into is that the method setPosition() for a google.maps.Marker is not rendering the position change in Safari or any Mobile browser.
The code set up is as follows:
I initialize an empty markers array
I initialize the map using Ext.Map() (sencha call)
I load data using a JSONP request every 5 seconds interval
Every time I get new data, I check if I have a marker for that bus id inside my markers array
If I don't I create a new marker and push it into my markers array
Otherwise I call setPosition with my new position on that marker in my markers array.
I then run a check to make sure the marker's position got updated to the position received from my JSON request
I have verified (I think) that the marker inside the markers array is getting the new position everytime. Also, in Chrome and Firefox, my buses move (as expected), but in safari and iPhone/Android browsers, nothing moves.
Here is the code snippet:
var markers = {};
var busesFunc = function()
{
Ext.util.JSONP.request({
url: 'http://m.cms-devl.bu.edu/rpc/bus/livebus.json.php',
callbackKey: 'callback',
params: {
},
callback: function(data) {
buses = data.ResultSet.Result;
for (var i = 0, ln = buses.length; i < ln; i++) {
var bus = buses[i];
var position = new google.maps.LatLng(bus.lat, bus.lng);
if(!markers[bus.id])
{
markers[bus.id] = new google.maps.Marker({
map: map.map,
title: 'hello',
clickable: true,
draggable: false,
position: position,
icon: "images/bg.png",
zIndex: 100
});
}
markers[bus.id].setPosition(position);
//markers[bus.id].setIcon("images/bg.png");
//markers[bus.id].setMap(map.map);
//markers[bus.id].setMap(map.map);
if(bus.lat != markers[bus.id].position.lat() || bus.lng != markers[bus.id].position.lng())
{
console.log(bus.id + " " + bus.lat + " " + bus.lng);
console.log(bus.id + " " + markers[bus.id].position.lat() + " " + markers[bus.id].position.lng());
}
}
}
});
}
setInterval(busesFunc, 5000);
You can view the sample here: http://www.bu.edu/nisdev/students/luiscarr/liveBusMobile/
And the whole javascript is called functions.js (I can't post more than one link)
[Sencha Person] markers not showing up is a known bug in the 0.93 beta release. The 0.94 release (current one) has this fixed.
Problem solved by making a unique request every interval. I figured it was a caching problem after some more debugging. So I added a timestamp parameter to the JSONP request and it was all fixed.