检查点是否在圆内

3

我有一个名为 spotCoordinates 的地点的 GPS 坐标,以及一个圆心坐标 this.state.center 和一个以公里为单位的半径 this.state.radius

我正试图制作一个方法来检查 spotCoordinates 是否在圆内,但我不知道如何将半径添加到坐标中,以及如何检查它是否真的在圆内。如果是一个正方形的话就更容易了。

 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
      });
  }

例如在控制台中打印的值 spotCoordinates = [41.5408446218337, -8.612296123028727] center = {lat: 41.536558, lng: -8.627487} radius = 25

enter image description here

需要帮助吗?


使用勾股定理来找到圆心的距离。如果它小于圆的直径,那么这个点在圆内。 - Mike Robinson
2
@MikeRobinson 你是指“如果它小于半径…”吗? - Teemu
41.5408446218337, -8.612296123028727 是一个点,而 41.536558, lng: -8.627487 是另一个点,对吗? - user3783243
@user3783243 我尝试了haversineDistance方法,但是它给我一些奇怪的值,比如0.0021208675369022113。我怎么知道它是在内部还是外部呢? - user12361681
@user12361681 这是点1和点2之间的距离,以英里为单位,所以如果你想要在半径范围内,就除以2。如果返回值小于12.5,则表示在范围内。 - user3783243
显示剩余2条评论
3个回答

4

感谢这个SO链接大圆距离的帮助。

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;
}


你能给我一个在外面的坐标吗? - Addis
38.817459, -9.282218 - user12361681
公里 - user12361681

1
你可以计算点到中心的距离,看看是否小于半径,这里有一个例子:

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);

以下是使用Google Maps演示此公式的示例: https://jsfiddle.net/dpr9shz3/ 要使用演示,请在地图上任意点击,警报将指定计算结果以及是否单击了圆形。


1
我认为这个假设地球是平的。附近的位置将不起作用。 - user12361681
@user12361681 如果只计算平面上的半径和距离,那么结果可能足够准确。但如果涉及到像地球这样的形状,情况就会变得相当复杂,因为地球并不是一个完美的球体,计算还必须考虑到坐标接近极点的程度。 - Titus
@user12361681 我看不出为什么这个方法不能适用于附近的位置。 - Titus
@user12361681 我已经编辑了我的答案,并添加了一个演示的fiddle。这里的代码假设半径是以公里为单位,而演示中使用的是米。 - Titus
@Addis 我猜我们都从同一个地方得到了计算两点之间距离的公式。 - Titus
显示剩余2条评论

0

这个的表达式是:

(center.x - pt.x)^2 + (center.y - pt.y)^2 < radius^2

您可以调整比较运算符来检查点是否在圆上(==),或者它是否在圆的边界之外(>)。

这里是一个JavaScript函数,如果点在圆内则返回-1,如果点在圆上则返回0,如果点在圆外则返回1。

/**
 * @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 (lhs < rhs) {
    return -1
} else if (lhs === rhs) {
    return 0
} else {
    return 1
}

使用方法:

ptInCircle([0, 1], [1, 0], 1)
// Returns 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接