Reputation: 107
I have a GPS Coordinate of a spot called spotCoordinates
and a center the a circle coordinates this.state.center
and a radius in kilometers this.state.radius
I'm trying to make a method to check if the spotCoordinates
is inside a circle but I don't know how I can add the radius to the coordinates and how to check if it's actually inside or not. It would be easier if it was a square.
calculateParkingSpotsInTheArea = () => {
this.state.parkingSpots.map(spot => {
let spotCoordinates = spot.coordinates;
console.log(spotCoordinates, this.state.center, this.state.radius);
// Calculate if the parking spot is inside the circle
});
}
E.g Values printed in the console spotCoordinates = [41.5408446218337, -8.612296123028727] center = {lat: 41.536558, lng: -8.627487} radius = 25
Any help?
Upvotes: 3
Views: 5872
Reputation: 4975
An expression for this would be:
(center.x - pt.x)^2 + (center.y - pt.y)^2 < radius^2
You can adjust the comparison operator to check if the pt is on the circle (==) or if it is outside the circle boundary (>).
Here is a JavaScript function that will return -1 if the pt is inside the circle, 0 if it is on the circle and 1 if it is outside the circle.
/**
* @description Check if a pt is in, on or outside of a circle.
* @param {[float]} pt The point to test. An array of two floats - x and y coordinates.
* @param {[float]} center The circle center. An array of two floats - x and y coordinates.
* @param {float} r The circle radius.
* @returns {-1 | 0 | 1} -1 if the point is inside, 0 if it is on and 1 if it is outside the circle.
*/
function ptInCircle(pt, center, r) {
const lhs = Math.pow(center[0] - pt[0], 2) + Math.pow(center[1] - pt[1], 2);
const rhs = Math.pow(r, 2);
return lhs < rhs ? -1 : (lhs === rhs ? 0 : 1);
}
If you don't like the shorthand nested ternary operator, you can swap the return line for this:
if (lhs < rhs) {
return -1
} else if (lhs === rhs) {
return 0
} else {
return 1
}
Usage:
ptInCircle([0, 1], [1, 0], 1)
// Returns 1
Upvotes: 2
Reputation: 22474
You can calculate the point's distance from the center and see if that is smaller then the radius, here is an example:
const spotCoordinates = {
lat: 41.5408446218337,
lng: -8.612296123028727
};
const center = {
lat: 41.536558,
lng: -8.627487
};
const radius = 25;
function degreesToRadians(degrees) {
return degrees * Math.PI / 180;
}
function distanceInKmBetweenEarthCoordinates(lat1, lon1, lat2, lon2) {
var earthRadiusKm = 6371;
var dLat = degreesToRadians(lat2-lat1);
var dLon = degreesToRadians(lon2-lon1);
lat1 = degreesToRadians(lat1);
lat2 = degreesToRadians(lat2);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return earthRadiusKm * c;
}
function isInCircle(latLng) {
const distance = distanceInKmBetweenEarthCoordinates(latLng.lat, latLng.lng, center.lat, center.lng);
const calculationResult = distance <= radius;
console.log("Is inside", calculationResult);
}
isInCircle(spotCoordinates);
And here is an example of this formula in action using Google Maps: https://jsfiddle.net/dpr9shz3/ to use the demo, just click anywhere on the map and the alert will specify the result of the calculation and whether the circle shape was clicked or not.
Upvotes: 1
Reputation: 2530
Credit to this SO link and Great-circle distance
let spotCoordinates1 = [41.5408446218337, -8.612296123028727];
let spotCoordinates2 = [38.817459, -9.282218]
let center = {lat: 41.536558, lng: -8.627487};
let radius = 25
checkIfInside(spotCoordinates1);
checkIfInside(spotCoordinates2);
function checkIfInside(spotCoordinates) {
let newRadius = distanceInKmBetweenEarthCoordinates(spotCoordinates[0], spotCoordinates[1], center.lat, center.lng);
console.log(newRadius)
if( newRadius < radius ) {
//point is inside the circle
console.log('inside')
}
else if(newRadius > radius) {
//point is outside the circle
console.log('outside')
}
else {
//point is on the circle
console.log('on the circle')
}
}
function distanceInKmBetweenEarthCoordinates(lat1, lon1, lat2, lon2) {
var earthRadiusKm = 6371;
var dLat = degreesToRadians(lat2-lat1);
var dLon = degreesToRadians(lon2-lon1);
lat1 = degreesToRadians(lat1);
lat2 = degreesToRadians(lat2);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return earthRadiusKm * c;
}
function degreesToRadians(degrees) {
return degrees * Math.PI / 180;
}
Upvotes: 4