Closed nicolas-raoul closed 5 months ago
Interesting, so we have to optimise the query to speed up the loading so that more pins can be loaded in a certain radius?
Wikishootme uses a rectangle query operation, which is probably more efficient than radius. We can use a web browser's Developer Tools to see the API calls they are using.
This is their Request URL:
https://query.wikidata.org/bigdata/namespace/wdq/sparql?query=%23TOOL%3A%20WikiShootMe%0ASELECT%20%3Fq%20%3FqLabel%20%3Flocation%20%3Fimage%20%3Freason%20%3Fdesc%20%3Fcommonscat%20%3Fstreet%20WHERE%20%7B%20SERVICE%20wikibase%3Abox%20%7B%20%3Fq%20wdt%3AP625%20%3Flocation%20.%20bd%3AserviceParam%20wikibase%3AcornerSouthWest%20%22Point(2.2610378265380864%2048.86160921192831)%22%5E%5Egeo%3AwktLiteral%20.%20bd%3AserviceParam%20wikibase%3AcornerNorthEast%20%22Point(2.327213287353516%2048.88142495734281)%22%5E%5Egeo%3AwktLiteral%20%7D%20%20OPTIONAL%20%7B%20%3Fq%20wdt%3AP18%20%3Fimage%20%7D%20%20OPTIONAL%20%7B%20%3Fq%20wdt%3AP373%20%3Fcommonscat%20%7D%20%20OPTIONAL%20%7B%20%3Fq%20wdt%3AP969%20%3Fstreet%20%7D%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%2Cen%2Cde%2Cfr%2Ces%2Cit%2Cnl%22%20.%20%3Fq%20schema%3Adescription%20%3Fdesc%20.%20%3Fq%20rdfs%3Alabel%20%3FqLabel%20%7D%20%7D%20LIMIT%203000
and This is the Response:
{
"head" : {
"vars" : [ "q", "qLabel", "location", "image", "reason", "desc", "commonscat", "street" ]
},
"results" : {
"bindings" : [ {
"q" : {
"type" : "uri",
"value" : "http://www.wikidata.org/entity/Q771548"
},
"location" : {
"datatype" : "http://www.opengis.net/ont/geosparql#wktLiteral",
"type" : "literal",
"value" : "Point(2.2780859 48.8640063)"
},
"image" : {
"type" : "uri",
"value" : "http://commons.wikimedia.org/wiki/Special:FilePath/Ruedelapompe.JPG"
},
"commonscat" : {
"type" : "literal",
"value" : "Rue de la Pompe (Paris Metro)"
},
"desc" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "Paris Métro station"
},
"qLabel" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "Rue de la Pompe"
}
}, {
"q" : {
"type" : "uri",
"value" : "http://www.wikidata.org/entity/Q800418"
},
"location" : {
"datatype" : "http://www.opengis.net/ont/geosparql#wktLiteral",
"type" : "literal",
"value" : "Point(2.2753 48.8706)"
},
"image" : {
"type" : "uri",
"value" : "http://commons.wikimedia.org/wiki/Special:FilePath/Vue%20de%20trois%20quarts%20b%C3%A2timent%20voyageurs%20gare%20de%20l%27Avenue%20Foch.jpg"
},
"commonscat" : {
"type" : "literal",
"value" : "Avenue Foch (Paris)"
},
"desc" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "railway station"
},
"qLabel" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "Gare de l'Avenue Foch"
}
}, {
"q" : {
"type" : "uri",
"value" : "http://www.wikidata.org/entity/Q800418"
},
"location" : {
"datatype" : "http://www.opengis.net/ont/geosparql#wktLiteral",
"type" : "literal",
"value" : "Point(2.2753 48.8706)"
},
"image" : {
"type" : "uri",
"value" : "http://commons.wikimedia.org/wiki/Special:FilePath/Vue%20de%20trois%20quarts%20b%C3%A2timent%20voyageurs%20gare%20de%20l%27Avenue%20Foch.jpg"
},
"commonscat" : {
"type" : "literal",
"value" : "Gare de l'avenue Foch"
},
"desc" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "railway station"
},
"qLabel" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "Gare de l'Avenue Foch"
}
}, {
"q" : {
"type" : "uri",
"value" : "http://www.wikidata.org/entity/Q1431541"
},
"location" : {
"datatype" : "http://www.opengis.net/ont/geosparql#wktLiteral",
"type" : "literal",
"value" : "Point(2.27988889 48.86535556)"
},
"image" : {
"type" : "uri",
"value" : "http://commons.wikimedia.org/wiki/Special:FilePath/Lyc%C3%A9e%20Janson-de-Sailly%2C%20106%20rue%20de%20la%20Pompe%2C%20Paris%2016e%201.jpg"
},
"commonscat" : {
"type" : "literal",
"value" : "Lycée Janson-de-Sailly"
},
"desc" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "secondary education in France"
},
"qLabel" : {
"xml:lang" : "en",
"type" : "literal",
"value" : "Lycée Janson-de-Sailly"
}
}...
So to Implement this we'll have to create a new List<Place> getNearbyPlaces(final LatLng cur, final String language, final double radius, final boolean shouldQueryForMonuments, final String customQuery)
method which takes params for a rectangle Instead of Radius and make a query according to that ?
Sounds right, yes!
Hi @nicolas-raoul I want to work on this ? Please assign it to me.
Can I work on this? Can you assisgn this to me ? @nicolas-raoul
wow difficult situation but I guess @awanishyadav967 asked first... sorry @shashankiitbhu and thanks for your research!
No Issue @nicolas-raoul , it's an interesting task so best of luck @awanishyadav967
Just asking in curiosity ,If we increase the number of pins ,so that it fill all the screen ,cannot it affect the app's performance? and also we're aiming to load more pins at the default zoom level, and I am thinking it can be solve by just increasing the radius of circle. @nicolas-raoul
@awanishyadav967
I don't think it will affecting performance in terms of CPU/memory. The bottleneck will always be network bandwidth.
We tried increasing the radius but unfortunately the query becomes too slow. As wikishootme demonstrates, rectangle queries seem to be much faster.
Hi @nicolas-raoul I change the query from wiki around to wiki box for the rectangle query and it work perfectly for the real coordinates but when I replace with placeholder it cannot get my real coordinates.
Here is code for query:
WHERE {
# Around given location
SERVICE wikibase:box {
?item wdt:P625 ?location.
bd:serviceParam wikibase:cornerWest "Point(${LAT_WEST} ${LONG_WEST})"^^geo:wktLiteral.
bd:serviceParam wikibase:cornerEast "Point(${LAT_EAST} ${LONG_EAST})"^^geo:wktLiteral.
}
Here is OkHttpJsonApiClient.java code:
@Nullable
public List<Place> getNearbyPlaces(final LatLng cur, final String language, final double radius,
final boolean shouldQueryForMonuments, final String customQuery)
throws Exception {
Timber.d("Fetching nearby items at radius %s", radius);
Timber.d("CUSTOM_SPARQL%s", String.valueOf(customQuery != null));
final String wikidataQuery;
if (customQuery != null) {
wikidataQuery = customQuery;
} else if (!shouldQueryForMonuments) {
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query.rq");
} else {
wikidataQuery = FileUtils.readFromResource("/queries/nearby_query_monuments.rq");
}
final double diagonalDistance = 0.012;
final double diagonalAngle = 45.0;
// Convert distance to degrees
final double distanceInDegrees = diagonalDistance /111.32;
// Calculate diagonal distances in latitude and longitude directions
final double deltaLat = distanceInDegrees * Math.sin(diagonalAngle);
final double deltaLong = distanceInDegrees * Math.cos(diagonalAngle);
// Calculate bounding box coordinates
final double westCornerLat = cur.getLatitude() - deltaLat;
final double westCornerLong = cur.getLongitude() + deltaLong;
final double eastCornerLat = cur.getLatitude() + deltaLat;
final double eastCornerLong = cur.getLongitude() - deltaLong;
/* final double westCornerLat = 77.96077;
final double westCornerLong = 30.30209;
final double eastCornerLat = 78.07047;
final double eastCornerLong = 30.25851;*/
final String query = wikidataQuery
.replace("${LAT_WEST}", String.format(Locale.ROOT, "%.4f", westCornerLat))
.replace("${LONG_WEST}", String.format(Locale.ROOT, "%.4f", westCornerLong))
.replace("${LAT_EAST}", String.format(Locale.ROOT, "%.4f", eastCornerLat))
.replace("${LONG_EAST}", String.format(Locale.ROOT, "%.4f", eastCornerLong))
.replace("${LANG}", language);
Timber.d("Latitude: %s, Longitude: %s", cur.getLatitude(), cur.getLongitude());
Timber.d("West Corner Lat: %s, West Corner Long: %s", westCornerLat, westCornerLong);
Timber.d("East Corner Lat: %s, East Corner Long: %s", eastCornerLat, eastCornerLong);
I need little help ,I thing my calculation is wrong for getting coordinates.
Here is how it look for any random coordinates
Hey @awanishyadav967 ,
How about using this code in NearbyParentFragment.java
to get LatLng for Top Right and Bottom Left, then using them as east and west. It will also help us during different zoom levels. I tried this code inside populatePlacesForAnotherLocation
and
populatePlacesForCurrentLocation
it is working for me.
IGeoPoint screenTopRight = mapView.getProjection().fromPixels(mapView.getWidth(), 0);
IGeoPoint screenBottomLeft = mapView.getProjection().fromPixels(0, mapView.getHeight());
fr.free.nrw.commons.location.LatLng screenTopRightLatLng = new fr.free.nrw.commons.location.LatLng(screenBottomLeft.getLatitude(),screenBottomLeft.getLongitude(),0);
fr.free.nrw.commons.location.LatLng screenBottomLeftLatLng = new fr.free.nrw.commons.location.LatLng(screenTopRight.getLatitude(),screenTopRight.getLongitude(),0);
Hey @nicolas-raoul, Can I work on this issue 🙂
Currently Nearby shows pins in a way that often does not cover the whole screen:
At least at default zoom level, I feel that it should be possible to load more pins, enough to fill all areas of the screen.
Similar to how Wikishootme loads pins:
Wikishootme loads rather fast, our query is more complex but it is worth trying. We can also speed it up with some trick like #4560