Check if point exists within a polygon in react-native-maps? - google-maps

I have an API that returns an array of latitudes and longitudes that define the boundaries of an area on a map(polygon).
In my react-native app, I have react-native-maps installed. How do I check if the user's location is in the polygon returned by the api?
I know this can be achieved with google maps web with the containsLocation() function. Does a function like that exist for react-native-maps?

For anyone still looking for an easier alternative (or for Circle support just like I needed it), look into using geolib: https://github.com/manuelbieh/Geolib.
Installation is simple and straightforward:
$yarn add geolib
Afterward in your React Native project, import it using:
import geolib from 'geolib'
And then just use the API as explained in the README.md.

react-native-maps doesn't expose that function, but there are two packages that I'm aware of that can help you:
react-native-geo-fencing that does the same as the google maps utility you've mentioned.
react-native-geo-fence handles location checks for you and exposes events you can hook into.

geolibe
is the best solution.
react-native-geo-fencing is deprecated and it cause more errors to your project and also
react-native-geo-fence is not what you want

My code to check if lat, lon is inside object of many polys. It returns true if coordinate is inside one of the polygons.
isInsidePoly = (lat, lon, multiPolycoords) => {
// ray-casting algorithm based on
// https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html/pnpoly.html
var x = lat,
y = lon;
var inside = false;
multiPolycoords.map(poly => {
vs = poly;
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i].latitude,
yi = vs[i].longitude;
var xj = vs[j].latitude,
yj = vs[j].longitude;
var intersect =
yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
if (intersect) inside = !inside;
}
});
return inside;
};

Related

Google Map Road API not interpolating path and not giving smooth route

I am trying to get smooth route for below route path using road API in Roads Inspector but not getting smooth route.Google road api failing to provide smooth route.Some portion of route is not smooth with actual road route e.g at turns, at bridges etc. Please have look for below route path and provide solution to get smooth route/more accurate route along actual road.
Points:
42.04144333333333,-88.060575|42.04123666666667,-88.06014333333333|42.04119166666667,-88.06017166666666|42.040835,-88.05990166666666|42.03982666666667,-88.05242333333334|42.03903666666667,-88.04572333333333|42.03903833333333,-88.04572|42.038495,-88.04141833333334|42.03774666666666,-88.03593833333333|42.037683333333334,-88.03549|42.034861666666664,-88.03204166666667|42.02808,-88.031215|42.02045666666667,-88.03131166666667|42.012881666666665,-88.02988833333333|42.00522333333333,-88.02747666666667|41.997353333333336,-88.02500333333333|41.98961333333333,-88.02349333333333|41.982191666666665,-88.02351333333333|41.97412833333333,-88.02447333333333|41.96599,-88.02588166666666|41.95825833333333,-88.027075|41.952605,-88.03345|41.945281666666666,-88.0377|41.937595,-88.03779333333334|41.92935,-88.037845|41.92084333333333,-88.03799166666667|41.91231,-88.038075|41.90379,-88.038145|41.89564,-88.03784166666667|41.887255,-88.036495|41.87881,-88.03291666666667|41.87096833333333,-88.03694333333334|41.863101666666665,-88.04085166666667|41.85484833333334,-88.04049166666667|41.848978333333335,-88.03315166666667|41.842145,-88.02940833333334|41.83407,-88.02922|41.826135,-88.029025|41.820256666666666,-88.02674333333333|41.813515,-88.02884833333333|41.80965333333333,-88.03722166666667|41.810065,-88.04824833333333|41.8104,-88.06018333333333|41.81016666666667,-88.07216833333334|41.80704166666666,-88.08223833333334|41.80573666666667,-88.09275|41.80591166666667,-88.10409166666666|41.80608,-88.11518333333333|41.80625166666667,-88.12632166666667|41.806415,-88.13737333333333|41.80649666666667,-88.14849166666667|41.80653,-88.15959333333333|41.80652666666667,-88.17042666666667|41.805715,-88.181295|41.80482833333333,-88.19194333333333|41.803918333333336,-88.202765|41.80304666666667,-88.212815|41.802146666666665,-88.22354833333333|41.801383333333334,-88.23485666666667|41.80068833333333,-88.24686666666666|41.8,-88.25845333333334|41.799368333333334,-88.26976833333333|41.798743333333334,-88.28041666666667|41.80003166666667,-88.28312833333334|41.795566666666666,-88.28211666666667|41.79022,-88.28205833333334|41.785465,-88.28198|41.784135,-88.28193833333333|41.782473333333336,-88.283865|41.78230833333333,-88.28874666666667|41.782226666666666,-88.288225|41.781863333333334,-88.287305|41.78176833333333,-88.28751333333334|41.78176833333333,-88.28751333333334
points in the "inspector"
Your points don't look like the full output of a GPS tracker (the use case for which this API is designed), and thus you have stretches that are too far apart. Please increase the resolution of your GPS recording to get better output.
Google maps seems not to snap far points,
(if the distance between is longer than 300m - 400m).
As a solution I added some fake points between points that too far apart.
And now Google Maps snapping my route correctly.
List<LatLon> extendedPointsList = new List<LatLon>();
var lastLatLon = OrigionalRoute[0];
extendedPointsList.Add(lastLatLon);
indexesBeforeAddingPoints.Add(0);
for (int i = 1; i < OrigionalRoute.Count; i++)
{
var currentLatlon = OrigionalRoute[i];
double estimatedDistance =
getEstimatedDistanceBetweenPoints(currentLatlon, lastLatLon);
//estimated 400 meters
if (estimatedDistance > 0.004)
{
//estimated 340 meters
int countOfPoints = (int)Math.Round(estimatedDistance / 0.0034);
if (countOfPoints > 1)
{
var latDiff = (currentLatlon.Lat - lastLatLon.Lat) / countOfPoints;
var lonDiff = (currentLatlon.Lon - lastLatLon.Lon) / countOfPoints;
for (int j = 1; j < countOfPoints; j++)
{
var aveLat = lastLatLon.Lat + (latDiff * j);
var aveLon = lastLatLon.Lon + (lonDiff * j);
indexesBeforeAddingPoints.Add(i - 1);
extendedPointsList.Add(new LatLon(aveLat, aveLon));
}
}
}
indexesBeforeAddingPoints.Add(i);
extendedPointsList.Add(currentLatlon);
lastLatLon = currentLatlon;
}
OrigionalRoute = extendedPointsList;
The method to estimate distance (I ignored earth's sphere and projection).
private static double getEstimatedDistanceBetweenPoints(LatLon pointA, LatLon pointB)
{
return Math.Sqrt(Math.Pow((pointA.Lat - pointB.Lat), 2) + Math.Pow((pointA.Lon - pointB.Lon), 2));
}

Google Maps Custom Markers in an Area [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Calculate “as the crow flies” distance php
I am trying to develop a GoogleMaps page where I can get the user location and show custom marker points from an XML file that fells within the calculated area around the user.
To make things more clear :
I have a radius parameter from WebConfig file, say 5000 (in meters)
I've found the user location on map,
Using the xml list that I own (xml has the Lat-Long values of
each store) I want to put custom markers on map which fell within
the 5 km^2 area range with the user's location as center.
Is there a way to achieve this goal?
How do I calculate a point's Lat & Long values by only passing user's location coordinates and a distance parameter (say 5000 in my case)?
Edit :
My XML doc is kinda huge including whitegoods stores all around the
country. My main problem is to filter these rows of data (long,latt)
using user's current location.
I need something like:
func distanceCale(int long, int latt, int radius)
to return me some values that can help me filter my XML data.
I guess my question was not clear enough at the firs place. :)
You can achieve this using the Haversine formula. This formula has been used in a Demo from an XML file showing markers within a given radius.
For your application the javascript code is used to generate markers from XML file.
function deg2rad(degrees){
radians = degrees * (Math.PI/180);
//document.write(radians);
return radians;
}
function Haversine(lat1,lon1,lat2,lon2) {
deltaLat = lat2 - lat1 ;
deltaLon = lon2 - lon1 ;
earthRadius = 3959; // in miles 6371 in meters.
alpha = deltaLat/2;
beta = deltaLon/2;
a = Math.sin(deg2rad(alpha)) * Math.sin(deg2rad(alpha)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(deg2rad(beta)) * Math.sin(deg2rad(beta)) ;
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
distance = earthRadius * c;
return distance.toFixed(2);
}
The Haversine function is used when parsing XML
var radius = document.getElementById('radiusSelect').value;
for (var i = 0; i < markerNodes.length; i++) {
var lat = parseFloat(markerNodes[i].getAttribute("lat"));
var lng = parseFloat(markerNodes[i].getAttribute("lng"));
var latlng = new google.maps.LatLng(
lat,
lng);
var distance = Haversine(center.lat(),center.lng(),lat,lng);
if(distance<=radius) {
createOption(name, distance, i);
createMarker(latlng, name, distance);
bounds.extend(latlng);
}

Compute the distance between polyline (route) and marker in Google Maps API v3

Is there any convenient way to compute the direct (shortest) distance between Polyline (the route generated by Google Directions) and markers that are NOT situated on that polyline?
The only way I found out is to cycle through Polyline.getPath() vertices manually to calculate the shortest distance but it seems to be a bit harsh:
var path = routes[0].overview_path;
for (var i = 0; i < data.points.length; i++) {
var latLngA = new LatLng(data.points[i].lat, data.points[i].lng);
var shortest_distance = null;
for (var j = 0; j < path.length; j++) {
var distance = google.maps.geometry.spherical.computeDistanceBetween(latLngA, path[i]);
if (shortest_distance == null || distance < shortest_distance) {
shortest_distance = distance;
}
}
console.log(data.points[i].point_title, shortest_distance);
}
Thanks in advance!
As far as I know, the Google Maps API does not give you a way to do this easily. And unfortunately, the algorithm you use will not give an accurate answer, because it gives the distance from the marker to the closest vertex on the path, not the closest point on the polyline itself, which will usually not be one of the points.
If you really need an accurate calculation, the best option I know of is to use the Javascript Topology Suite (JSTS). JSTS has a ton of geographic formulas for calculating this sort of thing. That means converting the polyline returned from the directions API into a JSTS object and calling the right utility function. Not trivial, but not too difficult either.
Use turf - modular geospatial analysis engine.
https://turfjs.org/docs/

Retrieving destination coordinates from direction services by distance

I need to retrieve a destination's coordinates using the google maps api directions service. I already have the starting point coordinates, however instead of specifying an ending point in coordinates, I wish to retrieve the coordinates by specifying a distance (in km).
So I guess my question is the following: is it possible to retrieve the destination latlong coordinates (based/calculated on the road's distance and not directional/straight line) by specifying a distance (amount in km) with the directions service or perhaps any alternative way?
I have an image illustration, however unfortunately am unable to attach to this question as I do not have enough reputation. If my question is unclear in any way, or you wish to see the illustration then please contact me and I'll send it off.
I don't think you can do this as the request parameters say that origin and destination parameters are required.
I beliave it will help someone.
There is a method to get coordinates in the google maps library:
google.maps.geometry.spherical.computeOffset(fromCoordinates, distanceInMeters, headingInDegrees)
I believe you are correct. There doesn't seem to be any current method in the api which would allow you to do the following.
Instead I looped through the coordinates returned from the directions service call, and used a function to calculate the distance between coordinates. However even this was not accurate enough as the coordinates returned also seemed to be aggregated and doesn't return an accurate value/distance when calculating the distances between each coordinate as they are aggregated and therefore each coordinate is not necessary along the road.
To work around the above issue, I ended up adding a click event, and plotted the coordinates along the road myself and then stored them in a local json file which I cache and call using an xmlhttprequest.
Fortunately, for my situation I only need to calculate the distance between point A & B on one individual road, so my alternative won't work in cases when you're using multiple or generic roads/locations. You could instead use the first method described, given that you're happy to live with the aggregated data and an in-accurate calculation.
Below are the functions used to calculate the distances between coordinates and then also the final calculation to find the point & coordinates between the final two points. Please note this code relies on and uses jQuery methods.
1. Calculate distance (in meters) between two coordinates
function pointDistance( begin, end )
{
var begin = { lat: begin[0], long: begin[1] },
end = { lat: end[0], long: end[1] };
// General calculations
var earthRadius = 6371, //km
distanceLat = (end.lat - begin.lat).toRad(),
distanceLong = (end.long - begin.long).toRad();
// Convert lats to radiants
begin.lat = begin.lat.toRad();
end.lat = end.lat.toRad();
// Calculation
var a = Math.sin(distanceLat / 2) * Math.sin(distanceLat / 2) +
Math.sin(distanceLong / 2) * Math.sin(distanceLong / 2) * Math.cos(begin.lat) * Math.cos(end.lat);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var distance = (earthRadius * c) - 0.000536;
return (distance * 1000);
}
2. Fetch coordinate of final A-B coordinate (based on percentage remaining). The 'matrix' variable is a json array of coordinates.
function getCoordinates( totalDistance )
{
var lastPoint = { lat: null, long: null },
total = parseFloat(0),
position = { start: null, end: null, distance: 0 };
$(matrix).each(function()
{
if ( lastPoint.lat == null )
{
lastPoint = { lat: this[0], long: this[1] };
return;
}
var distance = pointDistance([lastPoint.lat, lastPoint.long], [this[0], this[1]]);
total = total + distance;
if ( (total / 1000) >= totalDistance )
{
position.start = new google.maps.LatLng(lastPoint.lat, lastPoint.long);
position.end = new google.maps.LatLng(this[0], this[1]);
position.distance = total;
return false;
}
lastPoint = { lat: this[0], long: this[1] };
});
return position;
}
3. Convert numeric degrees to radians
if ( typeof(Number.prototype.toRad) === 'undefined' ) {
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}
Hope the following helps any one with the same or simular problem. I haven't investigated this as I've had no need to, but, perhaps if you're dealing with google's paid services, they don't aggregate the data returned by the call?

What is a good algorithm for mapping GPS coordinates to screen locations when using Google maps?

I need an algorithm that will convert a GPS coordinate to a screen location on a displayed google map. I would think this would be simple- get the coordinates for the four corners of the displayed map, find the differential and create a scaling factor for a pixel location on the screen. Is this correct or am I missing something. I'm know this has been done ad nauseum but I am hoping I can hear from someone who has implemented it successfully or has a resource for implementing it.
Basically you need the code for Transverse Mercator projection (which is used by Google maps and others). Here's a C# snippet I used my Kosmos software:
public Point2<int> ConvertMapToViewCoords (Point2<double> mapCoords)
{
double x = (mapCoords.X - MapPosition.Longitude) / resolution;
double y = Math.Log (Math.Tan (Math.PI*(0.25 + mapCoords.Y/360)))*u180dPiResolution;
return new Point2<int> ((int)(x + viewWidthHalf), (int)((y0 - y) + viewHeightHalf));
}
variables used:
double resolution = 360.0 / (Math.Pow (2, MapPosition.ZoomFactor) * 256);
double u180dPiResolution = 40.7436654315252 * Math.Pow(2, MapPosition.ZoomFactor);
double y0 = Math.Log(Math.Tan(Math.PI * (0.25 + MapPosition.Latitude / 360))) * u180dPiResolution;
float viewWidthHalf = ViewWidth / 2.0f;
float viewHeightHalf = ViewHeight / 2.0f;
ZoomFactor is Google zoom level (see http://laudontech.com/GISBlog/?p=28).
BTW the same code works for OpenStreetMap, Yahoo Maps etc., since they all use the same projection and tiling system.
The Google Maps API lets you do stuff like this.
Here is some JS code I've written using the APIs that does something similar:
var map = new GMap2(document.getElementById("map"));
//...
var location = new GLatLng(37.771008, -122.41175);
map.setCenter(location);
var marker = new GMarker(location);
var overlay_caption = "Our location!";
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(overlay_caption);
});
map.addOverlay(marker);
marker.openInfoWindowHtml(overlay_caption);
You can also redirect the page to a new map with a URL like this:
http://maps.google.com/maps?q=37.771008,+-122.41175+(You+can+insert+your+text+here)&iwloc=A&hl=en
If you need the pixel coordinate of a latitude/longitude position of a current instance of Google Maps you may use the fromLatLngToDivPixel() function.
Assuming map is an instance of an initialized GMap2:
var location = new GLatLng(37.771008, -122.41175);
var point = map.fromLatLngToDivPixel(location);
alert("X: " + point.x + ", Y: " + point.y);
Depending on your needs, see also fromLatLngToContainerPixel.