[geocoding] 주어진 위도 / 경도 위치에 대한 경계 상자를 계산하는 방법은 무엇입니까?

위도와 경도로 정의 된 위치를 지정했습니다. 이제 그 지점에서 10km 이내의 경계 상자를 계산하고 싶습니다.

경계 상자는 latmin, lngmin 및 latmax, lngmax로 정의되어야합니다.

panoramio API 를 사용하려면이 항목이 필요합니다 .

누군가 thos 포인트를 얻는 방법의 공식을 알고 있습니까?

편집 : 여러분은 lat & lng를 입력으로 취하고 경계 상자를 latmin & lngmin 및 latmax & latmin으로 반환하는 공식 / 함수를 찾고 있습니다. mysql, php, c #, javascript는 괜찮지 만 의사 코드도 괜찮습니다.

편집 : 2 점의 거리를 보여주는 솔루션을 찾고 있지 않습니다.



답변

나는 주어진 위도에서 WGS84 타원체에 의해 주어진 반지름을 가진 구체로 지구 표면을 국부적으로 근사하는 것을 제안합니다. latMin과 latMax의 정확한 계산에는 타원 함수가 필요하고 정확도가 눈에 띄게 증가하지 않을 것이라고 생각합니다 (WGS84 자체는 근사치입니다).

내 구현은 다음과 같습니다 (Python으로 작성되었으며 테스트하지 않았습니다).

# degrees to radians
def deg2rad(degrees):
    return math.pi*degrees/180.0
# radians to degrees
def rad2deg(radians):
    return 180.0*radians/math.pi

# Semi-axes of WGS-84 geoidal reference
WGS84_a = 6378137.0  # Major semiaxis [m]
WGS84_b = 6356752.3  # Minor semiaxis [m]

# Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
def WGS84EarthRadius(lat):
    # http://en.wikipedia.org/wiki/Earth_radius
    An = WGS84_a*WGS84_a * math.cos(lat)
    Bn = WGS84_b*WGS84_b * math.sin(lat)
    Ad = WGS84_a * math.cos(lat)
    Bd = WGS84_b * math.sin(lat)
    return math.sqrt( (An*An + Bn*Bn)/(Ad*Ad + Bd*Bd) )

# Bounding box surrounding the point at given coordinates,
# assuming local approximation of Earth surface as a sphere
# of radius given by WGS84
def boundingBox(latitudeInDegrees, longitudeInDegrees, halfSideInKm):
    lat = deg2rad(latitudeInDegrees)
    lon = deg2rad(longitudeInDegrees)
    halfSide = 1000*halfSideInKm

    # Radius of Earth at given latitude
    radius = WGS84EarthRadius(lat)
    # Radius of the parallel at given latitude
    pradius = radius*math.cos(lat)

    latMin = lat - halfSide/radius
    latMax = lat + halfSide/radius
    lonMin = lon - halfSide/pradius
    lonMax = lon + halfSide/pradius

    return (rad2deg(latMin), rad2deg(lonMin), rad2deg(latMax), rad2deg(lonMax))

편집 : 다음 코드는 (도, 소수, 초)를도 + 도의 분수로, 그 반대로 변환합니다 (테스트되지 않음).

def dps2deg(degrees, primes, seconds):
    return degrees + primes/60.0 + seconds/3600.0

def deg2dps(degrees):
    intdeg = math.floor(degrees)
    primes = (degrees - intdeg)*60.0
    intpri = math.floor(primes)
    seconds = (primes - intpri)*60.0
    intsec = round(seconds)
    return (int(intdeg), int(intpri), int(intsec))


답변

경계 좌표를 찾는 방법에 대한 기사를 썼습니다.

http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates

이 기사에서는 공식에 대해 설명하고 Java 구현도 제공합니다. (또한 최소 / 최대 경도에 대한 Federico의 공식이 부정확 한 이유도 보여줍니다.)


답변

여기에 관심있는 사람을 위해 Federico A. Ramponi의 답변을 C #으로 변환했습니다.

public class MapPoint
{
    public double Longitude { get; set; } // In Degrees
    public double Latitude { get; set; } // In Degrees
}

public class BoundingBox
{
    public MapPoint MinPoint { get; set; }
    public MapPoint MaxPoint { get; set; }
}

// Semi-axes of WGS-84 geoidal reference
private const double WGS84_a = 6378137.0; // Major semiaxis [m]
private const double WGS84_b = 6356752.3; // Minor semiaxis [m]

// 'halfSideInKm' is the half length of the bounding box you want in kilometers.
public static BoundingBox GetBoundingBox(MapPoint point, double halfSideInKm)
{
    // Bounding box surrounding the point at given coordinates,
    // assuming local approximation of Earth surface as a sphere
    // of radius given by WGS84
    var lat = Deg2rad(point.Latitude);
    var lon = Deg2rad(point.Longitude);
    var halfSide = 1000 * halfSideInKm;

    // Radius of Earth at given latitude
    var radius = WGS84EarthRadius(lat);
    // Radius of the parallel at given latitude
    var pradius = radius * Math.Cos(lat);

    var latMin = lat - halfSide / radius;
    var latMax = lat + halfSide / radius;
    var lonMin = lon - halfSide / pradius;
    var lonMax = lon + halfSide / pradius;

    return new BoundingBox {
        MinPoint = new MapPoint { Latitude = Rad2deg(latMin), Longitude = Rad2deg(lonMin) },
        MaxPoint = new MapPoint { Latitude = Rad2deg(latMax), Longitude = Rad2deg(lonMax) }
    };
}

// degrees to radians
private static double Deg2rad(double degrees)
{
    return Math.PI * degrees / 180.0;
}

// radians to degrees
private static double Rad2deg(double radians)
{
    return 180.0 * radians / Math.PI;
}

// Earth radius at a given latitude, according to the WGS-84 ellipsoid [m]
private static double WGS84EarthRadius(double lat)
{
    // http://en.wikipedia.org/wiki/Earth_radius
    var An = WGS84_a * WGS84_a * Math.Cos(lat);
    var Bn = WGS84_b * WGS84_b * Math.Sin(lat);
    var Ad = WGS84_a * Math.Cos(lat);
    var Bd = WGS84_b * Math.Sin(lat);
    return Math.Sqrt((An*An + Bn*Bn) / (Ad*Ad + Bd*Bd));
}


답변

거리와 좌표 쌍이 주어지면 사각형 경계 상자의 네 좌표를 반환하는 JavaScript 함수를 작성했습니다.

'use strict';

/**
 * @param {number} distance - distance (km) from the point represented by centerPoint
 * @param {array} centerPoint - two-dimensional array containing center coords [latitude, longitude]
 * @description
 *   Computes the bounding coordinates of all points on the surface of a sphere
 *   that has a great circle distance to the point represented by the centerPoint
 *   argument that is less or equal to the distance argument.
 *   Technique from: Jan Matuschek <http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates>
 * @author Alex Salisbury
*/

getBoundingBox = function (centerPoint, distance) {
  var MIN_LAT, MAX_LAT, MIN_LON, MAX_LON, R, radDist, degLat, degLon, radLat, radLon, minLat, maxLat, minLon, maxLon, deltaLon;
  if (distance < 0) {
    return 'Illegal arguments';
  }
  // helper functions (degrees<–>radians)
  Number.prototype.degToRad = function () {
    return this * (Math.PI / 180);
  };
  Number.prototype.radToDeg = function () {
    return (180 * this) / Math.PI;
  };
  // coordinate limits
  MIN_LAT = (-90).degToRad();
  MAX_LAT = (90).degToRad();
  MIN_LON = (-180).degToRad();
  MAX_LON = (180).degToRad();
  // Earth's radius (km)
  R = 6378.1;
  // angular distance in radians on a great circle
  radDist = distance / R;
  // center point coordinates (deg)
  degLat = centerPoint[0];
  degLon = centerPoint[1];
  // center point coordinates (rad)
  radLat = degLat.degToRad();
  radLon = degLon.degToRad();
  // minimum and maximum latitudes for given distance
  minLat = radLat - radDist;
  maxLat = radLat + radDist;
  // minimum and maximum longitudes for given distance
  minLon = void 0;
  maxLon = void 0;
  // define deltaLon to help determine min and max longitudes
  deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat));
  if (minLat > MIN_LAT && maxLat < MAX_LAT) {
    minLon = radLon - deltaLon;
    maxLon = radLon + deltaLon;
    if (minLon < MIN_LON) {
      minLon = minLon + 2 * Math.PI;
    }
    if (maxLon > MAX_LON) {
      maxLon = maxLon - 2 * Math.PI;
    }
  }
  // a pole is within the given distance
  else {
    minLat = Math.max(minLat, MIN_LAT);
    maxLat = Math.min(maxLat, MAX_LAT);
    minLon = MIN_LON;
    maxLon = MAX_LON;
  }
  return [
    minLon.radToDeg(),
    minLat.radToDeg(),
    maxLon.radToDeg(),
    maxLat.radToDeg()
  ];
};


답변

매우 대략적인 견적이 필요했기 때문에 elasticsearch 쿼리에서 불필요한 문서를 필터링하기 위해 아래 공식을 사용했습니다.

Min.lat = Given.Lat - (0.009 x N)
Max.lat = Given.Lat + (0.009 x N)
Min.lon = Given.lon - (0.009 x N)
Max.lon = Given.lon + (0.009 x N)

N = 주어진 위치에서 필요한 kms. 귀하의 경우 N = 10

정확하지는 않지만 편리합니다.


답변

타원체 공식을 찾고 있습니다.

코딩을 시작하기에 가장 좋은 곳은 CPAN의 Geo :: Ellipsoid 라이브러리를 기반으로합니다. 테스트를 생성하고 결과와 결과를 비교할 수있는 기준을 제공합니다. 이전 직장에서 PHP 용 유사한 라이브러리의 기반으로 사용했습니다.

Geo :: Ellipsoid

location방법을 살펴보십시오 . 두 번 전화하면 bbox가 있습니다.

사용중인 언어를 게시하지 않았습니다. 이미 사용 가능한 지오 코딩 라이브러리가있을 수 있습니다.

아, 그리고 지금까지 이해하지 못했다면 Google지도는 WGS84 타원체를 사용합니다.


답변

@Jan Philip Matuschek의 훌륭한 설명의 일러스트 (이것이 아닌 그의 답변에 찬성표를 보내주세요; 원래 답변을 이해하는 데 약간의 시간이 걸렸기 때문에 이것을 추가하고 있습니다)

가장 가까운 이웃 찾기를 최적화하는 경계 상자 기술은 거리 d에서 점 P에 대해 최소 및 최대 위도, 경도 쌍을 유도해야합니다. 이것들 밖에있는 모든 점들은 확실히 점으로부터 d보다 더 큰 거리에 있습니다. 여기서 주목해야 할 한 가지는 Jan Philip Matuschek 설명에서 강조된대로 교차 위도 계산입니다. 교차 위도는 점 P의 위도가 아니라 약간 오프셋됩니다. 이것은 거리 d에 대한 점 P에 대한 정확한 최소 및 최대 경계 경도를 결정하는 데 자주 놓치지 만 중요한 부분이며 검증에도 유용합니다.

P의 (교차 위도, 경도)에서 (위도, 경도) 사이의 하 베사 인 거리는 거리 d와 같습니다.

여기 파이썬 요점 https://gist.github.com/alexcpn/f95ae83a7ee0293a5225

여기에 이미지 설명 입력