I'm using Google maps API that geolocates the user and, if they are in the city of Los Angeles, will tell them what LAPD reporting district they are in. I have a geojson overlay of the reporting districts (RD's) that's loading from here.
I want to get the geolocated coordinates, and use Turfjs's booleanPointInPolygon to determine if it's in an RD and if so, return that RD.
But no matter what I do, the turfjs function always returns false even though I'm clearly in an RD/Polygon.
I downloaded the geojson file and import it locally as a regular json file.
Here is my function:
getRd() {
const repdist = require("../assets/LAPD_Reporting_Districts.json");
let point = turf.point([34.05350702472784, -118.24291762202074]);
var poly;
repdist.features.forEach(rd => {
poly = turf.polygon(rd.geometry.coordinates);
var found = turf.booleanPointInPolygon(point, poly);
console.log("found: ", found);
});
As far as I can tell, the turf.point and turf.polygon array are properly formed and there are no errors on execution. I've stepped through the turf function and everything seemed fine.
Given the coords in the code sample (LA City Hall, which is in RD 124), I would expect the result to return true, but "found" returns 1135 falses.
I'd suggest checking two things:
The turf.point coordinate must be Lon,Lat instead of Lat,Lon. This might be the issue because -118 is not a valid latitude. Lon,Lat is a very common convention.
Also check the value passed in to booleanPointInPolygon The documentation shows the coordinate arrays being wrapped in two arrays, not just one.
Related
I try to use turf.js and its function intersect in my Leaflet project. My original question can be found here. The problem is I cannot get a proper polygon in order to call it. The idea is to get the waypoints of the calculated route make a polgyon out of them and check where they intersect with a given buffered area.
var testpoint = turf.point([9.9354, 49.799]);
var buffered = turf.buffer(testpoint, 50, {units: 'meters'});
var array = []
control._routes[0]['coordinates'].forEach(function(e){
array.push([e['lat'],e['lng']])
});
var test = turf.polygon(L.polygon([[array]]))
var intersection = turf.lineIntersect(buffered, test)
I am getting the following error message:
Uncaught Error: Input geometry is not a valid Polygon or MultiPolygon
Here I have to point out that, when using line.intersect(buffered,buffered) it is working correctly, therefore I am assuming that the buffered variable is correct.
When it comes down to the test variable, I have tried with no [], one pair and double pair. But they all result in the same problem. I also tried to pass the array to turf.polygon but it couldn`t be done.
I'm having a problem
I would like to ask what the most efficient way is to check if latitude and longitude coordinates are inside a range (for example 100 meters) from a list of latitudes and longitude points.
For example I have this list of coordinates:
[[48.34483,51.16.24517],[48.484,16.2585],[48.361,51.87739419],[6.38477205,51.87745015],[48.3645,51.16.73167],[6.38391099,51.87755068],[48.3575,16.725],[6.38380232,51.87720004],[6.38376297,51.87708017],[6.38375183,51.87704018],[6.38373055,51.8769829]]
I would like somehow that all points that are in a specific range (100m for example),
to be somehow grouped.
Is there any way how I can indicate that for example from the above list:
[48.484,16.2585],[48.361,51.87739419] and [48.3575,16.725]
are in a radius of 100m ( distance between these points is less then 100m) and they should be groped
Sounds like a great question for a GIS professional; you could perhaps post on gis.stackexchange.com. Are you using a mapping technology where you already have access to an API? The functionality that you're looking for are referred to as geometric operations. I'd start by looking into geometry functions available in an API which calculate the distance between points. You could find the geometric center of all of the points, then request the geometry API to create a buffer around that point. Next, query if each point falls within that buffer.
Found a post which might help with finding the center of the points here:
How do I find the center of a number of geographic points?
Also found a post on stackexchange which sounds very similar to yours, only the post is in reference to ArcGIS and the Point Distance (Analysis) tool:
https://gis.stackexchange.com/q/91571/81346
Ideally you'd use a geospatial db for this, to avoid performance issues when dealing with increasing numbers of points. MySQL, Postgres etc all support geospatial functions.
But as you've tagged your question with javascript, I'll post a JS solution. There's an npm package called haversine - with it, you should be able to loop through each point and return the other points that are within 100m. Something like:
// bring in haversine from npm
var haversine = require("haversine");
// define the full list of points
var data = [
[48.34483,51.1624517],
[48.484,16.2585],
[48.361,51.87739419],
[6.38477205,51.87745015],
[48.3645,51.1673167],
[6.38391099,51.87755068],
[48.3575,16.725],
[6.38380232,51.87720004],
[6.38376297,51.87708017],
[6.38375183,51.87704018],
[6.38373055,51.8769829]
];
var points = data.map(point => new Object({latitude: point[0], longitude: point[1]}));
// var to store results in
var results = [];
// loop through the points
points.forEach((pair) => {
var nearby = points;
// filter the full list to those within 100m of pair
nearby.filter(point => haversine(pair, point, {unit: 'mile'}) <= 100);
results.push({
'point': pair,
'nearby': nearby
});
});
console.log(results);
Note: I corrected some of the points in your list, which had double decimals so weren't valid
I am making a react native app which includes a map and want to place markers at the centres of different countries. However to create each marker you must provide a set of coordinates so I need a function to which I can pass a country name and it returns the coordinates for somewhere in that country (either of its centre or its capital would be good).
getCoords = (country_name) => {
return coords {
latitude: lat_of_country_centre
longitude: long_of_country_centre
}
}
Does anyone know of a function or api that does this?
You would want to use a geocoding API like OpenCageData to convert a country name into a country.
For example, using OpenCageData, the request https://api.opencagedata.com/geocode/v1/json?key=YOUR_KEY&q=Germany would return a JSON object which contains various information about that location name.
In this case, the coordinates would be located at the path in the JSON object results[0].annotations.DMS, which contains lat and lng, latitude and longitude coordinates in degrees, minutes, and seconds (e.g.) 51° 5' 0.31056'' N for latitude and 10° 25' 24.40884'' E for longitude.
Experimentation with this API or others like it may help you find data that is the best for your specific application.
I would take a look at the Google Maps API. That’ll give you a good starting point.
you can take data from google i.e lat and long coords.
and load to your spreadsheet and write a simple program and load this into the array.
I am using turf.js to find a point inside a polygon and i found the problem persisting for several use cases one of such use case is as below below mentioned use case (i.e. for point (X=32.8,Y=40). I have also plotted the image for reference for which turf.booleanPointInPolygon is showing false.
Image of Graph plot
var turf = require("#turf/turf");
var pt = turf.point([32.8,40]);
var poly = turf.polygon([[
[ 7.2 , 160.0],
[38.3, 30.0],
[65.1 , 30.0],
[62.3 , 96.0],
[18.4 , 325.0],
[7.6 , 380.0],
[7.5 , 307.0],
[7.4 , 234.0],
[7.2 , 160.0]
]]);
var bool = turf.booleanPointInPolygon(pt, poly, {ignoreBoundary: false});
//bool = false, even though the point is inside the polygon
failed to recognize a point within the polygon, this is a glitch from turf.js.
How to report to turf.js. Anyone please help in fixing this.
I converted the cartesian x-axis array, y-axis array and the point to be found to log scale using Math.log(x) in javascript before feeding to turf.js for creating polygon and the point to be found within it. It is rendering correctly now. The major flaw was that i plotted my coordinates in log scale and was seeking turfs solution by passing cartesian data (which i converted to log scale before sending to turf)
Your point is not inside the polygon. There is no bug in turf.js. You probably been tricked because your plotted graph is completely wrong.
Here it is how your polygon should look likes on a graph. You see that your point (J) is clearly outside:
I'm using the ESRI JavaScript API v3.8. (I know 3.11 is out - can't upgrade yet.)
What I'm trying to do is to create a geometric buffer of a size provided by the user from an arbitrary line (or point) selected by the user. Some of the relevant code is shown below:
var params = new esri.tasks.BufferParameters();
params.distances = [values.distance]; //the input distance
params.geometries = [gr.geometry]; //the input geometry
params.unit = esri.tasks.GeometryService.UNIT_FOOT;
params.outSpatialReference = mapView.map.spatialReference; //always 3857
params.bufferSpatialReference = gr.geometry.spatialReference; //always 3857
esri.config.defaults.io.corsEnabledServers.push('mydomain.com');
esri.config.defaults.io.proxyUrl = 'https://serverdomain.com/proxy';
var gsvc = new esri.tasks.GeometryService('https://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer');
gsvc.simplify(params.geometries, function(geometries){
params.geometries = geometries;
gsvc.buffer(params, function(geometries){
//add output geometry to the map and perform spatial query with it
}, function(err){
//handle error
});
}, function(err){
//handle error
});
The problem is that, if I use an input distance of 500 (feet), then measure the distance from the center line of the input geometry on self._queryGeometry, using ESRI's measurement tool, the actual width of the polygon created is something like 370 feet on either side of the center line.
I've managed to get this to work more accurately using the Illinois State Plane spatial reference, as my test objects are in Illinois, but the logic needs to work everywhere.
When I try various incarnations of doing a geodesic buffer, the input distance unit seems to get ignored and, using an input distance value of 500, I get a buffer that spans the entire world! Either that or the results are exactly the same, depending on how things are set up.
I believe I need to do a geodesic buffer, but I have absolutely no idea how to go about that in such a way that the geometry service will actually pay attention to the units I'm sending in.
Any ideas would be greatly appreciated. Let me know if I've left anything out.
Sounds like there might be a spatial reference issue somewhere. You can try re-projecting geometry into 3857 if that's what the map is and I would inspect the geometry being returned from the buffer and simplify to make sure it looks like what your expecting. I have had issues with the geometry service area's and length's returning slightly incorrect geometries and in my case it ended up being an issue with an incorrect spatial reference. Also, I know you said you can't upgrade, but 3.13 is out and can do geometry options locally without the need for a proxy or any network requests, if possible, it would be worth trying out.