As many of you know I have been producing a Leaflet map with a KNN function to show the closest pubs to a user's location.
Live example to test for yourself: https://ces-web2.southwales.ac.uk/students/18018815/mitchtut/giscw3/Geoserv2.php
The system itself works on mine and various others PC's within Chrome, however, I when opened within other browsers it is a bit more finicky and requires either a cache refresh to work or it doesn't successfully preform the KNN function. Below shows the working script on my PC showing the closest pubs. This also works with other locations through Chrome's dev tools too.
Using remote target devices in Chrome, I had a look at the browser logs within my mobile device and received the error:
pg_query(): Query failed: ERROR: parse error - invalid geometry HINT:
"point()" <-- parse error at position 8
This suggests that the script or function cannot parse the data being return from the script.
The Chrome logs show that the device's location is being received and passed to the script but the data/points are not being returned.
The same issue can be seen within Microsoft Edge too, again location is being grabbed from the device but the KNN showing Blue Markers (closest pubs) does not show.
Is there any reason this error is occurring as I know the code itself works and as achieved from previous answers the race problem issue was fixed.
I have successful screenshots of colleagues and friends devices showing successful KNN execution, even within different browsers such as Edge and Safari, but on some devices this issue seems to persist.
My original thought process was that this could be something to be the decimal positions within the lat and long being too large to parse, however, the same coordinates spoofed into Chrome work. And this would not be an issue for more general Lat and Longs from IP address based locations as these are less accurate.
The current code for the script is:
//Map instantiation and layer calls
pub_map = L.map('mapspce');
pub_map.setView([54.00, -2.54],5.5);
pub_map.addLayer(basetiles);
//User location
var Position, Accuracy,test = null;
function onLocationFound(e) {
if(Position){
pub_map.removeLayer(Position);
pub_map.removeLayer(Accuracy);
}
test = e.latlng;
console.log("user lat long in script is: " + test);
lon = test.lng;
lat = test.lat;
lat = lat.toString();
lon = lon.toString();
kLOC = lon + " " + lat;
console.log("lon lat " + kLOC);
var radius = e.accuracy / 2;
//pop up stating the users position
Position = L.marker(e.latlng).addTo(pub_map).bindPopup("<h4>You are here</h4><p>You are within " + radius + " metres from here</p>").openPopup();
Accuracy = L.circle(e.latlng, radius).addTo(pub_map);
/* var lat, lon;
lat = parseFloat(Position.coords.latitude);
lon = parseFloat(Position.coords.longitude);
console.log("user lat is: " +lat);
console.log("user lat is: "+lon); */
//return lon;
//return lat;
return test;
}
//error message if user location cannot be found
function onLocationError(e) {
alert(e.message);
}
//display the layers to the map
pub_map.on('locationfound', onLocationFound);
pub_map.on('locationerror', onLocationError);
//locate function
pub_map.locate({setView: true, maxZoom:16});
//knn feature
var kTable = 'geoupload.pubs';
var kColumn =["id", "p_name", "address1", "postcode", "local_authority"];
var kGeom = "geom";
var kLOC;
//"51.59977 -3.325952";
//"307998 189349";
//var klocy = "User location is " + test;
//passing variable to the console to show values are being picked up
// console.log(kLOC);
// console.log("user lat long is: " + test);
// console.log("user lat is: " + lat);
// console.log("user lon is: " + lon);
$(document).ready(function(){
$.ajax({
url: "knn.php",
data:{ktable: kTable, kinclu: kColumn, kgeomy: kGeom, Loc: kLOC}
})
.done(function(data){
knnPubsLay = L.geoJSON(JSON.parse(data),{
pointToLayer: function (feature, latlng){
return L.circleMarker(latlng,nearStyle);
}});
console.log("after " + kLOC);
pub_map.addLayer(knnPubsLay);
knnPubsLay.bringToFront();
})
});
With the PHP script calling the KNN function being:
//call tables for knn query although same as the previous I have changed the variable names to keep them seperate
$ktable = $_GET['ktable'];
$kinclu = $_GET['kinclu'];
$kgeomy = $_GET['kgeomy'];
$Loc = $_GET['Loc'];
//substitutes
$fields = "";
foreach ($kinclu as $i => $col) {
$fields = $fields . $col . ", ";
}
$fields = $fields . $kgeomy;
$geom = " - " . $kgeomy;
//knn query
$knn1 =
"SELECT jsonb_build_object(
'type', 'FeatureCollection',
'features', jsonb_agg(feature))
FROM (
SELECT jsonb_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(st_transform(geom,4326),4)::jsonb,
'properties', to_jsonb(row) #omits#
) AS feature
FROM (SELECT #fields# FROM #table# as K, st_transform(st_geomfromtext('point(#location#)',4326),27700) ORDER BY st_distance(K.geom, st_transform(st_geomfromtext('point(#location#)',4326),27700)) LIMIT 5) row) features;";
//27700
//4326
//geomfromtext
//pointfromtext
//replace placeholders
$knn2 = str_replace("#table#", $ktable, $knn1);
$knn3 = str_replace("#fields#", $fields, $knn2);
$knn4 = str_replace("#location#", $Loc, $knn3);
$knn5 = str_replace("#omits#", $geom, $knn4);
ChromePhp::log($knn5);
//execute query
if (!$response = pg_query($conn, $knn5)) {
ChromePhp::error("*KNN script failed*");
exit;
}
//return data
while ($row = pg_fetch_row($response)) {
foreach ($row as $i => $attr){
echo $attr;
}
}